ia64/xen-unstable

changeset 13129:f99dd72ae205

[HVM] Clean up CPUID handling.
From: Xin B Li <xin.b.li@intel.com>
Signed-off-by: Keir Fraser <keir@xensource.com>
author kfraser@localhost.localdomain
date Wed Dec 20 10:09:42 2006 +0000 (2006-12-20)
parents 1818b322ede9
children 87dceaa715af
files xen/arch/x86/hvm/hvm.c xen/arch/x86/hvm/svm/svm.c xen/arch/x86/hvm/vmx/vmx.c xen/include/asm-x86/hvm/hvm.h xen/include/asm-x86/hvm/vmx/cpu.h
line diff
     1.1 --- a/xen/arch/x86/hvm/hvm.c	Wed Dec 20 10:06:33 2006 +0000
     1.2 +++ b/xen/arch/x86/hvm/hvm.c	Wed Dec 20 10:09:42 2006 +0000
     1.3 @@ -402,6 +402,47 @@ void hvm_print_line(struct vcpu *v, cons
     1.4      spin_unlock(&hd->pbuf_lock);
     1.5  }
     1.6  
     1.7 +void hvm_cpuid(unsigned int input, unsigned int *eax, unsigned int *ebx,
     1.8 +                                   unsigned int *ecx, unsigned int *edx)
     1.9 +{
    1.10 +    if ( !cpuid_hypervisor_leaves(input, eax, ebx, ecx, edx) )
    1.11 +    {
    1.12 +        cpuid(input, eax, ebx, ecx, edx);
    1.13 +
    1.14 +        if ( input == 0x00000001 )
    1.15 +        {
    1.16 +            struct vcpu *v = current;
    1.17 +
    1.18 +            clear_bit(X86_FEATURE_MWAIT & 31, ecx);
    1.19 +
    1.20 +            if ( vlapic_hw_disabled(vcpu_vlapic(v)) )
    1.21 +                clear_bit(X86_FEATURE_APIC & 31, edx);
    1.22 +
    1.23 +#if CONFIG_PAGING_LEVELS >= 3
    1.24 +            if ( !v->domain->arch.hvm_domain.params[HVM_PARAM_PAE_ENABLED] )
    1.25 +#endif
    1.26 +                clear_bit(X86_FEATURE_PAE & 31, edx);
    1.27 +
    1.28 +            clear_bit(X86_FEATURE_PSE36 & 31, edx);
    1.29 +        }
    1.30 +        else if ( input == 0x80000001 )
    1.31 +        {
    1.32 +#if CONFIG_PAGING_LEVELS >= 3
    1.33 +            struct vcpu *v = current;
    1.34 +            if ( !v->domain->arch.hvm_domain.params[HVM_PARAM_PAE_ENABLED] )
    1.35 +#endif
    1.36 +                clear_bit(X86_FEATURE_NX & 31, edx);
    1.37 +#ifdef __i386__
    1.38 +            /* Mask feature for Intel ia32e or AMD long mode. */
    1.39 +            clear_bit(X86_FEATURE_LAHF_LM & 31, ecx);
    1.40 +
    1.41 +            clear_bit(X86_FEATURE_LM & 31, edx);
    1.42 +            clear_bit(X86_FEATURE_SYSCALL & 31, edx);
    1.43 +#endif
    1.44 +        }
    1.45 +    }
    1.46 +}
    1.47 +
    1.48  typedef unsigned long hvm_hypercall_t(
    1.49      unsigned long, unsigned long, unsigned long, unsigned long, unsigned long);
    1.50  
     2.1 --- a/xen/arch/x86/hvm/svm/svm.c	Wed Dec 20 10:06:33 2006 +0000
     2.2 +++ b/xen/arch/x86/hvm/svm/svm.c	Wed Dec 20 10:09:42 2006 +0000
     2.3 @@ -999,91 +999,65 @@ static void svm_do_general_protection_fa
     2.4  /* Reserved bits EDX: [31:29], [27], [22:20], [18], [10] */
     2.5  #define SVM_VCPU_CPUID_L1_EDX_RESERVED 0xe8740400
     2.6  
     2.7 -static void svm_vmexit_do_cpuid(struct vmcb_struct *vmcb, unsigned long input, 
     2.8 -                                struct cpu_user_regs *regs) 
     2.9 +static void svm_vmexit_do_cpuid(struct vmcb_struct *vmcb,
    2.10 +                                struct cpu_user_regs *regs)
    2.11  {
    2.12 +    unsigned long input = regs->eax;
    2.13      unsigned int eax, ebx, ecx, edx;
    2.14 -    unsigned long eip;
    2.15      struct vcpu *v = current;
    2.16      int inst_len;
    2.17  
    2.18      ASSERT(vmcb);
    2.19  
    2.20 -    eip = vmcb->rip;
    2.21 -
    2.22 -    HVM_DBG_LOG(DBG_LEVEL_1, 
    2.23 -                "do_cpuid: (eax) %lx, (ebx) %lx, (ecx) %lx, (edx) %lx,"
    2.24 -                " (esi) %lx, (edi) %lx",
    2.25 -                (unsigned long)regs->eax, (unsigned long)regs->ebx,
    2.26 -                (unsigned long)regs->ecx, (unsigned long)regs->edx,
    2.27 -                (unsigned long)regs->esi, (unsigned long)regs->edi);
    2.28 -
    2.29 -    if ( !cpuid_hypervisor_leaves(input, &eax, &ebx, &ecx, &edx) )
    2.30 +    hvm_cpuid(input, &eax, &ebx, &ecx, &edx);
    2.31 +
    2.32 +    if ( input == 0x00000001 )
    2.33      {
    2.34 -        cpuid(input, &eax, &ebx, &ecx, &edx);       
    2.35 -        if (input == 0x00000001 || input == 0x80000001 )
    2.36 -        {
    2.37 -            if ( vlapic_hw_disabled(vcpu_vlapic(v)) )
    2.38 -            {
    2.39 -                /* Since the apic is disabled, avoid any confusion 
    2.40 -                   about SMP cpus being available */
    2.41 -                clear_bit(X86_FEATURE_APIC, &edx);
    2.42 -            }
    2.43 +        /* Clear out reserved bits. */
    2.44 +        ecx &= ~SVM_VCPU_CPUID_L1_ECX_RESERVED;
    2.45 +        edx &= ~SVM_VCPU_CPUID_L1_EDX_RESERVED;
    2.46 +
    2.47 +        /* Guest should only see one logical processor.
    2.48 +         * See details on page 23 of AMD CPUID Specification.
    2.49 +         */
    2.50 +        clear_bit(X86_FEATURE_HT & 31, &edx);  /* clear the hyperthread bit */
    2.51 +        ebx &= 0xFF00FFFF;  /* clear the logical processor count when HTT=0 */
    2.52 +        ebx |= 0x00010000;  /* set to 1 just for precaution */
    2.53 +    }
    2.54 +    else if ( input == 0x80000001 )
    2.55 +    {
    2.56 +        if ( vlapic_hw_disabled(vcpu_vlapic(v)) )
    2.57 +            clear_bit(X86_FEATURE_APIC & 31, &edx);
    2.58 +
    2.59  #if CONFIG_PAGING_LEVELS >= 3
    2.60 -            if ( !v->domain->arch.hvm_domain.params[HVM_PARAM_PAE_ENABLED] )
    2.61 +        if ( !v->domain->arch.hvm_domain.params[HVM_PARAM_PAE_ENABLED] )
    2.62  #endif
    2.63 -            {
    2.64 -                clear_bit(X86_FEATURE_PAE, &edx);
    2.65 -                if (input == 0x80000001 )
    2.66 -                   clear_bit(X86_FEATURE_NX & 31, &edx);
    2.67 -            }
    2.68 -            clear_bit(X86_FEATURE_PSE36, &edx);
    2.69 -            if (input == 0x00000001 )
    2.70 -            {
    2.71 -                /* Clear out reserved bits. */
    2.72 -                ecx &= ~SVM_VCPU_CPUID_L1_ECX_RESERVED;
    2.73 -                edx &= ~SVM_VCPU_CPUID_L1_EDX_RESERVED;
    2.74 -
    2.75 -                clear_bit(X86_FEATURE_MWAIT & 31, &ecx);
    2.76 -
    2.77 -                /* Guest should only see one logical processor.
    2.78 -                 * See details on page 23 of AMD CPUID Specification. 
    2.79 -                 */
    2.80 -                clear_bit(X86_FEATURE_HT, &edx);  /* clear the hyperthread bit */
    2.81 -                ebx &= 0xFF00FFFF;  /* clear the logical processor count when HTT=0 */
    2.82 -                ebx |= 0x00010000;  /* set to 1 just for precaution */
    2.83 -            }
    2.84 -            else
    2.85 -            {
    2.86 -                /* Clear the Cmp_Legacy bit 
    2.87 -                 * This bit is supposed to be zero when HTT = 0.
    2.88 -                 * See details on page 23 of AMD CPUID Specification. 
    2.89 -                 */
    2.90 -                clear_bit(X86_FEATURE_CMP_LEGACY & 31, &ecx);
    2.91 -                /* Make SVM feature invisible to the guest. */
    2.92 -                clear_bit(X86_FEATURE_SVME & 31, &ecx);
    2.93 -#ifdef __i386__
    2.94 -                /* Mask feature for Intel ia32e or AMD long mode. */
    2.95 -                clear_bit(X86_FEATURE_LAHF_LM & 31, &ecx);
    2.96 -
    2.97 -                clear_bit(X86_FEATURE_LM & 31, &edx);
    2.98 -                clear_bit(X86_FEATURE_SYSCALL & 31, &edx);
    2.99 -#endif
   2.100 -                /* So far, we do not support 3DNow for the guest. */
   2.101 -                clear_bit(X86_FEATURE_3DNOW & 31, &edx);
   2.102 -                clear_bit(X86_FEATURE_3DNOWEXT & 31, &edx);
   2.103 -            }
   2.104 -        }
   2.105 -        else if ( ( input == 0x80000007 ) || ( input == 0x8000000A  ) )
   2.106 -        {
   2.107 -            /* Mask out features of power management and SVM extension. */
   2.108 -            eax = ebx = ecx = edx = 0;
   2.109 -        }
   2.110 -        else if ( input == 0x80000008 )
   2.111 -        {
   2.112 -            /* Make sure Number of CPU core is 1 when HTT=0 */
   2.113 -            ecx &= 0xFFFFFF00; 
   2.114 -        }
   2.115 +            clear_bit(X86_FEATURE_PAE & 31, &edx);
   2.116 +
   2.117 +        clear_bit(X86_FEATURE_PSE36 & 31, &edx);
   2.118 +
   2.119 +        /* Clear the Cmp_Legacy bit
   2.120 +         * This bit is supposed to be zero when HTT = 0.
   2.121 +         * See details on page 23 of AMD CPUID Specification.
   2.122 +         */
   2.123 +        clear_bit(X86_FEATURE_CMP_LEGACY & 31, &ecx);
   2.124 +
   2.125 +        /* Make SVM feature invisible to the guest. */
   2.126 +        clear_bit(X86_FEATURE_SVME & 31, &ecx);
   2.127 +
   2.128 +        /* So far, we do not support 3DNow for the guest. */
   2.129 +        clear_bit(X86_FEATURE_3DNOW & 31, &edx);
   2.130 +        clear_bit(X86_FEATURE_3DNOWEXT & 31, &edx);
   2.131 +    }
   2.132 +    else if ( input == 0x80000007 || input == 0x8000000A )
   2.133 +    {
   2.134 +        /* Mask out features of power management and SVM extension. */
   2.135 +        eax = ebx = ecx = edx = 0;
   2.136 +    }
   2.137 +    else if ( input == 0x80000008 )
   2.138 +    {
   2.139 +        /* Make sure Number of CPU core is 1 when HTT=0 */
   2.140 +        ecx &= 0xFFFFFF00;
   2.141      }
   2.142  
   2.143      regs->eax = (unsigned long)eax;
   2.144 @@ -1091,17 +1065,11 @@ static void svm_vmexit_do_cpuid(struct v
   2.145      regs->ecx = (unsigned long)ecx;
   2.146      regs->edx = (unsigned long)edx;
   2.147  
   2.148 -    HVM_DBG_LOG(DBG_LEVEL_1, 
   2.149 -                "svm_vmexit_do_cpuid: eip: %lx, input: %lx, out:eax=%x, "
   2.150 -                "ebx=%x, ecx=%x, edx=%x",
   2.151 -                eip, input, eax, ebx, ecx, edx);
   2.152 -
   2.153      inst_len = __get_instruction_length(vmcb, INSTR_CPUID, NULL);
   2.154      ASSERT(inst_len > 0);
   2.155      __update_guest_eip(vmcb, inst_len);
   2.156  }
   2.157  
   2.158 -
   2.159  static inline unsigned long *get_reg_p(unsigned int gpreg, 
   2.160                                         struct cpu_user_regs *regs, struct vmcb_struct *vmcb)
   2.161  {
   2.162 @@ -2828,7 +2796,7 @@ asmlinkage void svm_vmexit_handler(struc
   2.163          goto exit_and_crash;
   2.164  
   2.165      case VMEXIT_CPUID:
   2.166 -        svm_vmexit_do_cpuid(vmcb, regs->eax, regs);
   2.167 +        svm_vmexit_do_cpuid(vmcb, regs);
   2.168          break;
   2.169  
   2.170      case VMEXIT_HLT:
     3.1 --- a/xen/arch/x86/hvm/vmx/vmx.c	Wed Dec 20 10:06:33 2006 +0000
     3.2 +++ b/xen/arch/x86/hvm/vmx/vmx.c	Wed Dec 20 10:09:42 2006 +0000
     3.3 @@ -899,24 +899,14 @@ static void vmx_do_no_device_fault(void)
     3.4      }
     3.5  }
     3.6  
     3.7 -#define bitmaskof(idx) (1U << ((idx)&31))
     3.8 +#define bitmaskof(idx)  (1U << ((idx) & 31))
     3.9  static void vmx_do_cpuid(struct cpu_user_regs *regs)
    3.10  {
    3.11      unsigned int input = (unsigned int)regs->eax;
    3.12      unsigned int count = (unsigned int)regs->ecx;
    3.13      unsigned int eax, ebx, ecx, edx;
    3.14 -    unsigned long eip;
    3.15 -    struct vcpu *v = current;
    3.16  
    3.17 -    eip = __vmread(GUEST_RIP);
    3.18 -
    3.19 -    HVM_DBG_LOG(DBG_LEVEL_3, "(eax) 0x%08lx, (ebx) 0x%08lx, "
    3.20 -                "(ecx) 0x%08lx, (edx) 0x%08lx, (esi) 0x%08lx, (edi) 0x%08lx",
    3.21 -                (unsigned long)regs->eax, (unsigned long)regs->ebx,
    3.22 -                (unsigned long)regs->ecx, (unsigned long)regs->edx,
    3.23 -                (unsigned long)regs->esi, (unsigned long)regs->edi);
    3.24 -
    3.25 -    if ( input == CPUID_LEAF_0x4 )
    3.26 +    if ( input == 0x00000004 )
    3.27      {
    3.28          cpuid_count(input, count, &eax, &ebx, &ecx, &edx);
    3.29          eax &= NUM_CORES_RESET_MASK;
    3.30 @@ -929,6 +919,7 @@ static void vmx_do_cpuid(struct cpu_user
    3.31           */
    3.32          u64 value = ((u64)regs->edx << 32) | (u32)regs->ecx;
    3.33          unsigned long mfn = get_mfn_from_gpfn(value >> PAGE_SHIFT);
    3.34 +        struct vcpu *v = current;
    3.35          char *p;
    3.36  
    3.37          gdprintk(XENLOG_INFO, "Input address is 0x%"PRIx64".\n", value);
    3.38 @@ -946,72 +937,37 @@ static void vmx_do_cpuid(struct cpu_user
    3.39          unmap_domain_page(p);
    3.40  
    3.41          gdprintk(XENLOG_INFO, "Output value is 0x%"PRIx64".\n", value);
    3.42 -        ecx = (u32)(value >>  0);
    3.43 +        ecx = (u32)value;
    3.44          edx = (u32)(value >> 32);
    3.45 -    }
    3.46 -    else if ( !cpuid_hypervisor_leaves(input, &eax, &ebx, &ecx, &edx) )
    3.47 -    {
    3.48 -        cpuid(input, &eax, &ebx, &ecx, &edx);
    3.49 +    } else {
    3.50 +        hvm_cpuid(input, &eax, &ebx, &ecx, &edx);
    3.51  
    3.52 -        if ( input == CPUID_LEAF_0x1 )
    3.53 +        if ( input == 0x00000001 )
    3.54          {
    3.55              /* Mask off reserved bits. */
    3.56              ecx &= ~VMX_VCPU_CPUID_L1_ECX_RESERVED;
    3.57  
    3.58 -            if ( vlapic_hw_disabled(vcpu_vlapic(v)) )
    3.59 -                clear_bit(X86_FEATURE_APIC, &edx);
    3.60 -
    3.61 -#if CONFIG_PAGING_LEVELS >= 3
    3.62 -            if ( !v->domain->arch.hvm_domain.params[HVM_PARAM_PAE_ENABLED] )
    3.63 -#endif
    3.64 -                clear_bit(X86_FEATURE_PAE, &edx);
    3.65 -            clear_bit(X86_FEATURE_PSE36, &edx);
    3.66 -
    3.67              ebx &= NUM_THREADS_RESET_MASK;
    3.68  
    3.69              /* Unsupportable for virtualised CPUs. */
    3.70 -            ecx &= ~(bitmaskof(X86_FEATURE_VMXE)  |
    3.71 -                     bitmaskof(X86_FEATURE_EST)   |
    3.72 -                     bitmaskof(X86_FEATURE_TM2)   |
    3.73 -                     bitmaskof(X86_FEATURE_CID)   |
    3.74 -                     bitmaskof(X86_FEATURE_MWAIT) );
    3.75 +            ecx &= ~(bitmaskof(X86_FEATURE_VMXE) |
    3.76 +                     bitmaskof(X86_FEATURE_EST)  |
    3.77 +                     bitmaskof(X86_FEATURE_TM2)  |
    3.78 +                     bitmaskof(X86_FEATURE_CID));
    3.79  
    3.80 -            edx &= ~( bitmaskof(X86_FEATURE_HT)   |
    3.81 -                     bitmaskof(X86_FEATURE_ACPI)  |
    3.82 -                     bitmaskof(X86_FEATURE_ACC) );
    3.83 +            edx &= ~(bitmaskof(X86_FEATURE_HT)   |
    3.84 +                     bitmaskof(X86_FEATURE_ACPI) |
    3.85 +                     bitmaskof(X86_FEATURE_ACC));
    3.86          }
    3.87 -        else if (  ( input == CPUID_LEAF_0x6 )
    3.88 -                || ( input == CPUID_LEAF_0x9 )
    3.89 -                || ( input == CPUID_LEAF_0xA ))
    3.90 -        {
    3.91 +
    3.92 +        if ( input == 0x00000006 || input == 0x00000009 || input == 0x0000000A )
    3.93              eax = ebx = ecx = edx = 0x0;
    3.94 -        }
    3.95 -        else if ( input == CPUID_LEAF_0x80000001 )
    3.96 -        {
    3.97 -#if CONFIG_PAGING_LEVELS >= 3
    3.98 -            if ( !v->domain->arch.hvm_domain.params[HVM_PARAM_PAE_ENABLED] )
    3.99 -#endif
   3.100 -                clear_bit(X86_FEATURE_NX & 31, &edx);
   3.101 -#ifdef __i386__
   3.102 -            clear_bit(X86_FEATURE_LAHF_LM & 31, &ecx);
   3.103 -
   3.104 -            clear_bit(X86_FEATURE_LM & 31, &edx);
   3.105 -            clear_bit(X86_FEATURE_SYSCALL & 31, &edx);
   3.106 -#endif
   3.107 -        }
   3.108      }
   3.109  
   3.110 -    regs->eax = (unsigned long) eax;
   3.111 -    regs->ebx = (unsigned long) ebx;
   3.112 -    regs->ecx = (unsigned long) ecx;
   3.113 -    regs->edx = (unsigned long) edx;
   3.114 -
   3.115 -    HVM_DBG_LOG(DBG_LEVEL_3, "eip@%lx, input: 0x%lx, "
   3.116 -                "output: eax = 0x%08lx, ebx = 0x%08lx, "
   3.117 -                "ecx = 0x%08lx, edx = 0x%08lx",
   3.118 -                (unsigned long)eip, (unsigned long)input,
   3.119 -                (unsigned long)eax, (unsigned long)ebx,
   3.120 -                (unsigned long)ecx, (unsigned long)edx);
   3.121 +    regs->eax = (unsigned long)eax;
   3.122 +    regs->ebx = (unsigned long)ebx;
   3.123 +    regs->ecx = (unsigned long)ecx;
   3.124 +    regs->edx = (unsigned long)edx;
   3.125  }
   3.126  
   3.127  #define CASE_GET_REG_P(REG, reg)    \
     4.1 --- a/xen/include/asm-x86/hvm/hvm.h	Wed Dec 20 10:06:33 2006 +0000
     4.2 +++ b/xen/include/asm-x86/hvm/hvm.h	Wed Dec 20 10:09:42 2006 +0000
     4.3 @@ -219,6 +219,8 @@ hvm_get_segment_register(struct vcpu *v,
     4.4      hvm_funcs.get_segment_register(v, seg, reg);
     4.5  }
     4.6  
     4.7 +void hvm_cpuid(unsigned int input, unsigned int *eax, unsigned int *ebx,
     4.8 +                                   unsigned int *ecx, unsigned int *edx);
     4.9  void hvm_stts(struct vcpu *v);
    4.10  void hvm_set_guest_time(struct vcpu *v, u64 gtime);
    4.11  void hvm_freeze_time(struct vcpu *v);
     5.1 --- a/xen/include/asm-x86/hvm/vmx/cpu.h	Wed Dec 20 10:06:33 2006 +0000
     5.2 +++ b/xen/include/asm-x86/hvm/vmx/cpu.h	Wed Dec 20 10:09:42 2006 +0000
     5.3 @@ -32,21 +32,14 @@ struct arch_state_struct {
     5.4  #define VMX_MF_32       1
     5.5  #define VMX_MF_64       2
     5.6  
     5.7 -#define CPUID_LEAF_0x1        0x1
     5.8 -#define CPUID_LEAF_0x4        0x4
     5.9 -#define CPUID_LEAF_0x6        0x6
    5.10 -#define CPUID_LEAF_0x9        0x9
    5.11 -#define CPUID_LEAF_0xA        0xA
    5.12 -#define CPUID_LEAF_0x80000001 0x80000001
    5.13 -
    5.14  #define NUM_CORES_RESET_MASK                 0x00003FFF
    5.15  #define NUM_THREADS_RESET_MASK               0xFF00FFFF
    5.16  
    5.17  #define VMX_VCPU_CPUID_L1_ECX_RESERVED_18    0x00040000
    5.18  #define VMX_VCPU_CPUID_L1_ECX_RESERVED_6     0x00000040
    5.19  
    5.20 -#define VMX_VCPU_CPUID_L1_ECX_RESERVED             \
    5.21 -            ( VMX_VCPU_CPUID_L1_ECX_RESERVED_18  | \
    5.22 -              VMX_VCPU_CPUID_L1_ECX_RESERVED_6   )
    5.23 +#define VMX_VCPU_CPUID_L1_ECX_RESERVED              \
    5.24 +            ( VMX_VCPU_CPUID_L1_ECX_RESERVED_18 |   \
    5.25 +              VMX_VCPU_CPUID_L1_ECX_RESERVED_6 )
    5.26  
    5.27  #endif /* __ASM_X86_HVM_VMX_CPU_H__ */