[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [PATCH RFC 2/2] xen/x86: Introduce XEN_SYSCTL_cpuid hypercall



which permits a toolstack to execute an arbitrary cpuid instruction on a
specified physical cpu.

Signed-off-by: Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
CC: Keir Fraser <keir@xxxxxxx>
CC: Jan Beulich <JBeulich@xxxxxxxx>
CC: Tim Deegan <tim@xxxxxxx>
CC: Ian Campbell <Ian.Campbell@xxxxxxxxxx>
CC: Ian Jackson <Ian.Jackson@xxxxxxxxxxxxx>
---
 tools/libxc/xc_misc.c       |   25 +++++++++++++++++++++++++
 tools/libxc/xenctrl.h       |    7 +++++++
 xen/arch/x86/sysctl.c       |   30 ++++++++++++++++++++++++++++++
 xen/include/public/sysctl.h |    9 +++++++++
 4 files changed, 71 insertions(+)

diff --git a/tools/libxc/xc_misc.c b/tools/libxc/xc_misc.c
index 4f672ce..48ef33e 100644
--- a/tools/libxc/xc_misc.c
+++ b/tools/libxc/xc_misc.c
@@ -774,6 +774,31 @@ int xc_hvm_inject_trap(
     return rc;
 }
 
+int xc_xen_cpuid(xc_interface *xch, uint32_t cpu, uint32_t *eax,
+                 uint32_t *ebx, uint32_t *ecx, uint32_t *edx)
+{
+    int ret;
+    DECLARE_SYSCTL;
+
+    sysctl.cmd = XEN_SYSCTL_cpuid;
+    sysctl.u.cpuid.cpu = cpu;
+    sysctl.u.cpuid.eax = *eax;
+    sysctl.u.cpuid.ebx = *ebx;
+    sysctl.u.cpuid.ecx = *ecx;
+    sysctl.u.cpuid.edx = *edx;
+
+    ret = do_sysctl(xch, &sysctl);
+    if ( ret )
+        return ret;
+
+    *eax = sysctl.u.cpuid.eax;
+    *ebx = sysctl.u.cpuid.ebx;
+    *ecx = sysctl.u.cpuid.ecx;
+    *edx = sysctl.u.cpuid.edx;
+
+    return 0;
+}
+
 /*
  * Local variables:
  * mode: C
diff --git a/tools/libxc/xenctrl.h b/tools/libxc/xenctrl.h
index 50126ae..a714156 100644
--- a/tools/libxc/xenctrl.h
+++ b/tools/libxc/xenctrl.h
@@ -1801,6 +1801,13 @@ int xc_hvm_inject_trap(
     uint64_t cr2);
 
 /*
+ * Run the cpuid instruction on a specificied physical cpu with the given
+ * parameters.
+ */
+int xc_xen_cpuid(xc_interface *xch, uint32_t cpu, uint32_t *eax,
+                 uint32_t *ebx, uint32_t *ecx, uint32_t *edx);
+
+/*
  *  LOGGING AND ERROR REPORTING
  */
 
diff --git a/xen/arch/x86/sysctl.c b/xen/arch/x86/sysctl.c
index 15d4b91..dbad1ee 100644
--- a/xen/arch/x86/sysctl.c
+++ b/xen/arch/x86/sysctl.c
@@ -66,6 +66,18 @@ void arch_do_physinfo(xen_sysctl_physinfo_t *pi)
         pi->capabilities |= XEN_SYSCTL_PHYSCAP_hvm_directio;
 }
 
+void sysctl_cpuid_helper(void *data)
+{
+    struct xen_sysctl_cpuid *cpuid = data;
+
+    ASSERT(smp_processor_id() == cpuid->cpu);
+    asm volatile ("cpuid"
+                  : "=a" (cpuid->eax), "=b" (cpuid->ebx),
+                    "=c" (cpuid->ecx), "=d" (cpuid->edx)
+                  : "a" (cpuid->eax), "b" (cpuid->ebx),
+                    "c" (cpuid->ecx), "d" (cpuid->edx) );
+}
+
 long arch_do_sysctl(
     struct xen_sysctl *sysctl, XEN_GUEST_HANDLE_PARAM(xen_sysctl_t) u_sysctl)
 {
@@ -101,6 +113,24 @@ long arch_do_sysctl(
     }
     break;
 
+    case XEN_SYSCTL_cpuid:
+    {
+        int cpu = sysctl->u.cpuid.cpu;
+
+        if ( cpu == smp_processor_id() )
+            sysctl_cpuid_helper(&sysctl->u.cpuid);
+        else if ( cpu >= nr_cpu_ids || !cpu_online(cpu) )
+            ret = -EINVAL;
+        else
+            on_selected_cpus(cpumask_of(cpu),
+                             sysctl_cpuid_helper,
+                             &sysctl->u.cpuid, 1);
+
+        if ( !ret && __copy_to_guest(u_sysctl, sysctl, 1) )
+            ret = -EFAULT;
+    }
+    break;
+
     default:
         ret = -ENOSYS;
         break;
diff --git a/xen/include/public/sysctl.h b/xen/include/public/sysctl.h
index 8437d31..afa8a73 100644
--- a/xen/include/public/sysctl.h
+++ b/xen/include/public/sysctl.h
@@ -633,6 +633,13 @@ typedef struct xen_sysctl_coverage_op 
xen_sysctl_coverage_op_t;
 DEFINE_XEN_GUEST_HANDLE(xen_sysctl_coverage_op_t);
 
 
+struct xen_sysctl_cpuid {
+    uint32_t cpu; /* IN - Pcpu to execute on */
+    uint32_t eax, ebx, ecx, edx; /* IN/OUT - Parameters to `cpuid` */
+};
+typedef struct xen_sysctl_cpuid xen_sysctl_cpuid_t;
+DEFINE_XEN_GUEST_HANDLE(xen_sysctl_cpuid_t);
+
 struct xen_sysctl {
     uint32_t cmd;
 #define XEN_SYSCTL_readconsole                    1
@@ -654,6 +661,7 @@ struct xen_sysctl {
 #define XEN_SYSCTL_cpupool_op                    18
 #define XEN_SYSCTL_scheduler_op                  19
 #define XEN_SYSCTL_coverage_op                   20
+#define XEN_SYSCTL_cpuid                         21
     uint32_t interface_version; /* XEN_SYSCTL_INTERFACE_VERSION */
     union {
         struct xen_sysctl_readconsole       readconsole;
@@ -675,6 +683,7 @@ struct xen_sysctl {
         struct xen_sysctl_cpupool_op        cpupool_op;
         struct xen_sysctl_scheduler_op      scheduler_op;
         struct xen_sysctl_coverage_op       coverage_op;
+        struct xen_sysctl_cpuid             cpuid;
         uint8_t                             pad[128];
     } u;
 };
-- 
1.7.10.4


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel


 


Rackspace

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