[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] [HVM] Clean up CPUID handling.
# HG changeset patch # User kfraser@xxxxxxxxxxxxxxxxxxxxx # Date 1166609382 0 # Node ID f99dd72ae205556994f3ea5ff065c6cfb02c42d0 # Parent 1818b322ede953f4fcca2d3d1239ce5111a811c5 [HVM] Clean up CPUID handling. From: Xin B Li <xin.b.li@xxxxxxxxx> Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx> --- xen/arch/x86/hvm/hvm.c | 41 +++++++++++ xen/arch/x86/hvm/svm/svm.c | 136 ++++++++++++++------------------------ xen/arch/x86/hvm/vmx/vmx.c | 96 +++++++------------------- xen/include/asm-x86/hvm/hvm.h | 2 xen/include/asm-x86/hvm/vmx/cpu.h | 13 --- 5 files changed, 124 insertions(+), 164 deletions(-) diff -r 1818b322ede9 -r f99dd72ae205 xen/arch/x86/hvm/hvm.c --- a/xen/arch/x86/hvm/hvm.c Wed Dec 20 10:06:33 2006 +0000 +++ b/xen/arch/x86/hvm/hvm.c Wed Dec 20 10:09:42 2006 +0000 @@ -400,6 +400,47 @@ void hvm_print_line(struct vcpu *v, cons hd->pbuf_idx = 0; } spin_unlock(&hd->pbuf_lock); +} + +void hvm_cpuid(unsigned int input, unsigned int *eax, unsigned int *ebx, + unsigned int *ecx, unsigned int *edx) +{ + if ( !cpuid_hypervisor_leaves(input, eax, ebx, ecx, edx) ) + { + cpuid(input, eax, ebx, ecx, edx); + + if ( input == 0x00000001 ) + { + struct vcpu *v = current; + + clear_bit(X86_FEATURE_MWAIT & 31, ecx); + + if ( vlapic_hw_disabled(vcpu_vlapic(v)) ) + clear_bit(X86_FEATURE_APIC & 31, edx); + +#if CONFIG_PAGING_LEVELS >= 3 + if ( !v->domain->arch.hvm_domain.params[HVM_PARAM_PAE_ENABLED] ) +#endif + clear_bit(X86_FEATURE_PAE & 31, edx); + + clear_bit(X86_FEATURE_PSE36 & 31, edx); + } + else if ( input == 0x80000001 ) + { +#if CONFIG_PAGING_LEVELS >= 3 + struct vcpu *v = current; + if ( !v->domain->arch.hvm_domain.params[HVM_PARAM_PAE_ENABLED] ) +#endif + clear_bit(X86_FEATURE_NX & 31, edx); +#ifdef __i386__ + /* Mask feature for Intel ia32e or AMD long mode. */ + clear_bit(X86_FEATURE_LAHF_LM & 31, ecx); + + clear_bit(X86_FEATURE_LM & 31, edx); + clear_bit(X86_FEATURE_SYSCALL & 31, edx); +#endif + } + } } typedef unsigned long hvm_hypercall_t( diff -r 1818b322ede9 -r f99dd72ae205 xen/arch/x86/hvm/svm/svm.c --- a/xen/arch/x86/hvm/svm/svm.c Wed Dec 20 10:06:33 2006 +0000 +++ b/xen/arch/x86/hvm/svm/svm.c Wed Dec 20 10:09:42 2006 +0000 @@ -999,91 +999,65 @@ static void svm_do_general_protection_fa /* Reserved bits EDX: [31:29], [27], [22:20], [18], [10] */ #define SVM_VCPU_CPUID_L1_EDX_RESERVED 0xe8740400 -static void svm_vmexit_do_cpuid(struct vmcb_struct *vmcb, unsigned long input, - struct cpu_user_regs *regs) -{ +static void svm_vmexit_do_cpuid(struct vmcb_struct *vmcb, + struct cpu_user_regs *regs) +{ + unsigned long input = regs->eax; unsigned int eax, ebx, ecx, edx; - unsigned long eip; struct vcpu *v = current; int inst_len; ASSERT(vmcb); - eip = vmcb->rip; - - HVM_DBG_LOG(DBG_LEVEL_1, - "do_cpuid: (eax) %lx, (ebx) %lx, (ecx) %lx, (edx) %lx," - " (esi) %lx, (edi) %lx", - (unsigned long)regs->eax, (unsigned long)regs->ebx, - (unsigned long)regs->ecx, (unsigned long)regs->edx, - (unsigned long)regs->esi, (unsigned long)regs->edi); - - if ( !cpuid_hypervisor_leaves(input, &eax, &ebx, &ecx, &edx) ) - { - cpuid(input, &eax, &ebx, &ecx, &edx); - if (input == 0x00000001 || input == 0x80000001 ) - { - if ( vlapic_hw_disabled(vcpu_vlapic(v)) ) - { - /* Since the apic is disabled, avoid any confusion - about SMP cpus being available */ - clear_bit(X86_FEATURE_APIC, &edx); - } + hvm_cpuid(input, &eax, &ebx, &ecx, &edx); + + if ( input == 0x00000001 ) + { + /* Clear out reserved bits. */ + ecx &= ~SVM_VCPU_CPUID_L1_ECX_RESERVED; + edx &= ~SVM_VCPU_CPUID_L1_EDX_RESERVED; + + /* Guest should only see one logical processor. + * See details on page 23 of AMD CPUID Specification. + */ + clear_bit(X86_FEATURE_HT & 31, &edx); /* clear the hyperthread bit */ + ebx &= 0xFF00FFFF; /* clear the logical processor count when HTT=0 */ + ebx |= 0x00010000; /* set to 1 just for precaution */ + } + else if ( input == 0x80000001 ) + { + if ( vlapic_hw_disabled(vcpu_vlapic(v)) ) + clear_bit(X86_FEATURE_APIC & 31, &edx); + #if CONFIG_PAGING_LEVELS >= 3 - if ( !v->domain->arch.hvm_domain.params[HVM_PARAM_PAE_ENABLED] ) + if ( !v->domain->arch.hvm_domain.params[HVM_PARAM_PAE_ENABLED] ) #endif - { - clear_bit(X86_FEATURE_PAE, &edx); - if (input == 0x80000001 ) - clear_bit(X86_FEATURE_NX & 31, &edx); - } - clear_bit(X86_FEATURE_PSE36, &edx); - if (input == 0x00000001 ) - { - /* Clear out reserved bits. */ - ecx &= ~SVM_VCPU_CPUID_L1_ECX_RESERVED; - edx &= ~SVM_VCPU_CPUID_L1_EDX_RESERVED; - - clear_bit(X86_FEATURE_MWAIT & 31, &ecx); - - /* Guest should only see one logical processor. - * See details on page 23 of AMD CPUID Specification. - */ - clear_bit(X86_FEATURE_HT, &edx); /* clear the hyperthread bit */ - ebx &= 0xFF00FFFF; /* clear the logical processor count when HTT=0 */ - ebx |= 0x00010000; /* set to 1 just for precaution */ - } - else - { - /* Clear the Cmp_Legacy bit - * This bit is supposed to be zero when HTT = 0. - * See details on page 23 of AMD CPUID Specification. - */ - clear_bit(X86_FEATURE_CMP_LEGACY & 31, &ecx); - /* Make SVM feature invisible to the guest. */ - clear_bit(X86_FEATURE_SVME & 31, &ecx); -#ifdef __i386__ - /* Mask feature for Intel ia32e or AMD long mode. */ - clear_bit(X86_FEATURE_LAHF_LM & 31, &ecx); - - clear_bit(X86_FEATURE_LM & 31, &edx); - clear_bit(X86_FEATURE_SYSCALL & 31, &edx); -#endif - /* So far, we do not support 3DNow for the guest. */ - clear_bit(X86_FEATURE_3DNOW & 31, &edx); - clear_bit(X86_FEATURE_3DNOWEXT & 31, &edx); - } - } - else if ( ( input == 0x80000007 ) || ( input == 0x8000000A ) ) - { - /* Mask out features of power management and SVM extension. */ - eax = ebx = ecx = edx = 0; - } - else if ( input == 0x80000008 ) - { - /* Make sure Number of CPU core is 1 when HTT=0 */ - ecx &= 0xFFFFFF00; - } + clear_bit(X86_FEATURE_PAE & 31, &edx); + + clear_bit(X86_FEATURE_PSE36 & 31, &edx); + + /* Clear the Cmp_Legacy bit + * This bit is supposed to be zero when HTT = 0. + * See details on page 23 of AMD CPUID Specification. + */ + clear_bit(X86_FEATURE_CMP_LEGACY & 31, &ecx); + + /* Make SVM feature invisible to the guest. */ + clear_bit(X86_FEATURE_SVME & 31, &ecx); + + /* So far, we do not support 3DNow for the guest. */ + clear_bit(X86_FEATURE_3DNOW & 31, &edx); + clear_bit(X86_FEATURE_3DNOWEXT & 31, &edx); + } + else if ( input == 0x80000007 || input == 0x8000000A ) + { + /* Mask out features of power management and SVM extension. */ + eax = ebx = ecx = edx = 0; + } + else if ( input == 0x80000008 ) + { + /* Make sure Number of CPU core is 1 when HTT=0 */ + ecx &= 0xFFFFFF00; } regs->eax = (unsigned long)eax; @@ -1091,16 +1065,10 @@ static void svm_vmexit_do_cpuid(struct v regs->ecx = (unsigned long)ecx; regs->edx = (unsigned long)edx; - HVM_DBG_LOG(DBG_LEVEL_1, - "svm_vmexit_do_cpuid: eip: %lx, input: %lx, out:eax=%x, " - "ebx=%x, ecx=%x, edx=%x", - eip, input, eax, ebx, ecx, edx); - inst_len = __get_instruction_length(vmcb, INSTR_CPUID, NULL); ASSERT(inst_len > 0); __update_guest_eip(vmcb, inst_len); } - static inline unsigned long *get_reg_p(unsigned int gpreg, struct cpu_user_regs *regs, struct vmcb_struct *vmcb) @@ -2828,7 +2796,7 @@ asmlinkage void svm_vmexit_handler(struc goto exit_and_crash; case VMEXIT_CPUID: - svm_vmexit_do_cpuid(vmcb, regs->eax, regs); + svm_vmexit_do_cpuid(vmcb, regs); break; case VMEXIT_HLT: diff -r 1818b322ede9 -r f99dd72ae205 xen/arch/x86/hvm/vmx/vmx.c --- a/xen/arch/x86/hvm/vmx/vmx.c Wed Dec 20 10:06:33 2006 +0000 +++ b/xen/arch/x86/hvm/vmx/vmx.c Wed Dec 20 10:09:42 2006 +0000 @@ -899,24 +899,14 @@ static void vmx_do_no_device_fault(void) } } -#define bitmaskof(idx) (1U << ((idx)&31)) +#define bitmaskof(idx) (1U << ((idx) & 31)) static void vmx_do_cpuid(struct cpu_user_regs *regs) { unsigned int input = (unsigned int)regs->eax; unsigned int count = (unsigned int)regs->ecx; unsigned int eax, ebx, ecx, edx; - unsigned long eip; - struct vcpu *v = current; - - eip = __vmread(GUEST_RIP); - - HVM_DBG_LOG(DBG_LEVEL_3, "(eax) 0x%08lx, (ebx) 0x%08lx, " - "(ecx) 0x%08lx, (edx) 0x%08lx, (esi) 0x%08lx, (edi) 0x%08lx", - (unsigned long)regs->eax, (unsigned long)regs->ebx, - (unsigned long)regs->ecx, (unsigned long)regs->edx, - (unsigned long)regs->esi, (unsigned long)regs->edi); - - if ( input == CPUID_LEAF_0x4 ) + + if ( input == 0x00000004 ) { cpuid_count(input, count, &eax, &ebx, &ecx, &edx); eax &= NUM_CORES_RESET_MASK; @@ -929,6 +919,7 @@ static void vmx_do_cpuid(struct cpu_user */ u64 value = ((u64)regs->edx << 32) | (u32)regs->ecx; unsigned long mfn = get_mfn_from_gpfn(value >> PAGE_SHIFT); + struct vcpu *v = current; char *p; gdprintk(XENLOG_INFO, "Input address is 0x%"PRIx64".\n", value); @@ -946,72 +937,37 @@ static void vmx_do_cpuid(struct cpu_user unmap_domain_page(p); gdprintk(XENLOG_INFO, "Output value is 0x%"PRIx64".\n", value); - ecx = (u32)(value >> 0); + ecx = (u32)value; edx = (u32)(value >> 32); - } - else if ( !cpuid_hypervisor_leaves(input, &eax, &ebx, &ecx, &edx) ) - { - cpuid(input, &eax, &ebx, &ecx, &edx); - - if ( input == CPUID_LEAF_0x1 ) + } else { + hvm_cpuid(input, &eax, &ebx, &ecx, &edx); + + if ( input == 0x00000001 ) { /* Mask off reserved bits. */ ecx &= ~VMX_VCPU_CPUID_L1_ECX_RESERVED; - if ( vlapic_hw_disabled(vcpu_vlapic(v)) ) - clear_bit(X86_FEATURE_APIC, &edx); - -#if CONFIG_PAGING_LEVELS >= 3 - if ( !v->domain->arch.hvm_domain.params[HVM_PARAM_PAE_ENABLED] ) -#endif - clear_bit(X86_FEATURE_PAE, &edx); - clear_bit(X86_FEATURE_PSE36, &edx); - ebx &= NUM_THREADS_RESET_MASK; /* Unsupportable for virtualised CPUs. */ - ecx &= ~(bitmaskof(X86_FEATURE_VMXE) | - bitmaskof(X86_FEATURE_EST) | - bitmaskof(X86_FEATURE_TM2) | - bitmaskof(X86_FEATURE_CID) | - bitmaskof(X86_FEATURE_MWAIT) ); - - edx &= ~( bitmaskof(X86_FEATURE_HT) | - bitmaskof(X86_FEATURE_ACPI) | - bitmaskof(X86_FEATURE_ACC) ); - } - else if ( ( input == CPUID_LEAF_0x6 ) - || ( input == CPUID_LEAF_0x9 ) - || ( input == CPUID_LEAF_0xA )) - { + ecx &= ~(bitmaskof(X86_FEATURE_VMXE) | + bitmaskof(X86_FEATURE_EST) | + bitmaskof(X86_FEATURE_TM2) | + bitmaskof(X86_FEATURE_CID)); + + edx &= ~(bitmaskof(X86_FEATURE_HT) | + bitmaskof(X86_FEATURE_ACPI) | + bitmaskof(X86_FEATURE_ACC)); + } + + if ( input == 0x00000006 || input == 0x00000009 || input == 0x0000000A ) eax = ebx = ecx = edx = 0x0; - } - else if ( input == CPUID_LEAF_0x80000001 ) - { -#if CONFIG_PAGING_LEVELS >= 3 - if ( !v->domain->arch.hvm_domain.params[HVM_PARAM_PAE_ENABLED] ) -#endif - clear_bit(X86_FEATURE_NX & 31, &edx); -#ifdef __i386__ - clear_bit(X86_FEATURE_LAHF_LM & 31, &ecx); - - clear_bit(X86_FEATURE_LM & 31, &edx); - clear_bit(X86_FEATURE_SYSCALL & 31, &edx); -#endif - } - } - - regs->eax = (unsigned long) eax; - regs->ebx = (unsigned long) ebx; - regs->ecx = (unsigned long) ecx; - regs->edx = (unsigned long) edx; - - HVM_DBG_LOG(DBG_LEVEL_3, "eip@%lx, input: 0x%lx, " - "output: eax = 0x%08lx, ebx = 0x%08lx, " - "ecx = 0x%08lx, edx = 0x%08lx", - (unsigned long)eip, (unsigned long)input, - (unsigned long)eax, (unsigned long)ebx, - (unsigned long)ecx, (unsigned long)edx); + } + + regs->eax = (unsigned long)eax; + regs->ebx = (unsigned long)ebx; + regs->ecx = (unsigned long)ecx; + regs->edx = (unsigned long)edx; } #define CASE_GET_REG_P(REG, reg) \ diff -r 1818b322ede9 -r f99dd72ae205 xen/include/asm-x86/hvm/hvm.h --- a/xen/include/asm-x86/hvm/hvm.h Wed Dec 20 10:06:33 2006 +0000 +++ b/xen/include/asm-x86/hvm/hvm.h Wed Dec 20 10:09:42 2006 +0000 @@ -219,6 +219,8 @@ hvm_get_segment_register(struct vcpu *v, hvm_funcs.get_segment_register(v, seg, reg); } +void hvm_cpuid(unsigned int input, unsigned int *eax, unsigned int *ebx, + unsigned int *ecx, unsigned int *edx); void hvm_stts(struct vcpu *v); void hvm_set_guest_time(struct vcpu *v, u64 gtime); void hvm_freeze_time(struct vcpu *v); diff -r 1818b322ede9 -r f99dd72ae205 xen/include/asm-x86/hvm/vmx/cpu.h --- a/xen/include/asm-x86/hvm/vmx/cpu.h Wed Dec 20 10:06:33 2006 +0000 +++ b/xen/include/asm-x86/hvm/vmx/cpu.h Wed Dec 20 10:09:42 2006 +0000 @@ -32,21 +32,14 @@ struct arch_state_struct { #define VMX_MF_32 1 #define VMX_MF_64 2 -#define CPUID_LEAF_0x1 0x1 -#define CPUID_LEAF_0x4 0x4 -#define CPUID_LEAF_0x6 0x6 -#define CPUID_LEAF_0x9 0x9 -#define CPUID_LEAF_0xA 0xA -#define CPUID_LEAF_0x80000001 0x80000001 - #define NUM_CORES_RESET_MASK 0x00003FFF #define NUM_THREADS_RESET_MASK 0xFF00FFFF #define VMX_VCPU_CPUID_L1_ECX_RESERVED_18 0x00040000 #define VMX_VCPU_CPUID_L1_ECX_RESERVED_6 0x00000040 -#define VMX_VCPU_CPUID_L1_ECX_RESERVED \ - ( VMX_VCPU_CPUID_L1_ECX_RESERVED_18 | \ - VMX_VCPU_CPUID_L1_ECX_RESERVED_6 ) +#define VMX_VCPU_CPUID_L1_ECX_RESERVED \ + ( VMX_VCPU_CPUID_L1_ECX_RESERVED_18 | \ + VMX_VCPU_CPUID_L1_ECX_RESERVED_6 ) #endif /* __ASM_X86_HVM_VMX_CPU_H__ */ _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |