Split CPUID from op_helper
KVM needs to call CPUID from outside of the TCG code. This patch splits out the CPUID logic into a separate helper that both the op helper and KVM can call. Signed-off-by: Anthony Liguori <aliguori@us.ibm.com> git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@5626 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
parent
0650f1ab30
commit
6fd805e1d4
@ -730,6 +730,10 @@ void cpu_smm_update(CPUX86State *env);
|
||||
/* will be suppressed */
|
||||
void cpu_x86_update_cr0(CPUX86State *env, uint32_t new_cr0);
|
||||
|
||||
void cpu_x86_cpuid(CPUX86State *env, uint32_t index,
|
||||
uint32_t *eax, uint32_t *ebx,
|
||||
uint32_t *ecx, uint32_t *edx);
|
||||
|
||||
/* used to debug */
|
||||
#define X86_DUMP_FPU 0x0001 /* dump FPU state too */
|
||||
#define X86_DUMP_CCOP 0x0002 /* dump qemu flag cache */
|
||||
|
@ -1287,3 +1287,169 @@ target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
|
||||
return paddr;
|
||||
}
|
||||
#endif /* !CONFIG_USER_ONLY */
|
||||
|
||||
void cpu_x86_cpuid(CPUX86State *env, uint32_t index,
|
||||
uint32_t *eax, uint32_t *ebx,
|
||||
uint32_t *ecx, uint32_t *edx)
|
||||
{
|
||||
/* test if maximum index reached */
|
||||
if (index & 0x80000000) {
|
||||
if (index > env->cpuid_xlevel)
|
||||
index = env->cpuid_level;
|
||||
} else {
|
||||
if (index > env->cpuid_level)
|
||||
index = env->cpuid_level;
|
||||
}
|
||||
|
||||
switch(index) {
|
||||
case 0:
|
||||
*eax = env->cpuid_level;
|
||||
*ebx = env->cpuid_vendor1;
|
||||
*edx = env->cpuid_vendor2;
|
||||
*ecx = env->cpuid_vendor3;
|
||||
break;
|
||||
case 1:
|
||||
*eax = env->cpuid_version;
|
||||
*ebx = (env->cpuid_apic_id << 24) | 8 << 8; /* CLFLUSH size in quad words, Linux wants it. */
|
||||
*ecx = env->cpuid_ext_features;
|
||||
*edx = env->cpuid_features;
|
||||
break;
|
||||
case 2:
|
||||
/* cache info: needed for Pentium Pro compatibility */
|
||||
*eax = 1;
|
||||
*ebx = 0;
|
||||
*ecx = 0;
|
||||
*edx = 0x2c307d;
|
||||
break;
|
||||
case 4:
|
||||
/* cache info: needed for Core compatibility */
|
||||
switch (*ecx) {
|
||||
case 0: /* L1 dcache info */
|
||||
*eax = 0x0000121;
|
||||
*ebx = 0x1c0003f;
|
||||
*ecx = 0x000003f;
|
||||
*edx = 0x0000001;
|
||||
break;
|
||||
case 1: /* L1 icache info */
|
||||
*eax = 0x0000122;
|
||||
*ebx = 0x1c0003f;
|
||||
*ecx = 0x000003f;
|
||||
*edx = 0x0000001;
|
||||
break;
|
||||
case 2: /* L2 cache info */
|
||||
*eax = 0x0000143;
|
||||
*ebx = 0x3c0003f;
|
||||
*ecx = 0x0000fff;
|
||||
*edx = 0x0000001;
|
||||
break;
|
||||
default: /* end of info */
|
||||
*eax = 0;
|
||||
*ebx = 0;
|
||||
*ecx = 0;
|
||||
*edx = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
case 5:
|
||||
/* mwait info: needed for Core compatibility */
|
||||
*eax = 0; /* Smallest monitor-line size in bytes */
|
||||
*ebx = 0; /* Largest monitor-line size in bytes */
|
||||
*ecx = CPUID_MWAIT_EMX | CPUID_MWAIT_IBE;
|
||||
*edx = 0;
|
||||
break;
|
||||
case 6:
|
||||
/* Thermal and Power Leaf */
|
||||
*eax = 0;
|
||||
*ebx = 0;
|
||||
*ecx = 0;
|
||||
*edx = 0;
|
||||
break;
|
||||
case 9:
|
||||
/* Direct Cache Access Information Leaf */
|
||||
*eax = 0; /* Bits 0-31 in DCA_CAP MSR */
|
||||
*ebx = 0;
|
||||
*ecx = 0;
|
||||
*edx = 0;
|
||||
break;
|
||||
case 0xA:
|
||||
/* Architectural Performance Monitoring Leaf */
|
||||
*eax = 0;
|
||||
*ebx = 0;
|
||||
*ecx = 0;
|
||||
*edx = 0;
|
||||
break;
|
||||
case 0x80000000:
|
||||
*eax = env->cpuid_xlevel;
|
||||
*ebx = env->cpuid_vendor1;
|
||||
*edx = env->cpuid_vendor2;
|
||||
*ecx = env->cpuid_vendor3;
|
||||
break;
|
||||
case 0x80000001:
|
||||
*eax = env->cpuid_features;
|
||||
*ebx = 0;
|
||||
*ecx = env->cpuid_ext3_features;
|
||||
*edx = env->cpuid_ext2_features;
|
||||
break;
|
||||
case 0x80000002:
|
||||
case 0x80000003:
|
||||
case 0x80000004:
|
||||
*eax = env->cpuid_model[(index - 0x80000002) * 4 + 0];
|
||||
*ebx = env->cpuid_model[(index - 0x80000002) * 4 + 1];
|
||||
*ecx = env->cpuid_model[(index - 0x80000002) * 4 + 2];
|
||||
*edx = env->cpuid_model[(index - 0x80000002) * 4 + 3];
|
||||
break;
|
||||
case 0x80000005:
|
||||
/* cache info (L1 cache) */
|
||||
*eax = 0x01ff01ff;
|
||||
*ebx = 0x01ff01ff;
|
||||
*ecx = 0x40020140;
|
||||
*edx = 0x40020140;
|
||||
break;
|
||||
case 0x80000006:
|
||||
/* cache info (L2 cache) */
|
||||
*eax = 0;
|
||||
*ebx = 0x42004200;
|
||||
*ecx = 0x02008140;
|
||||
*edx = 0;
|
||||
break;
|
||||
case 0x80000008:
|
||||
/* virtual & phys address size in low 2 bytes. */
|
||||
/* XXX: This value must match the one used in the MMU code. */
|
||||
if (env->cpuid_ext2_features & CPUID_EXT2_LM) {
|
||||
/* 64 bit processor */
|
||||
#if defined(USE_KQEMU)
|
||||
*eax = 0x00003020; /* 48 bits virtual, 32 bits physical */
|
||||
#else
|
||||
/* XXX: The physical address space is limited to 42 bits in exec.c. */
|
||||
*eax = 0x00003028; /* 48 bits virtual, 40 bits physical */
|
||||
#endif
|
||||
} else {
|
||||
#if defined(USE_KQEMU)
|
||||
*eax = 0x00000020; /* 32 bits physical */
|
||||
#else
|
||||
if (env->cpuid_features & CPUID_PSE36)
|
||||
*eax = 0x00000024; /* 36 bits physical */
|
||||
else
|
||||
*eax = 0x00000020; /* 32 bits physical */
|
||||
#endif
|
||||
}
|
||||
*ebx = 0;
|
||||
*ecx = 0;
|
||||
*edx = 0;
|
||||
break;
|
||||
case 0x8000000A:
|
||||
*eax = 0x00000001; /* SVM Revision */
|
||||
*ebx = 0x00000010; /* nr of ASIDs */
|
||||
*ecx = 0;
|
||||
*edx = 0; /* optional features */
|
||||
break;
|
||||
default:
|
||||
/* reserved values: zero */
|
||||
*eax = 0;
|
||||
*ebx = 0;
|
||||
*ecx = 0;
|
||||
*edx = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -1885,171 +1885,15 @@ void helper_single_step(void)
|
||||
|
||||
void helper_cpuid(void)
|
||||
{
|
||||
uint32_t index;
|
||||
uint32_t eax, ebx, ecx, edx;
|
||||
|
||||
helper_svm_check_intercept_param(SVM_EXIT_CPUID, 0);
|
||||
|
||||
index = (uint32_t)EAX;
|
||||
/* test if maximum index reached */
|
||||
if (index & 0x80000000) {
|
||||
if (index > env->cpuid_xlevel)
|
||||
index = env->cpuid_level;
|
||||
} else {
|
||||
if (index > env->cpuid_level)
|
||||
index = env->cpuid_level;
|
||||
}
|
||||
|
||||
switch(index) {
|
||||
case 0:
|
||||
EAX = env->cpuid_level;
|
||||
EBX = env->cpuid_vendor1;
|
||||
EDX = env->cpuid_vendor2;
|
||||
ECX = env->cpuid_vendor3;
|
||||
break;
|
||||
case 1:
|
||||
EAX = env->cpuid_version;
|
||||
EBX = (env->cpuid_apic_id << 24) | 8 << 8; /* CLFLUSH size in quad words, Linux wants it. */
|
||||
ECX = env->cpuid_ext_features;
|
||||
EDX = env->cpuid_features;
|
||||
break;
|
||||
case 2:
|
||||
/* cache info: needed for Pentium Pro compatibility */
|
||||
EAX = 1;
|
||||
EBX = 0;
|
||||
ECX = 0;
|
||||
EDX = 0x2c307d;
|
||||
break;
|
||||
case 4:
|
||||
/* cache info: needed for Core compatibility */
|
||||
switch (ECX) {
|
||||
case 0: /* L1 dcache info */
|
||||
EAX = 0x0000121;
|
||||
EBX = 0x1c0003f;
|
||||
ECX = 0x000003f;
|
||||
EDX = 0x0000001;
|
||||
break;
|
||||
case 1: /* L1 icache info */
|
||||
EAX = 0x0000122;
|
||||
EBX = 0x1c0003f;
|
||||
ECX = 0x000003f;
|
||||
EDX = 0x0000001;
|
||||
break;
|
||||
case 2: /* L2 cache info */
|
||||
EAX = 0x0000143;
|
||||
EBX = 0x3c0003f;
|
||||
ECX = 0x0000fff;
|
||||
EDX = 0x0000001;
|
||||
break;
|
||||
default: /* end of info */
|
||||
EAX = 0;
|
||||
EBX = 0;
|
||||
ECX = 0;
|
||||
EDX = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
case 5:
|
||||
/* mwait info: needed for Core compatibility */
|
||||
EAX = 0; /* Smallest monitor-line size in bytes */
|
||||
EBX = 0; /* Largest monitor-line size in bytes */
|
||||
ECX = CPUID_MWAIT_EMX | CPUID_MWAIT_IBE;
|
||||
EDX = 0;
|
||||
break;
|
||||
case 6:
|
||||
/* Thermal and Power Leaf */
|
||||
EAX = 0;
|
||||
EBX = 0;
|
||||
ECX = 0;
|
||||
EDX = 0;
|
||||
break;
|
||||
case 9:
|
||||
/* Direct Cache Access Information Leaf */
|
||||
EAX = 0; /* Bits 0-31 in DCA_CAP MSR */
|
||||
EBX = 0;
|
||||
ECX = 0;
|
||||
EDX = 0;
|
||||
break;
|
||||
case 0xA:
|
||||
/* Architectural Performance Monitoring Leaf */
|
||||
EAX = 0;
|
||||
EBX = 0;
|
||||
ECX = 0;
|
||||
EDX = 0;
|
||||
break;
|
||||
case 0x80000000:
|
||||
EAX = env->cpuid_xlevel;
|
||||
EBX = env->cpuid_vendor1;
|
||||
EDX = env->cpuid_vendor2;
|
||||
ECX = env->cpuid_vendor3;
|
||||
break;
|
||||
case 0x80000001:
|
||||
EAX = env->cpuid_features;
|
||||
EBX = 0;
|
||||
ECX = env->cpuid_ext3_features;
|
||||
EDX = env->cpuid_ext2_features;
|
||||
break;
|
||||
case 0x80000002:
|
||||
case 0x80000003:
|
||||
case 0x80000004:
|
||||
EAX = env->cpuid_model[(index - 0x80000002) * 4 + 0];
|
||||
EBX = env->cpuid_model[(index - 0x80000002) * 4 + 1];
|
||||
ECX = env->cpuid_model[(index - 0x80000002) * 4 + 2];
|
||||
EDX = env->cpuid_model[(index - 0x80000002) * 4 + 3];
|
||||
break;
|
||||
case 0x80000005:
|
||||
/* cache info (L1 cache) */
|
||||
EAX = 0x01ff01ff;
|
||||
EBX = 0x01ff01ff;
|
||||
ECX = 0x40020140;
|
||||
EDX = 0x40020140;
|
||||
break;
|
||||
case 0x80000006:
|
||||
/* cache info (L2 cache) */
|
||||
EAX = 0;
|
||||
EBX = 0x42004200;
|
||||
ECX = 0x02008140;
|
||||
EDX = 0;
|
||||
break;
|
||||
case 0x80000008:
|
||||
/* virtual & phys address size in low 2 bytes. */
|
||||
/* XXX: This value must match the one used in the MMU code. */
|
||||
if (env->cpuid_ext2_features & CPUID_EXT2_LM) {
|
||||
/* 64 bit processor */
|
||||
#if defined(USE_KQEMU)
|
||||
EAX = 0x00003020; /* 48 bits virtual, 32 bits physical */
|
||||
#else
|
||||
/* XXX: The physical address space is limited to 42 bits in exec.c. */
|
||||
EAX = 0x00003028; /* 48 bits virtual, 40 bits physical */
|
||||
#endif
|
||||
} else {
|
||||
#if defined(USE_KQEMU)
|
||||
EAX = 0x00000020; /* 32 bits physical */
|
||||
#else
|
||||
if (env->cpuid_features & CPUID_PSE36)
|
||||
EAX = 0x00000024; /* 36 bits physical */
|
||||
else
|
||||
EAX = 0x00000020; /* 32 bits physical */
|
||||
#endif
|
||||
}
|
||||
EBX = 0;
|
||||
ECX = 0;
|
||||
EDX = 0;
|
||||
break;
|
||||
case 0x8000000A:
|
||||
EAX = 0x00000001; /* SVM Revision */
|
||||
EBX = 0x00000010; /* nr of ASIDs */
|
||||
ECX = 0;
|
||||
EDX = 0; /* optional features */
|
||||
break;
|
||||
default:
|
||||
/* reserved values: zero */
|
||||
EAX = 0;
|
||||
EBX = 0;
|
||||
ECX = 0;
|
||||
EDX = 0;
|
||||
break;
|
||||
}
|
||||
cpu_x86_cpuid(env, (uint32_t)EAX, &eax, &ebx, &ecx, &edx);
|
||||
EAX = eax;
|
||||
EBX = ebx;
|
||||
ECX = ecx;
|
||||
EDX = edx;
|
||||
}
|
||||
|
||||
void helper_enter_level(int level, int data32, target_ulong t1)
|
||||
|
Loading…
Reference in New Issue
Block a user