mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 10:11:27 +01:00
x86/domctl: Implement XEN_DOMCTL_get_cpu_policy
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@citrix.com> Signed-off-by: Sergey Dyasli <sergey.dyasli@citrix.com> Acked-by: Daniel De Graaf <dgdegra@tycho.nsa.gov> Reviewed-by: Jan Beulich <jbeulich@suse.com> Acked-by: Wei Liu <wei.liu2@citrix.com>
This commit is contained in:
1 parent
6b85e42709
commit
60529dfeca
9 files changed
+138
-10
No files matched your search
@@ -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 };
|
||||
|
||||
|
||||
@@ -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 };
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
+50
-8
@@ -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);
|
||||
|
||||
@@ -1542,6 +1542,28 @@ 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;
|
||||
|
||||
/* 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;
|
||||
|
||||
copyback = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
ret = iommu_do_domctl(domctl, d, u_domctl);
|
||||
break;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||