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:
aliguori 2008-11-05 15:34:06 +00:00
parent 0650f1ab30
commit 6fd805e1d4
3 changed files with 176 additions and 162 deletions

View File

@ -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 */

View File

@ -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;
}
}

View File

@ -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)