WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-changelog

[Xen-changelog] [xen-unstable] x86: cpuid configuration for PV guest

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [xen-unstable] x86: cpuid configuration for PV guest
From: Xen patchbot-unstable <patchbot-unstable@xxxxxxxxxxxxxxxxxxx>
Date: Wed, 11 Jun 2008 07:30:10 -0700
Delivery-date: Wed, 11 Jun 2008 07:30:09 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-changelog-request@lists.xensource.com?subject=help>
List-id: BK change log <xen-changelog.lists.xensource.com>
List-post: <mailto:xen-changelog@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=unsubscribe>
Reply-to: xen-devel@xxxxxxxxxxxxxxxxxxx
Sender: xen-changelog-bounces@xxxxxxxxxxxxxxxxxxx
# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1213180535 -3600
# Node ID 7c771f0a24f37cbb3ab56db79f3a82106b42f4d8
# Parent  f292689f48ba62050f1e019dfad1da0bb6444034
x86: cpuid configuration for PV guest

Add pv guest support for the cpuid configuration and checking. That
feature only works for cpuid request which are coming from the guest's
kernel, a process could still call the cpuid directly.

A new policy for pv guest has been created in libxc. dom0 cpuid
emulation is left hardcoded in Xen.

Signed-off-by: Jean Guyader <jean.guyader@xxxxxxxxxxxxx>
Signed-off-by: Keir Fraser <keir.fraser@xxxxxxxxxx>
---
 tools/libxc/xc_cpuid_x86.c     |  177 +++++++++++++++++++++++++++++++----------
 tools/python/xen/xend/image.py |   78 ++++++++++--------
 xen/arch/x86/traps.c           |   69 +++++++++------
 3 files changed, 222 insertions(+), 102 deletions(-)

diff -r f292689f48ba -r 7c771f0a24f3 tools/libxc/xc_cpuid_x86.c
--- a/tools/libxc/xc_cpuid_x86.c        Wed Jun 11 09:44:42 2008 +0100
+++ b/tools/libxc/xc_cpuid_x86.c        Wed Jun 11 11:35:35 2008 +0100
@@ -25,8 +25,8 @@
 #include <xen/hvm/params.h>
 
 #define bitmaskof(idx)      (1u << ((idx) & 31))
-#define clear_bit(idx, dst) ((dst) &= ~(1u << (idx)))
-#define set_bit(idx, dst)   ((dst) |= (1u << (idx)))
+#define clear_bit(idx, dst) ((dst) &= ~(1u << ((idx) & 31)))
+#define set_bit(idx, dst)   ((dst) |= (1u << ((idx) & 31)))
 
 #define DEF_MAX_BASE 0x00000004u
 #define DEF_MAX_EXT  0x80000008u
@@ -36,6 +36,33 @@ static int hypervisor_is_64bit(int xc)
     xen_capabilities_info_t xen_caps = "";
     return ((xc_version(xc, XENVER_capabilities, &xen_caps) == 0) &&
             (strstr(xen_caps, "x86_64") != NULL));
+}
+
+static void cpuid(const unsigned int *input, unsigned int *regs)
+{
+    unsigned int count = (input[1] == XEN_CPUID_INPUT_UNUSED) ? 0 : input[1];
+    asm (
+#ifdef __i386__
+        "push %%ebx; cpuid; mov %%ebx,%1; pop %%ebx"
+#else
+        "push %%rbx; cpuid; mov %%ebx,%1; pop %%rbx"
+#endif
+        : "=a" (regs[0]), "=r" (regs[1]), "=c" (regs[2]), "=d" (regs[3])
+        : "0" (input[0]), "2" (count) );
+}
+
+/* Get the manufacturer brand name of the host processor. */
+static void xc_cpuid_brand_get(char *str)
+{
+    unsigned int input[2] = { 0, 0 };
+    unsigned int regs[4];
+
+    cpuid(input, regs);
+
+    *(uint32_t *)(str + 0) = regs[1];
+    *(uint32_t *)(str + 4) = regs[3];
+    *(uint32_t *)(str + 8) = regs[2];
+    str[12] = '\0';
 }
 
 static void amd_xc_cpuid_policy(
@@ -60,8 +87,8 @@ static void amd_xc_cpuid_policy(
         int is_64bit = hypervisor_is_64bit(xc) && is_pae;
 
         if ( !is_pae )
-            clear_bit(X86_FEATURE_PAE & 31, regs[3]);
-        clear_bit(X86_FEATURE_PSE36 & 31, regs[3]);
+            clear_bit(X86_FEATURE_PAE, regs[3]);
+        clear_bit(X86_FEATURE_PSE36, regs[3]);
 
         /* Filter all other features according to a whitelist. */
         regs[2] &= ((is_64bit ? bitmaskof(X86_FEATURE_LAHF_LM) : 0) |
@@ -113,42 +140,17 @@ static void intel_xc_cpuid_policy(
     }
 }
 
-static void cpuid(const unsigned int *input, unsigned int *regs)
-{
-    unsigned int count = (input[1] == XEN_CPUID_INPUT_UNUSED) ? 0 : input[1];
-    asm (
-#ifdef __i386__
-        "push %%ebx; cpuid; mov %%ebx,%1; pop %%ebx"
-#else
-        "push %%rbx; cpuid; mov %%ebx,%1; pop %%rbx"
-#endif
-        : "=a" (regs[0]), "=r" (regs[1]), "=c" (regs[2]), "=d" (regs[3])
-        : "0" (input[0]), "2" (count) );
-}
-
-/* Get the manufacturer brand name of the host processor. */
-static void xc_cpuid_brand_get(char *str)
-{
-    unsigned int input[2] = { 0, 0 };
-    unsigned int regs[4];
-
-    cpuid(input, regs);
-
-    *(uint32_t *)(str + 0) = regs[1];
-    *(uint32_t *)(str + 4) = regs[3];
-    *(uint32_t *)(str + 8) = regs[2];
-    str[12] = '\0';
-}
-
-static void xc_cpuid_policy(
+static void xc_cpuid_hvm_policy(
     int xc, domid_t domid, const unsigned int *input, unsigned int *regs)
 {
     char brand[13];
     unsigned long pae;
+    int is_pae;
 
     xc_get_hvm_param(xc, domid, HVM_PARAM_PAE_ENABLED, &pae);
-
-    switch( input[0] )
+    is_pae = !!pae;
+
+    switch ( input[0] )
     {
     case 0x00000000:
         if ( regs[0] > DEF_MAX_BASE )
@@ -188,8 +190,8 @@ static void xc_cpuid_policy(
         /* We always support MTRR MSRs. */
         regs[3] |= bitmaskof(X86_FEATURE_MTRR);
 
-        if ( !pae )
-            clear_bit(X86_FEATURE_PAE & 31, regs[3]);
+        if ( !is_pae )
+            clear_bit(X86_FEATURE_PAE, regs[3]);
         break;
 
     case 0x80000000:
@@ -198,8 +200,8 @@ static void xc_cpuid_policy(
         break;
 
     case 0x80000001:
-        if ( !pae )
-            clear_bit(X86_FEATURE_NX & 31, regs[3]);
+        if ( !is_pae )
+            clear_bit(X86_FEATURE_NX, regs[3]);
         break;
 
 
@@ -223,9 +225,104 @@ static void xc_cpuid_policy(
 
     xc_cpuid_brand_get(brand);
     if ( strstr(brand, "AMD") )
-        amd_xc_cpuid_policy(xc, domid, input, regs, !!pae);
+        amd_xc_cpuid_policy(xc, domid, input, regs, is_pae);
     else
-        intel_xc_cpuid_policy(xc, domid, input, regs, !!pae);
+        intel_xc_cpuid_policy(xc, domid, input, regs, is_pae);
+
+}
+
+static void xc_cpuid_pv_policy(
+    int xc, domid_t domid, const unsigned int *input, unsigned int *regs)
+{
+    DECLARE_DOMCTL;
+    int guest_64bit, xen_64bit = hypervisor_is_64bit(xc);
+    char brand[13];
+
+    xc_cpuid_brand_get(brand);
+
+    memset(&domctl, 0, sizeof(domctl));
+    domctl.domain = domid;
+    domctl.cmd = XEN_DOMCTL_get_address_size;
+    do_domctl(xc, &domctl);
+    guest_64bit = (domctl.u.address_size.size == 64);
+
+    if ( (input[0] & 0x7fffffff) == 1 )
+    {
+        clear_bit(X86_FEATURE_VME, regs[3]);
+        clear_bit(X86_FEATURE_PSE, regs[3]);
+        clear_bit(X86_FEATURE_PGE, regs[3]);
+        clear_bit(X86_FEATURE_MCE, regs[3]);
+        clear_bit(X86_FEATURE_MCA, regs[3]);
+        clear_bit(X86_FEATURE_MTRR, regs[3]);
+        clear_bit(X86_FEATURE_PSE36, regs[3]);
+    }
+
+    switch ( input[0] )
+    {
+    case 1:
+        if ( !xen_64bit || strstr(brand, "AMD") )
+            clear_bit(X86_FEATURE_SEP, regs[3]);
+        clear_bit(X86_FEATURE_DS, regs[3]);
+        clear_bit(X86_FEATURE_ACC, regs[3]);
+        clear_bit(X86_FEATURE_PBE, regs[3]);
+
+        clear_bit(X86_FEATURE_DTES64, regs[2]);
+        clear_bit(X86_FEATURE_MWAIT, regs[2]);
+        clear_bit(X86_FEATURE_DSCPL, regs[2]);
+        clear_bit(X86_FEATURE_VMXE, regs[2]);
+        clear_bit(X86_FEATURE_SMXE, regs[2]);
+        clear_bit(X86_FEATURE_EST, regs[2]);
+        clear_bit(X86_FEATURE_TM2, regs[2]);
+        if ( !guest_64bit )
+            clear_bit(X86_FEATURE_CX16, regs[2]);
+        clear_bit(X86_FEATURE_XTPR, regs[2]);
+        clear_bit(X86_FEATURE_PDCM, regs[2]);
+        clear_bit(X86_FEATURE_DCA, regs[2]);
+        break;
+    case 0x80000001:
+        if ( !guest_64bit )
+        {
+            clear_bit(X86_FEATURE_LM, regs[3]);
+            clear_bit(X86_FEATURE_LAHF_LM, regs[2]);
+            if ( !strstr(brand, "AMD") )
+                clear_bit(X86_FEATURE_SYSCALL, regs[3]);
+        }
+        else
+        {
+            set_bit(X86_FEATURE_SYSCALL, regs[3]);
+        }
+        clear_bit(X86_FEATURE_PAGE1GB, regs[3]);
+        clear_bit(X86_FEATURE_RDTSCP, regs[3]);
+
+        clear_bit(X86_FEATURE_SVME, regs[2]);
+        clear_bit(X86_FEATURE_OSVW, regs[2]);
+        clear_bit(X86_FEATURE_IBS, regs[2]);
+        clear_bit(X86_FEATURE_SKINIT, regs[2]);
+        clear_bit(X86_FEATURE_WDT, regs[2]);
+        break;
+    case 5: /* MONITOR/MWAIT */
+    case 0xa: /* Architectural Performance Monitor Features */
+    case 0x8000000a: /* SVM revision and features */
+    case 0x8000001b: /* Instruction Based Sampling */
+        regs[0] = regs[1] = regs[2] = regs[3] = 0;
+        break;
+    }
+}
+
+static int xc_cpuid_policy(
+    int xc, domid_t domid, const unsigned int *input, unsigned int *regs)
+{
+    xc_dominfo_t        info;
+
+    if ( xc_domain_getinfo(xc, domid, 1, &info) == 0 )
+        return -EINVAL;
+
+    if ( info.hvm )
+        xc_cpuid_hvm_policy(xc, domid, input, regs);
+    else
+        xc_cpuid_pv_policy(xc, domid, input, regs);
+
+    return 0;
 }
 
 static int xc_cpuid_do_domctl(
diff -r f292689f48ba -r 7c771f0a24f3 tools/python/xen/xend/image.py
--- a/tools/python/xen/xend/image.py    Wed Jun 11 09:44:42 2008 +0100
+++ b/tools/python/xen/xend/image.py    Wed Jun 11 11:35:35 2008 +0100
@@ -103,6 +103,12 @@ class ImageHandler:
         if rtc_timeoffset is not None:
             xc.domain_set_time_offset(self.vm.getDomid(), int(rtc_timeoffset))
 
+        self.cpuid = None
+        self.cpuid_check = None
+        if 'cpuid' in vmConfig:
+            self.cpuid = vmConfig['cpuid'];
+        if 'cpuid_check' in vmConfig:
+            self.cpuid_check = vmConfig['cpuid_check']
 
     def cleanupBootloading(self):
         if self.bootloader:
@@ -454,6 +460,37 @@ class ImageHandler:
             except:
                 pass
 
+    def setCpuid(self):
+        xc.domain_set_policy_cpuid(self.vm.getDomid())
+
+        if self.cpuid is not None:
+            cpuid = self.cpuid
+            transformed = {}
+            for sinput, regs in cpuid.iteritems():
+                inputs = sinput.split(',')
+                input = long(inputs[0])
+                sub_input = None
+                if len(inputs) == 2:
+                    sub_input = long(inputs[1])
+                t = xc.domain_set_cpuid(self.vm.getDomid(),
+                                        input, sub_input, regs)
+                transformed[sinput] = t
+            self.cpuid = transformed
+
+        if self.cpuid_check is not None:
+            cpuid_check = self.cpuid_check
+            transformed = {}
+            for sinput, regs_check in cpuid_check.iteritems():
+                inputs = sinput.split(',')
+                input = long(inputs[0])
+                sub_input = None
+                if len(inputs) == 2:
+                    sub_input = long(inputs[1])
+                t = xc.domain_check_cpuid(input, sub_input, regs_check)
+                transformed[sinput] = t
+            self.cpuid_check = transformed
+
+
 
 class LinuxImageHandler(ImageHandler):
 
@@ -536,38 +573,7 @@ class HVMImageHandler(ImageHandler):
         self.apic = int(vmConfig['platform'].get('apic', 0))
         self.acpi = int(vmConfig['platform'].get('acpi', 0))
         self.guest_os_type = vmConfig['platform'].get('guest_os_type')
-
-        self.vmConfig = vmConfig
            
-    def setCpuid(self):
-        xc.domain_set_policy_cpuid(self.vm.getDomid())
-
-        if 'cpuid' in self.vmConfig:
-            cpuid = self.vmConfig['cpuid']
-            transformed = {}
-            for sinput, regs in cpuid.iteritems():
-                inputs = sinput.split(',')
-                input = long(inputs[0])
-                sub_input = None
-                if len(inputs) == 2:
-                    sub_input = long(inputs[1])
-                t = xc.domain_set_cpuid(self.vm.getDomid(),
-                                        input, sub_input, regs)
-                transformed[sinput] = t
-            self.vmConfig['cpuid'] = transformed
-
-        if 'cpuid_check' in self.vmConfig:
-            cpuid_check = self.vmConfig['cpuid_check']
-            transformed = {}
-            for sinput, regs_check in cpuid_check.iteritems():
-                inputs = sinput.split(',')
-                input = long(inputs[0])
-                sub_input = None
-                if len(inputs) == 2:
-                    sub_input = long(inputs[1])
-                t = xc.domain_check_cpuid(input, sub_input, regs_check)
-                transformed[sinput] = t
-            self.vmConfig['cpuid_check'] = transformed
 
     # Return a list of cmd line args to the device models based on the
     # xm config file
@@ -730,6 +736,9 @@ class IA64_Linux_ImageHandler(LinuxImage
         LinuxImageHandler.configure(self, vmConfig)
         self.vhpt = int(vmConfig['platform'].get('vhpt',  0))
 
+    def setCpuid(self):
+        # Guest CPUID configuration is not implemented yet.
+        return
 
 class X86_HVM_ImageHandler(HVMImageHandler):
 
@@ -739,8 +748,9 @@ class X86_HVM_ImageHandler(HVMImageHandl
 
     def buildDomain(self):
         xc.hvm_set_param(self.vm.getDomid(), HVM_PARAM_PAE_ENABLED, self.pae)
+        rc = HVMImageHandler.buildDomain(self)
         self.setCpuid()
-        return HVMImageHandler.buildDomain(self)
+        return rc
 
     def getRequiredAvailableMemory(self, mem_kb):
         # Add 8 MiB overhead for QEMU's video RAM.
@@ -769,7 +779,9 @@ class X86_Linux_ImageHandler(LinuxImageH
         # add an 8MB slack to balance backend allocations.
         mem_kb = self.getRequiredMaximumReservation() + (8 * 1024)
         xc.domain_set_memmap_limit(self.vm.getDomid(), mem_kb)
-        return LinuxImageHandler.buildDomain(self)
+        rc = LinuxImageHandler.buildDomain(self)
+        self.setCpuid()
+        return rc
 
 _handlers = {
     "ia64": {
diff -r f292689f48ba -r 7c771f0a24f3 xen/arch/x86/traps.c
--- a/xen/arch/x86/traps.c      Wed Jun 11 09:44:42 2008 +0100
+++ b/xen/arch/x86/traps.c      Wed Jun 11 11:35:35 2008 +0100
@@ -649,37 +649,21 @@ int cpuid_hypervisor_leaves(
     return 1;
 }
 
-static int emulate_forced_invalid_op(struct cpu_user_regs *regs)
-{
-    char sig[5], instr[2];
+static void pv_cpuid(struct cpu_user_regs *regs)
+{
     uint32_t a, b, c, d;
-    unsigned long eip, rc;
 
     a = regs->eax;
     b = regs->ebx;
     c = regs->ecx;
     d = regs->edx;
-    eip = regs->eip;
-
-    /* Check for forced emulation signature: ud2 ; .ascii "xen". */
-    if ( (rc = copy_from_user(sig, (char *)eip, sizeof(sig))) != 0 )
-    {
-        propagate_page_fault(eip + sizeof(sig) - rc, 0);
-        return EXCRET_fault_fixed;
-    }
-    if ( memcmp(sig, "\xf\xbxen", sizeof(sig)) )
-        return 0;
-    eip += sizeof(sig);
-
-    /* We only emulate CPUID. */
-    if ( ( rc = copy_from_user(instr, (char *)eip, sizeof(instr))) != 0 )
-    {
-        propagate_page_fault(eip + sizeof(instr) - rc, 0);
-        return EXCRET_fault_fixed;
-    }
-    if ( memcmp(instr, "\xf\xa2", sizeof(instr)) )
-        return 0;
-    eip += sizeof(instr);
+
+    if ( current->domain->domain_id != 0 )
+    {
+        if ( !cpuid_hypervisor_leaves(a, &a, &b, &c, &d) )
+            domain_cpuid(current->domain, a, b, &a, &b, &c, &d);
+        goto out;
+    }
 
     asm ( 
         "cpuid"
@@ -694,8 +678,6 @@ static int emulate_forced_invalid_op(str
         __clear_bit(X86_FEATURE_PGE, &d);
         __clear_bit(X86_FEATURE_MCE, &d);
         __clear_bit(X86_FEATURE_MCA, &d);
-        if ( !IS_PRIV(current->domain) )
-            __clear_bit(X86_FEATURE_MTRR, &d);
         __clear_bit(X86_FEATURE_PSE36, &d);
     }
     switch ( (uint32_t)regs->eax )
@@ -717,8 +699,6 @@ static int emulate_forced_invalid_op(str
         __clear_bit(X86_FEATURE_DSCPL % 32, &c);
         __clear_bit(X86_FEATURE_VMXE % 32, &c);
         __clear_bit(X86_FEATURE_SMXE % 32, &c);
-        if ( !IS_PRIV(current->domain) )
-            __clear_bit(X86_FEATURE_EST % 32, &c);
         __clear_bit(X86_FEATURE_TM2 % 32, &c);
         if ( is_pv_32bit_vcpu(current) )
             __clear_bit(X86_FEATURE_CX16 % 32, &c);
@@ -758,10 +738,41 @@ static int emulate_forced_invalid_op(str
         break;
     }
 
+ out:
     regs->eax = a;
     regs->ebx = b;
     regs->ecx = c;
     regs->edx = d;
+}
+
+static int emulate_forced_invalid_op(struct cpu_user_regs *regs)
+{
+    char sig[5], instr[2];
+    unsigned long eip, rc;
+
+    eip = regs->eip;
+
+    /* Check for forced emulation signature: ud2 ; .ascii "xen". */
+    if ( (rc = copy_from_user(sig, (char *)eip, sizeof(sig))) != 0 )
+    {
+        propagate_page_fault(eip + sizeof(sig) - rc, 0);
+        return EXCRET_fault_fixed;
+    }
+    if ( memcmp(sig, "\xf\xbxen", sizeof(sig)) )
+        return 0;
+    eip += sizeof(sig);
+
+    /* We only emulate CPUID. */
+    if ( ( rc = copy_from_user(instr, (char *)eip, sizeof(instr))) != 0 )
+    {
+        propagate_page_fault(eip + sizeof(instr) - rc, 0);
+        return EXCRET_fault_fixed;
+    }
+    if ( memcmp(instr, "\xf\xa2", sizeof(instr)) )
+        return 0;
+    eip += sizeof(instr);
+
+    pv_cpuid(regs);
 
     instruction_done(regs, eip, 0);
 

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] [xen-unstable] x86: cpuid configuration for PV guest, Xen patchbot-unstable <=