Commit 6fd805e1 authored by Anthony Liguori's avatar Anthony Liguori
Browse files

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: default avatarAnthony Liguori <aliguori@us.ibm.com>



git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@5626 c046a42c-6fe2-441c-8c8c-71466251a162
parent 0650f1ab
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -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 */
+166 −0
Original line number Diff line number Diff line
@@ -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;
    }
}
+6 −162
Original line number Diff line number Diff line
@@ -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)