|
[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 |