void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,

                   uint32_t *eax, uint32_t *ebx,

                   uint32_t *ecx, uint32_t *edx)

{

    X86CPU *cpu = x86_env_get_cpu(env);

    CPUState *cs = CPU(cpu);

    uint32_t pkg_offset;



    /* test if maximum index reached */

    if (index & 0x80000000) {

        if (index > env->cpuid_xlevel) {

            if (env->cpuid_xlevel2 > 0) {

                /* Handle the Centaur's CPUID instruction. */

                if (index > env->cpuid_xlevel2) {

                    index = env->cpuid_xlevel2;

                } else if (index < 0xC0000000) {

                    index = env->cpuid_xlevel;

                }

            } else {

                /* Intel documentation states that invalid EAX input will

                 * return the same information as EAX=cpuid_level

                 * (Intel SDM Vol. 2A - Instruction Set Reference - CPUID)

                 */

                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 = (cpu->apic_id << 24) |

               8 << 8; /* CLFLUSH size in quad words, Linux wants it. */

        *ecx = env->features[FEAT_1_ECX];

        if ((*ecx & CPUID_EXT_XSAVE) && (env->cr[4] & CR4_OSXSAVE_MASK)) {

            *ecx |= CPUID_EXT_OSXSAVE;

        }

        *edx = env->features[FEAT_1_EDX];

        if (cs->nr_cores * cs->nr_threads > 1) {

            *ebx |= (cs->nr_cores * cs->nr_threads) << 16;

            *edx |= CPUID_HT;

        }

        break;

    case 2:

        /* cache info: needed for Pentium Pro compatibility */

        if (cpu->cache_info_passthrough) {

            host_cpuid(index, 0, eax, ebx, ecx, edx);

            break;

        }

        *eax = 1; /* Number of CPUID[EAX=2] calls required */

        *ebx = 0;

        if (!cpu->enable_l3_cache) {

            *ecx = 0;

        } else {

            *ecx = L3_N_DESCRIPTOR;

        }

        *edx = (L1D_DESCRIPTOR << 16) | \

               (L1I_DESCRIPTOR <<  8) | \

               (L2_DESCRIPTOR);

        break;

    case 4:

        /* cache info: needed for Core compatibility */

        if (cpu->cache_info_passthrough) {

            host_cpuid(index, count, eax, ebx, ecx, edx);

            *eax &= ~0xFC000000;

        } else {

            *eax = 0;

            switch (count) {

            case 0: /* L1 dcache info */

                *eax |= CPUID_4_TYPE_DCACHE | \

                        CPUID_4_LEVEL(1) | \

                        CPUID_4_SELF_INIT_LEVEL;

                *ebx = (L1D_LINE_SIZE - 1) | \

                       ((L1D_PARTITIONS - 1) << 12) | \

                       ((L1D_ASSOCIATIVITY - 1) << 22);

                *ecx = L1D_SETS - 1;

                *edx = CPUID_4_NO_INVD_SHARING;

                break;

            case 1: /* L1 icache info */

                *eax |= CPUID_4_TYPE_ICACHE | \

                        CPUID_4_LEVEL(1) | \

                        CPUID_4_SELF_INIT_LEVEL;

                *ebx = (L1I_LINE_SIZE - 1) | \

                       ((L1I_PARTITIONS - 1) << 12) | \

                       ((L1I_ASSOCIATIVITY - 1) << 22);

                *ecx = L1I_SETS - 1;

                *edx = CPUID_4_NO_INVD_SHARING;

                break;

            case 2: /* L2 cache info */

                *eax |= CPUID_4_TYPE_UNIFIED | \

                        CPUID_4_LEVEL(2) | \

                        CPUID_4_SELF_INIT_LEVEL;

                if (cs->nr_threads > 1) {

                    *eax |= (cs->nr_threads - 1) << 14;

                }

                *ebx = (L2_LINE_SIZE - 1) | \

                       ((L2_PARTITIONS - 1) << 12) | \

                       ((L2_ASSOCIATIVITY - 1) << 22);

                *ecx = L2_SETS - 1;

                *edx = CPUID_4_NO_INVD_SHARING;

                break;

            case 3: /* L3 cache info */

                if (!cpu->enable_l3_cache) {

                    *eax = 0;

                    *ebx = 0;

                    *ecx = 0;

                    *edx = 0;

                    break;

                }

                *eax |= CPUID_4_TYPE_UNIFIED | \

                        CPUID_4_LEVEL(3) | \

                        CPUID_4_SELF_INIT_LEVEL;

                pkg_offset = apicid_pkg_offset(cs->nr_cores, cs->nr_threads);

                *eax |= ((1 << pkg_offset) - 1) << 14;

                *ebx = (L3_N_LINE_SIZE - 1) | \

                       ((L3_N_PARTITIONS - 1) << 12) | \

                       ((L3_N_ASSOCIATIVITY - 1) << 22);

                *ecx = L3_N_SETS - 1;

                *edx = CPUID_4_INCLUSIVE | CPUID_4_COMPLEX_IDX;

                break;

            default: /* end of info */

                *eax = 0;

                *ebx = 0;

                *ecx = 0;

                *edx = 0;

                break;

            }

        }



        /* QEMU gives out its own APIC IDs, never pass down bits 31..26.  */

        if ((*eax & 31) && cs->nr_cores > 1) {

            *eax |= (cs->nr_cores - 1) << 26;

        }

        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 = env->features[FEAT_6_EAX];

        *ebx = 0;

        *ecx = 0;

        *edx = 0;

        break;

    case 7:

        /* Structured Extended Feature Flags Enumeration Leaf */

        if (count == 0) {

            *eax = 0; /* Maximum ECX value for sub-leaves */

            *ebx = env->features[FEAT_7_0_EBX]; /* Feature flags */

            *ecx = env->features[FEAT_7_0_ECX]; /* Feature flags */

            if ((*ecx & CPUID_7_0_ECX_PKU) && env->cr[4] & CR4_PKE_MASK) {

                *ecx |= CPUID_7_0_ECX_OSPKE;

            }

            *edx = 0; /* Reserved */

        } else {

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

        if (kvm_enabled() && cpu->enable_pmu) {

            KVMState *s = cs->kvm_state;



            *eax = kvm_arch_get_supported_cpuid(s, 0xA, count, R_EAX);

            *ebx = kvm_arch_get_supported_cpuid(s, 0xA, count, R_EBX);

            *ecx = kvm_arch_get_supported_cpuid(s, 0xA, count, R_ECX);

            *edx = kvm_arch_get_supported_cpuid(s, 0xA, count, R_EDX);

        } else {

            *eax = 0;

            *ebx = 0;

            *ecx = 0;

            *edx = 0;

        }

        break;

    case 0xB:

        /* Extended Topology Enumeration Leaf */

        if (!cpu->enable_cpuid_0xb) {

                *eax = *ebx = *ecx = *edx = 0;

                break;

        }



        *ecx = count & 0xff;

        *edx = cpu->apic_id;



        switch (count) {

        case 0:

            *eax = apicid_core_offset(cs->nr_cores, cs->nr_threads);

            *ebx = cs->nr_threads;

            *ecx |= CPUID_TOPOLOGY_LEVEL_SMT;

            break;

        case 1:

            *eax = apicid_pkg_offset(cs->nr_cores, cs->nr_threads);

            *ebx = cs->nr_cores * cs->nr_threads;

            *ecx |= CPUID_TOPOLOGY_LEVEL_CORE;

            break;

        default:

            *eax = 0;

            *ebx = 0;

            *ecx |= CPUID_TOPOLOGY_LEVEL_INVALID;

        }



        assert(!(*eax & ~0x1f));

        *ebx &= 0xffff; /* The count doesn't need to be reliable. */

        break;

    case 0xD: {

        KVMState *s = cs->kvm_state;

        uint64_t ena_mask;

        int i;



        /* Processor Extended State */

        *eax = 0;

        *ebx = 0;

        *ecx = 0;

        *edx = 0;

        if (!(env->features[FEAT_1_ECX] & CPUID_EXT_XSAVE)) {

            break;

        }

        if (kvm_enabled()) {

            ena_mask = kvm_arch_get_supported_cpuid(s, 0xd, 0, R_EDX);

            ena_mask <<= 32;

            ena_mask |= kvm_arch_get_supported_cpuid(s, 0xd, 0, R_EAX);

        } else {

            ena_mask = -1;

        }



        if (count == 0) {

            *ecx = 0x240;

            for (i = 2; i < ARRAY_SIZE(x86_ext_save_areas); i++) {

                const ExtSaveArea *esa = &x86_ext_save_areas[i];

                if ((env->features[esa->feature] & esa->bits) == esa->bits

                    && ((ena_mask >> i) & 1) != 0) {

                    if (i < 32) {

                        *eax |= 1u << i;

                    } else {

                        *edx |= 1u << (i - 32);

                    }

                    *ecx = MAX(*ecx, esa->offset + esa->size);

                }

            }

            *eax |= ena_mask & (XSTATE_FP_MASK | XSTATE_SSE_MASK);

            *ebx = *ecx;

        } else if (count == 1) {

            *eax = env->features[FEAT_XSAVE];

        } else if (count < ARRAY_SIZE(x86_ext_save_areas)) {

            const ExtSaveArea *esa = &x86_ext_save_areas[count];

            if ((env->features[esa->feature] & esa->bits) == esa->bits

                && ((ena_mask >> count) & 1) != 0) {

                *eax = esa->size;

                *ebx = esa->offset;

            }

        }

        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_version;

        *ebx = 0;

        *ecx = env->features[FEAT_8000_0001_ECX];

        *edx = env->features[FEAT_8000_0001_EDX];



        /* The Linux kernel checks for the CMPLegacy bit and

         * discards multiple thread information if it is set.

         * So don't set it here for Intel to make Linux guests happy.

         */

        if (cs->nr_cores * cs->nr_threads > 1) {

            if (env->cpuid_vendor1 != CPUID_VENDOR_INTEL_1 ||

                env->cpuid_vendor2 != CPUID_VENDOR_INTEL_2 ||

                env->cpuid_vendor3 != CPUID_VENDOR_INTEL_3) {

                *ecx |= 1 << 1;    /* CmpLegacy bit */

            }

        }

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

        if (cpu->cache_info_passthrough) {

            host_cpuid(index, 0, eax, ebx, ecx, edx);

            break;

        }

        *eax = (L1_DTLB_2M_ASSOC << 24) | (L1_DTLB_2M_ENTRIES << 16) | \

               (L1_ITLB_2M_ASSOC <<  8) | (L1_ITLB_2M_ENTRIES);

        *ebx = (L1_DTLB_4K_ASSOC << 24) | (L1_DTLB_4K_ENTRIES << 16) | \

               (L1_ITLB_4K_ASSOC <<  8) | (L1_ITLB_4K_ENTRIES);

        *ecx = (L1D_SIZE_KB_AMD << 24) | (L1D_ASSOCIATIVITY_AMD << 16) | \

               (L1D_LINES_PER_TAG << 8) | (L1D_LINE_SIZE);

        *edx = (L1I_SIZE_KB_AMD << 24) | (L1I_ASSOCIATIVITY_AMD << 16) | \

               (L1I_LINES_PER_TAG << 8) | (L1I_LINE_SIZE);

        break;

    case 0x80000006:

        /* cache info (L2 cache) */

        if (cpu->cache_info_passthrough) {

            host_cpuid(index, 0, eax, ebx, ecx, edx);

            break;

        }

        *eax = (AMD_ENC_ASSOC(L2_DTLB_2M_ASSOC) << 28) | \

               (L2_DTLB_2M_ENTRIES << 16) | \

               (AMD_ENC_ASSOC(L2_ITLB_2M_ASSOC) << 12) | \

               (L2_ITLB_2M_ENTRIES);

        *ebx = (AMD_ENC_ASSOC(L2_DTLB_4K_ASSOC) << 28) | \

               (L2_DTLB_4K_ENTRIES << 16) | \

               (AMD_ENC_ASSOC(L2_ITLB_4K_ASSOC) << 12) | \

               (L2_ITLB_4K_ENTRIES);

        *ecx = (L2_SIZE_KB_AMD << 16) | \

               (AMD_ENC_ASSOC(L2_ASSOCIATIVITY) << 12) | \

               (L2_LINES_PER_TAG << 8) | (L2_LINE_SIZE);

        if (!cpu->enable_l3_cache) {

            *edx = ((L3_SIZE_KB / 512) << 18) | \

                   (AMD_ENC_ASSOC(L3_ASSOCIATIVITY) << 12) | \

                   (L3_LINES_PER_TAG << 8) | (L3_LINE_SIZE);

        } else {

            *edx = ((L3_N_SIZE_KB_AMD / 512) << 18) | \

                   (AMD_ENC_ASSOC(L3_N_ASSOCIATIVITY) << 12) | \

                   (L3_N_LINES_PER_TAG << 8) | (L3_N_LINE_SIZE);

        }

        break;

    case 0x80000007:

        *eax = 0;

        *ebx = 0;

        *ecx = 0;

        *edx = env->features[FEAT_8000_0007_EDX];

        break;

    case 0x80000008:

        /* virtual & phys address size in low 2 bytes. */

        if (env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_LM) {

            /* 64 bit processor, 48 bits virtual, configurable

             * physical bits.

             */

            *eax = 0x00003000 + cpu->phys_bits;

        } else {

            *eax = cpu->phys_bits;

        }

        *ebx = 0;

        *ecx = 0;

        *edx = 0;

        if (cs->nr_cores * cs->nr_threads > 1) {

            *ecx |= (cs->nr_cores * cs->nr_threads) - 1;

        }

        break;

    case 0x8000000A:

        if (env->features[FEAT_8000_0001_ECX] & CPUID_EXT3_SVM) {

            *eax = 0x00000001; /* SVM Revision */

            *ebx = 0x00000010; /* nr of ASIDs */

            *ecx = 0;

            *edx = env->features[FEAT_SVM]; /* optional features */

        } else {

            *eax = 0;

            *ebx = 0;

            *ecx = 0;

            *edx = 0;

        }

        break;

    case 0xC0000000:

        *eax = env->cpuid_xlevel2;

        *ebx = 0;

        *ecx = 0;

        *edx = 0;

        break;

    case 0xC0000001:

        /* Support for VIA CPU's CPUID instruction */

        *eax = env->cpuid_version;

        *ebx = 0;

        *ecx = 0;

        *edx = env->features[FEAT_C000_0001_EDX];

        break;

    case 0xC0000002:

    case 0xC0000003:

    case 0xC0000004:

        /* Reserved for the future, and now filled with zero */

        *eax = 0;

        *ebx = 0;

        *ecx = 0;

        *edx = 0;

        break;

    default:

        /* reserved values: zero */

        *eax = 0;

        *ebx = 0;

        *ecx = 0;

        *edx = 0;

        break;

    }

}

void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,

                   uint32_t *eax, uint32_t *ebx,

                   uint32_t *ecx, uint32_t *edx)

{

    X86CPU *cpu = x86_env_get_cpu(env);

    CPUState *cs = CPU(cpu);

    uint32_t pkg_offset;



    

    if (index & 0x80000000) {

        if (index > env->cpuid_xlevel) {

            if (env->cpuid_xlevel2 > 0) {

                

                if (index > env->cpuid_xlevel2) {

                    index = env->cpuid_xlevel2;

                } else if (index < 0xC0000000) {

                    index = env->cpuid_xlevel;

                }

            } else {

                







                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 = (cpu->apic_id << 24) |

               8 << 8; 

        *ecx = env->features[FEAT_1_ECX];

        if ((*ecx & CPUID_EXT_XSAVE) && (env->cr[4] & CR4_OSXSAVE_MASK)) {

            *ecx |= CPUID_EXT_OSXSAVE;

        }

        *edx = env->features[FEAT_1_EDX];

        if (cs->nr_cores * cs->nr_threads > 1) {

            *ebx |= (cs->nr_cores * cs->nr_threads) << 16;

            *edx |= CPUID_HT;

        }

        break;

    case 2:

        

        if (cpu->cache_info_passthrough) {

            host_cpuid(index, 0, eax, ebx, ecx, edx);

            break;

        }

        *eax = 1; 

        *ebx = 0;

        if (!cpu->enable_l3_cache) {

            *ecx = 0;

        } else {

            *ecx = L3_N_DESCRIPTOR;

        }

        *edx = (L1D_DESCRIPTOR << 16) | \

               (L1I_DESCRIPTOR <<  8) | \

               (L2_DESCRIPTOR);

        break;

    case 4:

        

        if (cpu->cache_info_passthrough) {

            host_cpuid(index, count, eax, ebx, ecx, edx);

            *eax &= ~0xFC000000;

        } else {

            *eax = 0;

            switch (count) {

            case 0: 

                *eax |= CPUID_4_TYPE_DCACHE | \

                        CPUID_4_LEVEL(1) | \

                        CPUID_4_SELF_INIT_LEVEL;

                *ebx = (L1D_LINE_SIZE - 1) | \

                       ((L1D_PARTITIONS - 1) << 12) | \

                       ((L1D_ASSOCIATIVITY - 1) << 22);

                *ecx = L1D_SETS - 1;

                *edx = CPUID_4_NO_INVD_SHARING;

                break;

            case 1: 

                *eax |= CPUID_4_TYPE_ICACHE | \

                        CPUID_4_LEVEL(1) | \

                        CPUID_4_SELF_INIT_LEVEL;

                *ebx = (L1I_LINE_SIZE - 1) | \

                       ((L1I_PARTITIONS - 1) << 12) | \

                       ((L1I_ASSOCIATIVITY - 1) << 22);

                *ecx = L1I_SETS - 1;

                *edx = CPUID_4_NO_INVD_SHARING;

                break;

            case 2: 

                *eax |= CPUID_4_TYPE_UNIFIED | \

                        CPUID_4_LEVEL(2) | \

                        CPUID_4_SELF_INIT_LEVEL;

                if (cs->nr_threads > 1) {

                    *eax |= (cs->nr_threads - 1) << 14;

                }

                *ebx = (L2_LINE_SIZE - 1) | \

                       ((L2_PARTITIONS - 1) << 12) | \

                       ((L2_ASSOCIATIVITY - 1) << 22);

                *ecx = L2_SETS - 1;

                *edx = CPUID_4_NO_INVD_SHARING;

                break;

            case 3: 

                if (!cpu->enable_l3_cache) {

                    *eax = 0;

                    *ebx = 0;

                    *ecx = 0;

                    *edx = 0;

                    break;

                }

                *eax |= CPUID_4_TYPE_UNIFIED | \

                        CPUID_4_LEVEL(3) | \

                        CPUID_4_SELF_INIT_LEVEL;

                pkg_offset = apicid_pkg_offset(cs->nr_cores, cs->nr_threads);

                *eax |= ((1 << pkg_offset) - 1) << 14;

                *ebx = (L3_N_LINE_SIZE - 1) | \

                       ((L3_N_PARTITIONS - 1) << 12) | \

                       ((L3_N_ASSOCIATIVITY - 1) << 22);

                *ecx = L3_N_SETS - 1;

                *edx = CPUID_4_INCLUSIVE | CPUID_4_COMPLEX_IDX;

                break;

            default: 

                *eax = 0;

                *ebx = 0;

                *ecx = 0;

                *edx = 0;

                break;

            }

        }



        

        if ((*eax & 31) && cs->nr_cores > 1) {

            *eax |= (cs->nr_cores - 1) << 26;

        }

        break;

    case 5:

        

        *eax = 0; 

        *ebx = 0; 

        *ecx = CPUID_MWAIT_EMX | CPUID_MWAIT_IBE;

        *edx = 0;

        break;

    case 6:

        

        *eax = env->features[FEAT_6_EAX];

        *ebx = 0;

        *ecx = 0;

        *edx = 0;

        break;

    case 7:

        

        if (count == 0) {

            *eax = 0; 

            *ebx = env->features[FEAT_7_0_EBX]; 

            *ecx = env->features[FEAT_7_0_ECX]; 

            if ((*ecx & CPUID_7_0_ECX_PKU) && env->cr[4] & CR4_PKE_MASK) {

                *ecx |= CPUID_7_0_ECX_OSPKE;

            }

            *edx = 0; 

        } else {

            *eax = 0;

            *ebx = 0;

            *ecx = 0;

            *edx = 0;

        }

        break;

    case 9:

        

        *eax = 0; 

        *ebx = 0;

        *ecx = 0;

        *edx = 0;

        break;

    case 0xA:

        

        if (kvm_enabled() && cpu->enable_pmu) {

            KVMState *s = cs->kvm_state;



            *eax = kvm_arch_get_supported_cpuid(s, 0xA, count, R_EAX);

            *ebx = kvm_arch_get_supported_cpuid(s, 0xA, count, R_EBX);

            *ecx = kvm_arch_get_supported_cpuid(s, 0xA, count, R_ECX);

            *edx = kvm_arch_get_supported_cpuid(s, 0xA, count, R_EDX);

        } else {

            *eax = 0;

            *ebx = 0;

            *ecx = 0;

            *edx = 0;

        }

        break;

    case 0xB:

        

        if (!cpu->enable_cpuid_0xb) {

                *eax = *ebx = *ecx = *edx = 0;

                break;

        }



        *ecx = count & 0xff;

        *edx = cpu->apic_id;



        switch (count) {

        case 0:

            *eax = apicid_core_offset(cs->nr_cores, cs->nr_threads);

            *ebx = cs->nr_threads;

            *ecx |= CPUID_TOPOLOGY_LEVEL_SMT;

            break;

        case 1:

            *eax = apicid_pkg_offset(cs->nr_cores, cs->nr_threads);

            *ebx = cs->nr_cores * cs->nr_threads;

            *ecx |= CPUID_TOPOLOGY_LEVEL_CORE;

            break;

        default:

            *eax = 0;

            *ebx = 0;

            *ecx |= CPUID_TOPOLOGY_LEVEL_INVALID;

        }



        assert(!(*eax & ~0x1f));

        *ebx &= 0xffff; 

        break;

    case 0xD: {

        KVMState *s = cs->kvm_state;

        uint64_t ena_mask;

        int i;



        

        *eax = 0;

        *ebx = 0;

        *ecx = 0;

        *edx = 0;

        if (!(env->features[FEAT_1_ECX] & CPUID_EXT_XSAVE)) {

            break;

        }

        if (kvm_enabled()) {

            ena_mask = kvm_arch_get_supported_cpuid(s, 0xd, 0, R_EDX);

            ena_mask <<= 32;

            ena_mask |= kvm_arch_get_supported_cpuid(s, 0xd, 0, R_EAX);

        } else {

            ena_mask = -1;

        }



        if (count == 0) {

            *ecx = 0x240;

            for (i = 2; i < ARRAY_SIZE(x86_ext_save_areas); i++) {

                const ExtSaveArea *esa = &x86_ext_save_areas[i];

                if ((env->features[esa->feature] & esa->bits) == esa->bits

                    && ((ena_mask >> i) & 1) != 0) {

                    if (i < 32) {

                        *eax |= 1u << i;

                    } else {

                        *edx |= 1u << (i - 32);

                    }

                    *ecx = MAX(*ecx, esa->offset + esa->size);

                }

            }

            *eax |= ena_mask & (XSTATE_FP_MASK | XSTATE_SSE_MASK);

            *ebx = *ecx;

        } else if (count == 1) {

            *eax = env->features[FEAT_XSAVE];

        } else if (count < ARRAY_SIZE(x86_ext_save_areas)) {

            const ExtSaveArea *esa = &x86_ext_save_areas[count];

            if ((env->features[esa->feature] & esa->bits) == esa->bits

                && ((ena_mask >> count) & 1) != 0) {

                *eax = esa->size;

                *ebx = esa->offset;

            }

        }

        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_version;

        *ebx = 0;

        *ecx = env->features[FEAT_8000_0001_ECX];

        *edx = env->features[FEAT_8000_0001_EDX];



        







        if (cs->nr_cores * cs->nr_threads > 1) {

            if (env->cpuid_vendor1 != CPUID_VENDOR_INTEL_1 ||

                env->cpuid_vendor2 != CPUID_VENDOR_INTEL_2 ||

                env->cpuid_vendor3 != CPUID_VENDOR_INTEL_3) {

                *ecx |= 1 << 1;    

            }

        }

        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:

        

        if (cpu->cache_info_passthrough) {

            host_cpuid(index, 0, eax, ebx, ecx, edx);

            break;

        }

        *eax = (L1_DTLB_2M_ASSOC << 24) | (L1_DTLB_2M_ENTRIES << 16) | \

               (L1_ITLB_2M_ASSOC <<  8) | (L1_ITLB_2M_ENTRIES);

        *ebx = (L1_DTLB_4K_ASSOC << 24) | (L1_DTLB_4K_ENTRIES << 16) | \

               (L1_ITLB_4K_ASSOC <<  8) | (L1_ITLB_4K_ENTRIES);

        *ecx = (L1D_SIZE_KB_AMD << 24) | (L1D_ASSOCIATIVITY_AMD << 16) | \

               (L1D_LINES_PER_TAG << 8) | (L1D_LINE_SIZE);

        *edx = (L1I_SIZE_KB_AMD << 24) | (L1I_ASSOCIATIVITY_AMD << 16) | \

               (L1I_LINES_PER_TAG << 8) | (L1I_LINE_SIZE);

        break;

    case 0x80000006:

        

        if (cpu->cache_info_passthrough) {

            host_cpuid(index, 0, eax, ebx, ecx, edx);

            break;

        }

        *eax = (AMD_ENC_ASSOC(L2_DTLB_2M_ASSOC) << 28) | \

               (L2_DTLB_2M_ENTRIES << 16) | \

               (AMD_ENC_ASSOC(L2_ITLB_2M_ASSOC) << 12) | \

               (L2_ITLB_2M_ENTRIES);

        *ebx = (AMD_ENC_ASSOC(L2_DTLB_4K_ASSOC) << 28) | \

               (L2_DTLB_4K_ENTRIES << 16) | \

               (AMD_ENC_ASSOC(L2_ITLB_4K_ASSOC) << 12) | \

               (L2_ITLB_4K_ENTRIES);

        *ecx = (L2_SIZE_KB_AMD << 16) | \

               (AMD_ENC_ASSOC(L2_ASSOCIATIVITY) << 12) | \

               (L2_LINES_PER_TAG << 8) | (L2_LINE_SIZE);

        if (!cpu->enable_l3_cache) {

            *edx = ((L3_SIZE_KB / 512) << 18) | \

                   (AMD_ENC_ASSOC(L3_ASSOCIATIVITY) << 12) | \

                   (L3_LINES_PER_TAG << 8) | (L3_LINE_SIZE);

        } else {

            *edx = ((L3_N_SIZE_KB_AMD / 512) << 18) | \

                   (AMD_ENC_ASSOC(L3_N_ASSOCIATIVITY) << 12) | \

                   (L3_N_LINES_PER_TAG << 8) | (L3_N_LINE_SIZE);

        }

        break;

    case 0x80000007:

        *eax = 0;

        *ebx = 0;

        *ecx = 0;

        *edx = env->features[FEAT_8000_0007_EDX];

        break;

    case 0x80000008:

        

        if (env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_LM) {

            





            *eax = 0x00003000 + cpu->phys_bits;

        } else {

            *eax = cpu->phys_bits;

        }

        *ebx = 0;

        *ecx = 0;

        *edx = 0;

        if (cs->nr_cores * cs->nr_threads > 1) {

            *ecx |= (cs->nr_cores * cs->nr_threads) - 1;

        }

        break;

    case 0x8000000A:

        if (env->features[FEAT_8000_0001_ECX] & CPUID_EXT3_SVM) {

            *eax = 0x00000001; 

            *ebx = 0x00000010; 

            *ecx = 0;

            *edx = env->features[FEAT_SVM]; 

        } else {

            *eax = 0;

            *ebx = 0;

            *ecx = 0;

            *edx = 0;

        }

        break;

    case 0xC0000000:

        *eax = env->cpuid_xlevel2;

        *ebx = 0;

        *ecx = 0;

        *edx = 0;

        break;

    case 0xC0000001:

        

        *eax = env->cpuid_version;

        *ebx = 0;

        *ecx = 0;

        *edx = env->features[FEAT_C000_0001_EDX];

        break;

    case 0xC0000002:

    case 0xC0000003:

    case 0xC0000004:

        

        *eax = 0;

        *ebx = 0;

        *ecx = 0;

        *edx = 0;

        break;

    default:

        

        *eax = 0;

        *ebx = 0;

        *ecx = 0;

        *edx = 0;

        break;

    }

}

void FUNC_0(CPUX86State *VAR_0, uint32_t VAR_1, uint32_t VAR_2,

                   uint32_t *VAR_3, uint32_t *VAR_4,

                   uint32_t *VAR_5, uint32_t *VAR_6)

{

    X86CPU *cpu = x86_env_get_cpu(VAR_0);

    CPUState *cs = CPU(cpu);

    uint32_t pkg_offset;



    

    if (VAR_1 & 0x80000000) {

        if (VAR_1 > VAR_0->cpuid_xlevel) {

            if (VAR_0->cpuid_xlevel2 > 0) {

                

                if (VAR_1 > VAR_0->cpuid_xlevel2) {

                    VAR_1 = VAR_0->cpuid_xlevel2;

                } else if (VAR_1 < 0xC0000000) {

                    VAR_1 = VAR_0->cpuid_xlevel;

                }

            } else {

                







                VAR_1 =  VAR_0->cpuid_level;

            }

        }

    } else {

        if (VAR_1 > VAR_0->cpuid_level)

            VAR_1 = VAR_0->cpuid_level;

    }



    switch(VAR_1) {

    case 0:

        *VAR_3 = VAR_0->cpuid_level;

        *VAR_4 = VAR_0->cpuid_vendor1;

        *VAR_6 = VAR_0->cpuid_vendor2;

        *VAR_5 = VAR_0->cpuid_vendor3;

        break;

    case 1:

        *VAR_3 = VAR_0->cpuid_version;

        *VAR_4 = (cpu->apic_id << 24) |

               8 << 8; 

        *VAR_5 = VAR_0->features[FEAT_1_ECX];

        if ((*VAR_5 & CPUID_EXT_XSAVE) && (VAR_0->cr[4] & CR4_OSXSAVE_MASK)) {

            *VAR_5 |= CPUID_EXT_OSXSAVE;

        }

        *VAR_6 = VAR_0->features[FEAT_1_EDX];

        if (cs->nr_cores * cs->nr_threads > 1) {

            *VAR_4 |= (cs->nr_cores * cs->nr_threads) << 16;

            *VAR_6 |= CPUID_HT;

        }

        break;

    case 2:

        

        if (cpu->cache_info_passthrough) {

            host_cpuid(VAR_1, 0, VAR_3, VAR_4, VAR_5, VAR_6);

            break;

        }

        *VAR_3 = 1; 

        *VAR_4 = 0;

        if (!cpu->enable_l3_cache) {

            *VAR_5 = 0;

        } else {

            *VAR_5 = L3_N_DESCRIPTOR;

        }

        *VAR_6 = (L1D_DESCRIPTOR << 16) | \

               (L1I_DESCRIPTOR <<  8) | \

               (L2_DESCRIPTOR);

        break;

    case 4:

        

        if (cpu->cache_info_passthrough) {

            host_cpuid(VAR_1, VAR_2, VAR_3, VAR_4, VAR_5, VAR_6);

            *VAR_3 &= ~0xFC000000;

        } else {

            *VAR_3 = 0;

            switch (VAR_2) {

            case 0: 

                *VAR_3 |= CPUID_4_TYPE_DCACHE | \

                        CPUID_4_LEVEL(1) | \

                        CPUID_4_SELF_INIT_LEVEL;

                *VAR_4 = (L1D_LINE_SIZE - 1) | \

                       ((L1D_PARTITIONS - 1) << 12) | \

                       ((L1D_ASSOCIATIVITY - 1) << 22);

                *VAR_5 = L1D_SETS - 1;

                *VAR_6 = CPUID_4_NO_INVD_SHARING;

                break;

            case 1: 

                *VAR_3 |= CPUID_4_TYPE_ICACHE | \

                        CPUID_4_LEVEL(1) | \

                        CPUID_4_SELF_INIT_LEVEL;

                *VAR_4 = (L1I_LINE_SIZE - 1) | \

                       ((L1I_PARTITIONS - 1) << 12) | \

                       ((L1I_ASSOCIATIVITY - 1) << 22);

                *VAR_5 = L1I_SETS - 1;

                *VAR_6 = CPUID_4_NO_INVD_SHARING;

                break;

            case 2: 

                *VAR_3 |= CPUID_4_TYPE_UNIFIED | \

                        CPUID_4_LEVEL(2) | \

                        CPUID_4_SELF_INIT_LEVEL;

                if (cs->nr_threads > 1) {

                    *VAR_3 |= (cs->nr_threads - 1) << 14;

                }

                *VAR_4 = (L2_LINE_SIZE - 1) | \

                       ((L2_PARTITIONS - 1) << 12) | \

                       ((L2_ASSOCIATIVITY - 1) << 22);

                *VAR_5 = L2_SETS - 1;

                *VAR_6 = CPUID_4_NO_INVD_SHARING;

                break;

            case 3: 

                if (!cpu->enable_l3_cache) {

                    *VAR_3 = 0;

                    *VAR_4 = 0;

                    *VAR_5 = 0;

                    *VAR_6 = 0;

                    break;

                }

                *VAR_3 |= CPUID_4_TYPE_UNIFIED | \

                        CPUID_4_LEVEL(3) | \

                        CPUID_4_SELF_INIT_LEVEL;

                pkg_offset = apicid_pkg_offset(cs->nr_cores, cs->nr_threads);

                *VAR_3 |= ((1 << pkg_offset) - 1) << 14;

                *VAR_4 = (L3_N_LINE_SIZE - 1) | \

                       ((L3_N_PARTITIONS - 1) << 12) | \

                       ((L3_N_ASSOCIATIVITY - 1) << 22);

                *VAR_5 = L3_N_SETS - 1;

                *VAR_6 = CPUID_4_INCLUSIVE | CPUID_4_COMPLEX_IDX;

                break;

            default: 

                *VAR_3 = 0;

                *VAR_4 = 0;

                *VAR_5 = 0;

                *VAR_6 = 0;

                break;

            }

        }



        

        if ((*VAR_3 & 31) && cs->nr_cores > 1) {

            *VAR_3 |= (cs->nr_cores - 1) << 26;

        }

        break;

    case 5:

        

        *VAR_3 = 0; 

        *VAR_4 = 0; 

        *VAR_5 = CPUID_MWAIT_EMX | CPUID_MWAIT_IBE;

        *VAR_6 = 0;

        break;

    case 6:

        

        *VAR_3 = VAR_0->features[FEAT_6_EAX];

        *VAR_4 = 0;

        *VAR_5 = 0;

        *VAR_6 = 0;

        break;

    case 7:

        

        if (VAR_2 == 0) {

            *VAR_3 = 0; 

            *VAR_4 = VAR_0->features[FEAT_7_0_EBX]; 

            *VAR_5 = VAR_0->features[FEAT_7_0_ECX]; 

            if ((*VAR_5 & CPUID_7_0_ECX_PKU) && VAR_0->cr[4] & CR4_PKE_MASK) {

                *VAR_5 |= CPUID_7_0_ECX_OSPKE;

            }

            *VAR_6 = 0; 

        } else {

            *VAR_3 = 0;

            *VAR_4 = 0;

            *VAR_5 = 0;

            *VAR_6 = 0;

        }

        break;

    case 9:

        

        *VAR_3 = 0; 

        *VAR_4 = 0;

        *VAR_5 = 0;

        *VAR_6 = 0;

        break;

    case 0xA:

        

        if (kvm_enabled() && cpu->enable_pmu) {

            KVMState *s = cs->kvm_state;



            *VAR_3 = kvm_arch_get_supported_cpuid(s, 0xA, VAR_2, R_EAX);

            *VAR_4 = kvm_arch_get_supported_cpuid(s, 0xA, VAR_2, R_EBX);

            *VAR_5 = kvm_arch_get_supported_cpuid(s, 0xA, VAR_2, R_ECX);

            *VAR_6 = kvm_arch_get_supported_cpuid(s, 0xA, VAR_2, R_EDX);

        } else {

            *VAR_3 = 0;

            *VAR_4 = 0;

            *VAR_5 = 0;

            *VAR_6 = 0;

        }

        break;

    case 0xB:

        

        if (!cpu->enable_cpuid_0xb) {

                *VAR_3 = *VAR_4 = *VAR_5 = *VAR_6 = 0;

                break;

        }



        *VAR_5 = VAR_2 & 0xff;

        *VAR_6 = cpu->apic_id;



        switch (VAR_2) {

        case 0:

            *VAR_3 = apicid_core_offset(cs->nr_cores, cs->nr_threads);

            *VAR_4 = cs->nr_threads;

            *VAR_5 |= CPUID_TOPOLOGY_LEVEL_SMT;

            break;

        case 1:

            *VAR_3 = apicid_pkg_offset(cs->nr_cores, cs->nr_threads);

            *VAR_4 = cs->nr_cores * cs->nr_threads;

            *VAR_5 |= CPUID_TOPOLOGY_LEVEL_CORE;

            break;

        default:

            *VAR_3 = 0;

            *VAR_4 = 0;

            *VAR_5 |= CPUID_TOPOLOGY_LEVEL_INVALID;

        }



        assert(!(*VAR_3 & ~0x1f));

        *VAR_4 &= 0xffff; 

        break;

    case 0xD: {

        KVMState *s = cs->kvm_state;

        uint64_t ena_mask;

        int VAR_7;



        

        *VAR_3 = 0;

        *VAR_4 = 0;

        *VAR_5 = 0;

        *VAR_6 = 0;

        if (!(VAR_0->features[FEAT_1_ECX] & CPUID_EXT_XSAVE)) {

            break;

        }

        if (kvm_enabled()) {

            ena_mask = kvm_arch_get_supported_cpuid(s, 0xd, 0, R_EDX);

            ena_mask <<= 32;

            ena_mask |= kvm_arch_get_supported_cpuid(s, 0xd, 0, R_EAX);

        } else {

            ena_mask = -1;

        }



        if (VAR_2 == 0) {

            *VAR_5 = 0x240;

            for (VAR_7 = 2; VAR_7 < ARRAY_SIZE(x86_ext_save_areas); VAR_7++) {

                const ExtSaveArea *VAR_8 = &x86_ext_save_areas[VAR_7];

                if ((VAR_0->features[VAR_8->feature] & VAR_8->bits) == VAR_8->bits

                    && ((ena_mask >> VAR_7) & 1) != 0) {

                    if (VAR_7 < 32) {

                        *VAR_3 |= 1u << VAR_7;

                    } else {

                        *VAR_6 |= 1u << (VAR_7 - 32);

                    }

                    *VAR_5 = MAX(*VAR_5, VAR_8->offset + VAR_8->size);

                }

            }

            *VAR_3 |= ena_mask & (XSTATE_FP_MASK | XSTATE_SSE_MASK);

            *VAR_4 = *VAR_5;

        } else if (VAR_2 == 1) {

            *VAR_3 = VAR_0->features[FEAT_XSAVE];

        } else if (VAR_2 < ARRAY_SIZE(x86_ext_save_areas)) {

            const ExtSaveArea *VAR_8 = &x86_ext_save_areas[VAR_2];

            if ((VAR_0->features[VAR_8->feature] & VAR_8->bits) == VAR_8->bits

                && ((ena_mask >> VAR_2) & 1) != 0) {

                *VAR_3 = VAR_8->size;

                *VAR_4 = VAR_8->offset;

            }

        }

        break;

    }

    case 0x80000000:

        *VAR_3 = VAR_0->cpuid_xlevel;

        *VAR_4 = VAR_0->cpuid_vendor1;

        *VAR_6 = VAR_0->cpuid_vendor2;

        *VAR_5 = VAR_0->cpuid_vendor3;

        break;

    case 0x80000001:

        *VAR_3 = VAR_0->cpuid_version;

        *VAR_4 = 0;

        *VAR_5 = VAR_0->features[FEAT_8000_0001_ECX];

        *VAR_6 = VAR_0->features[FEAT_8000_0001_EDX];



        







        if (cs->nr_cores * cs->nr_threads > 1) {

            if (VAR_0->cpuid_vendor1 != CPUID_VENDOR_INTEL_1 ||

                VAR_0->cpuid_vendor2 != CPUID_VENDOR_INTEL_2 ||

                VAR_0->cpuid_vendor3 != CPUID_VENDOR_INTEL_3) {

                *VAR_5 |= 1 << 1;    

            }

        }

        break;

    case 0x80000002:

    case 0x80000003:

    case 0x80000004:

        *VAR_3 = VAR_0->cpuid_model[(VAR_1 - 0x80000002) * 4 + 0];

        *VAR_4 = VAR_0->cpuid_model[(VAR_1 - 0x80000002) * 4 + 1];

        *VAR_5 = VAR_0->cpuid_model[(VAR_1 - 0x80000002) * 4 + 2];

        *VAR_6 = VAR_0->cpuid_model[(VAR_1 - 0x80000002) * 4 + 3];

        break;

    case 0x80000005:

        

        if (cpu->cache_info_passthrough) {

            host_cpuid(VAR_1, 0, VAR_3, VAR_4, VAR_5, VAR_6);

            break;

        }

        *VAR_3 = (L1_DTLB_2M_ASSOC << 24) | (L1_DTLB_2M_ENTRIES << 16) | \

               (L1_ITLB_2M_ASSOC <<  8) | (L1_ITLB_2M_ENTRIES);

        *VAR_4 = (L1_DTLB_4K_ASSOC << 24) | (L1_DTLB_4K_ENTRIES << 16) | \

               (L1_ITLB_4K_ASSOC <<  8) | (L1_ITLB_4K_ENTRIES);

        *VAR_5 = (L1D_SIZE_KB_AMD << 24) | (L1D_ASSOCIATIVITY_AMD << 16) | \

               (L1D_LINES_PER_TAG << 8) | (L1D_LINE_SIZE);

        *VAR_6 = (L1I_SIZE_KB_AMD << 24) | (L1I_ASSOCIATIVITY_AMD << 16) | \

               (L1I_LINES_PER_TAG << 8) | (L1I_LINE_SIZE);

        break;

    case 0x80000006:

        

        if (cpu->cache_info_passthrough) {

            host_cpuid(VAR_1, 0, VAR_3, VAR_4, VAR_5, VAR_6);

            break;

        }

        *VAR_3 = (AMD_ENC_ASSOC(L2_DTLB_2M_ASSOC) << 28) | \

               (L2_DTLB_2M_ENTRIES << 16) | \

               (AMD_ENC_ASSOC(L2_ITLB_2M_ASSOC) << 12) | \

               (L2_ITLB_2M_ENTRIES);

        *VAR_4 = (AMD_ENC_ASSOC(L2_DTLB_4K_ASSOC) << 28) | \

               (L2_DTLB_4K_ENTRIES << 16) | \

               (AMD_ENC_ASSOC(L2_ITLB_4K_ASSOC) << 12) | \

               (L2_ITLB_4K_ENTRIES);

        *VAR_5 = (L2_SIZE_KB_AMD << 16) | \

               (AMD_ENC_ASSOC(L2_ASSOCIATIVITY) << 12) | \

               (L2_LINES_PER_TAG << 8) | (L2_LINE_SIZE);

        if (!cpu->enable_l3_cache) {

            *VAR_6 = ((L3_SIZE_KB / 512) << 18) | \

                   (AMD_ENC_ASSOC(L3_ASSOCIATIVITY) << 12) | \

                   (L3_LINES_PER_TAG << 8) | (L3_LINE_SIZE);

        } else {

            *VAR_6 = ((L3_N_SIZE_KB_AMD / 512) << 18) | \

                   (AMD_ENC_ASSOC(L3_N_ASSOCIATIVITY) << 12) | \

                   (L3_N_LINES_PER_TAG << 8) | (L3_N_LINE_SIZE);

        }

        break;

    case 0x80000007:

        *VAR_3 = 0;

        *VAR_4 = 0;

        *VAR_5 = 0;

        *VAR_6 = VAR_0->features[FEAT_8000_0007_EDX];

        break;

    case 0x80000008:

        

        if (VAR_0->features[FEAT_8000_0001_EDX] & CPUID_EXT2_LM) {

            





            *VAR_3 = 0x00003000 + cpu->phys_bits;

        } else {

            *VAR_3 = cpu->phys_bits;

        }

        *VAR_4 = 0;

        *VAR_5 = 0;

        *VAR_6 = 0;

        if (cs->nr_cores * cs->nr_threads > 1) {

            *VAR_5 |= (cs->nr_cores * cs->nr_threads) - 1;

        }

        break;

    case 0x8000000A:

        if (VAR_0->features[FEAT_8000_0001_ECX] & CPUID_EXT3_SVM) {

            *VAR_3 = 0x00000001; 

            *VAR_4 = 0x00000010; 

            *VAR_5 = 0;

            *VAR_6 = VAR_0->features[FEAT_SVM]; 

        } else {

            *VAR_3 = 0;

            *VAR_4 = 0;

            *VAR_5 = 0;

            *VAR_6 = 0;

        }

        break;

    case 0xC0000000:

        *VAR_3 = VAR_0->cpuid_xlevel2;

        *VAR_4 = 0;

        *VAR_5 = 0;

        *VAR_6 = 0;

        break;

    case 0xC0000001:

        

        *VAR_3 = VAR_0->cpuid_version;

        *VAR_4 = 0;

        *VAR_5 = 0;

        *VAR_6 = VAR_0->features[FEAT_C000_0001_EDX];

        break;

    case 0xC0000002:

    case 0xC0000003:

    case 0xC0000004:

        

        *VAR_3 = 0;

        *VAR_4 = 0;

        *VAR_5 = 0;

        *VAR_6 = 0;

        break;

    default:

        

        *VAR_3 = 0;

        *VAR_4 = 0;

        *VAR_5 = 0;

        *VAR_6 = 0;

        break;

    }

}

void FUNC_0(CPUX86State *VAR_0, uint32_t VAR_1, uint32_t VAR_2,
uint32_t *VAR_3, uint32_t *VAR_4,
uint32_t *VAR_5, uint32_t *VAR_6)
{ X86CPU *cpu = x86_env_get_cpu(VAR_0); CPUState *cs = CPU(cpu); uint32_t pkg_offset; if (VAR_1 & 0x80000000) { if (VAR_1 > VAR_0->cpuid_xlevel) { if (VAR_0->cpuid_xlevel2 > 0) { if (VAR_1 > VAR_0->cpuid_xlevel2) { VAR_1 = VAR_0->cpuid_xlevel2; } else if (VAR_1 < 0xC0000000) { VAR_1 = VAR_0->cpuid_xlevel; } } else { VAR_1 =  VAR_0->cpuid_level; } } } else { if (VAR_1 > VAR_0->cpuid_level)
VAR_1 = VAR_0->cpuid_level; } switch(VAR_1) { case 0:
*VAR_3 = VAR_0->cpuid_level; *VAR_4 = VAR_0->cpuid_vendor1; *VAR_6 = VAR_0->cpuid_vendor2; *VAR_5 = VAR_0->cpuid_vendor3; break; case 1:
*VAR_3 = VAR_0->cpuid_version; *VAR_4 = (cpu->apic_id << 24) |
8 << 8; *VAR_5 = VAR_0->features[FEAT_1_ECX]; if ((*VAR_5 & CPUID_EXT_XSAVE) && (VAR_0->cr[4] & CR4_OSXSAVE_MASK)) { *VAR_5 |= CPUID_EXT_OSXSAVE; } *VAR_6 = VAR_0->features[FEAT_1_EDX]; if (cs->nr_cores * cs->nr_threads > 1) { *VAR_4 |= (cs->nr_cores * cs->nr_threads) << 16; *VAR_6 |= CPUID_HT; } break; case 2:
if (cpu->cache_info_passthrough) { host_cpuid(VAR_1, 0, VAR_3, VAR_4, VAR_5, VAR_6); break; } *VAR_3 = 1; *VAR_4 = 0; if (!cpu->enable_l3_cache) { *VAR_5 = 0; } else { *VAR_5 = L3_N_DESCRIPTOR; } *VAR_6 = (L1D_DESCRIPTOR << 16) | \
(L1I_DESCRIPTOR <<  8) | \
(L2_DESCRIPTOR); break; case 4:
if (cpu->cache_info_passthrough) { host_cpuid(VAR_1, VAR_2, VAR_3, VAR_4, VAR_5, VAR_6); *VAR_3 &= ~0xFC000000; } else { *VAR_3 = 0; switch (VAR_2) { case 0:
*VAR_3 |= CPUID_4_TYPE_DCACHE | \
CPUID_4_LEVEL(1) | \
CPUID_4_SELF_INIT_LEVEL; *VAR_4 = (L1D_LINE_SIZE - 1) | \
((L1D_PARTITIONS - 1) << 12) | \
((L1D_ASSOCIATIVITY - 1) << 22); *VAR_5 = L1D_SETS - 1; *VAR_6 = CPUID_4_NO_INVD_SHARING; break; case 1:
*VAR_3 |= CPUID_4_TYPE_ICACHE | \
CPUID_4_LEVEL(1) | \
CPUID_4_SELF_INIT_LEVEL; *VAR_4 = (L1I_LINE_SIZE - 1) | \
((L1I_PARTITIONS - 1) << 12) | \
((L1I_ASSOCIATIVITY - 1) << 22); *VAR_5 = L1I_SETS - 1; *VAR_6 = CPUID_4_NO_INVD_SHARING; break; case 2:
*VAR_3 |= CPUID_4_TYPE_UNIFIED | \
CPUID_4_LEVEL(2) | \
CPUID_4_SELF_INIT_LEVEL; if (cs->nr_threads > 1) { *VAR_3 |= (cs->nr_threads - 1) << 14; } *VAR_4 = (L2_LINE_SIZE - 1) | \
((L2_PARTITIONS - 1) << 12) | \
((L2_ASSOCIATIVITY - 1) << 22); *VAR_5 = L2_SETS - 1; *VAR_6 = CPUID_4_NO_INVD_SHARING; break; case 3:
if (!cpu->enable_l3_cache) { *VAR_3 = 0; *VAR_4 = 0; *VAR_5 = 0; *VAR_6 = 0; break; } *VAR_3 |= CPUID_4_TYPE_UNIFIED | \
CPUID_4_LEVEL(3) | \
CPUID_4_SELF_INIT_LEVEL; pkg_offset = apicid_pkg_offset(cs->nr_cores, cs->nr_threads); *VAR_3 |= ((1 << pkg_offset) - 1) << 14; *VAR_4 = (L3_N_LINE_SIZE - 1) | \
((L3_N_PARTITIONS - 1) << 12) | \
((L3_N_ASSOCIATIVITY - 1) << 22); *VAR_5 = L3_N_SETS - 1; *VAR_6 = CPUID_4_INCLUSIVE | CPUID_4_COMPLEX_IDX; break; default:
*VAR_3 = 0; *VAR_4 = 0; *VAR_5 = 0; *VAR_6 = 0; break; } } if ((*VAR_3 & 31) && cs->nr_cores > 1) { *VAR_3 |= (cs->nr_cores - 1) << 26; } break; case 5:
*VAR_3 = 0; *VAR_4 = 0; *VAR_5 = CPUID_MWAIT_EMX | CPUID_MWAIT_IBE; *VAR_6 = 0; break; case 6:
*VAR_3 = VAR_0->features[FEAT_6_EAX]; *VAR_4 = 0; *VAR_5 = 0; *VAR_6 = 0; break; case 7:
if (VAR_2 == 0) { *VAR_3 = 0; *VAR_4 = VAR_0->features[FEAT_7_0_EBX]; *VAR_5 = VAR_0->features[FEAT_7_0_ECX]; if ((*VAR_5 & CPUID_7_0_ECX_PKU) && VAR_0->cr[4] & CR4_PKE_MASK) { *VAR_5 |= CPUID_7_0_ECX_OSPKE; } *VAR_6 = 0; } else { *VAR_3 = 0; *VAR_4 = 0; *VAR_5 = 0; *VAR_6 = 0; } break; case 9:
*VAR_3 = 0; *VAR_4 = 0; *VAR_5 = 0; *VAR_6 = 0; break; case 0xA:
if (kvm_enabled() && cpu->enable_pmu) { KVMState *s = cs->kvm_state; *VAR_3 = kvm_arch_get_supported_cpuid(s, 0xA, VAR_2, R_EAX); *VAR_4 = kvm_arch_get_supported_cpuid(s, 0xA, VAR_2, R_EBX); *VAR_5 = kvm_arch_get_supported_cpuid(s, 0xA, VAR_2, R_ECX); *VAR_6 = kvm_arch_get_supported_cpuid(s, 0xA, VAR_2, R_EDX); } else { *VAR_3 = 0; *VAR_4 = 0; *VAR_5 = 0; *VAR_6 = 0; } break; case 0xB:
if (!cpu->enable_cpuid_0xb) { *VAR_3 = *VAR_4 = *VAR_5 = *VAR_6 = 0; break; } *VAR_5 = VAR_2 & 0xff; *VAR_6 = cpu->apic_id; switch (VAR_2) { case 0:
*VAR_3 = apicid_core_offset(cs->nr_cores, cs->nr_threads); *VAR_4 = cs->nr_threads; *VAR_5 |= CPUID_TOPOLOGY_LEVEL_SMT; break; case 1:
*VAR_3 = apicid_pkg_offset(cs->nr_cores, cs->nr_threads); *VAR_4 = cs->nr_cores * cs->nr_threads; *VAR_5 |= CPUID_TOPOLOGY_LEVEL_CORE; break; default:
*VAR_3 = 0; *VAR_4 = 0; *VAR_5 |= CPUID_TOPOLOGY_LEVEL_INVALID; } assert(!(*VAR_3 & ~0x1f)); *VAR_4 &= 0xffff; break; case 0xD: { KVMState *s = cs->kvm_state; uint64_t ena_mask; int VAR_7; *VAR_3 = 0; *VAR_4 = 0; *VAR_5 = 0; *VAR_6 = 0; if (!(VAR_0->features[FEAT_1_ECX] & CPUID_EXT_XSAVE)) { break; } if (kvm_enabled()) { ena_mask = kvm_arch_get_supported_cpuid(s, 0xd, 0, R_EDX); ena_mask <<= 32; ena_mask |= kvm_arch_get_supported_cpuid(s, 0xd, 0, R_EAX); } else { ena_mask = -1; } if (VAR_2 == 0) { *VAR_5 = 0x240; for (VAR_7 = 2; VAR_7 < ARRAY_SIZE(x86_ext_save_areas); VAR_7++) { const ExtSaveArea *VAR_8 = &x86_ext_save_areas[VAR_7]; if ((VAR_0->features[VAR_8->feature] & VAR_8->bits) == VAR_8->bits
&& ((ena_mask >> VAR_7) & 1) != 0) { if (VAR_7 < 32) { *VAR_3 |= 1u << VAR_7; } else { *VAR_6 |= 1u << (VAR_7 - 32); } *VAR_5 = MAX(*VAR_5, VAR_8->offset + VAR_8->size); } } *VAR_3 |= ena_mask & (XSTATE_FP_MASK | XSTATE_SSE_MASK); *VAR_4 = *VAR_5; } else if (VAR_2 == 1) { *VAR_3 = VAR_0->features[FEAT_XSAVE]; } else if (VAR_2 < ARRAY_SIZE(x86_ext_save_areas)) { const ExtSaveArea *VAR_8 = &x86_ext_save_areas[VAR_2]; if ((VAR_0->features[VAR_8->feature] & VAR_8->bits) == VAR_8->bits
&& ((ena_mask >> VAR_2) & 1) != 0) { *VAR_3 = VAR_8->size; *VAR_4 = VAR_8->offset; } } break; } case 0x80000000:
*VAR_3 = VAR_0->cpuid_xlevel; *VAR_4 = VAR_0->cpuid_vendor1; *VAR_6 = VAR_0->cpuid_vendor2; *VAR_5 = VAR_0->cpuid_vendor3; break; case 0x80000001:
*VAR_3 = VAR_0->cpuid_version; *VAR_4 = 0; *VAR_5 = VAR_0->features[FEAT_8000_0001_ECX]; *VAR_6 = VAR_0->features[FEAT_8000_0001_EDX]; if (cs->nr_cores * cs->nr_threads > 1) { if (VAR_0->cpuid_vendor1 != CPUID_VENDOR_INTEL_1 ||
VAR_0->cpuid_vendor2 != CPUID_VENDOR_INTEL_2 ||
VAR_0->cpuid_vendor3 != CPUID_VENDOR_INTEL_3) { *VAR_5 |= 1 << 1; } } break; case 0x80000002:
case 0x80000003:
case 0x80000004:
*VAR_3 = VAR_0->cpuid_model[(VAR_1 - 0x80000002) * 4 + 0]; *VAR_4 = VAR_0->cpuid_model[(VAR_1 - 0x80000002) * 4 + 1]; *VAR_5 = VAR_0->cpuid_model[(VAR_1 - 0x80000002) * 4 + 2]; *VAR_6 = VAR_0->cpuid_model[(VAR_1 - 0x80000002) * 4 + 3]; break; case 0x80000005:
if (cpu->cache_info_passthrough) { host_cpuid(VAR_1, 0, VAR_3, VAR_4, VAR_5, VAR_6); break; } *VAR_3 = (L1_DTLB_2M_ASSOC << 24) | (L1_DTLB_2M_ENTRIES << 16) | \
(L1_ITLB_2M_ASSOC <<  8) | (L1_ITLB_2M_ENTRIES); *VAR_4 = (L1_DTLB_4K_ASSOC << 24) | (L1_DTLB_4K_ENTRIES << 16) | \
(L1_ITLB_4K_ASSOC <<  8) | (L1_ITLB_4K_ENTRIES); *VAR_5 = (L1D_SIZE_KB_AMD << 24) | (L1D_ASSOCIATIVITY_AMD << 16) | \
(L1D_LINES_PER_TAG << 8) | (L1D_LINE_SIZE); *VAR_6 = (L1I_SIZE_KB_AMD << 24) | (L1I_ASSOCIATIVITY_AMD << 16) | \
(L1I_LINES_PER_TAG << 8) | (L1I_LINE_SIZE); break; case 0x80000006:
if (cpu->cache_info_passthrough) { host_cpuid(VAR_1, 0, VAR_3, VAR_4, VAR_5, VAR_6); break; } *VAR_3 = (AMD_ENC_ASSOC(L2_DTLB_2M_ASSOC) << 28) | \
(L2_DTLB_2M_ENTRIES << 16) | \
(AMD_ENC_ASSOC(L2_ITLB_2M_ASSOC) << 12) | \
(L2_ITLB_2M_ENTRIES); *VAR_4 = (AMD_ENC_ASSOC(L2_DTLB_4K_ASSOC) << 28) | \
(L2_DTLB_4K_ENTRIES << 16) | \
(AMD_ENC_ASSOC(L2_ITLB_4K_ASSOC) << 12) | \
(L2_ITLB_4K_ENTRIES); *VAR_5 = (L2_SIZE_KB_AMD << 16) | \
(AMD_ENC_ASSOC(L2_ASSOCIATIVITY) << 12) | \
(L2_LINES_PER_TAG << 8) | (L2_LINE_SIZE); if (!cpu->enable_l3_cache) { *VAR_6 = ((L3_SIZE_KB / 512) << 18) | \
(AMD_ENC_ASSOC(L3_ASSOCIATIVITY) << 12) | \
(L3_LINES_PER_TAG << 8) | (L3_LINE_SIZE); } else { *VAR_6 = ((L3_N_SIZE_KB_AMD / 512) << 18) | \
(AMD_ENC_ASSOC(L3_N_ASSOCIATIVITY) << 12) | \
(L3_N_LINES_PER_TAG << 8) | (L3_N_LINE_SIZE); } break; case 0x80000007:
*VAR_3 = 0; *VAR_4 = 0; *VAR_5 = 0; *VAR_6 = VAR_0->features[FEAT_8000_0007_EDX]; break; case 0x80000008:
if (VAR_0->features[FEAT_8000_0001_EDX] & CPUID_EXT2_LM) { *VAR_3 = 0x00003000 + cpu->phys_bits; } else { *VAR_3 = cpu->phys_bits; } *VAR_4 = 0; *VAR_5 = 0; *VAR_6 = 0; if (cs->nr_cores * cs->nr_threads > 1) { *VAR_5 |= (cs->nr_cores * cs->nr_threads) - 1; } break; case 0x8000000A:
if (VAR_0->features[FEAT_8000_0001_ECX] & CPUID_EXT3_SVM) { *VAR_3 = 0x00000001; *VAR_4 = 0x00000010; *VAR_5 = 0; *VAR_6 = VAR_0->features[FEAT_SVM]; } else { *VAR_3 = 0; *VAR_4 = 0; *VAR_5 = 0; *VAR_6 = 0; } break; case 0xC0000000:
*VAR_3 = VAR_0->cpuid_xlevel2; *VAR_4 = 0; *VAR_5 = 0; *VAR_6 = 0; break; case 0xC0000001:
*VAR_3 = VAR_0->cpuid_version; *VAR_4 = 0; *VAR_5 = 0; *VAR_6 = VAR_0->features[FEAT_C000_0001_EDX]; break; case 0xC0000002:
case 0xC0000003:
case 0xC0000004:
*VAR_3 = 0; *VAR_4 = 0; *VAR_5 = 0; *VAR_6 = 0; break; default:
*VAR_3 = 0; *VAR_4 = 0; *VAR_5 = 0; *VAR_6 = 0; break; } }