Revision 6d9fef1a
b/target-i386/helper.c | ||
---|---|---|
1638 | 1638 |
#endif |
1639 | 1639 |
} |
1640 | 1640 |
|
1641 |
static void get_cpuid_vendor(CPUX86State *env, uint32_t *ebx, |
|
1642 |
uint32_t *ecx, uint32_t *edx) |
|
1643 |
{ |
|
1644 |
*ebx = env->cpuid_vendor1; |
|
1645 |
*edx = env->cpuid_vendor2; |
|
1646 |
*ecx = env->cpuid_vendor3; |
|
1647 |
|
|
1648 |
/* sysenter isn't supported on compatibility mode on AMD, syscall |
|
1649 |
* isn't supported in compatibility mode on Intel. |
|
1650 |
* Normally we advertise the actual cpu vendor, but you can override |
|
1651 |
* this if you want to use KVM's sysenter/syscall emulation |
|
1652 |
* in compatibility mode and when doing cross vendor migration |
|
1653 |
*/ |
|
1654 |
if (kvm_enabled() && env->cpuid_vendor_override) { |
|
1655 |
host_cpuid(0, 0, NULL, ebx, ecx, edx); |
|
1656 |
} |
|
1657 |
} |
|
1658 |
|
|
1641 | 1659 |
void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count, |
1642 | 1660 |
uint32_t *eax, uint32_t *ebx, |
1643 | 1661 |
uint32_t *ecx, uint32_t *edx) |
... | ... | |
1654 | 1672 |
switch(index) { |
1655 | 1673 |
case 0: |
1656 | 1674 |
*eax = env->cpuid_level; |
1657 |
*ebx = env->cpuid_vendor1; |
|
1658 |
*edx = env->cpuid_vendor2; |
|
1659 |
*ecx = env->cpuid_vendor3; |
|
1660 |
|
|
1661 |
/* sysenter isn't supported on compatibility mode on AMD. and syscall |
|
1662 |
* isn't supported in compatibility mode on Intel. so advertise the |
|
1663 |
* actuall cpu, and say goodbye to migration between different vendors |
|
1664 |
* is you use compatibility mode. */ |
|
1665 |
if (kvm_enabled() && !env->cpuid_vendor_override) |
|
1666 |
host_cpuid(0, 0, NULL, ebx, ecx, edx); |
|
1675 |
get_cpuid_vendor(env, ebx, ecx, edx); |
|
1667 | 1676 |
break; |
1668 | 1677 |
case 1: |
1669 | 1678 |
*eax = env->cpuid_version; |
... | ... | |
1759 | 1768 |
*ecx = env->cpuid_ext3_features; |
1760 | 1769 |
*edx = env->cpuid_ext2_features; |
1761 | 1770 |
|
1762 |
if (env->nr_cores * env->nr_threads > 1 && |
|
1763 |
env->cpuid_vendor1 == CPUID_VENDOR_AMD_1 && |
|
1764 |
env->cpuid_vendor2 == CPUID_VENDOR_AMD_2 && |
|
1765 |
env->cpuid_vendor3 == CPUID_VENDOR_AMD_3) { |
|
1766 |
*ecx |= 1 << 1; /* CmpLegacy bit */ |
|
1771 |
/* The Linux kernel checks for the CMPLegacy bit and |
|
1772 |
* discards multiple thread information if it is set. |
|
1773 |
* So dont set it here for Intel to make Linux guests happy. |
|
1774 |
*/ |
|
1775 |
if (env->nr_cores * env->nr_threads > 1) { |
|
1776 |
uint32_t tebx, tecx, tedx; |
|
1777 |
get_cpuid_vendor(env, &tebx, &tecx, &tedx); |
|
1778 |
if (tebx != CPUID_VENDOR_INTEL_1 || |
|
1779 |
tedx != CPUID_VENDOR_INTEL_2 || |
|
1780 |
tecx != CPUID_VENDOR_INTEL_3) { |
|
1781 |
*ecx |= 1 << 1; /* CmpLegacy bit */ |
|
1782 |
} |
|
1767 | 1783 |
} |
1768 | 1784 |
|
1769 | 1785 |
if (kvm_enabled()) { |
Also available in: Unified diff