mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 02:01:24 +01:00
x86/sysctl: Implement XEN_SYSCTL_get_cpu_policy
Provide a SYSCTL for the toolstack to obtain complete system CPUID and MSR
policy information.
For the flask 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
Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Signed-off-by: Sergey Dyasli <sergey.dyasli@citrix.com>
Signed-off-by: Roger Pau Monné <roger.pau@citrix.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
Acked-by: Daniel De Graaf <dgdegra@tycho.nsa.gov>
Acked-by: Wei Liu <wei.liu2@citrix.com>
This commit is contained in:
1 parent
9b2d12455b
commit
6b85e42709
7 files changed
+214
-4
No files matched your search
@@ -2533,6 +2533,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_cpu_policy_size(xc_interface *xch, uint32_t *nr_leaves,
|
||||
uint32_t *nr_msrs);
|
||||
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);
|
||||
|
||||
uint32_t xc_get_cpu_featureset_size(void);
|
||||
|
||||
enum xc_static_cpu_featuremask {
|
||||
|
||||
@@ -132,6 +132,63 @@ const uint32_t *xc_get_static_cpu_featuremask(
|
||||
}
|
||||
}
|
||||
|
||||
int xc_get_cpu_policy_size(xc_interface *xch, uint32_t *nr_leaves,
|
||||
uint32_t *nr_msrs)
|
||||
{
|
||||
struct xen_sysctl sysctl = {};
|
||||
int ret;
|
||||
|
||||
sysctl.cmd = XEN_SYSCTL_get_cpu_policy;
|
||||
|
||||
ret = do_sysctl(xch, &sysctl);
|
||||
|
||||
if ( !ret )
|
||||
{
|
||||
*nr_leaves = sysctl.u.cpu_policy.nr_leaves;
|
||||
*nr_msrs = sysctl.u.cpu_policy.nr_msrs;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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) ||
|
||||
xc_hypercall_bounce_pre(xch, msrs) )
|
||||
return -1;
|
||||
|
||||
sysctl.cmd = XEN_SYSCTL_get_cpu_policy;
|
||||
sysctl.u.cpu_policy.index = index;
|
||||
sysctl.u.cpu_policy.nr_leaves = *nr_leaves;
|
||||
set_xen_guest_handle(sysctl.u.cpu_policy.cpuid_policy, leaves);
|
||||
sysctl.u.cpu_policy.nr_msrs = *nr_msrs;
|
||||
set_xen_guest_handle(sysctl.u.cpu_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.cpu_policy.nr_leaves;
|
||||
*nr_msrs = sysctl.u.cpu_policy.nr_msrs;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct cpuid_domain_info
|
||||
{
|
||||
enum
|
||||
|
||||
+83
-3
@@ -277,9 +277,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();
|
||||
@@ -293,10 +321,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;
|
||||
@@ -314,6 +343,10 @@ int main(int argc, char **argv)
|
||||
mode = MODE_INFO;
|
||||
break;
|
||||
|
||||
case 'p':
|
||||
mode = MODE_POLICY;
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
case 'v':
|
||||
mode = MODE_DETAIL;
|
||||
@@ -344,7 +377,54 @@ 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_cpu_policy_raw ] = "Raw",
|
||||
[ XEN_SYSCTL_cpu_policy_host ] = "Host",
|
||||
[ XEN_SYSCTL_cpu_policy_pv_max ] = "PV Max",
|
||||
[ XEN_SYSCTL_cpu_policy_hvm_max ] = "HVM Max",
|
||||
[ XEN_SYSCTL_cpu_policy_pv_default ] = "PV Default",
|
||||
[ XEN_SYSCTL_cpu_policy_hvm_default ] = "HVM Default",
|
||||
};
|
||||
xen_cpuid_leaf_t *leaves;
|
||||
xen_msr_entry_t *msrs;
|
||||
uint32_t i, max_leaves, max_msrs;
|
||||
|
||||
xc_interface *xch = xc_interface_open(0, 0, 0);
|
||||
|
||||
if ( !xch )
|
||||
err(1, "xc_interface_open");
|
||||
|
||||
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);
|
||||
|
||||
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 ( 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);
|
||||
free(msrs);
|
||||
xc_interface_close(xch);
|
||||
}
|
||||
else if ( mode == MODE_INFO || mode == MODE_DETAIL )
|
||||
{
|
||||
xc_interface *xch = xc_interface_open(0, 0, 0);
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include <xen/types.h>
|
||||
#include <xen/lib.h>
|
||||
#include <xen/mm.h>
|
||||
#include <xen/nospec.h>
|
||||
#include <xen/guest_access.h>
|
||||
#include <xen/hypercall.h>
|
||||
#include <public/sysctl.h>
|
||||
@@ -336,6 +337,53 @@ long arch_do_sysctl(
|
||||
break;
|
||||
}
|
||||
|
||||
case XEN_SYSCTL_get_cpu_policy:
|
||||
{
|
||||
const struct cpu_policy *policy;
|
||||
|
||||
/* Reserved field set, or bad policy index? */
|
||||
if ( sysctl->u.cpu_policy._rsvd ||
|
||||
sysctl->u.cpu_policy.index >= ARRAY_SIZE(system_policies) )
|
||||
{
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
policy = &system_policies[
|
||||
array_index_nospec(sysctl->u.cpu_policy.index,
|
||||
ARRAY_SIZE(system_policies))];
|
||||
|
||||
/* Process the CPUID leaves. */
|
||||
if ( guest_handle_is_null(sysctl->u.cpu_policy.cpuid_policy) )
|
||||
sysctl->u.cpu_policy.nr_leaves = CPUID_MAX_SERIALISED_LEAVES;
|
||||
else if ( (ret = x86_cpuid_copy_to_buffer(
|
||||
policy->cpuid,
|
||||
sysctl->u.cpu_policy.cpuid_policy,
|
||||
&sysctl->u.cpu_policy.nr_leaves)) )
|
||||
break;
|
||||
|
||||
if ( __copy_field_to_guest(u_sysctl, sysctl,
|
||||
u.cpu_policy.nr_leaves) )
|
||||
{
|
||||
ret = -EFAULT;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Process the MSR entries. */
|
||||
if ( guest_handle_is_null(sysctl->u.cpu_policy.msr_policy) )
|
||||
sysctl->u.cpu_policy.nr_msrs = MSR_MAX_SERIALISED_ENTRIES;
|
||||
else if ( (ret = x86_msr_copy_to_buffer(
|
||||
policy->msr,
|
||||
sysctl->u.cpu_policy.msr_policy,
|
||||
&sysctl->u.cpu_policy.nr_msrs)) )
|
||||
break;
|
||||
|
||||
if ( __copy_field_to_guest(u_sysctl, sysctl,
|
||||
u.cpu_policy.nr_msrs) )
|
||||
ret = -EFAULT;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
ret = -ENOSYS;
|
||||
break;
|
||||
|
||||
@@ -1075,12 +1075,26 @@ struct xen_sysctl_set_parameter {
|
||||
* - Default_*: Default set of features a PV or HVM guest can use. This is
|
||||
* the security supported set.
|
||||
*/
|
||||
struct xen_sysctl_cpu_policy {
|
||||
#define XEN_SYSCTL_cpu_policy_raw 0
|
||||
#define XEN_SYSCTL_cpu_policy_host 1
|
||||
#define XEN_SYSCTL_cpu_policy_pv_max 2
|
||||
#define XEN_SYSCTL_cpu_policy_hvm_max 3
|
||||
#define XEN_SYSCTL_cpu_policy_pv_default 4
|
||||
#define XEN_SYSCTL_cpu_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 the guest handle is NULL. */
|
||||
uint32_t nr_msrs; /* IN/OUT: Number of MSRs in/written to
|
||||
* 'msr_policy', or the maximum number of MSRs if
|
||||
* the guest handle is NULL. */
|
||||
uint32_t _rsvd; /* Must be zero. */
|
||||
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_cpu_policy xen_sysctl_cpu_policy_t;
|
||||
DEFINE_XEN_GUEST_HANDLE(xen_sysctl_cpu_policy_t);
|
||||
#endif
|
||||
|
||||
struct xen_sysctl {
|
||||
@@ -1112,6 +1126,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_cpu_policy 29
|
||||
uint32_t interface_version; /* XEN_SYSCTL_INTERFACE_VERSION */
|
||||
union {
|
||||
struct xen_sysctl_readconsole readconsole;
|
||||
@@ -1141,6 +1156,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_cpu_policy cpu_policy;
|
||||
#endif
|
||||
uint8_t pad[128];
|
||||
} u;
|
||||
};
|
||||
|
||||
@@ -795,6 +795,7 @@ static int flask_sysctl(int cmd)
|
||||
case XEN_SYSCTL_cputopoinfo:
|
||||
case XEN_SYSCTL_numainfo:
|
||||
case XEN_SYSCTL_pcitopoinfo:
|
||||
case XEN_SYSCTL_get_cpu_policy:
|
||||
return domain_has_xen(current->domain, XEN__PHYSINFO);
|
||||
|
||||
case XEN_SYSCTL_psr_cmt_op:
|
||||
|
||||
@@ -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_cpu_policy
|
||||
physinfo
|
||||
# XENPF_platform_quirk
|
||||
quirk
|
||||
|
||||