[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH v3 5/5] x86/domctl: Implement XEN_DOMCTL_get_cpu_policy
From: Sergey Dyasli <sergey.dyasli@xxxxxxxxxx> This finally (after literally years of work!) marks the point where the toolstack can ask the hypervisor for the current CPUID configuration of a specific domain. Introduce a new flask access vector and update the default policies. Also extend xen-cpuid's --policy mode to be able to take a domid and dump a specific domains CPUID and MSR policy. Signed-off-by: Andrew Cooper <andrew.cooper3@xxxxxxxxxx> Signed-off-by: Sergey Dyasli <sergey.dyasli@xxxxxxxxxx> --- CC: Jan Beulich <JBeulich@xxxxxxxx> CC: Ian Jackson <Ian.Jackson@xxxxxxxxxxxxx> CC: Wei Liu <wei.liu2@xxxxxxxxxx> CC: Roger Pau Monné <roger.pau@xxxxxxxxxx> CC: Sergey Dyasli <sergey.dyasli@xxxxxxxxxx> CC: Daniel De Graaf <dgdegra@xxxxxxxxxxxxx> v3: * Misc code hygene * Fix comments to avoid having a SYSCTL/DOMCTL paste error * Introduce a new flask vector rather than reusing set_cpuid --- tools/flask/policy/modules/dom0.te | 2 +- tools/flask/policy/modules/xen.if | 2 +- tools/libxc/include/xenctrl.h | 3 ++ tools/libxc/xc_cpuid_x86.c | 38 ++++++++++++++++++++++++ tools/misc/xen-cpuid.c | 58 ++++++++++++++++++++++++++++++++----- xen/arch/x86/domctl.c | 32 ++++++++++++++++++++ xen/include/public/domctl.h | 18 ++++++++++++ xen/xsm/flask/hooks.c | 3 ++ xen/xsm/flask/policy/access_vectors | 2 ++ 9 files changed, 148 insertions(+), 10 deletions(-) diff --git a/tools/flask/policy/modules/dom0.te b/tools/flask/policy/modules/dom0.te index dfdcdcd..c7d565d 100644 --- a/tools/flask/policy/modules/dom0.te +++ b/tools/flask/policy/modules/dom0.te @@ -39,7 +39,7 @@ allow dom0_t dom0_t:domain { }; allow dom0_t dom0_t:domain2 { set_cpuid gettsc settsc setscheduler set_vnumainfo - get_vnumainfo psr_cmt_op psr_alloc + get_vnumainfo psr_cmt_op psr_alloc get_cpu_policy }; allow dom0_t dom0_t:resource { add remove }; diff --git a/tools/flask/policy/modules/xen.if b/tools/flask/policy/modules/xen.if index 4e06cfc..de5fb33 100644 --- a/tools/flask/policy/modules/xen.if +++ b/tools/flask/policy/modules/xen.if @@ -53,7 +53,7 @@ define(`create_domain_common', ` allow $1 $2:domain2 { set_cpuid settsc setscheduler setclaim set_vnumainfo get_vnumainfo cacheflush psr_cmt_op psr_alloc soft_reset - resource_map }; + resource_map get_cpu_policy }; allow $1 $2:security check_context; allow $1 $2:shadow enable; allow $1 $2:mmu { map_read map_write adjust memorymap physmap pinpage mmuext_op updatemp }; diff --git a/tools/libxc/include/xenctrl.h b/tools/libxc/include/xenctrl.h index 74fa88b..97ae965 100644 --- a/tools/libxc/include/xenctrl.h +++ b/tools/libxc/include/xenctrl.h @@ -2538,6 +2538,9 @@ int xc_get_cpu_policy_size(xc_interface *xch, uint32_t *nr_leaves, int xc_get_system_cpu_policy(xc_interface *xch, uint32_t index, uint32_t *nr_leaves, xen_cpuid_leaf_t *leaves, uint32_t *nr_msrs, xen_msr_entry_t *msrs); +int xc_get_domain_cpu_policy(xc_interface *xch, uint32_t domid, + uint32_t *nr_leaves, xen_cpuid_leaf_t *leaves, + uint32_t *nr_msrs, xen_msr_entry_t *msrs); uint32_t xc_get_cpu_featureset_size(void); diff --git a/tools/libxc/xc_cpuid_x86.c b/tools/libxc/xc_cpuid_x86.c index 00e27f0..9e47fc8 100644 --- a/tools/libxc/xc_cpuid_x86.c +++ b/tools/libxc/xc_cpuid_x86.c @@ -189,6 +189,44 @@ int xc_get_system_cpu_policy(xc_interface *xch, uint32_t index, return ret; } +int xc_get_domain_cpu_policy(xc_interface *xch, uint32_t domid, + uint32_t *nr_leaves, xen_cpuid_leaf_t *leaves, + uint32_t *nr_msrs, xen_msr_entry_t *msrs) +{ + DECLARE_DOMCTL; + DECLARE_HYPERCALL_BOUNCE(leaves, + *nr_leaves * sizeof(*leaves), + XC_HYPERCALL_BUFFER_BOUNCE_OUT); + DECLARE_HYPERCALL_BOUNCE(msrs, + *nr_msrs * sizeof(*msrs), + XC_HYPERCALL_BUFFER_BOUNCE_OUT); + int ret; + + if ( xc_hypercall_bounce_pre(xch, leaves) || + xc_hypercall_bounce_pre(xch, msrs) ) + return -1; + + domctl.cmd = XEN_DOMCTL_get_cpu_policy; + domctl.domain = domid; + domctl.u.cpu_policy.nr_leaves = *nr_leaves; + set_xen_guest_handle(domctl.u.cpu_policy.cpuid_policy, leaves); + domctl.u.cpu_policy.nr_msrs = *nr_msrs; + set_xen_guest_handle(domctl.u.cpu_policy.msr_policy, msrs); + + ret = do_domctl(xch, &domctl); + + xc_hypercall_bounce_post(xch, leaves); + xc_hypercall_bounce_post(xch, msrs); + + if ( !ret ) + { + *nr_leaves = domctl.u.cpu_policy.nr_leaves; + *nr_msrs = domctl.u.cpu_policy.nr_msrs; + } + + return ret; +} + struct cpuid_domain_info { enum diff --git a/tools/misc/xen-cpuid.c b/tools/misc/xen-cpuid.c index 95ed853..2c41031 100644 --- a/tools/misc/xen-cpuid.c +++ b/tools/misc/xen-cpuid.c @@ -3,6 +3,8 @@ #include <err.h> #include <getopt.h> #include <string.h> +#include <errno.h> +#include <limits.h> #include <xenctrl.h> @@ -309,11 +311,13 @@ int main(int argc, char **argv) { enum { MODE_UNKNOWN, MODE_INFO, MODE_DETAIL, MODE_INTERPRET, MODE_POLICY } mode = MODE_UNKNOWN; + int domid = -1; nr_features = xc_get_cpu_featureset_size(); for ( ;; ) { + const char *tmp_optarg; int option_index = 0, c; static struct option long_options[] = { @@ -321,11 +325,11 @@ int main(int argc, char **argv) { "info", no_argument, NULL, 'i' }, { "detail", no_argument, NULL, 'd' }, { "verbose", no_argument, NULL, 'v' }, - { "policy", no_argument, NULL, 'p' }, + { "policy", optional_argument, NULL, 'p' }, { NULL, 0, NULL, 0 }, }; - c = getopt_long(argc, argv, "hidvp", long_options, &option_index); + c = getopt_long(argc, argv, "hidvp::", long_options, &option_index); if ( c == -1 ) break; @@ -345,6 +349,24 @@ int main(int argc, char **argv) case 'p': mode = MODE_POLICY; + + tmp_optarg = optarg; + + /* Make "--policy $DOMID" and "-p $DOMID" work. */ + if ( !optarg && optind < argc && + argv[optind] != NULL && argv[optind][0] != '\0' && + argv[optind][0] != '-' ) + tmp_optarg = argv[optind++]; + + if ( tmp_optarg ) + { + char *endptr; + + errno = 0; + domid = strtol(tmp_optarg, &endptr, 0); + if ( errno || endptr == tmp_optarg ) + err(1, "strtol(%s,,)", tmp_optarg); + } break; case 'd': @@ -398,8 +420,9 @@ int main(int argc, char **argv) if ( xc_get_cpu_policy_size(xch, &max_leaves, &max_msrs) ) err(1, "xc_get_cpu_policy_size(...)"); - printf("Xen reports there are maximum %u leaves and %u MSRs\n", - max_leaves, max_msrs); + if ( domid == -1 ) + printf("Xen reports there are maximum %u leaves and %u MSRs\n", + max_leaves, max_msrs); leaves = calloc(max_leaves, sizeof(xen_cpuid_leaf_t)); if ( !leaves ) @@ -408,16 +431,35 @@ int main(int argc, char **argv) if ( !msrs ) err(1, "calloc(max_msrs)"); - for ( i = 0; i < ARRAY_SIZE(sys_policies); ++i ) + if ( domid != -1 ) { + char name[20]; uint32_t nr_leaves = max_leaves; uint32_t nr_msrs = max_msrs; - if ( xc_get_system_cpu_policy(xch, i, &nr_leaves, leaves, + if ( xc_get_domain_cpu_policy(xch, domid, &nr_leaves, leaves, &nr_msrs, msrs) ) - err(1, "xc_get_system_cpu_policy(, %s,,)", sys_policies[i]); + err(1, "xc_get_domain_cpu_policy(, %d, %d,, %d,)", + domid, nr_leaves, nr_msrs); - print_policy(sys_policies[i], leaves, nr_leaves, msrs, nr_msrs); + snprintf(name, sizeof(name), "Domain %d", domid); + print_policy(name, leaves, nr_leaves, msrs, nr_msrs); + } + else + { + /* Get system policies */ + for ( i = 0; i < ARRAY_SIZE(sys_policies); ++i ) + { + uint32_t nr_leaves = max_leaves; + uint32_t nr_msrs = max_msrs; + + if ( xc_get_system_cpu_policy(xch, i, &nr_leaves, leaves, + &nr_msrs, msrs) ) + err(1, "xc_get_system_cpu_policy(, %s,,)", sys_policies[i]); + + print_policy(sys_policies[i], leaves, nr_leaves, + msrs, nr_msrs); + } } free(leaves); diff --git a/xen/arch/x86/domctl.c b/xen/arch/x86/domctl.c index f79827e..d91b6ab 100644 --- a/xen/arch/x86/domctl.c +++ b/xen/arch/x86/domctl.c @@ -1528,6 +1528,38 @@ long arch_do_domctl( recalculate_cpuid_policy(d); break; + case XEN_DOMCTL_get_cpu_policy: + /* Process the CPUID leaves. */ + if ( guest_handle_is_null(domctl->u.cpu_policy.cpuid_policy) ) + domctl->u.cpu_policy.nr_leaves = CPUID_MAX_SERIALISED_LEAVES; + else if ( (ret = x86_cpuid_copy_to_buffer( + d->arch.cpuid, + domctl->u.cpu_policy.cpuid_policy, + &domctl->u.cpu_policy.nr_leaves)) ) + break; + + if ( __copy_field_to_guest(u_domctl, domctl, + u.cpu_policy.nr_leaves) ) + { + ret = -EFAULT; + break; + } + + /* Process the MSR entries. */ + if ( guest_handle_is_null(domctl->u.cpu_policy.msr_policy) ) + domctl->u.cpu_policy.nr_msrs = MSR_MAX_SERIALISED_ENTRIES; + else if ( (ret = x86_msr_copy_to_buffer( + d->arch.msr, + domctl->u.cpu_policy.msr_policy, + &domctl->u.cpu_policy.nr_msrs)) ) + break; + + if ( __copy_field_to_guest(u_domctl, domctl, + u.cpu_policy.nr_msrs) ) + ret = -EFAULT; + + break; + default: ret = iommu_do_domctl(domctl, d, u_domctl); break; diff --git a/xen/include/public/domctl.h b/xen/include/public/domctl.h index 1bbdcd9..4a46c28 100644 --- a/xen/include/public/domctl.h +++ b/xen/include/public/domctl.h @@ -652,6 +652,22 @@ struct xen_domctl_cpuid { uint32_t ecx; uint32_t edx; }; + +/* + * XEN_DOMCTL_get_cpu_policy (x86 specific) + * + * Query the CPUID and MSR policies for a specific domain. + */ +struct xen_domctl_cpu_policy { + uint32_t nr_leaves; /* IN/OUT: Number of leaves in/written to + * 'cpuid_policy'. */ + uint32_t nr_msrs; /* IN/OUT: Number of MSRs in/written to + * 'msr_domain_policy' */ + XEN_GUEST_HANDLE_64(xen_cpuid_leaf_t) cpuid_policy; /* OUT */ + XEN_GUEST_HANDLE_64(xen_msr_entry_t) msr_policy; /* OUT */ +}; +typedef struct xen_domctl_cpu_policy xen_domctl_cpu_policy_t; +DEFINE_XEN_GUEST_HANDLE(xen_domctl_cpu_policy_t); #endif /* @@ -1177,6 +1193,7 @@ struct xen_domctl { #define XEN_DOMCTL_soft_reset 79 /* #define XEN_DOMCTL_set_gnttab_limits 80 - Moved into XEN_DOMCTL_createdomain */ #define XEN_DOMCTL_vuart_op 81 +#define XEN_DOMCTL_get_cpu_policy 82 #define XEN_DOMCTL_gdbsx_guestmemio 1000 #define XEN_DOMCTL_gdbsx_pausevcpu 1001 #define XEN_DOMCTL_gdbsx_unpausevcpu 1002 @@ -1221,6 +1238,7 @@ struct xen_domctl { struct xen_domctl_mem_sharing_op mem_sharing_op; #if defined(__i386__) || defined(__x86_64__) struct xen_domctl_cpuid cpuid; + struct xen_domctl_cpu_policy cpu_policy; struct xen_domctl_vcpuextstate vcpuextstate; struct xen_domctl_vcpu_msrs vcpu_msrs; #endif diff --git a/xen/xsm/flask/hooks.c b/xen/xsm/flask/hooks.c index e5b0c60..96d31aa 100644 --- a/xen/xsm/flask/hooks.c +++ b/xen/xsm/flask/hooks.c @@ -742,6 +742,9 @@ static int flask_domctl(struct domain *d, int cmd) case XEN_DOMCTL_soft_reset: return current_has_perm(d, SECCLASS_DOMAIN2, DOMAIN2__SOFT_RESET); + case XEN_DOMCTL_get_cpu_policy: + return current_has_perm(d, SECCLASS_DOMAIN2, DOMAIN2__GET_CPU_POLICY); + default: return avc_unknown_permission("domctl", cmd); } diff --git a/xen/xsm/flask/policy/access_vectors b/xen/xsm/flask/policy/access_vectors index e58a50d..6fecfda 100644 --- a/xen/xsm/flask/policy/access_vectors +++ b/xen/xsm/flask/policy/access_vectors @@ -248,6 +248,8 @@ class domain2 psr_alloc # XENMEM_resource_map resource_map +# XEN_DOMCTL_get_cpu_policy + get_cpu_policy } # Similar to class domain, but primarily contains domctls related to HVM domains -- 2.1.4 _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxxxxxxxxx https://lists.xenproject.org/mailman/listinfo/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |