ia64/xen-unstable

changeset 17832:7c771f0a24f3

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@eu.citrix.com>
Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Wed Jun 11 11:35:35 2008 +0100 (2008-06-11)
parents f292689f48ba
children 54c6fc432763
files tools/libxc/xc_cpuid_x86.c tools/python/xen/xend/image.py xen/arch/x86/traps.c
line diff
     1.1 --- a/tools/libxc/xc_cpuid_x86.c	Wed Jun 11 09:44:42 2008 +0100
     1.2 +++ b/tools/libxc/xc_cpuid_x86.c	Wed Jun 11 11:35:35 2008 +0100
     1.3 @@ -25,8 +25,8 @@
     1.4  #include <xen/hvm/params.h>
     1.5  
     1.6  #define bitmaskof(idx)      (1u << ((idx) & 31))
     1.7 -#define clear_bit(idx, dst) ((dst) &= ~(1u << (idx)))
     1.8 -#define set_bit(idx, dst)   ((dst) |= (1u << (idx)))
     1.9 +#define clear_bit(idx, dst) ((dst) &= ~(1u << ((idx) & 31)))
    1.10 +#define set_bit(idx, dst)   ((dst) |= (1u << ((idx) & 31)))
    1.11  
    1.12  #define DEF_MAX_BASE 0x00000004u
    1.13  #define DEF_MAX_EXT  0x80000008u
    1.14 @@ -38,6 +38,33 @@ static int hypervisor_is_64bit(int xc)
    1.15              (strstr(xen_caps, "x86_64") != NULL));
    1.16  }
    1.17  
    1.18 +static void cpuid(const unsigned int *input, unsigned int *regs)
    1.19 +{
    1.20 +    unsigned int count = (input[1] == XEN_CPUID_INPUT_UNUSED) ? 0 : input[1];
    1.21 +    asm (
    1.22 +#ifdef __i386__
    1.23 +        "push %%ebx; cpuid; mov %%ebx,%1; pop %%ebx"
    1.24 +#else
    1.25 +        "push %%rbx; cpuid; mov %%ebx,%1; pop %%rbx"
    1.26 +#endif
    1.27 +        : "=a" (regs[0]), "=r" (regs[1]), "=c" (regs[2]), "=d" (regs[3])
    1.28 +        : "0" (input[0]), "2" (count) );
    1.29 +}
    1.30 +
    1.31 +/* Get the manufacturer brand name of the host processor. */
    1.32 +static void xc_cpuid_brand_get(char *str)
    1.33 +{
    1.34 +    unsigned int input[2] = { 0, 0 };
    1.35 +    unsigned int regs[4];
    1.36 +
    1.37 +    cpuid(input, regs);
    1.38 +
    1.39 +    *(uint32_t *)(str + 0) = regs[1];
    1.40 +    *(uint32_t *)(str + 4) = regs[3];
    1.41 +    *(uint32_t *)(str + 8) = regs[2];
    1.42 +    str[12] = '\0';
    1.43 +}
    1.44 +
    1.45  static void amd_xc_cpuid_policy(
    1.46      int xc, domid_t domid, const unsigned int *input, unsigned int *regs,
    1.47      int is_pae)
    1.48 @@ -60,8 +87,8 @@ static void amd_xc_cpuid_policy(
    1.49          int is_64bit = hypervisor_is_64bit(xc) && is_pae;
    1.50  
    1.51          if ( !is_pae )
    1.52 -            clear_bit(X86_FEATURE_PAE & 31, regs[3]);
    1.53 -        clear_bit(X86_FEATURE_PSE36 & 31, regs[3]);
    1.54 +            clear_bit(X86_FEATURE_PAE, regs[3]);
    1.55 +        clear_bit(X86_FEATURE_PSE36, regs[3]);
    1.56  
    1.57          /* Filter all other features according to a whitelist. */
    1.58          regs[2] &= ((is_64bit ? bitmaskof(X86_FEATURE_LAHF_LM) : 0) |
    1.59 @@ -113,42 +140,17 @@ static void intel_xc_cpuid_policy(
    1.60      }
    1.61  }
    1.62  
    1.63 -static void cpuid(const unsigned int *input, unsigned int *regs)
    1.64 -{
    1.65 -    unsigned int count = (input[1] == XEN_CPUID_INPUT_UNUSED) ? 0 : input[1];
    1.66 -    asm (
    1.67 -#ifdef __i386__
    1.68 -        "push %%ebx; cpuid; mov %%ebx,%1; pop %%ebx"
    1.69 -#else
    1.70 -        "push %%rbx; cpuid; mov %%ebx,%1; pop %%rbx"
    1.71 -#endif
    1.72 -        : "=a" (regs[0]), "=r" (regs[1]), "=c" (regs[2]), "=d" (regs[3])
    1.73 -        : "0" (input[0]), "2" (count) );
    1.74 -}
    1.75 -
    1.76 -/* Get the manufacturer brand name of the host processor. */
    1.77 -static void xc_cpuid_brand_get(char *str)
    1.78 -{
    1.79 -    unsigned int input[2] = { 0, 0 };
    1.80 -    unsigned int regs[4];
    1.81 -
    1.82 -    cpuid(input, regs);
    1.83 -
    1.84 -    *(uint32_t *)(str + 0) = regs[1];
    1.85 -    *(uint32_t *)(str + 4) = regs[3];
    1.86 -    *(uint32_t *)(str + 8) = regs[2];
    1.87 -    str[12] = '\0';
    1.88 -}
    1.89 -
    1.90 -static void xc_cpuid_policy(
    1.91 +static void xc_cpuid_hvm_policy(
    1.92      int xc, domid_t domid, const unsigned int *input, unsigned int *regs)
    1.93  {
    1.94      char brand[13];
    1.95      unsigned long pae;
    1.96 +    int is_pae;
    1.97  
    1.98      xc_get_hvm_param(xc, domid, HVM_PARAM_PAE_ENABLED, &pae);
    1.99 +    is_pae = !!pae;
   1.100  
   1.101 -    switch( input[0] )
   1.102 +    switch ( input[0] )
   1.103      {
   1.104      case 0x00000000:
   1.105          if ( regs[0] > DEF_MAX_BASE )
   1.106 @@ -188,8 +190,8 @@ static void xc_cpuid_policy(
   1.107          /* We always support MTRR MSRs. */
   1.108          regs[3] |= bitmaskof(X86_FEATURE_MTRR);
   1.109  
   1.110 -        if ( !pae )
   1.111 -            clear_bit(X86_FEATURE_PAE & 31, regs[3]);
   1.112 +        if ( !is_pae )
   1.113 +            clear_bit(X86_FEATURE_PAE, regs[3]);
   1.114          break;
   1.115  
   1.116      case 0x80000000:
   1.117 @@ -198,8 +200,8 @@ static void xc_cpuid_policy(
   1.118          break;
   1.119  
   1.120      case 0x80000001:
   1.121 -        if ( !pae )
   1.122 -            clear_bit(X86_FEATURE_NX & 31, regs[3]);
   1.123 +        if ( !is_pae )
   1.124 +            clear_bit(X86_FEATURE_NX, regs[3]);
   1.125          break;
   1.126  
   1.127  
   1.128 @@ -223,9 +225,104 @@ static void xc_cpuid_policy(
   1.129  
   1.130      xc_cpuid_brand_get(brand);
   1.131      if ( strstr(brand, "AMD") )
   1.132 -        amd_xc_cpuid_policy(xc, domid, input, regs, !!pae);
   1.133 +        amd_xc_cpuid_policy(xc, domid, input, regs, is_pae);
   1.134      else
   1.135 -        intel_xc_cpuid_policy(xc, domid, input, regs, !!pae);
   1.136 +        intel_xc_cpuid_policy(xc, domid, input, regs, is_pae);
   1.137 +
   1.138 +}
   1.139 +
   1.140 +static void xc_cpuid_pv_policy(
   1.141 +    int xc, domid_t domid, const unsigned int *input, unsigned int *regs)
   1.142 +{
   1.143 +    DECLARE_DOMCTL;
   1.144 +    int guest_64bit, xen_64bit = hypervisor_is_64bit(xc);
   1.145 +    char brand[13];
   1.146 +
   1.147 +    xc_cpuid_brand_get(brand);
   1.148 +
   1.149 +    memset(&domctl, 0, sizeof(domctl));
   1.150 +    domctl.domain = domid;
   1.151 +    domctl.cmd = XEN_DOMCTL_get_address_size;
   1.152 +    do_domctl(xc, &domctl);
   1.153 +    guest_64bit = (domctl.u.address_size.size == 64);
   1.154 +
   1.155 +    if ( (input[0] & 0x7fffffff) == 1 )
   1.156 +    {
   1.157 +        clear_bit(X86_FEATURE_VME, regs[3]);
   1.158 +        clear_bit(X86_FEATURE_PSE, regs[3]);
   1.159 +        clear_bit(X86_FEATURE_PGE, regs[3]);
   1.160 +        clear_bit(X86_FEATURE_MCE, regs[3]);
   1.161 +        clear_bit(X86_FEATURE_MCA, regs[3]);
   1.162 +        clear_bit(X86_FEATURE_MTRR, regs[3]);
   1.163 +        clear_bit(X86_FEATURE_PSE36, regs[3]);
   1.164 +    }
   1.165 +
   1.166 +    switch ( input[0] )
   1.167 +    {
   1.168 +    case 1:
   1.169 +        if ( !xen_64bit || strstr(brand, "AMD") )
   1.170 +            clear_bit(X86_FEATURE_SEP, regs[3]);
   1.171 +        clear_bit(X86_FEATURE_DS, regs[3]);
   1.172 +        clear_bit(X86_FEATURE_ACC, regs[3]);
   1.173 +        clear_bit(X86_FEATURE_PBE, regs[3]);
   1.174 +
   1.175 +        clear_bit(X86_FEATURE_DTES64, regs[2]);
   1.176 +        clear_bit(X86_FEATURE_MWAIT, regs[2]);
   1.177 +        clear_bit(X86_FEATURE_DSCPL, regs[2]);
   1.178 +        clear_bit(X86_FEATURE_VMXE, regs[2]);
   1.179 +        clear_bit(X86_FEATURE_SMXE, regs[2]);
   1.180 +        clear_bit(X86_FEATURE_EST, regs[2]);
   1.181 +        clear_bit(X86_FEATURE_TM2, regs[2]);
   1.182 +        if ( !guest_64bit )
   1.183 +            clear_bit(X86_FEATURE_CX16, regs[2]);
   1.184 +        clear_bit(X86_FEATURE_XTPR, regs[2]);
   1.185 +        clear_bit(X86_FEATURE_PDCM, regs[2]);
   1.186 +        clear_bit(X86_FEATURE_DCA, regs[2]);
   1.187 +        break;
   1.188 +    case 0x80000001:
   1.189 +        if ( !guest_64bit )
   1.190 +        {
   1.191 +            clear_bit(X86_FEATURE_LM, regs[3]);
   1.192 +            clear_bit(X86_FEATURE_LAHF_LM, regs[2]);
   1.193 +            if ( !strstr(brand, "AMD") )
   1.194 +                clear_bit(X86_FEATURE_SYSCALL, regs[3]);
   1.195 +        }
   1.196 +        else
   1.197 +        {
   1.198 +            set_bit(X86_FEATURE_SYSCALL, regs[3]);
   1.199 +        }
   1.200 +        clear_bit(X86_FEATURE_PAGE1GB, regs[3]);
   1.201 +        clear_bit(X86_FEATURE_RDTSCP, regs[3]);
   1.202 +
   1.203 +        clear_bit(X86_FEATURE_SVME, regs[2]);
   1.204 +        clear_bit(X86_FEATURE_OSVW, regs[2]);
   1.205 +        clear_bit(X86_FEATURE_IBS, regs[2]);
   1.206 +        clear_bit(X86_FEATURE_SKINIT, regs[2]);
   1.207 +        clear_bit(X86_FEATURE_WDT, regs[2]);
   1.208 +        break;
   1.209 +    case 5: /* MONITOR/MWAIT */
   1.210 +    case 0xa: /* Architectural Performance Monitor Features */
   1.211 +    case 0x8000000a: /* SVM revision and features */
   1.212 +    case 0x8000001b: /* Instruction Based Sampling */
   1.213 +        regs[0] = regs[1] = regs[2] = regs[3] = 0;
   1.214 +        break;
   1.215 +    }
   1.216 +}
   1.217 +
   1.218 +static int xc_cpuid_policy(
   1.219 +    int xc, domid_t domid, const unsigned int *input, unsigned int *regs)
   1.220 +{
   1.221 +    xc_dominfo_t        info;
   1.222 +
   1.223 +    if ( xc_domain_getinfo(xc, domid, 1, &info) == 0 )
   1.224 +        return -EINVAL;
   1.225 +
   1.226 +    if ( info.hvm )
   1.227 +        xc_cpuid_hvm_policy(xc, domid, input, regs);
   1.228 +    else
   1.229 +        xc_cpuid_pv_policy(xc, domid, input, regs);
   1.230 +
   1.231 +    return 0;
   1.232  }
   1.233  
   1.234  static int xc_cpuid_do_domctl(
     2.1 --- a/tools/python/xen/xend/image.py	Wed Jun 11 09:44:42 2008 +0100
     2.2 +++ b/tools/python/xen/xend/image.py	Wed Jun 11 11:35:35 2008 +0100
     2.3 @@ -103,6 +103,12 @@ class ImageHandler:
     2.4          if rtc_timeoffset is not None:
     2.5              xc.domain_set_time_offset(self.vm.getDomid(), int(rtc_timeoffset))
     2.6  
     2.7 +        self.cpuid = None
     2.8 +        self.cpuid_check = None
     2.9 +        if 'cpuid' in vmConfig:
    2.10 +            self.cpuid = vmConfig['cpuid'];
    2.11 +        if 'cpuid_check' in vmConfig:
    2.12 +            self.cpuid_check = vmConfig['cpuid_check']
    2.13  
    2.14      def cleanupBootloading(self):
    2.15          if self.bootloader:
    2.16 @@ -454,6 +460,37 @@ class ImageHandler:
    2.17              except:
    2.18                  pass
    2.19  
    2.20 +    def setCpuid(self):
    2.21 +        xc.domain_set_policy_cpuid(self.vm.getDomid())
    2.22 +
    2.23 +        if self.cpuid is not None:
    2.24 +            cpuid = self.cpuid
    2.25 +            transformed = {}
    2.26 +            for sinput, regs in cpuid.iteritems():
    2.27 +                inputs = sinput.split(',')
    2.28 +                input = long(inputs[0])
    2.29 +                sub_input = None
    2.30 +                if len(inputs) == 2:
    2.31 +                    sub_input = long(inputs[1])
    2.32 +                t = xc.domain_set_cpuid(self.vm.getDomid(),
    2.33 +                                        input, sub_input, regs)
    2.34 +                transformed[sinput] = t
    2.35 +            self.cpuid = transformed
    2.36 +
    2.37 +        if self.cpuid_check is not None:
    2.38 +            cpuid_check = self.cpuid_check
    2.39 +            transformed = {}
    2.40 +            for sinput, regs_check in cpuid_check.iteritems():
    2.41 +                inputs = sinput.split(',')
    2.42 +                input = long(inputs[0])
    2.43 +                sub_input = None
    2.44 +                if len(inputs) == 2:
    2.45 +                    sub_input = long(inputs[1])
    2.46 +                t = xc.domain_check_cpuid(input, sub_input, regs_check)
    2.47 +                transformed[sinput] = t
    2.48 +            self.cpuid_check = transformed
    2.49 +
    2.50 +
    2.51  
    2.52  class LinuxImageHandler(ImageHandler):
    2.53  
    2.54 @@ -536,38 +573,7 @@ class HVMImageHandler(ImageHandler):
    2.55          self.apic = int(vmConfig['platform'].get('apic', 0))
    2.56          self.acpi = int(vmConfig['platform'].get('acpi', 0))
    2.57          self.guest_os_type = vmConfig['platform'].get('guest_os_type')
    2.58 -
    2.59 -        self.vmConfig = vmConfig
    2.60             
    2.61 -    def setCpuid(self):
    2.62 -        xc.domain_set_policy_cpuid(self.vm.getDomid())
    2.63 -
    2.64 -        if 'cpuid' in self.vmConfig:
    2.65 -            cpuid = self.vmConfig['cpuid']
    2.66 -            transformed = {}
    2.67 -            for sinput, regs in cpuid.iteritems():
    2.68 -                inputs = sinput.split(',')
    2.69 -                input = long(inputs[0])
    2.70 -                sub_input = None
    2.71 -                if len(inputs) == 2:
    2.72 -                    sub_input = long(inputs[1])
    2.73 -                t = xc.domain_set_cpuid(self.vm.getDomid(),
    2.74 -                                        input, sub_input, regs)
    2.75 -                transformed[sinput] = t
    2.76 -            self.vmConfig['cpuid'] = transformed
    2.77 -
    2.78 -        if 'cpuid_check' in self.vmConfig:
    2.79 -            cpuid_check = self.vmConfig['cpuid_check']
    2.80 -            transformed = {}
    2.81 -            for sinput, regs_check in cpuid_check.iteritems():
    2.82 -                inputs = sinput.split(',')
    2.83 -                input = long(inputs[0])
    2.84 -                sub_input = None
    2.85 -                if len(inputs) == 2:
    2.86 -                    sub_input = long(inputs[1])
    2.87 -                t = xc.domain_check_cpuid(input, sub_input, regs_check)
    2.88 -                transformed[sinput] = t
    2.89 -            self.vmConfig['cpuid_check'] = transformed
    2.90  
    2.91      # Return a list of cmd line args to the device models based on the
    2.92      # xm config file
    2.93 @@ -730,6 +736,9 @@ class IA64_Linux_ImageHandler(LinuxImage
    2.94          LinuxImageHandler.configure(self, vmConfig)
    2.95          self.vhpt = int(vmConfig['platform'].get('vhpt',  0))
    2.96  
    2.97 +    def setCpuid(self):
    2.98 +        # Guest CPUID configuration is not implemented yet.
    2.99 +        return
   2.100  
   2.101  class X86_HVM_ImageHandler(HVMImageHandler):
   2.102  
   2.103 @@ -739,8 +748,9 @@ class X86_HVM_ImageHandler(HVMImageHandl
   2.104  
   2.105      def buildDomain(self):
   2.106          xc.hvm_set_param(self.vm.getDomid(), HVM_PARAM_PAE_ENABLED, self.pae)
   2.107 +        rc = HVMImageHandler.buildDomain(self)
   2.108          self.setCpuid()
   2.109 -        return HVMImageHandler.buildDomain(self)
   2.110 +        return rc
   2.111  
   2.112      def getRequiredAvailableMemory(self, mem_kb):
   2.113          # Add 8 MiB overhead for QEMU's video RAM.
   2.114 @@ -769,7 +779,9 @@ class X86_Linux_ImageHandler(LinuxImageH
   2.115          # add an 8MB slack to balance backend allocations.
   2.116          mem_kb = self.getRequiredMaximumReservation() + (8 * 1024)
   2.117          xc.domain_set_memmap_limit(self.vm.getDomid(), mem_kb)
   2.118 -        return LinuxImageHandler.buildDomain(self)
   2.119 +        rc = LinuxImageHandler.buildDomain(self)
   2.120 +        self.setCpuid()
   2.121 +        return rc
   2.122  
   2.123  _handlers = {
   2.124      "ia64": {
     3.1 --- a/xen/arch/x86/traps.c	Wed Jun 11 09:44:42 2008 +0100
     3.2 +++ b/xen/arch/x86/traps.c	Wed Jun 11 11:35:35 2008 +0100
     3.3 @@ -649,37 +649,21 @@ int cpuid_hypervisor_leaves(
     3.4      return 1;
     3.5  }
     3.6  
     3.7 -static int emulate_forced_invalid_op(struct cpu_user_regs *regs)
     3.8 +static void pv_cpuid(struct cpu_user_regs *regs)
     3.9  {
    3.10 -    char sig[5], instr[2];
    3.11      uint32_t a, b, c, d;
    3.12 -    unsigned long eip, rc;
    3.13  
    3.14      a = regs->eax;
    3.15      b = regs->ebx;
    3.16      c = regs->ecx;
    3.17      d = regs->edx;
    3.18 -    eip = regs->eip;
    3.19 -
    3.20 -    /* Check for forced emulation signature: ud2 ; .ascii "xen". */
    3.21 -    if ( (rc = copy_from_user(sig, (char *)eip, sizeof(sig))) != 0 )
    3.22 +
    3.23 +    if ( current->domain->domain_id != 0 )
    3.24      {
    3.25 -        propagate_page_fault(eip + sizeof(sig) - rc, 0);
    3.26 -        return EXCRET_fault_fixed;
    3.27 +        if ( !cpuid_hypervisor_leaves(a, &a, &b, &c, &d) )
    3.28 +            domain_cpuid(current->domain, a, b, &a, &b, &c, &d);
    3.29 +        goto out;
    3.30      }
    3.31 -    if ( memcmp(sig, "\xf\xbxen", sizeof(sig)) )
    3.32 -        return 0;
    3.33 -    eip += sizeof(sig);
    3.34 -
    3.35 -    /* We only emulate CPUID. */
    3.36 -    if ( ( rc = copy_from_user(instr, (char *)eip, sizeof(instr))) != 0 )
    3.37 -    {
    3.38 -        propagate_page_fault(eip + sizeof(instr) - rc, 0);
    3.39 -        return EXCRET_fault_fixed;
    3.40 -    }
    3.41 -    if ( memcmp(instr, "\xf\xa2", sizeof(instr)) )
    3.42 -        return 0;
    3.43 -    eip += sizeof(instr);
    3.44  
    3.45      asm ( 
    3.46          "cpuid"
    3.47 @@ -694,8 +678,6 @@ static int emulate_forced_invalid_op(str
    3.48          __clear_bit(X86_FEATURE_PGE, &d);
    3.49          __clear_bit(X86_FEATURE_MCE, &d);
    3.50          __clear_bit(X86_FEATURE_MCA, &d);
    3.51 -        if ( !IS_PRIV(current->domain) )
    3.52 -            __clear_bit(X86_FEATURE_MTRR, &d);
    3.53          __clear_bit(X86_FEATURE_PSE36, &d);
    3.54      }
    3.55      switch ( (uint32_t)regs->eax )
    3.56 @@ -717,8 +699,6 @@ static int emulate_forced_invalid_op(str
    3.57          __clear_bit(X86_FEATURE_DSCPL % 32, &c);
    3.58          __clear_bit(X86_FEATURE_VMXE % 32, &c);
    3.59          __clear_bit(X86_FEATURE_SMXE % 32, &c);
    3.60 -        if ( !IS_PRIV(current->domain) )
    3.61 -            __clear_bit(X86_FEATURE_EST % 32, &c);
    3.62          __clear_bit(X86_FEATURE_TM2 % 32, &c);
    3.63          if ( is_pv_32bit_vcpu(current) )
    3.64              __clear_bit(X86_FEATURE_CX16 % 32, &c);
    3.65 @@ -758,10 +738,41 @@ static int emulate_forced_invalid_op(str
    3.66          break;
    3.67      }
    3.68  
    3.69 + out:
    3.70      regs->eax = a;
    3.71      regs->ebx = b;
    3.72      regs->ecx = c;
    3.73      regs->edx = d;
    3.74 +}
    3.75 +
    3.76 +static int emulate_forced_invalid_op(struct cpu_user_regs *regs)
    3.77 +{
    3.78 +    char sig[5], instr[2];
    3.79 +    unsigned long eip, rc;
    3.80 +
    3.81 +    eip = regs->eip;
    3.82 +
    3.83 +    /* Check for forced emulation signature: ud2 ; .ascii "xen". */
    3.84 +    if ( (rc = copy_from_user(sig, (char *)eip, sizeof(sig))) != 0 )
    3.85 +    {
    3.86 +        propagate_page_fault(eip + sizeof(sig) - rc, 0);
    3.87 +        return EXCRET_fault_fixed;
    3.88 +    }
    3.89 +    if ( memcmp(sig, "\xf\xbxen", sizeof(sig)) )
    3.90 +        return 0;
    3.91 +    eip += sizeof(sig);
    3.92 +
    3.93 +    /* We only emulate CPUID. */
    3.94 +    if ( ( rc = copy_from_user(instr, (char *)eip, sizeof(instr))) != 0 )
    3.95 +    {
    3.96 +        propagate_page_fault(eip + sizeof(instr) - rc, 0);
    3.97 +        return EXCRET_fault_fixed;
    3.98 +    }
    3.99 +    if ( memcmp(instr, "\xf\xa2", sizeof(instr)) )
   3.100 +        return 0;
   3.101 +    eip += sizeof(instr);
   3.102 +
   3.103 +    pv_cpuid(regs);
   3.104  
   3.105      instruction_done(regs, eip, 0);
   3.106