diff options
Diffstat (limited to 'target-i386/cpu.c')
-rw-r--r-- | target-i386/cpu.c | 500 |
1 files changed, 303 insertions, 197 deletions
diff --git a/target-i386/cpu.c b/target-i386/cpu.c index 423e00905..f3708e63b 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -61,15 +61,19 @@ static const char *ext_feature_name[] = { "tsc-deadline", "aes", "xsave", "osxsave", "avx", NULL, NULL, "hypervisor", }; +/* Feature names that are already defined on feature_name[] but are set on + * CPUID[8000_0001].EDX on AMD CPUs don't have their names on + * ext2_feature_name[]. They are copied automatically to cpuid_ext2_features + * if and only if CPU vendor is AMD. + */ static const char *ext2_feature_name[] = { - "fpu", "vme", "de", "pse", - "tsc", "msr", "pae", "mce", - "cx8" /* AMD CMPXCHG8B */, "apic", NULL, "syscall", - "mtrr", "pge", "mca", "cmov", - "pat", "pse36", NULL, NULL /* Linux mp */, - "nx|xd", NULL, "mmxext", "mmx", - "fxsr", "fxsr_opt|ffxsr", "pdpe1gb" /* AMD Page1GB */, "rdtscp", - NULL, "lm|i64", "3dnowext", "3dnow", + NULL /* fpu */, NULL /* vme */, NULL /* de */, NULL /* pse */, + NULL /* tsc */, NULL /* msr */, NULL /* pae */, NULL /* mce */, + NULL /* cx8 */ /* AMD CMPXCHG8B */, NULL /* apic */, NULL, "syscall", + NULL /* mtrr */, NULL /* pge */, NULL /* mca */, NULL /* cmov */, + NULL /* pat */, NULL /* pse36 */, NULL, NULL /* Linux mp */, + "nx|xd", NULL, "mmxext", NULL /* mmx */, + NULL /* fxsr */, "fxsr_opt|ffxsr", "pdpe1gb" /* AMD Page1GB */, "rdtscp", }; static const char *ext3_feature_name[] = { "lahf_lm" /* AMD LahfSahf */, "cmp_legacy", "svm", "extapic" /* AMD ExtApicSpace */, @@ -100,6 +104,13 @@ static const char *svm_feature_name[] = { NULL, NULL, NULL, NULL, }; +static const char *cpuid_7_0_ebx_feature_name[] = { + NULL, NULL, NULL, NULL, NULL, NULL, NULL, "smep", + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "smap", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +}; + /* collects per-function cpuid data */ typedef struct model_features_t { @@ -215,14 +226,17 @@ static void add_flagname_to_bitmaps(const char *flagname, uint32_t *features, uint32_t *ext2_features, uint32_t *ext3_features, uint32_t *kvm_features, - uint32_t *svm_features) + uint32_t *svm_features, + uint32_t *cpuid_7_0_ebx_features) { if (!lookup_feature(features, flagname, NULL, feature_name) && !lookup_feature(ext_features, flagname, NULL, ext_feature_name) && !lookup_feature(ext2_features, flagname, NULL, ext2_feature_name) && !lookup_feature(ext3_features, flagname, NULL, ext3_feature_name) && !lookup_feature(kvm_features, flagname, NULL, kvm_feature_name) && - !lookup_feature(svm_features, flagname, NULL, svm_feature_name)) + !lookup_feature(svm_features, flagname, NULL, svm_feature_name) && + !lookup_feature(cpuid_7_0_ebx_features, flagname, NULL, + cpuid_7_0_ebx_feature_name)) fprintf(stderr, "CPU feature %s not found\n", flagname); } @@ -240,7 +254,6 @@ typedef struct x86_def_t { uint32_t xlevel; char model_id[48]; int vendor_override; - uint32_t flags; /* Store the results of Centaur's CPUID instructions */ uint32_t ext4_features; uint32_t xlevel2; @@ -259,7 +272,6 @@ typedef struct x86_def_t { CPUID_MSR | CPUID_MCE | CPUID_CX8 | CPUID_PGE | CPUID_CMOV | \ CPUID_PAT | CPUID_FXSR | CPUID_MMX | CPUID_SSE | CPUID_SSE2 | \ CPUID_PAE | CPUID_SEP | CPUID_APIC) -#define EXT2_FEATURE_MASK 0x0183F3FF #define TCG_FEATURES (CPUID_FP87 | CPUID_PSE | CPUID_TSC | CPUID_MSR | \ CPUID_PAE | CPUID_MCE | CPUID_CX8 | CPUID_APIC | CPUID_SEP | \ @@ -277,7 +289,7 @@ typedef struct x86_def_t { /* missing: CPUID_EXT_DTES64, CPUID_EXT_DSCPL, CPUID_EXT_VMX, CPUID_EXT_EST, CPUID_EXT_TM2, CPUID_EXT_XTPR, CPUID_EXT_PDCM, CPUID_EXT_XSAVE */ -#define TCG_EXT2_FEATURES ((TCG_FEATURES & EXT2_FEATURE_MASK) | \ +#define TCG_EXT2_FEATURES ((TCG_FEATURES & CPUID_EXT2_AMD_ALIASES) | \ CPUID_EXT2_NX | CPUID_EXT2_MMXEXT | CPUID_EXT2_RDTSCP | \ CPUID_EXT2_3DNOW | CPUID_EXT2_3DNOWEXT) /* missing: @@ -285,6 +297,7 @@ typedef struct x86_def_t { #define TCG_EXT3_FEATURES (CPUID_EXT3_LAHF_LM | CPUID_EXT3_SVM | \ CPUID_EXT3_CR8LEG | CPUID_EXT3_ABM | CPUID_EXT3_SSE4A) #define TCG_SVM_FEATURES 0 +#define TCG_7_0_EBX_FEATURES (CPUID_7_0_EBX_SMEP | CPUID_7_0_EBX_SMAP) /* maintains list of cpu model definitions */ @@ -306,7 +319,7 @@ static x86_def_t builtin_x86_defs[] = { CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA | CPUID_PSE36, .ext_features = CPUID_EXT_SSE3 | CPUID_EXT_CX16 | CPUID_EXT_POPCNT, - .ext2_features = (PPRO_FEATURES & EXT2_FEATURE_MASK) | + .ext2_features = (PPRO_FEATURES & CPUID_EXT2_AMD_ALIASES) | CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX, .ext3_features = CPUID_EXT3_LAHF_LM | CPUID_EXT3_SVM | CPUID_EXT3_ABM | CPUID_EXT3_SSE4A, @@ -326,7 +339,7 @@ static x86_def_t builtin_x86_defs[] = { CPUID_PSE36 | CPUID_VME | CPUID_HT, .ext_features = CPUID_EXT_SSE3 | CPUID_EXT_MONITOR | CPUID_EXT_CX16 | CPUID_EXT_POPCNT, - .ext2_features = (PPRO_FEATURES & EXT2_FEATURE_MASK) | + .ext2_features = (PPRO_FEATURES & CPUID_EXT2_AMD_ALIASES) | CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX | CPUID_EXT2_3DNOW | CPUID_EXT2_3DNOWEXT | CPUID_EXT2_MMXEXT | CPUID_EXT2_FFXSR | CPUID_EXT2_PDPE1GB | CPUID_EXT2_RDTSCP, @@ -374,7 +387,7 @@ static x86_def_t builtin_x86_defs[] = { /* Missing: CPUID_EXT_POPCNT, CPUID_EXT_MONITOR */ .ext_features = CPUID_EXT_SSE3 | CPUID_EXT_CX16, /* Missing: CPUID_EXT2_PDPE1GB, CPUID_EXT2_RDTSCP */ - .ext2_features = (PPRO_FEATURES & EXT2_FEATURE_MASK) | + .ext2_features = (PPRO_FEATURES & CPUID_EXT2_AMD_ALIASES) | CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX, /* Missing: CPUID_EXT3_LAHF_LM, CPUID_EXT3_CMP_LEG, CPUID_EXT3_EXTAPIC, CPUID_EXT3_CR8LEG, CPUID_EXT3_ABM, CPUID_EXT3_SSE4A, @@ -403,7 +416,7 @@ static x86_def_t builtin_x86_defs[] = { .features = PPRO_FEATURES | CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA | CPUID_PSE36, .ext_features = CPUID_EXT_SSE3, - .ext2_features = PPRO_FEATURES & EXT2_FEATURE_MASK, + .ext2_features = PPRO_FEATURES & CPUID_EXT2_AMD_ALIASES, .ext3_features = 0, .xlevel = 0x80000008, .model_id = "Common 32-bit KVM processor" @@ -468,8 +481,10 @@ static x86_def_t builtin_x86_defs[] = { .family = 6, .model = 2, .stepping = 3, - .features = PPRO_FEATURES | CPUID_PSE36 | CPUID_VME | CPUID_MTRR | CPUID_MCA, - .ext2_features = (PPRO_FEATURES & EXT2_FEATURE_MASK) | CPUID_EXT2_MMXEXT | CPUID_EXT2_3DNOW | CPUID_EXT2_3DNOWEXT, + .features = PPRO_FEATURES | CPUID_PSE36 | CPUID_VME | CPUID_MTRR | + CPUID_MCA, + .ext2_features = (PPRO_FEATURES & CPUID_EXT2_AMD_ALIASES) | + CPUID_EXT2_MMXEXT | CPUID_EXT2_3DNOW | CPUID_EXT2_3DNOWEXT, .xlevel = 0x80000008, }, { @@ -485,11 +500,231 @@ static x86_def_t builtin_x86_defs[] = { /* Some CPUs got no CPUID_SEP */ .ext_features = CPUID_EXT_SSE3 | CPUID_EXT_MONITOR | CPUID_EXT_SSSE3 | CPUID_EXT_DSCPL | CPUID_EXT_EST | CPUID_EXT_TM2 | CPUID_EXT_XTPR, - .ext2_features = (PPRO_FEATURES & EXT2_FEATURE_MASK) | CPUID_EXT2_NX, + .ext2_features = (PPRO_FEATURES & CPUID_EXT2_AMD_ALIASES) | + CPUID_EXT2_NX, .ext3_features = CPUID_EXT3_LAHF_LM, .xlevel = 0x8000000A, .model_id = "Intel(R) Atom(TM) CPU N270 @ 1.60GHz", }, + { + .name = "Conroe", + .level = 2, + .vendor1 = CPUID_VENDOR_INTEL_1, + .vendor2 = CPUID_VENDOR_INTEL_2, + .vendor3 = CPUID_VENDOR_INTEL_3, + .family = 6, + .model = 2, + .stepping = 3, + .features = CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX | + CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA | + CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 | + CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE | + CPUID_DE | CPUID_FP87, + .ext_features = CPUID_EXT_SSSE3 | CPUID_EXT_SSE3, + .ext2_features = CPUID_EXT2_LM | CPUID_EXT2_NX | CPUID_EXT2_SYSCALL, + .ext3_features = CPUID_EXT3_LAHF_LM, + .xlevel = 0x8000000A, + .model_id = "Intel Celeron_4x0 (Conroe/Merom Class Core 2)", + }, + { + .name = "Penryn", + .level = 2, + .vendor1 = CPUID_VENDOR_INTEL_1, + .vendor2 = CPUID_VENDOR_INTEL_2, + .vendor3 = CPUID_VENDOR_INTEL_3, + .family = 6, + .model = 2, + .stepping = 3, + .features = CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX | + CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA | + CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 | + CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE | + CPUID_DE | CPUID_FP87, + .ext_features = CPUID_EXT_SSE41 | CPUID_EXT_CX16 | CPUID_EXT_SSSE3 | + CPUID_EXT_SSE3, + .ext2_features = CPUID_EXT2_LM | CPUID_EXT2_NX | CPUID_EXT2_SYSCALL, + .ext3_features = CPUID_EXT3_LAHF_LM, + .xlevel = 0x8000000A, + .model_id = "Intel Core 2 Duo P9xxx (Penryn Class Core 2)", + }, + { + .name = "Nehalem", + .level = 2, + .vendor1 = CPUID_VENDOR_INTEL_1, + .vendor2 = CPUID_VENDOR_INTEL_2, + .vendor3 = CPUID_VENDOR_INTEL_3, + .family = 6, + .model = 2, + .stepping = 3, + .features = CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX | + CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA | + CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 | + CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE | + CPUID_DE | CPUID_FP87, + .ext_features = CPUID_EXT_POPCNT | CPUID_EXT_SSE42 | CPUID_EXT_SSE41 | + CPUID_EXT_CX16 | CPUID_EXT_SSSE3 | CPUID_EXT_SSE3, + .ext2_features = CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX, + .ext3_features = CPUID_EXT3_LAHF_LM, + .xlevel = 0x8000000A, + .model_id = "Intel Core i7 9xx (Nehalem Class Core i7)", + }, + { + .name = "Westmere", + .level = 11, + .vendor1 = CPUID_VENDOR_INTEL_1, + .vendor2 = CPUID_VENDOR_INTEL_2, + .vendor3 = CPUID_VENDOR_INTEL_3, + .family = 6, + .model = 44, + .stepping = 1, + .features = CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX | + CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA | + CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 | + CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE | + CPUID_DE | CPUID_FP87, + .ext_features = CPUID_EXT_AES | CPUID_EXT_POPCNT | CPUID_EXT_SSE42 | + CPUID_EXT_SSE41 | CPUID_EXT_CX16 | CPUID_EXT_SSSE3 | + CPUID_EXT_SSE3, + .ext2_features = CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX, + .ext3_features = CPUID_EXT3_LAHF_LM, + .xlevel = 0x8000000A, + .model_id = "Westmere E56xx/L56xx/X56xx (Nehalem-C)", + }, + { + .name = "SandyBridge", + .level = 0xd, + .vendor1 = CPUID_VENDOR_INTEL_1, + .vendor2 = CPUID_VENDOR_INTEL_2, + .vendor3 = CPUID_VENDOR_INTEL_3, + .family = 6, + .model = 42, + .stepping = 1, + .features = CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX | + CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA | + CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 | + CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE | + CPUID_DE | CPUID_FP87, + .ext_features = CPUID_EXT_AVX | CPUID_EXT_XSAVE | CPUID_EXT_AES | + CPUID_EXT_TSC_DEADLINE_TIMER | CPUID_EXT_POPCNT | + CPUID_EXT_X2APIC | CPUID_EXT_SSE42 | CPUID_EXT_SSE41 | + CPUID_EXT_CX16 | CPUID_EXT_SSSE3 | CPUID_EXT_PCLMULQDQ | + CPUID_EXT_SSE3, + .ext2_features = CPUID_EXT2_LM | CPUID_EXT2_RDTSCP | CPUID_EXT2_NX | + CPUID_EXT2_SYSCALL, + .ext3_features = CPUID_EXT3_LAHF_LM, + .xlevel = 0x8000000A, + .model_id = "Intel Xeon E312xx (Sandy Bridge)", + }, + { + .name = "Opteron_G1", + .level = 5, + .vendor1 = CPUID_VENDOR_AMD_1, + .vendor2 = CPUID_VENDOR_AMD_2, + .vendor3 = CPUID_VENDOR_AMD_3, + .family = 15, + .model = 6, + .stepping = 1, + .features = CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX | + CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA | + CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 | + CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE | + CPUID_DE | CPUID_FP87, + .ext_features = CPUID_EXT_SSE3, + .ext2_features = CPUID_EXT2_LM | CPUID_EXT2_FXSR | CPUID_EXT2_MMX | + CPUID_EXT2_NX | CPUID_EXT2_PSE36 | CPUID_EXT2_PAT | + CPUID_EXT2_CMOV | CPUID_EXT2_MCA | CPUID_EXT2_PGE | + CPUID_EXT2_MTRR | CPUID_EXT2_SYSCALL | CPUID_EXT2_APIC | + CPUID_EXT2_CX8 | CPUID_EXT2_MCE | CPUID_EXT2_PAE | CPUID_EXT2_MSR | + CPUID_EXT2_TSC | CPUID_EXT2_PSE | CPUID_EXT2_DE | CPUID_EXT2_FPU, + .xlevel = 0x80000008, + .model_id = "AMD Opteron 240 (Gen 1 Class Opteron)", + }, + { + .name = "Opteron_G2", + .level = 5, + .vendor1 = CPUID_VENDOR_AMD_1, + .vendor2 = CPUID_VENDOR_AMD_2, + .vendor3 = CPUID_VENDOR_AMD_3, + .family = 15, + .model = 6, + .stepping = 1, + .features = CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX | + CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA | + CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 | + CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE | + CPUID_DE | CPUID_FP87, + .ext_features = CPUID_EXT_CX16 | CPUID_EXT_SSE3, + .ext2_features = CPUID_EXT2_LM | CPUID_EXT2_RDTSCP | CPUID_EXT2_FXSR | + CPUID_EXT2_MMX | CPUID_EXT2_NX | CPUID_EXT2_PSE36 | + CPUID_EXT2_PAT | CPUID_EXT2_CMOV | CPUID_EXT2_MCA | + CPUID_EXT2_PGE | CPUID_EXT2_MTRR | CPUID_EXT2_SYSCALL | + CPUID_EXT2_APIC | CPUID_EXT2_CX8 | CPUID_EXT2_MCE | + CPUID_EXT2_PAE | CPUID_EXT2_MSR | CPUID_EXT2_TSC | CPUID_EXT2_PSE | + CPUID_EXT2_DE | CPUID_EXT2_FPU, + .ext3_features = CPUID_EXT3_SVM | CPUID_EXT3_LAHF_LM, + .xlevel = 0x80000008, + .model_id = "AMD Opteron 22xx (Gen 2 Class Opteron)", + }, + { + .name = "Opteron_G3", + .level = 5, + .vendor1 = CPUID_VENDOR_AMD_1, + .vendor2 = CPUID_VENDOR_AMD_2, + .vendor3 = CPUID_VENDOR_AMD_3, + .family = 15, + .model = 6, + .stepping = 1, + .features = CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX | + CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA | + CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 | + CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE | + CPUID_DE | CPUID_FP87, + .ext_features = CPUID_EXT_POPCNT | CPUID_EXT_CX16 | CPUID_EXT_MONITOR | + CPUID_EXT_SSE3, + .ext2_features = CPUID_EXT2_LM | CPUID_EXT2_RDTSCP | CPUID_EXT2_FXSR | + CPUID_EXT2_MMX | CPUID_EXT2_NX | CPUID_EXT2_PSE36 | + CPUID_EXT2_PAT | CPUID_EXT2_CMOV | CPUID_EXT2_MCA | + CPUID_EXT2_PGE | CPUID_EXT2_MTRR | CPUID_EXT2_SYSCALL | + CPUID_EXT2_APIC | CPUID_EXT2_CX8 | CPUID_EXT2_MCE | + CPUID_EXT2_PAE | CPUID_EXT2_MSR | CPUID_EXT2_TSC | CPUID_EXT2_PSE | + CPUID_EXT2_DE | CPUID_EXT2_FPU, + .ext3_features = CPUID_EXT3_MISALIGNSSE | CPUID_EXT3_SSE4A | + CPUID_EXT3_ABM | CPUID_EXT3_SVM | CPUID_EXT3_LAHF_LM, + .xlevel = 0x80000008, + .model_id = "AMD Opteron 23xx (Gen 3 Class Opteron)", + }, + { + .name = "Opteron_G4", + .level = 0xd, + .vendor1 = CPUID_VENDOR_AMD_1, + .vendor2 = CPUID_VENDOR_AMD_2, + .vendor3 = CPUID_VENDOR_AMD_3, + .family = 21, + .model = 1, + .stepping = 2, + .features = CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX | + CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA | + CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 | + CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE | + CPUID_DE | CPUID_FP87, + .ext_features = CPUID_EXT_AVX | CPUID_EXT_XSAVE | CPUID_EXT_AES | + CPUID_EXT_POPCNT | CPUID_EXT_SSE42 | CPUID_EXT_SSE41 | + CPUID_EXT_CX16 | CPUID_EXT_SSSE3 | CPUID_EXT_PCLMULQDQ | + CPUID_EXT_SSE3, + .ext2_features = CPUID_EXT2_LM | CPUID_EXT2_RDTSCP | + CPUID_EXT2_PDPE1GB | CPUID_EXT2_FXSR | CPUID_EXT2_MMX | + CPUID_EXT2_NX | CPUID_EXT2_PSE36 | CPUID_EXT2_PAT | + CPUID_EXT2_CMOV | CPUID_EXT2_MCA | CPUID_EXT2_PGE | + CPUID_EXT2_MTRR | CPUID_EXT2_SYSCALL | CPUID_EXT2_APIC | + CPUID_EXT2_CX8 | CPUID_EXT2_MCE | CPUID_EXT2_PAE | CPUID_EXT2_MSR | + CPUID_EXT2_TSC | CPUID_EXT2_PSE | CPUID_EXT2_DE | CPUID_EXT2_FPU, + .ext3_features = CPUID_EXT3_FMA4 | CPUID_EXT3_XOP | + CPUID_EXT3_3DNOWPREFETCH | CPUID_EXT3_MISALIGNSSE | + CPUID_EXT3_SSE4A | CPUID_EXT3_ABM | CPUID_EXT3_SVM | + CPUID_EXT3_LAHF_LM, + .xlevel = 0x8000001A, + .model_id = "AMD Opteron 62xx class CPU", + }, }; static int cpu_x86_fill_model_id(char *str) @@ -846,7 +1081,7 @@ static void x86_cpuid_set_tsc_freq(Object *obj, Visitor *v, void *opaque, { X86CPU *cpu = X86_CPU(obj); const int64_t min = 0; - const int64_t max = INT_MAX; + const int64_t max = INT64_MAX; int64_t value; visit_type_int(v, &value, name, errp); @@ -873,10 +1108,12 @@ static int cpu_x86_find_by_name(x86_def_t *x86_cpu_def, const char *cpu_model) uint32_t plus_features = 0, plus_ext_features = 0; uint32_t plus_ext2_features = 0, plus_ext3_features = 0; uint32_t plus_kvm_features = 0, plus_svm_features = 0; + uint32_t plus_7_0_ebx_features = 0; /* Features to be removed */ uint32_t minus_features = 0, minus_ext_features = 0; uint32_t minus_ext2_features = 0, minus_ext3_features = 0; uint32_t minus_kvm_features = 0, minus_svm_features = 0; + uint32_t minus_7_0_ebx_features = 0; uint32_t numvalue; for (def = x86_defs; def; def = def->next) @@ -903,8 +1140,8 @@ static int cpu_x86_find_by_name(x86_def_t *x86_cpu_def, const char *cpu_model) #endif add_flagname_to_bitmaps("hypervisor", &plus_features, - &plus_ext_features, &plus_ext2_features, &plus_ext3_features, - &plus_kvm_features, &plus_svm_features); + &plus_ext_features, &plus_ext2_features, &plus_ext3_features, + &plus_kvm_features, &plus_svm_features, &plus_7_0_ebx_features); featurestr = strtok(NULL, ","); @@ -914,12 +1151,12 @@ static int cpu_x86_find_by_name(x86_def_t *x86_cpu_def, const char *cpu_model) add_flagname_to_bitmaps(featurestr + 1, &plus_features, &plus_ext_features, &plus_ext2_features, &plus_ext3_features, &plus_kvm_features, - &plus_svm_features); + &plus_svm_features, &plus_7_0_ebx_features); } else if (featurestr[0] == '-') { add_flagname_to_bitmaps(featurestr + 1, &minus_features, &minus_ext_features, &minus_ext2_features, &minus_ext3_features, &minus_kvm_features, - &minus_svm_features); + &minus_svm_features, &minus_7_0_ebx_features); } else if ((val = strchr(featurestr, '='))) { *val = 0; val++; if (!strcmp(featurestr, "family")) { @@ -1025,16 +1262,21 @@ static int cpu_x86_find_by_name(x86_def_t *x86_cpu_def, const char *cpu_model) x86_cpu_def->ext3_features |= plus_ext3_features; x86_cpu_def->kvm_features |= plus_kvm_features; x86_cpu_def->svm_features |= plus_svm_features; + x86_cpu_def->cpuid_7_0_ebx_features |= plus_7_0_ebx_features; x86_cpu_def->features &= ~minus_features; x86_cpu_def->ext_features &= ~minus_ext_features; x86_cpu_def->ext2_features &= ~minus_ext2_features; x86_cpu_def->ext3_features &= ~minus_ext3_features; x86_cpu_def->kvm_features &= ~minus_kvm_features; x86_cpu_def->svm_features &= ~minus_svm_features; + x86_cpu_def->cpuid_7_0_ebx_features &= ~minus_7_0_ebx_features; if (check_cpuid) { if (check_features_against_host(x86_cpu_def) && enforce_cpuid) goto error; } + if (x86_cpu_def->cpuid_7_0_ebx_features && x86_cpu_def->level < 7) { + x86_cpu_def->level = 7; + } g_free(s); return 0; @@ -1073,70 +1315,28 @@ static void listflags(char *buf, int bufsize, uint32_t fbits, } } -/* generate CPU information: - * -? list model names - * -?model list model names/IDs - * -?dump output all model (x86_def_t) data - * -?cpuid list all recognized cpuid flag names - */ -void x86_cpu_list(FILE *f, fprintf_function cpu_fprintf, const char *optarg) +/* generate CPU information. */ +void x86_cpu_list(FILE *f, fprintf_function cpu_fprintf) { - unsigned char model = !strcmp("?model", optarg); - unsigned char dump = !strcmp("?dump", optarg); - unsigned char cpuid = !strcmp("?cpuid", optarg); x86_def_t *def; char buf[256]; - if (cpuid) { - (*cpu_fprintf)(f, "Recognized CPUID flags:\n"); - listflags(buf, sizeof (buf), (uint32_t)~0, feature_name, 1); - (*cpu_fprintf)(f, " f_edx: %s\n", buf); - listflags(buf, sizeof (buf), (uint32_t)~0, ext_feature_name, 1); - (*cpu_fprintf)(f, " f_ecx: %s\n", buf); - listflags(buf, sizeof (buf), (uint32_t)~0, ext2_feature_name, 1); - (*cpu_fprintf)(f, " extf_edx: %s\n", buf); - listflags(buf, sizeof (buf), (uint32_t)~0, ext3_feature_name, 1); - (*cpu_fprintf)(f, " extf_ecx: %s\n", buf); - return; - } for (def = x86_defs; def; def = def->next) { - snprintf(buf, sizeof (buf), def->flags ? "[%s]": "%s", def->name); - if (model || dump) { - (*cpu_fprintf)(f, "x86 %16s %-48s\n", buf, def->model_id); - } else { - (*cpu_fprintf)(f, "x86 %16s\n", buf); - } - if (dump) { - memcpy(buf, &def->vendor1, sizeof (def->vendor1)); - memcpy(buf + 4, &def->vendor2, sizeof (def->vendor2)); - memcpy(buf + 8, &def->vendor3, sizeof (def->vendor3)); - buf[12] = '\0'; - (*cpu_fprintf)(f, - " family %d model %d stepping %d level %d xlevel 0x%x" - " vendor \"%s\"\n", - def->family, def->model, def->stepping, def->level, - def->xlevel, buf); - listflags(buf, sizeof (buf), def->features, feature_name, 0); - (*cpu_fprintf)(f, " feature_edx %08x (%s)\n", def->features, - buf); - listflags(buf, sizeof (buf), def->ext_features, ext_feature_name, - 0); - (*cpu_fprintf)(f, " feature_ecx %08x (%s)\n", def->ext_features, - buf); - listflags(buf, sizeof (buf), def->ext2_features, ext2_feature_name, - 0); - (*cpu_fprintf)(f, " extfeature_edx %08x (%s)\n", - def->ext2_features, buf); - listflags(buf, sizeof (buf), def->ext3_features, ext3_feature_name, - 0); - (*cpu_fprintf)(f, " extfeature_ecx %08x (%s)\n", - def->ext3_features, buf); - (*cpu_fprintf)(f, "\n"); - } + snprintf(buf, sizeof(buf), "%s", def->name); + (*cpu_fprintf)(f, "x86 %16s %-48s\n", buf, def->model_id); } if (kvm_enabled()) { (*cpu_fprintf)(f, "x86 %16s\n", "[host]"); } + (*cpu_fprintf)(f, "\nRecognized CPUID flags:\n"); + listflags(buf, sizeof(buf), (uint32_t)~0, feature_name, 1); + (*cpu_fprintf)(f, " %s\n", buf); + listflags(buf, sizeof(buf), (uint32_t)~0, ext_feature_name, 1); + (*cpu_fprintf)(f, " %s\n", buf); + listflags(buf, sizeof(buf), (uint32_t)~0, ext2_feature_name, 1); + (*cpu_fprintf)(f, " %s\n", buf); + listflags(buf, sizeof(buf), (uint32_t)~0, ext3_feature_name, 1); + (*cpu_fprintf)(f, " %s\n", buf); } CpuDefinitionInfoList *arch_query_cpu_definitions(Error **errp) @@ -1192,10 +1392,21 @@ int cpu_x86_register(X86CPU *cpu, const char *cpu_model) env->cpuid_kvm_features = def->kvm_features; env->cpuid_svm_features = def->svm_features; env->cpuid_ext4_features = def->ext4_features; - env->cpuid_7_0_ebx = def->cpuid_7_0_ebx_features; + env->cpuid_7_0_ebx_features = def->cpuid_7_0_ebx_features; env->cpuid_xlevel2 = def->xlevel2; object_property_set_int(OBJECT(cpu), (int64_t)def->tsc_khz * 1000, "tsc-frequency", &error); + + /* On AMD CPUs, some CPUID[8000_0001].EDX bits must match the bits on + * CPUID[1].EDX. + */ + if (env->cpuid_vendor1 == CPUID_VENDOR_AMD_1 && + env->cpuid_vendor2 == CPUID_VENDOR_AMD_2 && + env->cpuid_vendor3 == CPUID_VENDOR_AMD_3) { + env->cpuid_ext2_features &= ~CPUID_EXT2_AMD_ALIASES; + env->cpuid_ext2_features |= (def->features & CPUID_EXT2_AMD_ALIASES); + } + if (!kvm_enabled()) { env->cpuid_features &= TCG_FEATURES; env->cpuid_ext_features &= TCG_EXT_FEATURES; @@ -1216,109 +1427,6 @@ int cpu_x86_register(X86CPU *cpu, const char *cpu_model) } #if !defined(CONFIG_USER_ONLY) -/* copy vendor id string to 32 bit register, nul pad as needed - */ -static void cpyid(const char *s, uint32_t *id) -{ - char *d = (char *)id; - char i; - - for (i = sizeof (*id); i--; ) - *d++ = *s ? *s++ : '\0'; -} - -/* interpret radix and convert from string to arbitrary scalar, - * otherwise flag failure - */ -#define setscalar(pval, str, perr) \ -{ \ - char *pend; \ - unsigned long ul; \ - \ - ul = strtoul(str, &pend, 0); \ - *str && !*pend ? (*pval = ul) : (*perr = 1); \ -} - -/* map cpuid options to feature bits, otherwise return failure - * (option tags in *str are delimited by whitespace) - */ -static void setfeatures(uint32_t *pval, const char *str, - const char **featureset, int *perr) -{ - const char *p, *q; - - for (q = p = str; *p || *q; q = p) { - while (iswhite(*p)) - q = ++p; - while (*p && !iswhite(*p)) - ++p; - if (!*q && !*p) - return; - if (!lookup_feature(pval, q, p, featureset)) { - fprintf(stderr, "error: feature \"%.*s\" not available in set\n", - (int)(p - q), q); - *perr = 1; - return; - } - } -} - -/* map config file options to x86_def_t form - */ -static int cpudef_setfield(const char *name, const char *str, void *opaque) -{ - x86_def_t *def = opaque; - int err = 0; - - if (!strcmp(name, "name")) { - g_free((void *)def->name); - def->name = g_strdup(str); - } else if (!strcmp(name, "model_id")) { - strncpy(def->model_id, str, sizeof (def->model_id)); - } else if (!strcmp(name, "level")) { - setscalar(&def->level, str, &err) - } else if (!strcmp(name, "vendor")) { - cpyid(&str[0], &def->vendor1); - cpyid(&str[4], &def->vendor2); - cpyid(&str[8], &def->vendor3); - } else if (!strcmp(name, "family")) { - setscalar(&def->family, str, &err) - } else if (!strcmp(name, "model")) { - setscalar(&def->model, str, &err) - } else if (!strcmp(name, "stepping")) { - setscalar(&def->stepping, str, &err) - } else if (!strcmp(name, "feature_edx")) { - setfeatures(&def->features, str, feature_name, &err); - } else if (!strcmp(name, "feature_ecx")) { - setfeatures(&def->ext_features, str, ext_feature_name, &err); - } else if (!strcmp(name, "extfeature_edx")) { - setfeatures(&def->ext2_features, str, ext2_feature_name, &err); - } else if (!strcmp(name, "extfeature_ecx")) { - setfeatures(&def->ext3_features, str, ext3_feature_name, &err); - } else if (!strcmp(name, "xlevel")) { - setscalar(&def->xlevel, str, &err) - } else { - fprintf(stderr, "error: unknown option [%s = %s]\n", name, str); - return (1); - } - if (err) { - fprintf(stderr, "error: bad option value [%s = %s]\n", name, str); - return (1); - } - return (0); -} - -/* register config file entry as x86_def_t - */ -static int cpudef_register(QemuOpts *opts, void *opaque) -{ - x86_def_t *def = g_malloc0(sizeof (x86_def_t)); - - qemu_opt_foreach(opts, cpudef_setfield, def, 1); - def->next = x86_defs; - x86_defs = def; - return (0); -} void cpu_clear_apic_feature(CPUX86State *env) { @@ -1327,8 +1435,7 @@ void cpu_clear_apic_feature(CPUX86State *env) #endif /* !CONFIG_USER_ONLY */ -/* register "cpudef" models defined in configuration file. Here we first - * preload any built-in definitions +/* Initialize list of CPU models, filling some non-static fields if necessary */ void x86_cpudef_setup(void) { @@ -1336,24 +1443,23 @@ void x86_cpudef_setup(void) static const char *model_with_versions[] = { "qemu32", "qemu64", "athlon" }; for (i = 0; i < ARRAY_SIZE(builtin_x86_defs); ++i) { - builtin_x86_defs[i].next = x86_defs; - builtin_x86_defs[i].flags = 1; + x86_def_t *def = &builtin_x86_defs[i]; + def->next = x86_defs; /* Look for specific "cpudef" models that */ /* have the QEMU version in .model_id */ for (j = 0; j < ARRAY_SIZE(model_with_versions); j++) { - if (strcmp(model_with_versions[j], builtin_x86_defs[i].name) == 0) { - pstrcpy(builtin_x86_defs[i].model_id, sizeof(builtin_x86_defs[i].model_id), "QEMU Virtual CPU version "); - pstrcat(builtin_x86_defs[i].model_id, sizeof(builtin_x86_defs[i].model_id), qemu_get_version()); + if (strcmp(model_with_versions[j], def->name) == 0) { + pstrcpy(def->model_id, sizeof(def->model_id), + "QEMU Virtual CPU version "); + pstrcat(def->model_id, sizeof(def->model_id), + qemu_get_version()); break; } } - x86_defs = &builtin_x86_defs[i]; + x86_defs = def; } -#if !defined(CONFIG_USER_ONLY) - qemu_opts_foreach(qemu_find_opts("cpudef"), cpudef_register, NULL, 0); -#endif } static void get_cpuid_vendor(CPUX86State *env, uint32_t *ebx, @@ -1474,7 +1580,7 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count, /* Structured Extended Feature Flags Enumeration Leaf */ if (count == 0) { *eax = 0; /* Maximum ECX value for sub-leaves */ - *ebx = env->cpuid_7_0_ebx; /* Feature flags */ + *ebx = env->cpuid_7_0_ebx_features; /* Feature flags */ *ecx = 0; /* Reserved */ *edx = 0; /* Reserved */ } else { @@ -1653,7 +1759,7 @@ static void x86_cpu_reset(CPUState *s) if (qemu_loglevel_mask(CPU_LOG_RESET)) { qemu_log("CPU Reset (CPU %d)\n", env->cpu_index); - log_cpu_state(env, X86_DUMP_FPU | X86_DUMP_CCOP); + log_cpu_state(env, CPU_DUMP_FPU | CPU_DUMP_CCOP); } xcc->parent_reset(s); |