[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

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.