mirror of
https://github.com/xen-project/xen.git
synced 2026-10-30 03:00:05 +01:00
[XEN] Add CPUID hypervisor-info leaves at index 0x40000000.
Currently only a signature leaf is defined ("Xen\0").
Signed-off-by: Keir Fraser <keir@xensource.com>
This commit is contained in:
1 parent
971ec7119c
commit
c014225684
4 files changed
+75
-45
No files matched your search
+44
-43
@@ -962,8 +962,8 @@ static void svm_vmexit_do_cpuid(struct vmcb_struct *vmcb, unsigned long input,
|
||||
!vlapic_global_enabled((VLAPIC(v))) )
|
||||
{
|
||||
/* Since the apic is disabled, avoid any confusion
|
||||
about SMP cpus being available */
|
||||
clear_bit(X86_FEATURE_APIC, &edx);
|
||||
about SMP cpus being available */
|
||||
clear_bit(X86_FEATURE_APIC, &edx);
|
||||
}
|
||||
|
||||
#if CONFIG_PAGING_LEVELS < 3
|
||||
@@ -974,52 +974,51 @@ static void svm_vmexit_do_cpuid(struct vmcb_struct *vmcb, unsigned long input,
|
||||
if ( v->domain->arch.ops->guest_paging_levels == PAGING_L2 )
|
||||
{
|
||||
if ( !v->domain->arch.hvm_domain.pae_enabled )
|
||||
{
|
||||
clear_bit(X86_FEATURE_PAE, &edx);
|
||||
}
|
||||
clear_bit(X86_FEATURE_PAE, &edx);
|
||||
clear_bit(X86_FEATURE_PSE, &edx);
|
||||
clear_bit(X86_FEATURE_PSE36, &edx);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
/* 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 */
|
||||
/* 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 */
|
||||
|
||||
/* Disable machine check architecture */
|
||||
clear_bit(X86_FEATURE_MCA, &edx);
|
||||
clear_bit(X86_FEATURE_MCE, &edx);
|
||||
/* Disable machine check architecture */
|
||||
clear_bit(X86_FEATURE_MCA, &edx);
|
||||
clear_bit(X86_FEATURE_MCE, &edx);
|
||||
}
|
||||
else if ( ( input > 0x00000005 ) && ( input < 0x80000000 ) )
|
||||
else if ( (input > 0x00000005) && (input < 0x80000000) )
|
||||
{
|
||||
eax = ebx = ecx = edx = 0x0;
|
||||
if ( !cpuid_hypervisor_leaves(input, &eax, &ebx, &ecx, &edx) )
|
||||
eax = ebx = ecx = edx = 0;
|
||||
}
|
||||
else if ( input == 0x80000001 )
|
||||
{
|
||||
/* We duplicate some CPUID_00000001 code because many bits of
|
||||
CPUID_80000001_EDX overlaps with CPUID_00000001_EDX. */
|
||||
/* We duplicate some CPUID_00000001 code because many bits of
|
||||
CPUID_80000001_EDX overlaps with CPUID_00000001_EDX. */
|
||||
|
||||
if ( !hvm_apic_support(v->domain) ||
|
||||
!vlapic_global_enabled((VLAPIC(v))) )
|
||||
!vlapic_global_enabled((VLAPIC(v))) )
|
||||
{
|
||||
/* Since the apic is disabled, avoid any confusion
|
||||
about SMP cpus being available */
|
||||
clear_bit(X86_FEATURE_APIC, &edx);
|
||||
about SMP cpus being available */
|
||||
clear_bit(X86_FEATURE_APIC, &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);
|
||||
/* 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);
|
||||
|
||||
#ifdef __i386__
|
||||
/* Mask feature for Intel ia32e or AMD long mode. */
|
||||
@@ -1030,7 +1029,7 @@ static void svm_vmexit_do_cpuid(struct vmcb_struct *vmcb, unsigned long input,
|
||||
#endif
|
||||
|
||||
#if CONFIG_PAGING_LEVELS < 3
|
||||
clear_bit(X86_FEATURE_NX & 31, &edx);
|
||||
clear_bit(X86_FEATURE_NX & 31, &edx);
|
||||
clear_bit(X86_FEATURE_PAE, &edx);
|
||||
clear_bit(X86_FEATURE_PSE, &edx);
|
||||
clear_bit(X86_FEATURE_PSE36, &edx);
|
||||
@@ -1039,29 +1038,29 @@ static void svm_vmexit_do_cpuid(struct vmcb_struct *vmcb, unsigned long input,
|
||||
{
|
||||
if ( !v->domain->arch.hvm_domain.pae_enabled )
|
||||
{
|
||||
clear_bit(X86_FEATURE_NX & 31, &edx);
|
||||
clear_bit(X86_FEATURE_PAE, &edx);
|
||||
clear_bit(X86_FEATURE_NX & 31, &edx);
|
||||
clear_bit(X86_FEATURE_PAE, &edx);
|
||||
}
|
||||
clear_bit(X86_FEATURE_PSE, &edx);
|
||||
clear_bit(X86_FEATURE_PSE36, &edx);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* 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);
|
||||
|
||||
/* 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;
|
||||
/* Mask out features of power management and SVM extension. */
|
||||
eax = ebx = ecx = edx = 0;
|
||||
}
|
||||
else if ( input == 0x80000008 )
|
||||
{
|
||||
ecx &= 0xFFFFFF00; /* Make sure Number of CPU core is 1 when HTT=0 */
|
||||
ecx &= 0xFFFFFF00; /* Make sure Number of CPU core is 1 when HTT=0 */
|
||||
}
|
||||
|
||||
regs->eax = (unsigned long)eax;
|
||||
@@ -1214,8 +1213,9 @@ static void svm_dr_access (struct vcpu *v, unsigned int reg, unsigned int type,
|
||||
}
|
||||
|
||||
|
||||
static void svm_get_prefix_info(struct vmcb_struct *vmcb,
|
||||
unsigned int dir, segment_selector_t **seg, unsigned int *asize)
|
||||
static void svm_get_prefix_info(
|
||||
struct vmcb_struct *vmcb,
|
||||
unsigned int dir, segment_selector_t **seg, unsigned int *asize)
|
||||
{
|
||||
unsigned char inst[MAX_INST_LEN];
|
||||
int i;
|
||||
@@ -1287,9 +1287,10 @@ static void svm_get_prefix_info(struct vmcb_struct *vmcb,
|
||||
|
||||
|
||||
/* Get the address of INS/OUTS instruction */
|
||||
static inline int svm_get_io_address(struct vcpu *v,
|
||||
struct cpu_user_regs *regs, unsigned int dir,
|
||||
unsigned long *count, unsigned long *addr)
|
||||
static inline int svm_get_io_address(
|
||||
struct vcpu *v,
|
||||
struct cpu_user_regs *regs, unsigned int dir,
|
||||
unsigned long *count, unsigned long *addr)
|
||||
{
|
||||
unsigned long reg;
|
||||
unsigned int asize = 0;
|
||||
|
||||
@@ -868,7 +868,7 @@ static void vmx_vmexit_do_cpuid(struct cpu_user_regs *regs)
|
||||
cpuid_count(input, count, &eax, &ebx, &ecx, &edx);
|
||||
eax &= NUM_CORES_RESET_MASK;
|
||||
}
|
||||
else
|
||||
else if ( !cpuid_hypervisor_leaves(input, &eax, &ebx, &ecx, &edx) )
|
||||
{
|
||||
cpuid(input, &eax, &ebx, &ecx, &edx);
|
||||
|
||||
|
||||
+27
-1
@@ -426,10 +426,32 @@ DO_ERROR_NOCODE(16, "fpu error", coprocessor_error)
|
||||
DO_ERROR(17, "alignment check", alignment_check)
|
||||
DO_ERROR_NOCODE(19, "simd error", simd_coprocessor_error)
|
||||
|
||||
int cpuid_hypervisor_leaves(
|
||||
uint32_t idx, uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx)
|
||||
{
|
||||
if ( (idx < 0x40000000) || (idx > 0x40000000) )
|
||||
return 0;
|
||||
|
||||
switch ( idx - 0x40000000 )
|
||||
{
|
||||
case 0:
|
||||
*eax = 0x40000000;
|
||||
*ebx = 0x006e6558; /* "Xen\0" */
|
||||
*ecx = *edx = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
BUG();
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int emulate_forced_invalid_op(struct cpu_user_regs *regs)
|
||||
{
|
||||
char signature[5], instr[2];
|
||||
unsigned long a, b, c, d, eip;
|
||||
uint32_t a, b, c, d;
|
||||
unsigned long eip;
|
||||
|
||||
a = regs->eax;
|
||||
b = regs->ebx;
|
||||
@@ -466,6 +488,10 @@ static int emulate_forced_invalid_op(struct cpu_user_regs *regs)
|
||||
if ( !IS_PRIV(current->domain) )
|
||||
clear_bit(X86_FEATURE_MTRR, &d);
|
||||
}
|
||||
else
|
||||
{
|
||||
(void)cpuid_hypervisor_leaves(regs->eax, &a, &b, &c, &d);
|
||||
}
|
||||
|
||||
regs->eax = a;
|
||||
regs->ebx = b;
|
||||
|
||||
@@ -545,6 +545,9 @@ extern void mtrr_bp_init(void);
|
||||
|
||||
extern void mcheck_init(struct cpuinfo_x86 *c);
|
||||
|
||||
int cpuid_hypervisor_leaves(
|
||||
uint32_t idx, uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx);
|
||||
|
||||
#endif /* !__ASSEMBLY__ */
|
||||
|
||||
#endif /* __ASM_X86_PROCESSOR_H */
|
||||
|
||||