[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH 09/13] x86/sysctl: Implement XEN_SYSCTL_get_cpumsr_policy
From: Sergey Dyasli <sergey.dyasli@xxxxxxxxxx> Provide a SYSCTL for the toolstack to obtain complete system CPUID and MSR policy information. The split of default vs max policies is introduced into the API, including a description of the intended behaviour. For now, max is the default, but this is intended to change moving forwards. For the XSM side of things, this subop is closely related to {phys,cputopo,numa}info, so shares the physinfo access vector. Extend the xen-cpuid utility to be able to dump the system policies. An example output is: Xen reports there are maximum 113 leaves and 3 MSRs Raw policy: 93 leaves, 3 MSRs CPUID: leaf subleaf -> eax ebx ecx edx 00000000:ffffffff -> 0000000d:756e6547:6c65746e:49656e69 00000001:ffffffff -> 000306c3:00100800:7ffafbff:bfebfbff 00000002:ffffffff -> 76036301:00f0b5ff:00000000:00c10000 00000004:00000000 -> 1c004121:01c0003f:0000003f:00000000 00000004:00000001 -> 1c004122:01c0003f:0000003f:00000000 00000004:00000002 -> 1c004143:01c0003f:000001ff:00000000 00000004:00000003 -> 1c03c163:03c0003f:00001fff:00000006 00000005:ffffffff -> 00000040:00000040:00000003:00042120 00000006:ffffffff -> 00000077:00000002:00000009:00000000 00000007:00000000 -> 00000000:000027ab:00000000:9c000000 0000000a:ffffffff -> 07300403:00000000:00000000:00000603 0000000b:00000000 -> 00000001:00000002:00000100:00000000 0000000b:00000001 -> 00000004:00000008:00000201:00000000 0000000d:00000000 -> 00000007:00000340:00000340:00000000 0000000d:00000001 -> 00000001:00000000:00000000:00000000 0000000d:00000002 -> 00000100:00000240:00000000:00000000 80000000:ffffffff -> 80000008:00000000:00000000:00000000 80000001:ffffffff -> 00000000:00000000:00000021:2c100800 80000002:ffffffff -> 65746e49:2952286c:6f655820:2952286e 80000003:ffffffff -> 55504320:2d334520:30343231:20337620 80000004:ffffffff -> 2e332040:48473034:0000007a:00000000 80000006:ffffffff -> 00000000:00000000:01006040:00000000 80000007:ffffffff -> 00000000:00000000:00000000:00000100 80000008:ffffffff -> 00003027:00000000:00000000:00000000 MSRs: index -> value 000000ce -> 0000000080000000 00000048 -> 0000000000000000 00000140 -> 0000000000000000 Signed-off-by: Andrew Cooper <andrew.cooper3@xxxxxxxxxx> Signed-off-by: Sergey Dyasli <sergey.dyasli@xxxxxxxxxx> Signed-off-by: Roger Pau Monné <roger.pau@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> --- tools/libxc/include/xenctrl.h | 6 +++ tools/libxc/xc_cpuid_x86.c | 59 ++++++++++++++++++++++++ tools/misc/xen-cpuid.c | 89 +++++++++++++++++++++++++++++++++++-- xen/arch/x86/sysctl.c | 86 +++++++++++++++++++++++++++++++++-- xen/include/public/sysctl.h | 41 +++++++++++++++++ xen/xsm/flask/hooks.c | 1 + xen/xsm/flask/policy/access_vectors | 2 +- 7 files changed, 275 insertions(+), 9 deletions(-) diff --git a/tools/libxc/include/xenctrl.h b/tools/libxc/include/xenctrl.h index 70f54e6..d1f0925c 100644 --- a/tools/libxc/include/xenctrl.h +++ b/tools/libxc/include/xenctrl.h @@ -2536,6 +2536,12 @@ int xc_get_cpu_levelling_caps(xc_interface *xch, uint32_t *caps); int xc_get_cpu_featureset(xc_interface *xch, uint32_t index, uint32_t *nr_features, uint32_t *featureset); +int xc_get_cpumsr_policy_size(xc_interface *xch, uint32_t *nr_leaves, + uint32_t *nr_msrs); +int xc_get_system_cpumsr_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); + uint32_t xc_get_cpu_featureset_size(void); enum xc_static_cpu_featuremask { diff --git a/tools/libxc/xc_cpuid_x86.c b/tools/libxc/xc_cpuid_x86.c index 900c639..ce2a584 100644 --- a/tools/libxc/xc_cpuid_x86.c +++ b/tools/libxc/xc_cpuid_x86.c @@ -134,6 +134,65 @@ const uint32_t *xc_get_static_cpu_featuremask( } } +int xc_get_cpumsr_policy_size(xc_interface *xch, uint32_t *nr_leaves, + uint32_t *nr_msrs) +{ + struct xen_sysctl sysctl = {}; + int ret; + + sysctl.cmd = XEN_SYSCTL_get_cpumsr_policy; + + ret = do_sysctl(xch, &sysctl); + + if ( !ret ) + { + *nr_leaves = sysctl.u.cpumsr_policy.nr_leaves; + *nr_msrs = sysctl.u.cpumsr_policy.nr_msrs; + } + + return ret; +} + +int xc_get_system_cpumsr_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) +{ + struct xen_sysctl sysctl = {}; + 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) ) + return -1; + + if ( xc_hypercall_bounce_pre(xch, msrs) ) + return -1; + + sysctl.cmd = XEN_SYSCTL_get_cpumsr_policy; + sysctl.u.cpumsr_policy.index = index; + sysctl.u.cpumsr_policy.nr_leaves = *nr_leaves; + set_xen_guest_handle(sysctl.u.cpumsr_policy.cpuid_policy, leaves); + sysctl.u.cpumsr_policy.nr_msrs = *nr_msrs; + set_xen_guest_handle(sysctl.u.cpumsr_policy.msr_policy, msrs); + + ret = do_sysctl(xch, &sysctl); + + xc_hypercall_bounce_post(xch, leaves); + xc_hypercall_bounce_post(xch, msrs); + + if ( !ret ) + { + *nr_leaves = sysctl.u.cpumsr_policy.nr_leaves; + *nr_msrs = sysctl.u.cpumsr_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 e116339..a5b3004 100644 --- a/tools/misc/xen-cpuid.c +++ b/tools/misc/xen-cpuid.c @@ -276,9 +276,37 @@ static void dump_info(xc_interface *xch, bool detail) free(featuresets[i].fs); } +static void print_policy(const char *name, + xen_cpuid_leaf_t *leaves, uint32_t nr_leaves, + xen_msr_entry_t *msrs, uint32_t nr_msrs) +{ + unsigned int l; + + printf("%s policy: %u leaves, %u MSRs\n", name, nr_leaves, nr_msrs); + printf(" CPUID:\n"); + printf(" %-8s %-8s -> %-8s %-8s %-8s %-8s\n", + "leaf", "subleaf", "eax", "ebx", "ecx", "edx"); + for ( l = 0; l < nr_leaves; ++l ) + { + /* Skip empty leaves. */ + if ( !leaves[l].a && !leaves[l].b && !leaves[l].c && !leaves[l].d ) + continue; + + printf(" %08x:%08x -> %08x:%08x:%08x:%08x\n", + leaves[l].leaf, leaves[l].subleaf, + leaves[l].a, leaves[l].b, leaves[l].c, leaves[l].d); + } + + printf(" MSRs:\n"); + printf(" %-8s -> %-16s\n", "index", "value"); + for ( l = 0; l < nr_msrs; ++l ) + printf(" %08x -> %016lx\n", + msrs[l].idx, msrs[l].val); +} + int main(int argc, char **argv) { - enum { MODE_UNKNOWN, MODE_INFO, MODE_DETAIL, MODE_INTERPRET } + enum { MODE_UNKNOWN, MODE_INFO, MODE_DETAIL, MODE_INTERPRET, MODE_POLICY } mode = MODE_UNKNOWN; nr_features = xc_get_cpu_featureset_size(); @@ -292,10 +320,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' }, { NULL, 0, NULL, 0 }, }; - c = getopt_long(argc, argv, "hidv", long_options, &option_index); + c = getopt_long(argc, argv, "hidvp", long_options, &option_index); if ( c == -1 ) break; @@ -313,6 +342,10 @@ int main(int argc, char **argv) mode = MODE_INFO; break; + case 'p': + mode = MODE_POLICY; + break; + case 'd': case 'v': mode = MODE_DETAIL; @@ -343,7 +376,55 @@ int main(int argc, char **argv) mode = MODE_INTERPRET; } - if ( mode == MODE_INFO || mode == MODE_DETAIL ) + if ( mode == MODE_POLICY ) + { + static const char *const sys_policies[] = { + [ XEN_SYSCTL_cpumsr_policy_raw ] = "Raw", + [ XEN_SYSCTL_cpumsr_policy_host ] = "Host", + [ XEN_SYSCTL_cpumsr_policy_pv_max ] = "PV Max", + [ XEN_SYSCTL_cpumsr_policy_hvm_max ] = "HVM Max", + [ XEN_SYSCTL_cpumsr_policy_pv_default ] = "PV Default", + [ XEN_SYSCTL_cpumsr_policy_hvm_default ] = "HVM Default", + }; + xen_cpuid_leaf_t *leaves; + xen_msr_entry_t *msrs; + uint32_t pol, max_leaves, max_msrs; + + xc_interface *xch = xc_interface_open(0, 0, 0); + + if ( !xch ) + err(1, "xc_interface_open"); + + if ( xc_get_cpumsr_policy_size(xch, &max_leaves, &max_msrs) ) + err(1, "xc_get_cpumsr_policy_size(...)"); + 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 ) + err(1, "calloc(max_leaves)"); + msrs = calloc(max_msrs, sizeof(xen_msr_entry_t)); + if ( !msrs ) + err(1, "calloc(max_msrs)"); + + for ( pol = 0; pol < ARRAY_SIZE(sys_policies); ++pol ) + { + uint32_t nr_leaves = max_leaves; + uint32_t nr_msrs = max_msrs; + + if ( xc_get_system_cpumsr_policy(xch, pol, &nr_leaves, leaves, + &nr_msrs, msrs) ) + err(1, "xc_get_system_cpumsr_policy(, %s,,)", + sys_policies[pol]); + + print_policy(sys_policies[pol], leaves, nr_leaves, msrs, nr_msrs); + } + + free(leaves); + free(msrs); + xc_interface_close(xch); + } + else if ( mode == MODE_INFO || mode == MODE_DETAIL ) { xc_interface *xch = xc_interface_open(0, 0, 0); @@ -377,7 +458,7 @@ int main(int argc, char **argv) if ( i == nr_features ) break; - if ( *ptr == ':' ) + if ( *ptr == ':' || *ptr == '-' ) { ptr++; continue; } diff --git a/xen/arch/x86/sysctl.c b/xen/arch/x86/sysctl.c index c5c00d0..067fc86 100644 --- a/xen/arch/x86/sysctl.c +++ b/xen/arch/x86/sysctl.c @@ -32,22 +32,32 @@ #include <asm/cpuid.h> const struct policy_group system_policies[] = { - { + [ XEN_SYSCTL_cpumsr_policy_raw ] = { &raw_cpuid_policy, &raw_msr_domain_policy, &raw_msr_vcpu_policy, }, - { + [ XEN_SYSCTL_cpumsr_policy_host ] = { &host_cpuid_policy, &host_msr_domain_policy, &host_msr_vcpu_policy, }, - { + [ XEN_SYSCTL_cpumsr_policy_pv_max ] = { &pv_max_cpuid_policy, &pv_max_msr_domain_policy, &pv_max_msr_vcpu_policy, }, - { + [ XEN_SYSCTL_cpumsr_policy_hvm_max ] = { + &hvm_max_cpuid_policy, + &hvm_max_msr_domain_policy, + &hvm_max_msr_vcpu_policy, + }, + [ XEN_SYSCTL_cpumsr_policy_pv_default ] = { + &pv_max_cpuid_policy, + &pv_max_msr_domain_policy, + &pv_max_msr_vcpu_policy, + }, + [ XEN_SYSCTL_cpumsr_policy_hvm_default ] = { &hvm_max_cpuid_policy, &hvm_max_msr_domain_policy, &hvm_max_msr_vcpu_policy, @@ -318,6 +328,74 @@ long arch_do_sysctl( break; } + case XEN_SYSCTL_get_cpumsr_policy: + { + const struct policy_group *group; + + /* Bad policy index? */ + if ( sysctl->u.cpumsr_policy.index >= ARRAY_SIZE(system_policies) ) + { + ret = -EINVAL; + break; + } + group = &system_policies[sysctl->u.cpumsr_policy.index]; + + /* Request for maximum number of leaves/MSRs? */ + if ( guest_handle_is_null(sysctl->u.cpumsr_policy.cpuid_policy) ) + { + sysctl->u.cpumsr_policy.nr_leaves = CPUID_MAX_SERIALISED_LEAVES; + if ( __copy_field_to_guest(u_sysctl, sysctl, + u.cpumsr_policy.nr_leaves) ) + { + ret = -EFAULT; + break; + } + } + if ( guest_handle_is_null(sysctl->u.cpumsr_policy.msr_policy) ) + { + sysctl->u.cpumsr_policy.nr_msrs = MSR_MAX_SERIALISED_ENTRIES; + if ( __copy_field_to_guest(u_sysctl, sysctl, + u.cpumsr_policy.nr_msrs) ) + { + ret = -EFAULT; + break; + } + } + + /* Serialise the information the caller wants. */ + if ( !guest_handle_is_null(sysctl->u.cpumsr_policy.cpuid_policy) ) + { + if ( (ret = x86_cpuid_copy_to_buffer( + group->cp, + sysctl->u.cpumsr_policy.cpuid_policy, + &sysctl->u.cpumsr_policy.nr_leaves)) ) + break; + + if ( __copy_field_to_guest(u_sysctl, sysctl, + u.cpumsr_policy.nr_leaves) ) + { + ret = -EFAULT; + break; + } + } + if ( !guest_handle_is_null(sysctl->u.cpumsr_policy.msr_policy) ) + { + if ( (ret = x86_msr_copy_to_buffer( + group->dp, group->vp, + sysctl->u.cpumsr_policy.msr_policy, + &sysctl->u.cpumsr_policy.nr_msrs)) ) + break; + + if ( __copy_field_to_guest(u_sysctl, sysctl, + u.cpumsr_policy.nr_msrs) ) + { + ret = -EFAULT; + break; + } + } + break; + } + default: ret = -ENOSYS; break; diff --git a/xen/include/public/sysctl.h b/xen/include/public/sysctl.h index 839c1b9..f04bfa8 100644 --- a/xen/include/public/sysctl.h +++ b/xen/include/public/sysctl.h @@ -1063,6 +1063,43 @@ struct xen_sysctl_set_parameter { uint16_t pad[3]; /* IN: MUST be zero. */ }; +#if defined(__i386__) || defined(__x86_64__) +/* + * XEN_SYSCTL_get_cpumsr_policy (x86 specific) + * + * Return information about CPUID and MSR policies available on this host. + * - Raw: The real H/W values. + * - Host: The values Xen is using, (after command line overrides, etc). + * - Max_*: Maximum set of features a PV or HVM guest can use. Includes + * experimental features outside of security support. + * - Default_*: Default set of features a PV or HVM guest can use. This is + * the security supported set. + */ +struct xen_sysctl_cpumsr_policy { +#define XEN_SYSCTL_cpumsr_policy_raw 0 +#define XEN_SYSCTL_cpumsr_policy_host 1 +#define XEN_SYSCTL_cpumsr_policy_pv_max 2 +#define XEN_SYSCTL_cpumsr_policy_hvm_max 3 +#define XEN_SYSCTL_cpumsr_policy_pv_default 4 +#define XEN_SYSCTL_cpumsr_policy_hvm_default 5 + uint32_t index; /* IN: Which policy to query? */ + uint32_t nr_leaves; /* IN/OUT: Number of leaves in/written to + * 'cpuid_policy', or the maximum number of leaves if + * any of the guest handles is NULL. + * NB. All policies come from the same space, + * so have the same maximum length. */ + uint32_t nr_msrs; /* IN/OUT: Number of MSRs in/written to + * 'msr_domain_policy', or the maximum number of MSRs + * if any of the guest handles is NULL. + * NB. All policies come from the same space, + * so have the same maximum length. */ + 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_sysctl_cpumsr_policy xen_sysctl_cpumsr_policy_t; +DEFINE_XEN_GUEST_HANDLE(xen_sysctl_cpumsr_policy_t); +#endif + struct xen_sysctl { uint32_t cmd; #define XEN_SYSCTL_readconsole 1 @@ -1092,6 +1129,7 @@ struct xen_sysctl { #define XEN_SYSCTL_get_cpu_featureset 26 #define XEN_SYSCTL_livepatch_op 27 #define XEN_SYSCTL_set_parameter 28 +#define XEN_SYSCTL_get_cpumsr_policy 29 uint32_t interface_version; /* XEN_SYSCTL_INTERFACE_VERSION */ union { struct xen_sysctl_readconsole readconsole; @@ -1121,6 +1159,9 @@ struct xen_sysctl { struct xen_sysctl_cpu_featureset cpu_featureset; struct xen_sysctl_livepatch_op livepatch; struct xen_sysctl_set_parameter set_parameter; +#if defined(__i386__) || defined(__x86_64__) + struct xen_sysctl_cpumsr_policy cpumsr_policy; +#endif uint8_t pad[128]; } u; }; diff --git a/xen/xsm/flask/hooks.c b/xen/xsm/flask/hooks.c index 78bc326..1d30b0e 100644 --- a/xen/xsm/flask/hooks.c +++ b/xen/xsm/flask/hooks.c @@ -801,6 +801,7 @@ static int flask_sysctl(int cmd) case XEN_SYSCTL_cputopoinfo: case XEN_SYSCTL_numainfo: case XEN_SYSCTL_pcitopoinfo: + case XEN_SYSCTL_get_cpumsr_policy: return domain_has_xen(current->domain, XEN__PHYSINFO); case XEN_SYSCTL_psr_cmt_op: diff --git a/xen/xsm/flask/policy/access_vectors b/xen/xsm/flask/policy/access_vectors index c5d8548..b5bc7a2 100644 --- a/xen/xsm/flask/policy/access_vectors +++ b/xen/xsm/flask/policy/access_vectors @@ -28,7 +28,7 @@ class xen # XENPF_microcode_update microcode # XEN_SYSCTL_physinfo, XEN_SYSCTL_cputopoinfo, XEN_SYSCTL_numainfo -# XEN_SYSCTL_pcitopoinfo +# XEN_SYSCTL_pcitopoinfo, XEN_SYSCTL_get_cpumsr_policy physinfo # XENPF_platform_quirk quirk -- 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 |