Message ID | 1355180372-6525-2-git-send-email-afaerber@suse.de |
---|---|
State | New |
Headers | show |
On Mon, 10 Dec 2012 23:59:31 +0100 Andreas Färber <afaerber@suse.de> wrote: > TODO: sort classes for -cpu ?, generalize X86CPUListState, more testing > > Signed-off-by: Andreas Färber <afaerber@suse.de> > Cc: Eduardo Habkost <ehabkost@redhat.com> > Cc: Igor Mammedov <imammedo@redhat.com> > --- > target-i386/cpu-qom.h | 17 + > target-i386/cpu.c | 1481 +++++++++++++++++++++++++++++-------------------- > target-i386/helper.c | 24 - > 3 Dateien geändert, 911 Zeilen hinzugefügt(+), 611 Zeilen entfernt(-) > > diff --git a/target-i386/cpu-qom.h b/target-i386/cpu-qom.h > index 5901140..19f5aa7 100644 > --- a/target-i386/cpu-qom.h > +++ b/target-i386/cpu-qom.h > @@ -49,6 +49,23 @@ typedef struct X86CPUClass { > /*< public >*/ > > void (*parent_reset)(CPUState *cpu); > + > + uint32_t level; > + uint32_t vendor1, vendor2, vendor3; > + int family; > + int model; > + int stepping; > + int tsc_khz; > + uint32_t features, ext_features, ext2_features, ext3_features; > + uint32_t kvm_features, svm_features; > + uint32_t xlevel; > + char model_id[48]; > + int vendor_override; > + /* Store the results of Centaur's CPUID instructions */ > + uint32_t ext4_features; > + uint32_t xlevel2; > + /* The feature bits on CPUID[EAX=7,ECX=0].EBX */ > + uint32_t cpuid_7_0_ebx_features; > } X86CPUClass; > > /** > diff --git a/target-i386/cpu.c b/target-i386/cpu.c > index 6465040..c59c6a5 100644 > --- a/target-i386/cpu.c > +++ b/target-i386/cpu.c > @@ -271,26 +271,6 @@ static void add_flagname_to_bitmaps(const char *flagname, uint32_t *features, > fprintf(stderr, "CPU feature %s not found\n", flagname); > } > > -typedef struct x86_def_t { > - const char *name; > - uint32_t level; > - uint32_t vendor1, vendor2, vendor3; > - int family; > - int model; > - int stepping; > - int tsc_khz; > - uint32_t features, ext_features, ext2_features, ext3_features; > - uint32_t kvm_features, svm_features; > - uint32_t xlevel; > - char model_id[48]; > - int vendor_override; > - /* Store the results of Centaur's CPUID instructions */ > - uint32_t ext4_features; > - uint32_t xlevel2; > - /* The feature bits on CPUID[EAX=7,ECX=0].EBX */ > - uint32_t cpuid_7_0_ebx_features; > -} x86_def_t; > - > #define I486_FEATURES (CPUID_FP87 | CPUID_VME | CPUID_PSE) > #define PENTIUM_FEATURES (I486_FEATURES | CPUID_DE | CPUID_TSC | \ > CPUID_MSR | CPUID_MCE | CPUID_CX8 | CPUID_MMX | CPUID_APIC) > @@ -331,488 +311,735 @@ typedef struct x86_def_t { > > /* built-in cpu model definitions > */ > -static x86_def_t builtin_x86_defs[] = { > - { > - .name = "qemu64", > - .level = 4, > - .vendor1 = CPUID_VENDOR_AMD_1, > - .vendor2 = CPUID_VENDOR_AMD_2, > - .vendor3 = CPUID_VENDOR_AMD_3, > - .family = 6, > - .model = 2, > - .stepping = 3, > - .features = PPRO_FEATURES | > + > +#define TYPE(x) x "-" TYPE_X86_CPU > + > +static void qemu64_cpu_class_init(ObjectClass *oc, void *data) > +{ > + X86CPUClass *xcc = X86_CPU_CLASS(oc); > + xcc->level = 4; > + xcc->vendor1 = CPUID_VENDOR_AMD_1; > + xcc->vendor2 = CPUID_VENDOR_AMD_2; > + xcc->vendor3 = CPUID_VENDOR_AMD_3; > + xcc->family = 6; > + xcc->model = 2; > + xcc->stepping = 3; > + xcc->features = PPRO_FEATURES | > CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA | > - CPUID_PSE36, > - .ext_features = CPUID_EXT_SSE3 | CPUID_EXT_CX16 | CPUID_EXT_POPCNT, > - .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, > - .xlevel = 0x8000000A, > - }, > - { > - .name = "phenom", > - .level = 5, > - .vendor1 = CPUID_VENDOR_AMD_1, > - .vendor2 = CPUID_VENDOR_AMD_2, > - .vendor3 = CPUID_VENDOR_AMD_3, > - .family = 16, > - .model = 2, > - .stepping = 3, > - .features = PPRO_FEATURES | > + CPUID_PSE36; > + xcc->ext_features = CPUID_EXT_SSE3 | CPUID_EXT_CX16 | CPUID_EXT_POPCNT; > + xcc->ext2_features = (PPRO_FEATURES & CPUID_EXT2_AMD_ALIASES) | > + CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX; > + xcc->ext3_features = CPUID_EXT3_LAHF_LM | CPUID_EXT3_SVM | > + CPUID_EXT3_ABM | CPUID_EXT3_SSE4A; > + xcc->xlevel = 0x8000000A; > + > + pstrcpy(xcc->model_id, sizeof(xcc->model_id), > + "QEMU Virtual CPU version "); > + pstrcat(xcc->model_id, sizeof(xcc->model_id), > + qemu_get_version()); > +} > + > +static const TypeInfo qemu64_cpu_type_info = { > + .name = TYPE("qemu64"), > + .parent = TYPE_X86_CPU, > + .class_init = qemu64_cpu_class_init, > +}; > + > +static void phenom_cpu_class_init(ObjectClass *oc, void *data) > +{ > + X86CPUClass *xcc = X86_CPU_CLASS(oc); > + > + xcc->level = 5; > + xcc->vendor1 = CPUID_VENDOR_AMD_1; > + xcc->vendor2 = CPUID_VENDOR_AMD_2; > + xcc->vendor3 = CPUID_VENDOR_AMD_3; > + xcc->family = 16; > + xcc->model = 2; > + xcc->stepping = 3; > + xcc->features = PPRO_FEATURES | > CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA | > - CPUID_PSE36 | CPUID_VME | CPUID_HT, > - .ext_features = CPUID_EXT_SSE3 | CPUID_EXT_MONITOR | CPUID_EXT_CX16 | > - CPUID_EXT_POPCNT, > - .ext2_features = (PPRO_FEATURES & CPUID_EXT2_AMD_ALIASES) | > + CPUID_PSE36 | CPUID_VME | CPUID_HT; > + xcc->ext_features = CPUID_EXT_SSE3 | CPUID_EXT_MONITOR | CPUID_EXT_CX16 | > + CPUID_EXT_POPCNT; > + xcc->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, > + CPUID_EXT2_FFXSR | CPUID_EXT2_PDPE1GB | CPUID_EXT2_RDTSCP; > /* Missing: CPUID_EXT3_CMP_LEG, CPUID_EXT3_EXTAPIC, > CPUID_EXT3_CR8LEG, > CPUID_EXT3_MISALIGNSSE, CPUID_EXT3_3DNOWPREFETCH, > CPUID_EXT3_OSVW, CPUID_EXT3_IBS */ > - .ext3_features = CPUID_EXT3_LAHF_LM | CPUID_EXT3_SVM | > - CPUID_EXT3_ABM | CPUID_EXT3_SSE4A, > - .svm_features = CPUID_SVM_NPT | CPUID_SVM_LBRV, > - .xlevel = 0x8000001A, > - .model_id = "AMD Phenom(tm) 9550 Quad-Core Processor" > - }, > - { > - .name = "core2duo", > - .level = 10, > - .family = 6, > - .model = 15, > - .stepping = 11, > - .features = PPRO_FEATURES | > + xcc->ext3_features = CPUID_EXT3_LAHF_LM | CPUID_EXT3_SVM | > + CPUID_EXT3_ABM | CPUID_EXT3_SSE4A; > + xcc->svm_features = CPUID_SVM_NPT | CPUID_SVM_LBRV; > + xcc->xlevel = 0x8000001A; > + pstrcpy(xcc->model_id, sizeof(xcc->model_id), > + "AMD Phenom(tm) 9550 Quad-Core Processor"); > +} > + > +static const TypeInfo phenom_cpu_type_info = { > + .name = TYPE("phenom"), > + .parent = TYPE_X86_CPU, > + .class_init = phenom_cpu_class_init, > +}; > + > +static void core2duo_cpu_class_init(ObjectClass *oc, void *data) > +{ > + X86CPUClass *xcc = X86_CPU_CLASS(oc); > + > + xcc->level = 10; > + xcc->family = 6; > + xcc->model = 15; > + xcc->stepping = 11; > + xcc->features = PPRO_FEATURES | > CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA | > CPUID_PSE36 | CPUID_VME | CPUID_DTS | CPUID_ACPI | CPUID_SS | > - CPUID_HT | CPUID_TM | CPUID_PBE, > - .ext_features = CPUID_EXT_SSE3 | CPUID_EXT_MONITOR | CPUID_EXT_SSSE3 | > + CPUID_HT | CPUID_TM | CPUID_PBE; > + xcc->ext_features = CPUID_EXT_SSE3 | CPUID_EXT_MONITOR | CPUID_EXT_SSSE3 | > CPUID_EXT_DTES64 | CPUID_EXT_DSCPL | CPUID_EXT_VMX | CPUID_EXT_EST | > - CPUID_EXT_TM2 | CPUID_EXT_CX16 | CPUID_EXT_XTPR | CPUID_EXT_PDCM, > - .ext2_features = CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX, > - .ext3_features = CPUID_EXT3_LAHF_LM, > - .xlevel = 0x80000008, > - .model_id = "Intel(R) Core(TM)2 Duo CPU T7700 @ 2.40GHz", > - }, > - { > - .name = "kvm64", > - .level = 5, > - .vendor1 = CPUID_VENDOR_INTEL_1, > - .vendor2 = CPUID_VENDOR_INTEL_2, > - .vendor3 = CPUID_VENDOR_INTEL_3, > - .family = 15, > - .model = 6, > - .stepping = 1, > + CPUID_EXT_TM2 | CPUID_EXT_CX16 | CPUID_EXT_XTPR | CPUID_EXT_PDCM; > + xcc->ext2_features = CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX; > + xcc->ext3_features = CPUID_EXT3_LAHF_LM; > + xcc->xlevel = 0x80000008; > + pstrcpy(xcc->model_id, sizeof(xcc->model_id), > + "Intel(R) Core(TM)2 Duo CPU T7700 @ 2.40GHz"); > +} > + > +static const TypeInfo core2duo_cpu_type_info = { > + .name = TYPE("core2duo"), > + .parent = TYPE_X86_CPU, > + .class_init = core2duo_cpu_class_init, > +}; > + > +static void kvm64_cpu_class_init(ObjectClass *oc, void *data) > +{ > + X86CPUClass *xcc = X86_CPU_CLASS(oc); > + > + xcc->level = 5; > + xcc->vendor1 = CPUID_VENDOR_INTEL_1; > + xcc->vendor2 = CPUID_VENDOR_INTEL_2; > + xcc->vendor3 = CPUID_VENDOR_INTEL_3; > + xcc->family = 15; > + xcc->model = 6; > + xcc->stepping = 1; > /* Missing: CPUID_VME, CPUID_HT */ > - .features = PPRO_FEATURES | > + xcc->features = PPRO_FEATURES | > CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA | > - CPUID_PSE36, > + CPUID_PSE36; > /* Missing: CPUID_EXT_POPCNT, CPUID_EXT_MONITOR */ > - .ext_features = CPUID_EXT_SSE3 | CPUID_EXT_CX16, > + xcc->ext_features = CPUID_EXT_SSE3 | CPUID_EXT_CX16; > /* Missing: CPUID_EXT2_PDPE1GB, CPUID_EXT2_RDTSCP */ > - .ext2_features = (PPRO_FEATURES & CPUID_EXT2_AMD_ALIASES) | > - CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX, > + xcc->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, > CPUID_EXT3_MISALIGNSSE, CPUID_EXT3_3DNOWPREFETCH, > CPUID_EXT3_OSVW, CPUID_EXT3_IBS, CPUID_EXT3_SVM */ > - .ext3_features = 0, > - .xlevel = 0x80000008, > - .model_id = "Common KVM processor" > - }, > - { > - .name = "qemu32", > - .level = 4, > - .family = 6, > - .model = 3, > - .stepping = 3, > - .features = PPRO_FEATURES, > - .ext_features = CPUID_EXT_SSE3 | CPUID_EXT_POPCNT, > - .xlevel = 0x80000004, > - }, > - { > - .name = "kvm32", > - .level = 5, > - .family = 15, > - .model = 6, > - .stepping = 1, > - .features = PPRO_FEATURES | > - CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA | CPUID_PSE36, > - .ext_features = CPUID_EXT_SSE3, > - .ext2_features = PPRO_FEATURES & CPUID_EXT2_AMD_ALIASES, > - .ext3_features = 0, > - .xlevel = 0x80000008, > - .model_id = "Common 32-bit KVM processor" > - }, > - { > - .name = "coreduo", > - .level = 10, > - .family = 6, > - .model = 14, > - .stepping = 8, > - .features = PPRO_FEATURES | CPUID_VME | > + xcc->ext3_features = 0; > + xcc->xlevel = 0x80000008; > + pstrcpy(xcc->model_id, sizeof(xcc->model_id), > + "Common KVM processor"); > +} > + > +static const TypeInfo kvm64_cpu_type_info = { > + .name = TYPE("kvm64"), > + .parent = TYPE_X86_CPU, > + .class_init = kvm64_cpu_class_init, > +}; > + > +static void qemu32_cpu_class_init(ObjectClass *oc, void *data) > +{ > + X86CPUClass *xcc = X86_CPU_CLASS(oc); > + > + xcc->level = 4; > + xcc->family = 6; > + xcc->model = 3; > + xcc->stepping = 3; > + xcc->features = PPRO_FEATURES; > + xcc->ext_features = CPUID_EXT_SSE3 | CPUID_EXT_POPCNT; > + xcc->xlevel = 0x80000004; > + > + pstrcpy(xcc->model_id, sizeof(xcc->model_id), > + "QEMU Virtual CPU version "); > + pstrcat(xcc->model_id, sizeof(xcc->model_id), > + qemu_get_version()); > +} > + > +static const TypeInfo qemu32_cpu_type_info = { > + .name = TYPE("qemu32"), > + .parent = TYPE_X86_CPU, > + .class_init = qemu32_cpu_class_init, > +}; > + > +static void kvm32_cpu_class_init(ObjectClass *oc, void *data) > +{ > + X86CPUClass *xcc = X86_CPU_CLASS(oc); > + > + xcc->level = 5; > + xcc->family = 15; > + xcc->model = 6; > + xcc->stepping = 1; > + xcc->features = PPRO_FEATURES | > + CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA | CPUID_PSE36; > + xcc->ext_features = CPUID_EXT_SSE3; > + xcc->ext2_features = PPRO_FEATURES & CPUID_EXT2_AMD_ALIASES; > + xcc->ext3_features = 0; > + xcc->xlevel = 0x80000008; > + pstrcpy(xcc->model_id, sizeof(xcc->model_id), > + "Common 32-bit KVM processor"); > +} > + > +static const TypeInfo kvm32_cpu_type_info = { > + .name = TYPE("kvm32"), > + .parent = TYPE_X86_CPU, > + .class_init = kvm32_cpu_class_init, > +}; > + > +static void coreduo_cpu_class_init(ObjectClass *oc, void *data) > +{ > + X86CPUClass *xcc = X86_CPU_CLASS(oc); > + > + xcc->level = 10; > + xcc->family = 6; > + xcc->model = 14; > + xcc->stepping = 8; > + xcc->features = PPRO_FEATURES | CPUID_VME | > CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA | CPUID_DTS | CPUID_ACPI | > - CPUID_SS | CPUID_HT | CPUID_TM | CPUID_PBE, > - .ext_features = CPUID_EXT_SSE3 | CPUID_EXT_MONITOR | CPUID_EXT_VMX | > - CPUID_EXT_EST | CPUID_EXT_TM2 | CPUID_EXT_XTPR | CPUID_EXT_PDCM, > - .ext2_features = CPUID_EXT2_NX, > - .xlevel = 0x80000008, > - .model_id = "Genuine Intel(R) CPU T2600 @ 2.16GHz", > - }, > - { > - .name = "486", > - .level = 1, > - .family = 4, > - .model = 0, > - .stepping = 0, > - .features = I486_FEATURES, > - .xlevel = 0, > - }, > - { > - .name = "pentium", > - .level = 1, > - .family = 5, > - .model = 4, > - .stepping = 3, > - .features = PENTIUM_FEATURES, > - .xlevel = 0, > - }, > - { > - .name = "pentium2", > - .level = 2, > - .family = 6, > - .model = 5, > - .stepping = 2, > - .features = PENTIUM2_FEATURES, > - .xlevel = 0, > - }, > - { > - .name = "pentium3", > - .level = 2, > - .family = 6, > - .model = 7, > - .stepping = 3, > - .features = PENTIUM3_FEATURES, > - .xlevel = 0, > - }, > - { > - .name = "athlon", > - .level = 2, > - .vendor1 = CPUID_VENDOR_AMD_1, > - .vendor2 = CPUID_VENDOR_AMD_2, > - .vendor3 = CPUID_VENDOR_AMD_3, > - .family = 6, > - .model = 2, > - .stepping = 3, > - .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, > - }, > - { > - .name = "n270", > - /* original is on level 10 */ > - .level = 5, > - .family = 6, > - .model = 28, > - .stepping = 2, > - .features = PPRO_FEATURES | > + CPUID_SS | CPUID_HT | CPUID_TM | CPUID_PBE; > + xcc->ext_features = CPUID_EXT_SSE3 | CPUID_EXT_MONITOR | CPUID_EXT_VMX | > + CPUID_EXT_EST | CPUID_EXT_TM2 | CPUID_EXT_XTPR | CPUID_EXT_PDCM; > + xcc->ext2_features = CPUID_EXT2_NX; > + xcc->xlevel = 0x80000008; > + pstrcpy(xcc->model_id, sizeof(xcc->model_id), > + "Genuine Intel(R) CPU T2600 @ 2.16GHz"); > +} > + > +static const TypeInfo coreduo_cpu_type_info = { > + .name = TYPE("coreduo"), > + .parent = TYPE_X86_CPU, > + .class_init = coreduo_cpu_class_init, > +}; > + > +static void i486_cpu_class_init(ObjectClass *oc, void *data) > +{ > + X86CPUClass *xcc = X86_CPU_CLASS(oc); > + > + xcc->level = 1; > + xcc->family = 4; > + xcc->model = 0; > + xcc->stepping = 0; > + xcc->features = I486_FEATURES; > + xcc->xlevel = 0; > +} > + > +static const TypeInfo i486_cpu_type_info = { > + .name = TYPE("486"), > + .parent = TYPE_X86_CPU, > + .class_init = i486_cpu_class_init, > +}; > + > +static void pentium_cpu_class_init(ObjectClass *oc, void *data) > +{ > + X86CPUClass *xcc = X86_CPU_CLASS(oc); > + > + xcc->level = 1; > + xcc->family = 5; > + xcc->model = 4; > + xcc->stepping = 3; > + xcc->features = PENTIUM_FEATURES; > + xcc->xlevel = 0; > +} > + > +static const TypeInfo pentium_cpu_type_info = { > + .name = TYPE("pentium"), > + .parent = TYPE_X86_CPU, > + .class_init = pentium_cpu_class_init, > +}; > + > +static void pentium2_cpu_class_init(ObjectClass *oc, void *data) > +{ > + X86CPUClass *xcc = X86_CPU_CLASS(oc); > + > + xcc->level = 2; > + xcc->family = 6; > + xcc->model = 5; > + xcc->stepping = 2; > + xcc->features = PENTIUM2_FEATURES; > + xcc->xlevel = 0; > +} > + > +static const TypeInfo pentium2_cpu_type_info = { > + .name = TYPE("pentium2"), > + .parent = TYPE_X86_CPU, > + .class_init = pentium2_cpu_class_init, > +}; > + > +static void pentium3_cpu_class_init(ObjectClass *oc, void *data) > +{ > + X86CPUClass *xcc = X86_CPU_CLASS(oc); > + > + xcc->level = 2; > + xcc->family = 6; > + xcc->model = 7; > + xcc->stepping = 3; > + xcc->features = PENTIUM3_FEATURES; > + xcc->xlevel = 0; > +} > + > +static const TypeInfo pentium3_cpu_type_info = { > + .name = TYPE("pentium3"), > + .parent = TYPE_X86_CPU, > + .class_init = pentium3_cpu_class_init, > +}; > + > +static void athlon_cpu_class_init(ObjectClass *oc, void *data) > +{ > + X86CPUClass *xcc = X86_CPU_CLASS(oc); > + > + xcc->level = 2; > + xcc->vendor1 = CPUID_VENDOR_AMD_1; > + xcc->vendor2 = CPUID_VENDOR_AMD_2; > + xcc->vendor3 = CPUID_VENDOR_AMD_3; > + xcc->family = 6; > + xcc->model = 2; > + xcc->stepping = 3; > + xcc->features = PPRO_FEATURES | CPUID_PSE36 | CPUID_VME | CPUID_MTRR | > + CPUID_MCA; > + xcc->ext2_features = (PPRO_FEATURES & CPUID_EXT2_AMD_ALIASES) | > + CPUID_EXT2_MMXEXT | CPUID_EXT2_3DNOW | CPUID_EXT2_3DNOWEXT; > + xcc->xlevel = 0x80000008; > + > + pstrcpy(xcc->model_id, sizeof(xcc->model_id), > + "QEMU Virtual CPU version "); > + pstrcat(xcc->model_id, sizeof(xcc->model_id), > + qemu_get_version()); > +} > + > +static const TypeInfo athlon_cpu_type_info = { > + .name = TYPE("athlon"), > + .parent = TYPE_X86_CPU, > + .class_init = athlon_cpu_class_init, > +}; > + > +static void n270_cpu_class_init(ObjectClass *oc, void *data) > +{ > + X86CPUClass *xcc = X86_CPU_CLASS(oc); > + > + /* original is on level 10 */ > + xcc->level = 5; > + xcc->family = 6; > + xcc->model = 28; > + xcc->stepping = 2; > + xcc->features = PPRO_FEATURES | > CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA | CPUID_VME | CPUID_DTS | > - CPUID_ACPI | CPUID_SS | CPUID_HT | CPUID_TM | CPUID_PBE, > + CPUID_ACPI | CPUID_SS | CPUID_HT | CPUID_TM | CPUID_PBE; > /* 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 & 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 | > + xcc->ext_features = CPUID_EXT_SSE3 | CPUID_EXT_MONITOR | CPUID_EXT_SSSE3 | > + CPUID_EXT_DSCPL | CPUID_EXT_EST | CPUID_EXT_TM2 | CPUID_EXT_XTPR; > + xcc->ext2_features = (PPRO_FEATURES & CPUID_EXT2_AMD_ALIASES) | > + CPUID_EXT2_NX; > + xcc->ext3_features = CPUID_EXT3_LAHF_LM; > + xcc->xlevel = 0x8000000A; > + pstrcpy(xcc->model_id, sizeof(xcc->model_id), > + "Intel(R) Atom(TM) CPU N270 @ 1.60GHz"); > +} > + > +static const TypeInfo n270_cpu_type_info = { > + .name = TYPE("n270"), > + .parent = TYPE_X86_CPU, > + .class_init = n270_cpu_class_init, > +}; > + > +static void conroe_cpu_class_init(ObjectClass *oc, void *data) > +{ > + X86CPUClass *xcc = X86_CPU_CLASS(oc); > + > + xcc->level = 2; > + xcc->vendor1 = CPUID_VENDOR_INTEL_1; > + xcc->vendor2 = CPUID_VENDOR_INTEL_2; > + xcc->vendor3 = CPUID_VENDOR_INTEL_3; > + xcc->family = 6; > + xcc->model = 2; > + xcc->stepping = 3; > + xcc->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_DE | CPUID_FP87; > + xcc->ext_features = CPUID_EXT_SSSE3 | CPUID_EXT_SSE3; > + xcc->ext2_features = CPUID_EXT2_LM | CPUID_EXT2_NX | CPUID_EXT2_SYSCALL; > + xcc->ext3_features = CPUID_EXT3_LAHF_LM; > + xcc->xlevel = 0x8000000A; > + pstrcpy(xcc->model_id, sizeof(xcc->model_id), > + "Intel Celeron_4x0 (Conroe/Merom Class Core 2)"); > +} > + > +static const TypeInfo conroe_cpu_type_info = { > + .name = TYPE("Conroe"), > + .parent = TYPE_X86_CPU, > + .class_init = conroe_cpu_class_init, > +}; > + > +static void penryn_cpu_class_init(ObjectClass *oc, void *data) > +{ > + X86CPUClass *xcc = X86_CPU_CLASS(oc); > + > + xcc->level = 2; > + xcc->vendor1 = CPUID_VENDOR_INTEL_1; > + xcc->vendor2 = CPUID_VENDOR_INTEL_2; > + xcc->vendor3 = CPUID_VENDOR_INTEL_3; > + xcc->family = 6; > + xcc->model = 2; > + xcc->stepping = 3; > + xcc->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_DE | CPUID_FP87; > + xcc->ext_features = CPUID_EXT_SSE41 | CPUID_EXT_CX16 | CPUID_EXT_SSSE3 | > + CPUID_EXT_SSE3; > + xcc->ext2_features = CPUID_EXT2_LM | CPUID_EXT2_NX | CPUID_EXT2_SYSCALL; > + xcc->ext3_features = CPUID_EXT3_LAHF_LM; > + xcc->xlevel = 0x8000000A; > + pstrcpy(xcc->model_id, sizeof(xcc->model_id), > + "Intel Core 2 Duo P9xxx (Penryn Class Core 2)"); > +} > + > +static const TypeInfo penryn_cpu_type_info = { > + .name = TYPE("Penryn"), > + .parent = TYPE_X86_CPU, > + .class_init = penryn_cpu_class_init, > +}; > + > +static void nehalem_cpu_class_init(ObjectClass *oc, void *data) > +{ > + X86CPUClass *xcc = X86_CPU_CLASS(oc); > + > + xcc->level = 2; > + xcc->vendor1 = CPUID_VENDOR_INTEL_1; > + xcc->vendor2 = CPUID_VENDOR_INTEL_2; > + xcc->vendor3 = CPUID_VENDOR_INTEL_3; > + xcc->family = 6; > + xcc->model = 2; > + xcc->stepping = 3; > + xcc->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_DE | CPUID_FP87; > + xcc->ext_features = CPUID_EXT_POPCNT | CPUID_EXT_SSE42 | CPUID_EXT_SSE41 | > + CPUID_EXT_CX16 | CPUID_EXT_SSSE3 | CPUID_EXT_SSE3; > + xcc->ext2_features = CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX; > + xcc->ext3_features = CPUID_EXT3_LAHF_LM; > + xcc->xlevel = 0x8000000A; > + pstrcpy(xcc->model_id, sizeof(xcc->model_id), > + "Intel Core i7 9xx (Nehalem Class Core i7)"); > +} > + > +static const TypeInfo nehalem_cpu_type_info = { > + .name = TYPE("Nehalem"), > + .parent = TYPE_X86_CPU, > + .class_init = nehalem_cpu_class_init, > +}; > + > +static void westmere_cpu_class_init(ObjectClass *oc, void *data) > +{ > + X86CPUClass *xcc = X86_CPU_CLASS(oc); > + > + xcc->level = 11; > + xcc->vendor1 = CPUID_VENDOR_INTEL_1; > + xcc->vendor2 = CPUID_VENDOR_INTEL_2; > + xcc->vendor3 = CPUID_VENDOR_INTEL_3; > + xcc->family = 6; > + xcc->model = 44; > + xcc->stepping = 1; > + xcc->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_DE | CPUID_FP87; > + xcc->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_EXT_SSE3; > + xcc->ext2_features = CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX; > + xcc->ext3_features = CPUID_EXT3_LAHF_LM; > + xcc->xlevel = 0x8000000A; > + pstrcpy(xcc->model_id, sizeof(xcc->model_id), > + "Westmere E56xx/L56xx/X56xx (Nehalem-C)"); > +} > + > +static const TypeInfo westmere_cpu_type_info = { > + .name = TYPE("Westmere"), > + .parent = TYPE_X86_CPU, > + .class_init = westmere_cpu_class_init, > +}; > + > +static void sandybridge_cpu_class_init(ObjectClass *oc, void *data) > +{ > + X86CPUClass *xcc = X86_CPU_CLASS(oc); > + > + xcc->level = 0xd; > + xcc->vendor1 = CPUID_VENDOR_INTEL_1; > + xcc->vendor2 = CPUID_VENDOR_INTEL_2; > + xcc->vendor3 = CPUID_VENDOR_INTEL_3; > + xcc->family = 6; > + xcc->model = 42; > + xcc->stepping = 1; > + xcc->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_DE | CPUID_FP87; > + xcc->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 = "Haswell", > - .level = 0xd, > - .vendor1 = CPUID_VENDOR_INTEL_1, > - .vendor2 = CPUID_VENDOR_INTEL_2, > - .vendor3 = CPUID_VENDOR_INTEL_3, > - .family = 6, > - .model = 60, > - .stepping = 1, > - .features = CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX | > + CPUID_EXT_SSE3; > + xcc->ext2_features = CPUID_EXT2_LM | CPUID_EXT2_RDTSCP | CPUID_EXT2_NX | > + CPUID_EXT2_SYSCALL; > + xcc->ext3_features = CPUID_EXT3_LAHF_LM; > + xcc->xlevel = 0x8000000A; > + pstrcpy(xcc->model_id, sizeof(xcc->model_id), > + "Intel Xeon E312xx (Sandy Bridge)"); > +} > + > +static const TypeInfo sandybridge_cpu_type_info = { > + .name = TYPE("SandyBridge"), > + .parent = TYPE_X86_CPU, > + .class_init = sandybridge_cpu_class_init, > +}; > + > +static void haswell_cpu_class_init(ObjectClass *oc, void *data) > +{ > + X86CPUClass *xcc = X86_CPU_CLASS(oc); > + > + xcc->level = 0xd; > + xcc->vendor1 = CPUID_VENDOR_INTEL_1; > + xcc->vendor2 = CPUID_VENDOR_INTEL_2; > + xcc->vendor3 = CPUID_VENDOR_INTEL_3; > + xcc->family = 6; > + xcc->model = 60; > + xcc->stepping = 1; > + xcc->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_DE | CPUID_FP87; > + xcc->ext_features = CPUID_EXT_AVX | CPUID_EXT_XSAVE | CPUID_EXT_AES | > CPUID_EXT_POPCNT | CPUID_EXT_X2APIC | CPUID_EXT_SSE42 | > CPUID_EXT_SSE41 | CPUID_EXT_CX16 | CPUID_EXT_SSSE3 | > CPUID_EXT_PCLMULQDQ | CPUID_EXT_SSE3 | > CPUID_EXT_TSC_DEADLINE_TIMER | CPUID_EXT_FMA | CPUID_EXT_MOVBE | > - CPUID_EXT_PCID, > - .ext2_features = CPUID_EXT2_LM | CPUID_EXT2_RDTSCP | CPUID_EXT2_NX | > - CPUID_EXT2_SYSCALL, > - .ext3_features = CPUID_EXT3_LAHF_LM, > - .cpuid_7_0_ebx_features = CPUID_7_0_EBX_FSGSBASE | CPUID_7_0_EBX_BMI1 | > + CPUID_EXT_PCID; > + xcc->ext2_features = CPUID_EXT2_LM | CPUID_EXT2_RDTSCP | CPUID_EXT2_NX | > + CPUID_EXT2_SYSCALL; > + xcc->ext3_features = CPUID_EXT3_LAHF_LM; > + xcc->cpuid_7_0_ebx_features = CPUID_7_0_EBX_FSGSBASE | CPUID_7_0_EBX_BMI1 | > CPUID_7_0_EBX_HLE | CPUID_7_0_EBX_AVX2 | CPUID_7_0_EBX_SMEP | > CPUID_7_0_EBX_BMI2 | CPUID_7_0_EBX_ERMS | CPUID_7_0_EBX_INVPCID | > - CPUID_7_0_EBX_RTM, > - .xlevel = 0x8000000A, > - .model_id = "Intel Core Processor (Haswell)", > - }, > - { > - .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_7_0_EBX_RTM; > + xcc->xlevel = 0x8000000A; > + pstrcpy(xcc->model_id, sizeof(xcc->model_id), > + "Intel Core Processor (Haswell)"); > +} > + > +static const TypeInfo haswell_cpu_type_info = { > + .name = TYPE("Haswell"), > + .parent = TYPE_X86_CPU, > + .class_init = haswell_cpu_class_init, > +}; > + > +static void opteron_g1_cpu_class_init(ObjectClass *oc, void *data) > +{ > + X86CPUClass *xcc = X86_CPU_CLASS(oc); > + > + xcc->level = 5; > + xcc->vendor1 = CPUID_VENDOR_AMD_1; > + xcc->vendor2 = CPUID_VENDOR_AMD_2; > + xcc->vendor3 = CPUID_VENDOR_AMD_3; > + xcc->family = 15; > + xcc->model = 6; > + xcc->stepping = 1; > + xcc->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_DE | CPUID_FP87; > + xcc->ext_features = CPUID_EXT_SSE3; > + xcc->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_EXT2_TSC | CPUID_EXT2_PSE | CPUID_EXT2_DE | CPUID_EXT2_FPU; > + xcc->xlevel = 0x80000008; > + pstrcpy(xcc->model_id, sizeof(xcc->model_id), > + "AMD Opteron 240 (Gen 1 Class Opteron)"); > +} > + > +static const TypeInfo opteron_g1_cpu_type_info = { > + .name = TYPE("Opteron_G1"), > + .parent = TYPE_X86_CPU, > + .class_init = opteron_g1_cpu_class_init, > +}; > + > +static void opteron_g2_cpu_class_init(ObjectClass *oc, void *data) > +{ > + X86CPUClass *xcc = X86_CPU_CLASS(oc); > + > + xcc->level = 5; > + xcc->vendor1 = CPUID_VENDOR_AMD_1; > + xcc->vendor2 = CPUID_VENDOR_AMD_2; > + xcc->vendor3 = CPUID_VENDOR_AMD_3; > + xcc->family = 15; > + xcc->model = 6; > + xcc->stepping = 1; > + xcc->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_DE | CPUID_FP87; > + xcc->ext_features = CPUID_EXT_CX16 | CPUID_EXT_SSE3; > + xcc->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_EXT2_DE | CPUID_EXT2_FPU; > + xcc->ext3_features = CPUID_EXT3_SVM | CPUID_EXT3_LAHF_LM; > + xcc->xlevel = 0x80000008; > + pstrcpy(xcc->model_id, sizeof(xcc->model_id), > + "AMD Opteron 22xx (Gen 2 Class Opteron)"); > +} > + > +static const TypeInfo opteron_g2_cpu_type_info = { > + .name = TYPE("Opteron_G2"), > + .parent = TYPE_X86_CPU, > + .class_init = opteron_g2_cpu_class_init, > +}; > + > +static void opteron_g3_cpu_class_init(ObjectClass *oc, void *data) > +{ > + X86CPUClass *xcc = X86_CPU_CLASS(oc); > + > + xcc->level = 5; > + xcc->vendor1 = CPUID_VENDOR_AMD_1; > + xcc->vendor2 = CPUID_VENDOR_AMD_2; > + xcc->vendor3 = CPUID_VENDOR_AMD_3; > + xcc->family = 15; > + xcc->model = 6; > + xcc->stepping = 1; > + xcc->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_DE | CPUID_FP87; > + xcc->ext_features = CPUID_EXT_POPCNT | CPUID_EXT_CX16 | CPUID_EXT_MONITOR | > + CPUID_EXT_SSE3; > + xcc->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_EXT2_DE | CPUID_EXT2_FPU; > + xcc->ext3_features = CPUID_EXT3_MISALIGNSSE | CPUID_EXT3_SSE4A | > + CPUID_EXT3_ABM | CPUID_EXT3_SVM | CPUID_EXT3_LAHF_LM; > + xcc->xlevel = 0x80000008; > + pstrcpy(xcc->model_id, sizeof(xcc->model_id), > + "AMD Opteron 23xx (Gen 3 Class Opteron)"); > +} > + > +static const TypeInfo opteron_g3_cpu_type_info = { > + .name = TYPE("Opteron_G3"), > + .parent = TYPE_X86_CPU, > + .class_init = opteron_g3_cpu_class_init, > +}; > + > +static void opteron_g4_cpu_class_init(ObjectClass *oc, void *data) > +{ > + X86CPUClass *xcc = X86_CPU_CLASS(oc); > + > + xcc->level = 0xd; > + xcc->vendor1 = CPUID_VENDOR_AMD_1; > + xcc->vendor2 = CPUID_VENDOR_AMD_2; > + xcc->vendor3 = CPUID_VENDOR_AMD_3; > + xcc->family = 21; > + xcc->model = 1; > + xcc->stepping = 2; > + xcc->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_DE | CPUID_FP87; > + xcc->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_EXT_SSE3; > + xcc->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_EXT2_TSC | CPUID_EXT2_PSE | CPUID_EXT2_DE | CPUID_EXT2_FPU; > + xcc->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", > - }, > - { > - .name = "Opteron_G5", > - .level = 0xd, > - .vendor1 = CPUID_VENDOR_AMD_1, > - .vendor2 = CPUID_VENDOR_AMD_2, > - .vendor3 = CPUID_VENDOR_AMD_3, > - .family = 21, > - .model = 2, > - .stepping = 0, > - .features = CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX | > + CPUID_EXT3_LAHF_LM; > + xcc->xlevel = 0x8000001A; > + pstrcpy(xcc->model_id, sizeof(xcc->model_id), > + "AMD Opteron 62xx class CPU"); > +} > + > +static const TypeInfo opteron_g4_cpu_type_info = { > + .name = TYPE("Opteron_G4"), > + .parent = TYPE_X86_CPU, > + .class_init = opteron_g4_cpu_class_init, > +}; > + > +static void opteron_g5_cpu_class_init(ObjectClass *oc, void *data) > +{ > + X86CPUClass *xcc = X86_CPU_CLASS(oc); > + > + xcc->level = 0xd; > + xcc->vendor1 = CPUID_VENDOR_AMD_1; > + xcc->vendor2 = CPUID_VENDOR_AMD_2; > + xcc->vendor3 = CPUID_VENDOR_AMD_3; > + xcc->family = 21; > + xcc->model = 2; > + xcc->stepping = 0; > + xcc->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_F16C | CPUID_EXT_AVX | CPUID_EXT_XSAVE | > + CPUID_DE | CPUID_FP87; > + xcc->ext_features = CPUID_EXT_F16C | CPUID_EXT_AVX | CPUID_EXT_XSAVE | > CPUID_EXT_AES | CPUID_EXT_POPCNT | CPUID_EXT_SSE42 | > CPUID_EXT_SSE41 | CPUID_EXT_CX16 | CPUID_EXT_FMA | > - CPUID_EXT_SSSE3 | CPUID_EXT_PCLMULQDQ | CPUID_EXT_SSE3, > - .ext2_features = CPUID_EXT2_LM | CPUID_EXT2_RDTSCP | > + CPUID_EXT_SSSE3 | CPUID_EXT_PCLMULQDQ | CPUID_EXT_SSE3; > + xcc->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_TBM | CPUID_EXT3_FMA4 | CPUID_EXT3_XOP | > + CPUID_EXT2_TSC | CPUID_EXT2_PSE | CPUID_EXT2_DE | CPUID_EXT2_FPU; > + xcc->ext3_features = CPUID_EXT3_TBM | 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 63xx class CPU", > - }, > + CPUID_EXT3_LAHF_LM; > + xcc->xlevel = 0x8000001A; > + pstrcpy(xcc->model_id, sizeof(xcc->model_id), > + "AMD Opteron 63xx class CPU"); > +} > + > +static const TypeInfo opteron_g5_cpu_type_info = { > + .name = TYPE("Opteron_G5"), > + .parent = TYPE_X86_CPU, > + .class_init = opteron_g5_cpu_class_init, > }; > > #ifdef CONFIG_KVM > @@ -832,61 +1059,60 @@ static int cpu_x86_fill_model_id(char *str) > } > #endif > > -/* Fill a x86_def_t struct with information about the host CPU, and > +#ifdef CONFIG_KVM > + > +/* Fill a CPU class with information about the host CPU, and > * the CPU features supported by the host hardware + host kernel > - * > - * This function may be called only if KVM is enabled. > */ > -static void kvm_cpu_fill_host(x86_def_t *x86_cpu_def) > +static void kvm_host_cpu_class_init(ObjectClass *oc, void *data) > { > -#ifdef CONFIG_KVM > + X86CPUClass *xcc = X86_CPU_CLASS(oc); > KVMState *s = kvm_state; > uint32_t eax = 0, ebx = 0, ecx = 0, edx = 0; > > assert(kvm_enabled()); > > - x86_cpu_def->name = "host"; > host_cpuid(0x0, 0, &eax, &ebx, &ecx, &edx); > - x86_cpu_def->vendor1 = ebx; > - x86_cpu_def->vendor2 = edx; > - x86_cpu_def->vendor3 = ecx; > + xcc->vendor1 = ebx; > + xcc->vendor2 = edx; > + xcc->vendor3 = ecx; > > host_cpuid(0x1, 0, &eax, &ebx, &ecx, &edx); > - x86_cpu_def->family = ((eax >> 8) & 0x0F) + ((eax >> 20) & 0xFF); > - x86_cpu_def->model = ((eax >> 4) & 0x0F) | ((eax & 0xF0000) >> 12); > - x86_cpu_def->stepping = eax & 0x0F; > + xcc->family = ((eax >> 8) & 0x0F) + ((eax >> 20) & 0xFF); > + xcc->model = ((eax >> 4) & 0x0F) | ((eax & 0xF0000) >> 12); > + xcc->stepping = eax & 0x0F; > > - x86_cpu_def->level = kvm_arch_get_supported_cpuid(s, 0x0, 0, R_EAX); > - x86_cpu_def->features = kvm_arch_get_supported_cpuid(s, 0x1, 0, R_EDX); > - x86_cpu_def->ext_features = kvm_arch_get_supported_cpuid(s, 0x1, 0, R_ECX); > + xcc->level = kvm_arch_get_supported_cpuid(s, 0x0, 0, R_EAX); > + xcc->features = kvm_arch_get_supported_cpuid(s, 0x1, 0, R_EDX); > + xcc->ext_features = kvm_arch_get_supported_cpuid(s, 0x1, 0, R_ECX); > > - if (x86_cpu_def->level >= 7) { > - x86_cpu_def->cpuid_7_0_ebx_features = > + if (xcc->level >= 7) { > + xcc->cpuid_7_0_ebx_features = > kvm_arch_get_supported_cpuid(s, 0x7, 0, R_EBX); > } else { > - x86_cpu_def->cpuid_7_0_ebx_features = 0; > + xcc->cpuid_7_0_ebx_features = 0; > } > > - x86_cpu_def->xlevel = kvm_arch_get_supported_cpuid(s, 0x80000000, 0, R_EAX); > - x86_cpu_def->ext2_features = > + xcc->xlevel = kvm_arch_get_supported_cpuid(s, 0x80000000, 0, R_EAX); > + xcc->ext2_features = > kvm_arch_get_supported_cpuid(s, 0x80000001, 0, R_EDX); > - x86_cpu_def->ext3_features = > + xcc->ext3_features = > kvm_arch_get_supported_cpuid(s, 0x80000001, 0, R_ECX); > > - cpu_x86_fill_model_id(x86_cpu_def->model_id); > - x86_cpu_def->vendor_override = 0; > + cpu_x86_fill_model_id(xcc->model_id); > + xcc->vendor_override = 0; > > /* Call Centaur's CPUID instruction. */ > - if (x86_cpu_def->vendor1 == CPUID_VENDOR_VIA_1 && > - x86_cpu_def->vendor2 == CPUID_VENDOR_VIA_2 && > - x86_cpu_def->vendor3 == CPUID_VENDOR_VIA_3) { > + if (xcc->vendor1 == CPUID_VENDOR_VIA_1 && > + xcc->vendor2 == CPUID_VENDOR_VIA_2 && > + xcc->vendor3 == CPUID_VENDOR_VIA_3) { > host_cpuid(0xC0000000, 0, &eax, &ebx, &ecx, &edx); > eax = kvm_arch_get_supported_cpuid(s, 0xC0000000, 0, R_EAX); > if (eax >= 0xC0000001) { > /* Support VIA max extended level */ > - x86_cpu_def->xlevel2 = eax; > + xcc->xlevel2 = eax; > host_cpuid(0xC0000001, 0, &eax, &ebx, &ecx, &edx); > - x86_cpu_def->ext4_features = > + xcc->ext4_features = > kvm_arch_get_supported_cpuid(s, 0xC0000001, 0, R_EDX); > } > } > @@ -897,10 +1123,17 @@ static void kvm_cpu_fill_host(x86_def_t *x86_cpu_def) > * available on the host hardware. Just set all bits and mask out the > * unsupported ones later. > */ > - x86_cpu_def->svm_features = -1; > -#endif /* CONFIG_KVM */ > + xcc->svm_features = -1; > } > > +static const TypeInfo kvm_host_cpu_type_info = { > + .name = TYPE("host"), > + .parent = TYPE_X86_CPU, > + .class_init = kvm_host_cpu_class_init, > +}; > + > +#endif /* CONFIG_KVM */ > + > static int unavailable_host_feature(struct model_features_t *f, uint32_t mask) > { > int i; > @@ -922,24 +1155,24 @@ static int unavailable_host_feature(struct model_features_t *f, uint32_t mask) > * > * This function may be called only if KVM is enabled. > */ > -static int kvm_check_features_against_host(x86_def_t *guest_def) > +static int kvm_check_features_against_host(X86CPU *guest_cpu) > { > - x86_def_t host_def; > + CPUX86State *guest_env = &guest_cpu->env; > + X86CPUClass *host_xcc = X86_CPU_CLASS(object_class_by_name(TYPE("host"))); > uint32_t mask; > int rv, i; > struct model_features_t ft[] = { > - {&guest_def->features, &host_def.features, > + {&guest_env->cpuid_features, &host_xcc->features, > ~0, feature_name, 0x00000000}, > - {&guest_def->ext_features, &host_def.ext_features, > + {&guest_env->cpuid_ext_features, &host_xcc->ext_features, > ~CPUID_EXT_HYPERVISOR, ext_feature_name, 0x00000001}, > - {&guest_def->ext2_features, &host_def.ext2_features, > + {&guest_env->cpuid_ext2_features, &host_xcc->ext2_features, > ~PPRO_FEATURES, ext2_feature_name, 0x80000000}, > - {&guest_def->ext3_features, &host_def.ext3_features, > + {&guest_env->cpuid_ext3_features, &host_xcc->ext3_features, > ~CPUID_EXT3_SVM, ext3_feature_name, 0x80000001}}; > > assert(kvm_enabled()); > > - kvm_cpu_fill_host(&host_def); > for (rv = 0, i = 0; i < ARRAY_SIZE(ft); ++i) > for (mask = 1; mask; mask <<= 1) > if (ft[i].check_feat & mask && *ft[i].guest_feat & mask && > @@ -1203,26 +1436,12 @@ static void x86_cpuid_set_tsc_freq(Object *obj, Visitor *v, void *opaque, > cpu->env.tsc_khz = value / 1000; > } > > -static int cpu_x86_find_by_name(x86_def_t *x86_cpu_def, const char *name) > -{ > - int i; > - > - for (i = 0; i < ARRAY_SIZE(builtin_x86_defs); i++) { > - x86_def_t *def = &builtin_x86_defs[i]; > - if (strcmp(name, def->name) == 0) { > - memcpy(x86_cpu_def, def, sizeof(*def)); > - return 0; > - } > - } > - > - return -1; > -} > - > /* Parse "+feature,-feature,feature=foo" CPU feature string > */ > -static int cpu_x86_parse_featurestr(x86_def_t *x86_cpu_def, char *features) > +static int cpu_x86_parse_featurestr(X86CPU *cpu, char *features) > { > - unsigned int i; > + CPUX86State *env = &cpu->env; > + Error *error = NULL; > char *featurestr; /* Single 'key=value" string being parsed */ > /* Features to be added */ > uint32_t plus_features = 0, plus_ext_features = 0; > @@ -1259,27 +1478,39 @@ static int cpu_x86_parse_featurestr(x86_def_t *x86_cpu_def, char *features) > if (!strcmp(featurestr, "family")) { > char *err; > numvalue = strtoul(val, &err, 0); > - if (!*val || *err || numvalue > 0xff + 0xf) { > + if (!*val || *err) { > fprintf(stderr, "bad numerical value %s\n", val); > goto error; > } > - x86_cpu_def->family = numvalue; > + object_property_set_int(OBJECT(cpu), numvalue, "family", > + &error); > + if (error != NULL) { > + goto error; > + } > } else if (!strcmp(featurestr, "model")) { > char *err; > numvalue = strtoul(val, &err, 0); > - if (!*val || *err || numvalue > 0xff) { > + if (!*val || *err) { > fprintf(stderr, "bad numerical value %s\n", val); > goto error; > } > - x86_cpu_def->model = numvalue; > + object_property_set_int(OBJECT(cpu), numvalue, "model", > + &error); > + if (error != NULL) { > + goto error; > + } > } else if (!strcmp(featurestr, "stepping")) { > char *err; > numvalue = strtoul(val, &err, 0); > - if (!*val || *err || numvalue > 0xf) { > + if (!*val || *err) { > fprintf(stderr, "bad numerical value %s\n", val); > goto error; > } > - x86_cpu_def->stepping = numvalue ; > + object_property_set_int(OBJECT(cpu), numvalue, "stepping", > + &error); > + if (error != NULL) { > + goto error; > + } > } else if (!strcmp(featurestr, "level")) { > char *err; > numvalue = strtoul(val, &err, 0); > @@ -1287,7 +1518,11 @@ static int cpu_x86_parse_featurestr(x86_def_t *x86_cpu_def, char *features) > fprintf(stderr, "bad numerical value %s\n", val); > goto error; > } > - x86_cpu_def->level = numvalue; > + object_property_set_int(OBJECT(cpu), numvalue, "level", > + &error); > + if (error != NULL) { > + goto error; > + } > } else if (!strcmp(featurestr, "xlevel")) { > char *err; > numvalue = strtoul(val, &err, 0); > @@ -1298,35 +1533,36 @@ static int cpu_x86_parse_featurestr(x86_def_t *x86_cpu_def, char *features) > if (numvalue < 0x80000000) { > numvalue += 0x80000000; > } > - x86_cpu_def->xlevel = numvalue; > - } else if (!strcmp(featurestr, "vendor")) { > - if (strlen(val) != 12) { > - fprintf(stderr, "vendor string must be 12 chars long\n"); > + object_property_set_int(OBJECT(cpu), numvalue, "xlevel", > + &error); > + if (error != NULL) { > goto error; > } > - x86_cpu_def->vendor1 = 0; > - x86_cpu_def->vendor2 = 0; > - x86_cpu_def->vendor3 = 0; > - for(i = 0; i < 4; i++) { > - x86_cpu_def->vendor1 |= ((uint8_t)val[i ]) << (8 * i); > - x86_cpu_def->vendor2 |= ((uint8_t)val[i + 4]) << (8 * i); > - x86_cpu_def->vendor3 |= ((uint8_t)val[i + 8]) << (8 * i); > + } else if (!strcmp(featurestr, "vendor")) { > + object_property_set_str(OBJECT(cpu), val, "vendor", &error); > + if (error != NULL) { > + goto error; > } > - x86_cpu_def->vendor_override = 1; > } else if (!strcmp(featurestr, "model_id")) { > - pstrcpy(x86_cpu_def->model_id, sizeof(x86_cpu_def->model_id), > - val); > + object_property_set_str(OBJECT(cpu), val, "model-id", &error); > + if (error != NULL) { > + goto error; > + } > } else if (!strcmp(featurestr, "tsc_freq")) { > int64_t tsc_freq; > char *err; > > tsc_freq = strtosz_suffix_unit(val, &err, > STRTOSZ_DEFSUFFIX_B, 1000); > - if (tsc_freq < 0 || *err) { > + if (*err) { > fprintf(stderr, "bad numerical value %s\n", val); > goto error; > } > - x86_cpu_def->tsc_khz = tsc_freq / 1000; > + object_property_set_int(OBJECT(cpu), tsc_freq, > + "tsc-frequency", &error); > + if (error != NULL) { > + goto error; > + } > } else if (!strcmp(featurestr, "hv_spinlocks")) { > char *err; > numvalue = strtoul(val, &err, 0); > @@ -1353,27 +1589,32 @@ static int cpu_x86_parse_featurestr(x86_def_t *x86_cpu_def, char *features) > } > featurestr = strtok(NULL, ","); > } > - x86_cpu_def->features |= plus_features; > - x86_cpu_def->ext_features |= plus_ext_features; > - x86_cpu_def->ext2_features |= plus_ext2_features; > - 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; > + env->cpuid_features |= plus_features; > + env->cpuid_ext_features |= plus_ext_features; > + env->cpuid_ext2_features |= plus_ext2_features; > + env->cpuid_ext3_features |= plus_ext3_features; > + env->cpuid_kvm_features |= plus_kvm_features; > + env->cpuid_svm_features |= plus_svm_features; > + env->cpuid_7_0_ebx_features |= plus_7_0_ebx_features; > + env->cpuid_features &= ~minus_features; > + env->cpuid_ext_features &= ~minus_ext_features; > + env->cpuid_ext2_features &= ~minus_ext2_features; > + env->cpuid_ext3_features &= ~minus_ext3_features; > + env->cpuid_kvm_features &= ~minus_kvm_features; > + env->cpuid_svm_features &= ~minus_svm_features; > + env->cpuid_7_0_ebx_features &= ~minus_7_0_ebx_features; > if (check_cpuid && kvm_enabled()) { > - if (kvm_check_features_against_host(x86_cpu_def) && enforce_cpuid) > + if (kvm_check_features_against_host(cpu) && enforce_cpuid) { > goto error; > + } > } > return 0; > > error: > + if (error != NULL) { > + fprintf(stderr, "%s\n", error_get_pretty(error)); > + error_free(error); > + } > return -1; > } > > @@ -1407,23 +1648,60 @@ static void listflags(char *buf, int bufsize, uint32_t fbits, > } > } > > +static ObjectClass *x86_cpu_class_by_name(const char *cpu_model) > +{ > + ObjectClass *oc; > + char *typename; > + > + oc = object_class_by_name(cpu_model); > + if (oc != NULL && object_class_dynamic_cast(oc, TYPE_X86_CPU) != NULL) { > + return oc; > + } > + > + typename = g_strdup_printf(TYPE("%s"), cpu_model); > + oc = object_class_by_name(typename); > + g_free(typename); > + if (oc != NULL && object_class_dynamic_cast(oc, TYPE_X86_CPU) != NULL) { > + return oc; > + } > + > + return NULL; > +} > + > /* generate CPU information. */ > + > +typedef struct X86CPUListState { > + fprintf_function cpu_fprintf; > + FILE *file; > +} X86CPUListState; > + > +static void x86_cpu_list_entry(gpointer data, gpointer user_data) > +{ > + ObjectClass *oc = data; > + X86CPUClass *xcc = X86_CPU_CLASS(oc); > + X86CPUListState *s = user_data; > + char buf[256]; > + > + snprintf(buf, MIN(sizeof(buf), strlen(object_class_get_name(oc)) > + - strlen("-" TYPE_X86_CPU) + 1), > + "%s", object_class_get_name(oc)); > + (*s->cpu_fprintf)(s->file, "x86 %16s %-48s\n", > + buf, xcc->model_id); > +} > + > void x86_cpu_list(FILE *f, fprintf_function cpu_fprintf) > { > - int i; > + X86CPUListState s = { > + .file = f, > + .cpu_fprintf = cpu_fprintf, > + }; > + GSList *list; > char buf[256]; > > - /* Force creation of CPU class */ > - object_class_by_name(TYPE_X86_CPU); > + list = object_class_get_list(TYPE_X86_CPU, false); > + g_slist_foreach(list, x86_cpu_list_entry, &s); > + g_slist_free(list); > > - for (i = 0; i < ARRAY_SIZE(builtin_x86_defs); i++) { > - x86_def_t *def = &builtin_x86_defs[i]; > - 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); > @@ -1435,25 +1713,38 @@ void x86_cpu_list(FILE *f, fprintf_function cpu_fprintf) > (*cpu_fprintf)(f, " %s\n", buf); > } > > -CpuDefinitionInfoList *arch_query_cpu_definitions(Error **errp) > -{ > - CpuDefinitionInfoList *cpu_list = NULL; > - int i; > +typedef struct X86CPUDefsState { > + CpuDefinitionInfoList *cpu_list; > +} X86CPUDefsState; > > - for (i = 0; i < ARRAY_SIZE(builtin_x86_defs); i++) { > - CpuDefinitionInfoList *entry; > - CpuDefinitionInfo *info; > +static void x86_cpu_defs_entry(gpointer data, gpointer user_data) > +{ > + ObjectClass *oc = data; > + X86CPUDefsState *s = user_data; > + CpuDefinitionInfoList *entry; > + CpuDefinitionInfo *info; > + > + info = g_malloc0(sizeof(*info)); > + info->name = g_strdup(object_class_get_name(oc)); > + > + entry = g_malloc0(sizeof(*entry)); > + entry->value = info; > + entry->next = s->cpu_list; > + s->cpu_list = entry; > +} > > - info = g_malloc0(sizeof(*info)); > - info->name = g_strdup(builtin_x86_defs[i].name); > +CpuDefinitionInfoList *arch_query_cpu_definitions(Error **errp) > +{ > + X86CPUDefsState s = { > + .cpu_list = NULL, > + }; > + GSList *list; > > - entry = g_malloc0(sizeof(*entry)); > - entry->value = info; > - entry->next = cpu_list; > - cpu_list = entry; > - } > + list = object_class_get_list(TYPE_X86_CPU, false); > + g_slist_foreach(list, x86_cpu_defs_entry, &s); > + g_slist_free(list); > > - return cpu_list; > + return s.cpu_list; > } > > #ifdef CONFIG_KVM > @@ -1482,16 +1773,16 @@ static void filter_features_for_kvm(X86CPU *cpu) > } > #endif > > -int cpu_x86_register(X86CPU *cpu, const char *cpu_model) > +X86CPU *cpu_x86_init(const char *cpu_model) > { > - CPUX86State *env = &cpu->env; > - x86_def_t def1, *def = &def1; > + X86CPU *cpu = NULL; > + CPUX86State *env; > + ObjectClass *oc; > + X86CPUClass *xcc; > Error *error = NULL; > char *name, *features; > gchar **model_pieces; > > - memset(def, 0, sizeof(*def)); > - > model_pieces = g_strsplit(cpu_model, ",", 2); > if (!model_pieces[0]) { > goto error; > @@ -1499,43 +1790,45 @@ int cpu_x86_register(X86CPU *cpu, const char *cpu_model) > name = model_pieces[0]; > features = model_pieces[1]; > > - if (kvm_enabled() && strcmp(name, "host") == 0) { > - kvm_cpu_fill_host(def); > - } else { > - if (cpu_x86_find_by_name(def, name) < 0) { > - goto error; > - } > + if (!kvm_enabled() && strcmp(name, "host") == 0) { > + goto error; > } > - > - if (cpu_x86_parse_featurestr(def, features) < 0) { > + oc = x86_cpu_class_by_name(name); > + if (oc == NULL) { > goto error; > } > - if (def->vendor1) { > - env->cpuid_vendor1 = def->vendor1; > - env->cpuid_vendor2 = def->vendor2; > - env->cpuid_vendor3 = def->vendor3; > + cpu = X86_CPU(object_new(object_class_get_name(oc))); > + env = &cpu->env; > + env->cpu_model_str = cpu_model; > + xcc = X86_CPU_GET_CLASS(cpu); > + > + if (xcc->vendor1) { > + env->cpuid_vendor1 = xcc->vendor1; > + env->cpuid_vendor2 = xcc->vendor2; > + env->cpuid_vendor3 = xcc->vendor3; > } else { > env->cpuid_vendor1 = CPUID_VENDOR_INTEL_1; > env->cpuid_vendor2 = CPUID_VENDOR_INTEL_2; > env->cpuid_vendor3 = CPUID_VENDOR_INTEL_3; > } > - env->cpuid_vendor_override = def->vendor_override; > - object_property_set_int(OBJECT(cpu), def->level, "level", &error); > - object_property_set_int(OBJECT(cpu), def->family, "family", &error); > - object_property_set_int(OBJECT(cpu), def->model, "model", &error); > - object_property_set_int(OBJECT(cpu), def->stepping, "stepping", &error); > - env->cpuid_features = def->features; > - env->cpuid_ext_features = def->ext_features; > - env->cpuid_ext2_features = def->ext2_features; > - env->cpuid_ext3_features = def->ext3_features; > - object_property_set_int(OBJECT(cpu), def->xlevel, "xlevel", &error); > - 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_features = def->cpuid_7_0_ebx_features; > - env->cpuid_xlevel2 = def->xlevel2; > - object_property_set_int(OBJECT(cpu), (int64_t)def->tsc_khz * 1000, > + env->cpuid_vendor_override = xcc->vendor_override; > + object_property_set_int(OBJECT(cpu), xcc->level, "level", &error); > + object_property_set_int(OBJECT(cpu), xcc->family, "family", &error); > + object_property_set_int(OBJECT(cpu), xcc->model, "model", &error); > + object_property_set_int(OBJECT(cpu), xcc->stepping, "stepping", &error); > + env->cpuid_features = xcc->features; > + env->cpuid_ext_features = xcc->ext_features; > + env->cpuid_ext2_features = xcc->ext2_features; > + env->cpuid_ext3_features = xcc->ext3_features; > + object_property_set_int(OBJECT(cpu), xcc->xlevel, "xlevel", &error); > + env->cpuid_kvm_features = xcc->kvm_features; > + env->cpuid_svm_features = xcc->svm_features; > + env->cpuid_ext4_features = xcc->ext4_features; > + env->cpuid_7_0_ebx_features = xcc->cpuid_7_0_ebx_features; > + env->cpuid_xlevel2 = xcc->xlevel2; > + object_property_set_int(OBJECT(cpu), (int64_t)xcc->tsc_khz * 1000, > "tsc-frequency", &error); > + object_property_set_str(OBJECT(cpu), xcc->model_id, "model-id", &error); > > /* On AMD CPUs, some CPUID[8000_0001].EDX bits must match the bits on > * CPUID[1].EDX. > @@ -1544,7 +1837,11 @@ int cpu_x86_register(X86CPU *cpu, const char *cpu_model) > 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); > + env->cpuid_ext2_features |= (xcc->features & CPUID_EXT2_AMD_ALIASES); > + } > + > + if (cpu_x86_parse_featurestr(cpu, features) < 0) { > + goto error; > } > > if (!kvm_enabled()) { > @@ -1562,7 +1859,13 @@ int cpu_x86_register(X86CPU *cpu, const char *cpu_model) > filter_features_for_kvm(cpu); > #endif > } > - object_property_set_str(OBJECT(cpu), def->model_id, "model-id", &error); > + if (error) { > + fprintf(stderr, "%s\n", error_get_pretty(error)); > + error_free(error); > + goto error; > + } > + > + x86_cpu_realize(OBJECT(cpu), &error); > if (error) { > fprintf(stderr, "%s\n", error_get_pretty(error)); > error_free(error); > @@ -1570,10 +1873,13 @@ int cpu_x86_register(X86CPU *cpu, const char *cpu_model) > } > > g_strfreev(model_pieces); > - return 0; > + return cpu; > error: > + if (cpu != NULL) { > + object_delete(OBJECT(cpu)); > + } > g_strfreev(model_pieces); > - return -1; > + return NULL; > } > > #if !defined(CONFIG_USER_ONLY) > @@ -1585,30 +1891,6 @@ void cpu_clear_apic_feature(CPUX86State *env) > > #endif /* !CONFIG_USER_ONLY */ > > -/* Initialize list of CPU models, filling some non-static fields if necessary > - */ > -static void x86_cpudef_setup(void) > -{ > - int i, j; > - static const char *model_with_versions[] = { "qemu32", "qemu64", "athlon" }; > - > - for (i = 0; i < ARRAY_SIZE(builtin_x86_defs); ++i) { > - x86_def_t *def = &builtin_x86_defs[i]; > - > - /* 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], 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; > - } > - } > - } > -} > - > static void get_cpuid_vendor(CPUX86State *env, uint32_t *ebx, > uint32_t *ecx, uint32_t *edx) > { > @@ -2140,8 +2422,6 @@ static void x86_cpu_common_class_init(ObjectClass *oc, void *data) > > xcc->parent_reset = cc->reset; > cc->reset = x86_cpu_reset; > - > - x86_cpudef_setup(); > } > > static const TypeInfo x86_cpu_type_info = { > @@ -2149,7 +2429,7 @@ static const TypeInfo x86_cpu_type_info = { > .parent = TYPE_CPU, > .instance_size = sizeof(X86CPU), > .instance_init = x86_cpu_initfn, > - .abstract = false, > + .abstract = true, > .class_size = sizeof(X86CPUClass), > .class_init = x86_cpu_common_class_init, > }; > @@ -2157,6 +2437,33 @@ static const TypeInfo x86_cpu_type_info = { > static void x86_cpu_register_types(void) > { > type_register_static(&x86_cpu_type_info); > + type_register_static(&qemu64_cpu_type_info); > + type_register_static(&phenom_cpu_type_info); > + type_register_static(&core2duo_cpu_type_info); > + type_register_static(&kvm64_cpu_type_info); > + type_register_static(&qemu32_cpu_type_info); > + type_register_static(&kvm32_cpu_type_info); > + type_register_static(&coreduo_cpu_type_info); > + type_register_static(&i486_cpu_type_info); > + type_register_static(&pentium_cpu_type_info); > + type_register_static(&pentium2_cpu_type_info); > + type_register_static(&pentium3_cpu_type_info); > + type_register_static(&athlon_cpu_type_info); > + type_register_static(&n270_cpu_type_info); > + type_register_static(&conroe_cpu_type_info); > + type_register_static(&penryn_cpu_type_info); > + type_register_static(&nehalem_cpu_type_info); > + type_register_static(&westmere_cpu_type_info); > + type_register_static(&sandybridge_cpu_type_info); > + type_register_static(&haswell_cpu_type_info); > + type_register_static(&opteron_g1_cpu_type_info); > + type_register_static(&opteron_g2_cpu_type_info); > + type_register_static(&opteron_g3_cpu_type_info); > + type_register_static(&opteron_g4_cpu_type_info); > + type_register_static(&opteron_g5_cpu_type_info); > +#ifdef CONFIG_KVM > + type_register_static(&kvm_host_cpu_type_info); > +#endif > } > > type_init(x86_cpu_register_types) > diff --git a/target-i386/helper.c b/target-i386/helper.c > index bf206cf..47b53ed 100644 > --- a/target-i386/helper.c > +++ b/target-i386/helper.c > @@ -1240,30 +1240,6 @@ int cpu_x86_get_descr_debug(CPUX86State *env, unsigned int selector, > return 1; > } > > -X86CPU *cpu_x86_init(const char *cpu_model) > -{ > - X86CPU *cpu; > - CPUX86State *env; > - Error *error = NULL; > - > - cpu = X86_CPU(object_new(TYPE_X86_CPU)); > - env = &cpu->env; > - env->cpu_model_str = cpu_model; > - > - if (cpu_x86_register(cpu, cpu_model) < 0) { > - object_delete(OBJECT(cpu)); > - return NULL; > - } > - > - x86_cpu_realize(OBJECT(cpu), &error); > - if (error) { > - error_free(error); > - object_delete(OBJECT(cpu)); > - return NULL; > - } > - return cpu; > -} > - > #if !defined(CONFIG_USER_ONLY) > void do_cpu_init(X86CPU *cpu) > { > -- > 1.7.10.4 > The patch is just renaming of the current builtin_x86_defs into a bunch of functions and polluting X86CPUClass with fields from the former x86_def_t. object_new() still creates a dummy cpu instance whose defaults are still manually copied from X86CPUClass instead of x86_def_t. What's the point in having dummy sub-classes? How it can help in your CPU re-factoring? On the other hand converting features to static properties first and then converting X86CPU to sub-classes, yields already initialized to defaults sub-class completely removing notion of x86_def_t and not polluting X86CPUClass with redundant fields. For example see following patches on https://github.com/imammedo/qemu/commits/x86-cpu-classes.Jan142013 e9fd18f qdev: extend DEFINE_GENERIC_PROP() to support default values c65eca9 qdev: make qdev_prop_find_bit return non const so prop default value could be modified 0311952 allow to expolit default value static props for model, family, stepping & vendor props 8b3080e target-i386: add helpers to change default values of static properties before object is created ed506d3 target-i386: prepare for subclasses to have its own instance of static properties definitions a48e252 target-i386: declare subclass for qemu64 cpu model 9c556c2 target-i386: move cpu_x86_init() & cpu_x86_register() into it and switch to subclasses. PS: implemended only for qemu64 f5dbfe6 CPU_CLASS_NAME(qemu64) hack 00e15b8 target-i386: properties list are per subclass: do not set them in superclass to avoid defaults set by subclass be over-written
On Tue, Jan 15, 2013 at 09:41:04AM +0100, Igor Mammedov wrote: > On Mon, 10 Dec 2012 23:59:31 +0100 > Andreas Färber <afaerber@suse.de> wrote: > > > TODO: sort classes for -cpu ?, generalize X86CPUListState, more testing > > > > Signed-off-by: Andreas Färber <afaerber@suse.de> > > Cc: Eduardo Habkost <ehabkost@redhat.com> > > Cc: Igor Mammedov <imammedo@redhat.com> [...] > The patch is just renaming of the current builtin_x86_defs > into a bunch of functions and polluting X86CPUClass > with fields from the former x86_def_t. > object_new() still creates a dummy cpu instance whose defaults > are still manually copied from X86CPUClass instead of x86_def_t. > That's a good thing, isn't it? It means the patch is easier to review. :-) No patch alone will do everything we want, because we want to do a lot. We need to do it one step at a time. (BTW, why are you looking at this RFC instead of the more recent one, that I have sent on Jan 4? [that's very similar to this one]) > What's the point in having dummy sub-classes? > How it can help in your CPU re-factoring? It will help us to unify the CPU creation/realization code that's duplicated over all the architectures. It will give libvirt an easy mechanism to list the available CPU models that won't require parsing help output (using "qom-list-types" QMP command). > > > On the other hand converting features to static properties first and > then converting X86CPU to sub-classes, yields already initialized to > defaults sub-class completely removing notion of x86_def_t and > not polluting X86CPUClass with redundant fields. I wouldn't disagree with this approach in principle, but I believe our main problem today is lack of reviewer bandwidth. I learned the hard way that trying to clean up everything before implementing something will make sure the code takes forever to be reviewed. > For example see following patches on > https://github.com/imammedo/qemu/commits/x86-cpu-classes.Jan142013 > > e9fd18f qdev: extend DEFINE_GENERIC_PROP() to support default values > c65eca9 qdev: make qdev_prop_find_bit return non const so prop default value could be modified > 0311952 allow to expolit default value static props for model, family, stepping & vendor props > 8b3080e target-i386: add helpers to change default values of static properties before object is created > ed506d3 target-i386: prepare for subclasses to have its own instance of static properties definitions > a48e252 target-i386: declare subclass for qemu64 cpu model > 9c556c2 target-i386: move cpu_x86_init() & cpu_x86_register() into it and switch to subclasses. PS: implemended only for qemu64 > f5dbfe6 CPU_CLASS_NAME(qemu64) hack > 00e15b8 target-i386: properties list are per subclass: do not set them in superclass to avoid defaults set by subclass be over-written > > -- > Regards, > Igor
diff --git a/target-i386/cpu-qom.h b/target-i386/cpu-qom.h index 5901140..19f5aa7 100644 --- a/target-i386/cpu-qom.h +++ b/target-i386/cpu-qom.h @@ -49,6 +49,23 @@ typedef struct X86CPUClass { /*< public >*/ void (*parent_reset)(CPUState *cpu); + + uint32_t level; + uint32_t vendor1, vendor2, vendor3; + int family; + int model; + int stepping; + int tsc_khz; + uint32_t features, ext_features, ext2_features, ext3_features; + uint32_t kvm_features, svm_features; + uint32_t xlevel; + char model_id[48]; + int vendor_override; + /* Store the results of Centaur's CPUID instructions */ + uint32_t ext4_features; + uint32_t xlevel2; + /* The feature bits on CPUID[EAX=7,ECX=0].EBX */ + uint32_t cpuid_7_0_ebx_features; } X86CPUClass; /** diff --git a/target-i386/cpu.c b/target-i386/cpu.c index 6465040..c59c6a5 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -271,26 +271,6 @@ static void add_flagname_to_bitmaps(const char *flagname, uint32_t *features, fprintf(stderr, "CPU feature %s not found\n", flagname); } -typedef struct x86_def_t { - const char *name; - uint32_t level; - uint32_t vendor1, vendor2, vendor3; - int family; - int model; - int stepping; - int tsc_khz; - uint32_t features, ext_features, ext2_features, ext3_features; - uint32_t kvm_features, svm_features; - uint32_t xlevel; - char model_id[48]; - int vendor_override; - /* Store the results of Centaur's CPUID instructions */ - uint32_t ext4_features; - uint32_t xlevel2; - /* The feature bits on CPUID[EAX=7,ECX=0].EBX */ - uint32_t cpuid_7_0_ebx_features; -} x86_def_t; - #define I486_FEATURES (CPUID_FP87 | CPUID_VME | CPUID_PSE) #define PENTIUM_FEATURES (I486_FEATURES | CPUID_DE | CPUID_TSC | \ CPUID_MSR | CPUID_MCE | CPUID_CX8 | CPUID_MMX | CPUID_APIC) @@ -331,488 +311,735 @@ typedef struct x86_def_t { /* built-in cpu model definitions */ -static x86_def_t builtin_x86_defs[] = { - { - .name = "qemu64", - .level = 4, - .vendor1 = CPUID_VENDOR_AMD_1, - .vendor2 = CPUID_VENDOR_AMD_2, - .vendor3 = CPUID_VENDOR_AMD_3, - .family = 6, - .model = 2, - .stepping = 3, - .features = PPRO_FEATURES | + +#define TYPE(x) x "-" TYPE_X86_CPU + +static void qemu64_cpu_class_init(ObjectClass *oc, void *data) +{ + X86CPUClass *xcc = X86_CPU_CLASS(oc); + xcc->level = 4; + xcc->vendor1 = CPUID_VENDOR_AMD_1; + xcc->vendor2 = CPUID_VENDOR_AMD_2; + xcc->vendor3 = CPUID_VENDOR_AMD_3; + xcc->family = 6; + xcc->model = 2; + xcc->stepping = 3; + xcc->features = PPRO_FEATURES | CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA | - CPUID_PSE36, - .ext_features = CPUID_EXT_SSE3 | CPUID_EXT_CX16 | CPUID_EXT_POPCNT, - .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, - .xlevel = 0x8000000A, - }, - { - .name = "phenom", - .level = 5, - .vendor1 = CPUID_VENDOR_AMD_1, - .vendor2 = CPUID_VENDOR_AMD_2, - .vendor3 = CPUID_VENDOR_AMD_3, - .family = 16, - .model = 2, - .stepping = 3, - .features = PPRO_FEATURES | + CPUID_PSE36; + xcc->ext_features = CPUID_EXT_SSE3 | CPUID_EXT_CX16 | CPUID_EXT_POPCNT; + xcc->ext2_features = (PPRO_FEATURES & CPUID_EXT2_AMD_ALIASES) | + CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX; + xcc->ext3_features = CPUID_EXT3_LAHF_LM | CPUID_EXT3_SVM | + CPUID_EXT3_ABM | CPUID_EXT3_SSE4A; + xcc->xlevel = 0x8000000A; + + pstrcpy(xcc->model_id, sizeof(xcc->model_id), + "QEMU Virtual CPU version "); + pstrcat(xcc->model_id, sizeof(xcc->model_id), + qemu_get_version()); +} + +static const TypeInfo qemu64_cpu_type_info = { + .name = TYPE("qemu64"), + .parent = TYPE_X86_CPU, + .class_init = qemu64_cpu_class_init, +}; + +static void phenom_cpu_class_init(ObjectClass *oc, void *data) +{ + X86CPUClass *xcc = X86_CPU_CLASS(oc); + + xcc->level = 5; + xcc->vendor1 = CPUID_VENDOR_AMD_1; + xcc->vendor2 = CPUID_VENDOR_AMD_2; + xcc->vendor3 = CPUID_VENDOR_AMD_3; + xcc->family = 16; + xcc->model = 2; + xcc->stepping = 3; + xcc->features = PPRO_FEATURES | CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA | - CPUID_PSE36 | CPUID_VME | CPUID_HT, - .ext_features = CPUID_EXT_SSE3 | CPUID_EXT_MONITOR | CPUID_EXT_CX16 | - CPUID_EXT_POPCNT, - .ext2_features = (PPRO_FEATURES & CPUID_EXT2_AMD_ALIASES) | + CPUID_PSE36 | CPUID_VME | CPUID_HT; + xcc->ext_features = CPUID_EXT_SSE3 | CPUID_EXT_MONITOR | CPUID_EXT_CX16 | + CPUID_EXT_POPCNT; + xcc->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, + CPUID_EXT2_FFXSR | CPUID_EXT2_PDPE1GB | CPUID_EXT2_RDTSCP; /* Missing: CPUID_EXT3_CMP_LEG, CPUID_EXT3_EXTAPIC, CPUID_EXT3_CR8LEG, CPUID_EXT3_MISALIGNSSE, CPUID_EXT3_3DNOWPREFETCH, CPUID_EXT3_OSVW, CPUID_EXT3_IBS */ - .ext3_features = CPUID_EXT3_LAHF_LM | CPUID_EXT3_SVM | - CPUID_EXT3_ABM | CPUID_EXT3_SSE4A, - .svm_features = CPUID_SVM_NPT | CPUID_SVM_LBRV, - .xlevel = 0x8000001A, - .model_id = "AMD Phenom(tm) 9550 Quad-Core Processor" - }, - { - .name = "core2duo", - .level = 10, - .family = 6, - .model = 15, - .stepping = 11, - .features = PPRO_FEATURES | + xcc->ext3_features = CPUID_EXT3_LAHF_LM | CPUID_EXT3_SVM | + CPUID_EXT3_ABM | CPUID_EXT3_SSE4A; + xcc->svm_features = CPUID_SVM_NPT | CPUID_SVM_LBRV; + xcc->xlevel = 0x8000001A; + pstrcpy(xcc->model_id, sizeof(xcc->model_id), + "AMD Phenom(tm) 9550 Quad-Core Processor"); +} + +static const TypeInfo phenom_cpu_type_info = { + .name = TYPE("phenom"), + .parent = TYPE_X86_CPU, + .class_init = phenom_cpu_class_init, +}; + +static void core2duo_cpu_class_init(ObjectClass *oc, void *data) +{ + X86CPUClass *xcc = X86_CPU_CLASS(oc); + + xcc->level = 10; + xcc->family = 6; + xcc->model = 15; + xcc->stepping = 11; + xcc->features = PPRO_FEATURES | CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA | CPUID_PSE36 | CPUID_VME | CPUID_DTS | CPUID_ACPI | CPUID_SS | - CPUID_HT | CPUID_TM | CPUID_PBE, - .ext_features = CPUID_EXT_SSE3 | CPUID_EXT_MONITOR | CPUID_EXT_SSSE3 | + CPUID_HT | CPUID_TM | CPUID_PBE; + xcc->ext_features = CPUID_EXT_SSE3 | CPUID_EXT_MONITOR | CPUID_EXT_SSSE3 | CPUID_EXT_DTES64 | CPUID_EXT_DSCPL | CPUID_EXT_VMX | CPUID_EXT_EST | - CPUID_EXT_TM2 | CPUID_EXT_CX16 | CPUID_EXT_XTPR | CPUID_EXT_PDCM, - .ext2_features = CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX, - .ext3_features = CPUID_EXT3_LAHF_LM, - .xlevel = 0x80000008, - .model_id = "Intel(R) Core(TM)2 Duo CPU T7700 @ 2.40GHz", - }, - { - .name = "kvm64", - .level = 5, - .vendor1 = CPUID_VENDOR_INTEL_1, - .vendor2 = CPUID_VENDOR_INTEL_2, - .vendor3 = CPUID_VENDOR_INTEL_3, - .family = 15, - .model = 6, - .stepping = 1, + CPUID_EXT_TM2 | CPUID_EXT_CX16 | CPUID_EXT_XTPR | CPUID_EXT_PDCM; + xcc->ext2_features = CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX; + xcc->ext3_features = CPUID_EXT3_LAHF_LM; + xcc->xlevel = 0x80000008; + pstrcpy(xcc->model_id, sizeof(xcc->model_id), + "Intel(R) Core(TM)2 Duo CPU T7700 @ 2.40GHz"); +} + +static const TypeInfo core2duo_cpu_type_info = { + .name = TYPE("core2duo"), + .parent = TYPE_X86_CPU, + .class_init = core2duo_cpu_class_init, +}; + +static void kvm64_cpu_class_init(ObjectClass *oc, void *data) +{ + X86CPUClass *xcc = X86_CPU_CLASS(oc); + + xcc->level = 5; + xcc->vendor1 = CPUID_VENDOR_INTEL_1; + xcc->vendor2 = CPUID_VENDOR_INTEL_2; + xcc->vendor3 = CPUID_VENDOR_INTEL_3; + xcc->family = 15; + xcc->model = 6; + xcc->stepping = 1; /* Missing: CPUID_VME, CPUID_HT */ - .features = PPRO_FEATURES | + xcc->features = PPRO_FEATURES | CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA | - CPUID_PSE36, + CPUID_PSE36; /* Missing: CPUID_EXT_POPCNT, CPUID_EXT_MONITOR */ - .ext_features = CPUID_EXT_SSE3 | CPUID_EXT_CX16, + xcc->ext_features = CPUID_EXT_SSE3 | CPUID_EXT_CX16; /* Missing: CPUID_EXT2_PDPE1GB, CPUID_EXT2_RDTSCP */ - .ext2_features = (PPRO_FEATURES & CPUID_EXT2_AMD_ALIASES) | - CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX, + xcc->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, CPUID_EXT3_MISALIGNSSE, CPUID_EXT3_3DNOWPREFETCH, CPUID_EXT3_OSVW, CPUID_EXT3_IBS, CPUID_EXT3_SVM */ - .ext3_features = 0, - .xlevel = 0x80000008, - .model_id = "Common KVM processor" - }, - { - .name = "qemu32", - .level = 4, - .family = 6, - .model = 3, - .stepping = 3, - .features = PPRO_FEATURES, - .ext_features = CPUID_EXT_SSE3 | CPUID_EXT_POPCNT, - .xlevel = 0x80000004, - }, - { - .name = "kvm32", - .level = 5, - .family = 15, - .model = 6, - .stepping = 1, - .features = PPRO_FEATURES | - CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA | CPUID_PSE36, - .ext_features = CPUID_EXT_SSE3, - .ext2_features = PPRO_FEATURES & CPUID_EXT2_AMD_ALIASES, - .ext3_features = 0, - .xlevel = 0x80000008, - .model_id = "Common 32-bit KVM processor" - }, - { - .name = "coreduo", - .level = 10, - .family = 6, - .model = 14, - .stepping = 8, - .features = PPRO_FEATURES | CPUID_VME | + xcc->ext3_features = 0; + xcc->xlevel = 0x80000008; + pstrcpy(xcc->model_id, sizeof(xcc->model_id), + "Common KVM processor"); +} + +static const TypeInfo kvm64_cpu_type_info = { + .name = TYPE("kvm64"), + .parent = TYPE_X86_CPU, + .class_init = kvm64_cpu_class_init, +}; + +static void qemu32_cpu_class_init(ObjectClass *oc, void *data) +{ + X86CPUClass *xcc = X86_CPU_CLASS(oc); + + xcc->level = 4; + xcc->family = 6; + xcc->model = 3; + xcc->stepping = 3; + xcc->features = PPRO_FEATURES; + xcc->ext_features = CPUID_EXT_SSE3 | CPUID_EXT_POPCNT; + xcc->xlevel = 0x80000004; + + pstrcpy(xcc->model_id, sizeof(xcc->model_id), + "QEMU Virtual CPU version "); + pstrcat(xcc->model_id, sizeof(xcc->model_id), + qemu_get_version()); +} + +static const TypeInfo qemu32_cpu_type_info = { + .name = TYPE("qemu32"), + .parent = TYPE_X86_CPU, + .class_init = qemu32_cpu_class_init, +}; + +static void kvm32_cpu_class_init(ObjectClass *oc, void *data) +{ + X86CPUClass *xcc = X86_CPU_CLASS(oc); + + xcc->level = 5; + xcc->family = 15; + xcc->model = 6; + xcc->stepping = 1; + xcc->features = PPRO_FEATURES | + CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA | CPUID_PSE36; + xcc->ext_features = CPUID_EXT_SSE3; + xcc->ext2_features = PPRO_FEATURES & CPUID_EXT2_AMD_ALIASES; + xcc->ext3_features = 0; + xcc->xlevel = 0x80000008; + pstrcpy(xcc->model_id, sizeof(xcc->model_id), + "Common 32-bit KVM processor"); +} + +static const TypeInfo kvm32_cpu_type_info = { + .name = TYPE("kvm32"), + .parent = TYPE_X86_CPU, + .class_init = kvm32_cpu_class_init, +}; + +static void coreduo_cpu_class_init(ObjectClass *oc, void *data) +{ + X86CPUClass *xcc = X86_CPU_CLASS(oc); + + xcc->level = 10; + xcc->family = 6; + xcc->model = 14; + xcc->stepping = 8; + xcc->features = PPRO_FEATURES | CPUID_VME | CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA | CPUID_DTS | CPUID_ACPI | - CPUID_SS | CPUID_HT | CPUID_TM | CPUID_PBE, - .ext_features = CPUID_EXT_SSE3 | CPUID_EXT_MONITOR | CPUID_EXT_VMX | - CPUID_EXT_EST | CPUID_EXT_TM2 | CPUID_EXT_XTPR | CPUID_EXT_PDCM, - .ext2_features = CPUID_EXT2_NX, - .xlevel = 0x80000008, - .model_id = "Genuine Intel(R) CPU T2600 @ 2.16GHz", - }, - { - .name = "486", - .level = 1, - .family = 4, - .model = 0, - .stepping = 0, - .features = I486_FEATURES, - .xlevel = 0, - }, - { - .name = "pentium", - .level = 1, - .family = 5, - .model = 4, - .stepping = 3, - .features = PENTIUM_FEATURES, - .xlevel = 0, - }, - { - .name = "pentium2", - .level = 2, - .family = 6, - .model = 5, - .stepping = 2, - .features = PENTIUM2_FEATURES, - .xlevel = 0, - }, - { - .name = "pentium3", - .level = 2, - .family = 6, - .model = 7, - .stepping = 3, - .features = PENTIUM3_FEATURES, - .xlevel = 0, - }, - { - .name = "athlon", - .level = 2, - .vendor1 = CPUID_VENDOR_AMD_1, - .vendor2 = CPUID_VENDOR_AMD_2, - .vendor3 = CPUID_VENDOR_AMD_3, - .family = 6, - .model = 2, - .stepping = 3, - .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, - }, - { - .name = "n270", - /* original is on level 10 */ - .level = 5, - .family = 6, - .model = 28, - .stepping = 2, - .features = PPRO_FEATURES | + CPUID_SS | CPUID_HT | CPUID_TM | CPUID_PBE; + xcc->ext_features = CPUID_EXT_SSE3 | CPUID_EXT_MONITOR | CPUID_EXT_VMX | + CPUID_EXT_EST | CPUID_EXT_TM2 | CPUID_EXT_XTPR | CPUID_EXT_PDCM; + xcc->ext2_features = CPUID_EXT2_NX; + xcc->xlevel = 0x80000008; + pstrcpy(xcc->model_id, sizeof(xcc->model_id), + "Genuine Intel(R) CPU T2600 @ 2.16GHz"); +} + +static const TypeInfo coreduo_cpu_type_info = { + .name = TYPE("coreduo"), + .parent = TYPE_X86_CPU, + .class_init = coreduo_cpu_class_init, +}; + +static void i486_cpu_class_init(ObjectClass *oc, void *data) +{ + X86CPUClass *xcc = X86_CPU_CLASS(oc); + + xcc->level = 1; + xcc->family = 4; + xcc->model = 0; + xcc->stepping = 0; + xcc->features = I486_FEATURES; + xcc->xlevel = 0; +} + +static const TypeInfo i486_cpu_type_info = { + .name = TYPE("486"), + .parent = TYPE_X86_CPU, + .class_init = i486_cpu_class_init, +}; + +static void pentium_cpu_class_init(ObjectClass *oc, void *data) +{ + X86CPUClass *xcc = X86_CPU_CLASS(oc); + + xcc->level = 1; + xcc->family = 5; + xcc->model = 4; + xcc->stepping = 3; + xcc->features = PENTIUM_FEATURES; + xcc->xlevel = 0; +} + +static const TypeInfo pentium_cpu_type_info = { + .name = TYPE("pentium"), + .parent = TYPE_X86_CPU, + .class_init = pentium_cpu_class_init, +}; + +static void pentium2_cpu_class_init(ObjectClass *oc, void *data) +{ + X86CPUClass *xcc = X86_CPU_CLASS(oc); + + xcc->level = 2; + xcc->family = 6; + xcc->model = 5; + xcc->stepping = 2; + xcc->features = PENTIUM2_FEATURES; + xcc->xlevel = 0; +} + +static const TypeInfo pentium2_cpu_type_info = { + .name = TYPE("pentium2"), + .parent = TYPE_X86_CPU, + .class_init = pentium2_cpu_class_init, +}; + +static void pentium3_cpu_class_init(ObjectClass *oc, void *data) +{ + X86CPUClass *xcc = X86_CPU_CLASS(oc); + + xcc->level = 2; + xcc->family = 6; + xcc->model = 7; + xcc->stepping = 3; + xcc->features = PENTIUM3_FEATURES; + xcc->xlevel = 0; +} + +static const TypeInfo pentium3_cpu_type_info = { + .name = TYPE("pentium3"), + .parent = TYPE_X86_CPU, + .class_init = pentium3_cpu_class_init, +}; + +static void athlon_cpu_class_init(ObjectClass *oc, void *data) +{ + X86CPUClass *xcc = X86_CPU_CLASS(oc); + + xcc->level = 2; + xcc->vendor1 = CPUID_VENDOR_AMD_1; + xcc->vendor2 = CPUID_VENDOR_AMD_2; + xcc->vendor3 = CPUID_VENDOR_AMD_3; + xcc->family = 6; + xcc->model = 2; + xcc->stepping = 3; + xcc->features = PPRO_FEATURES | CPUID_PSE36 | CPUID_VME | CPUID_MTRR | + CPUID_MCA; + xcc->ext2_features = (PPRO_FEATURES & CPUID_EXT2_AMD_ALIASES) | + CPUID_EXT2_MMXEXT | CPUID_EXT2_3DNOW | CPUID_EXT2_3DNOWEXT; + xcc->xlevel = 0x80000008; + + pstrcpy(xcc->model_id, sizeof(xcc->model_id), + "QEMU Virtual CPU version "); + pstrcat(xcc->model_id, sizeof(xcc->model_id), + qemu_get_version()); +} + +static const TypeInfo athlon_cpu_type_info = { + .name = TYPE("athlon"), + .parent = TYPE_X86_CPU, + .class_init = athlon_cpu_class_init, +}; + +static void n270_cpu_class_init(ObjectClass *oc, void *data) +{ + X86CPUClass *xcc = X86_CPU_CLASS(oc); + + /* original is on level 10 */ + xcc->level = 5; + xcc->family = 6; + xcc->model = 28; + xcc->stepping = 2; + xcc->features = PPRO_FEATURES | CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA | CPUID_VME | CPUID_DTS | - CPUID_ACPI | CPUID_SS | CPUID_HT | CPUID_TM | CPUID_PBE, + CPUID_ACPI | CPUID_SS | CPUID_HT | CPUID_TM | CPUID_PBE; /* 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 & 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 | + xcc->ext_features = CPUID_EXT_SSE3 | CPUID_EXT_MONITOR | CPUID_EXT_SSSE3 | + CPUID_EXT_DSCPL | CPUID_EXT_EST | CPUID_EXT_TM2 | CPUID_EXT_XTPR; + xcc->ext2_features = (PPRO_FEATURES & CPUID_EXT2_AMD_ALIASES) | + CPUID_EXT2_NX; + xcc->ext3_features = CPUID_EXT3_LAHF_LM; + xcc->xlevel = 0x8000000A; + pstrcpy(xcc->model_id, sizeof(xcc->model_id), + "Intel(R) Atom(TM) CPU N270 @ 1.60GHz"); +} + +static const TypeInfo n270_cpu_type_info = { + .name = TYPE("n270"), + .parent = TYPE_X86_CPU, + .class_init = n270_cpu_class_init, +}; + +static void conroe_cpu_class_init(ObjectClass *oc, void *data) +{ + X86CPUClass *xcc = X86_CPU_CLASS(oc); + + xcc->level = 2; + xcc->vendor1 = CPUID_VENDOR_INTEL_1; + xcc->vendor2 = CPUID_VENDOR_INTEL_2; + xcc->vendor3 = CPUID_VENDOR_INTEL_3; + xcc->family = 6; + xcc->model = 2; + xcc->stepping = 3; + xcc->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_DE | CPUID_FP87; + xcc->ext_features = CPUID_EXT_SSSE3 | CPUID_EXT_SSE3; + xcc->ext2_features = CPUID_EXT2_LM | CPUID_EXT2_NX | CPUID_EXT2_SYSCALL; + xcc->ext3_features = CPUID_EXT3_LAHF_LM; + xcc->xlevel = 0x8000000A; + pstrcpy(xcc->model_id, sizeof(xcc->model_id), + "Intel Celeron_4x0 (Conroe/Merom Class Core 2)"); +} + +static const TypeInfo conroe_cpu_type_info = { + .name = TYPE("Conroe"), + .parent = TYPE_X86_CPU, + .class_init = conroe_cpu_class_init, +}; + +static void penryn_cpu_class_init(ObjectClass *oc, void *data) +{ + X86CPUClass *xcc = X86_CPU_CLASS(oc); + + xcc->level = 2; + xcc->vendor1 = CPUID_VENDOR_INTEL_1; + xcc->vendor2 = CPUID_VENDOR_INTEL_2; + xcc->vendor3 = CPUID_VENDOR_INTEL_3; + xcc->family = 6; + xcc->model = 2; + xcc->stepping = 3; + xcc->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_DE | CPUID_FP87; + xcc->ext_features = CPUID_EXT_SSE41 | CPUID_EXT_CX16 | CPUID_EXT_SSSE3 | + CPUID_EXT_SSE3; + xcc->ext2_features = CPUID_EXT2_LM | CPUID_EXT2_NX | CPUID_EXT2_SYSCALL; + xcc->ext3_features = CPUID_EXT3_LAHF_LM; + xcc->xlevel = 0x8000000A; + pstrcpy(xcc->model_id, sizeof(xcc->model_id), + "Intel Core 2 Duo P9xxx (Penryn Class Core 2)"); +} + +static const TypeInfo penryn_cpu_type_info = { + .name = TYPE("Penryn"), + .parent = TYPE_X86_CPU, + .class_init = penryn_cpu_class_init, +}; + +static void nehalem_cpu_class_init(ObjectClass *oc, void *data) +{ + X86CPUClass *xcc = X86_CPU_CLASS(oc); + + xcc->level = 2; + xcc->vendor1 = CPUID_VENDOR_INTEL_1; + xcc->vendor2 = CPUID_VENDOR_INTEL_2; + xcc->vendor3 = CPUID_VENDOR_INTEL_3; + xcc->family = 6; + xcc->model = 2; + xcc->stepping = 3; + xcc->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_DE | CPUID_FP87; + xcc->ext_features = CPUID_EXT_POPCNT | CPUID_EXT_SSE42 | CPUID_EXT_SSE41 | + CPUID_EXT_CX16 | CPUID_EXT_SSSE3 | CPUID_EXT_SSE3; + xcc->ext2_features = CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX; + xcc->ext3_features = CPUID_EXT3_LAHF_LM; + xcc->xlevel = 0x8000000A; + pstrcpy(xcc->model_id, sizeof(xcc->model_id), + "Intel Core i7 9xx (Nehalem Class Core i7)"); +} + +static const TypeInfo nehalem_cpu_type_info = { + .name = TYPE("Nehalem"), + .parent = TYPE_X86_CPU, + .class_init = nehalem_cpu_class_init, +}; + +static void westmere_cpu_class_init(ObjectClass *oc, void *data) +{ + X86CPUClass *xcc = X86_CPU_CLASS(oc); + + xcc->level = 11; + xcc->vendor1 = CPUID_VENDOR_INTEL_1; + xcc->vendor2 = CPUID_VENDOR_INTEL_2; + xcc->vendor3 = CPUID_VENDOR_INTEL_3; + xcc->family = 6; + xcc->model = 44; + xcc->stepping = 1; + xcc->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_DE | CPUID_FP87; + xcc->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_EXT_SSE3; + xcc->ext2_features = CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX; + xcc->ext3_features = CPUID_EXT3_LAHF_LM; + xcc->xlevel = 0x8000000A; + pstrcpy(xcc->model_id, sizeof(xcc->model_id), + "Westmere E56xx/L56xx/X56xx (Nehalem-C)"); +} + +static const TypeInfo westmere_cpu_type_info = { + .name = TYPE("Westmere"), + .parent = TYPE_X86_CPU, + .class_init = westmere_cpu_class_init, +}; + +static void sandybridge_cpu_class_init(ObjectClass *oc, void *data) +{ + X86CPUClass *xcc = X86_CPU_CLASS(oc); + + xcc->level = 0xd; + xcc->vendor1 = CPUID_VENDOR_INTEL_1; + xcc->vendor2 = CPUID_VENDOR_INTEL_2; + xcc->vendor3 = CPUID_VENDOR_INTEL_3; + xcc->family = 6; + xcc->model = 42; + xcc->stepping = 1; + xcc->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_DE | CPUID_FP87; + xcc->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 = "Haswell", - .level = 0xd, - .vendor1 = CPUID_VENDOR_INTEL_1, - .vendor2 = CPUID_VENDOR_INTEL_2, - .vendor3 = CPUID_VENDOR_INTEL_3, - .family = 6, - .model = 60, - .stepping = 1, - .features = CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX | + CPUID_EXT_SSE3; + xcc->ext2_features = CPUID_EXT2_LM | CPUID_EXT2_RDTSCP | CPUID_EXT2_NX | + CPUID_EXT2_SYSCALL; + xcc->ext3_features = CPUID_EXT3_LAHF_LM; + xcc->xlevel = 0x8000000A; + pstrcpy(xcc->model_id, sizeof(xcc->model_id), + "Intel Xeon E312xx (Sandy Bridge)"); +} + +static const TypeInfo sandybridge_cpu_type_info = { + .name = TYPE("SandyBridge"), + .parent = TYPE_X86_CPU, + .class_init = sandybridge_cpu_class_init, +}; + +static void haswell_cpu_class_init(ObjectClass *oc, void *data) +{ + X86CPUClass *xcc = X86_CPU_CLASS(oc); + + xcc->level = 0xd; + xcc->vendor1 = CPUID_VENDOR_INTEL_1; + xcc->vendor2 = CPUID_VENDOR_INTEL_2; + xcc->vendor3 = CPUID_VENDOR_INTEL_3; + xcc->family = 6; + xcc->model = 60; + xcc->stepping = 1; + xcc->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_DE | CPUID_FP87; + xcc->ext_features = CPUID_EXT_AVX | CPUID_EXT_XSAVE | CPUID_EXT_AES | CPUID_EXT_POPCNT | CPUID_EXT_X2APIC | CPUID_EXT_SSE42 | CPUID_EXT_SSE41 | CPUID_EXT_CX16 | CPUID_EXT_SSSE3 | CPUID_EXT_PCLMULQDQ | CPUID_EXT_SSE3 | CPUID_EXT_TSC_DEADLINE_TIMER | CPUID_EXT_FMA | CPUID_EXT_MOVBE | - CPUID_EXT_PCID, - .ext2_features = CPUID_EXT2_LM | CPUID_EXT2_RDTSCP | CPUID_EXT2_NX | - CPUID_EXT2_SYSCALL, - .ext3_features = CPUID_EXT3_LAHF_LM, - .cpuid_7_0_ebx_features = CPUID_7_0_EBX_FSGSBASE | CPUID_7_0_EBX_BMI1 | + CPUID_EXT_PCID; + xcc->ext2_features = CPUID_EXT2_LM | CPUID_EXT2_RDTSCP | CPUID_EXT2_NX | + CPUID_EXT2_SYSCALL; + xcc->ext3_features = CPUID_EXT3_LAHF_LM; + xcc->cpuid_7_0_ebx_features = CPUID_7_0_EBX_FSGSBASE | CPUID_7_0_EBX_BMI1 | CPUID_7_0_EBX_HLE | CPUID_7_0_EBX_AVX2 | CPUID_7_0_EBX_SMEP | CPUID_7_0_EBX_BMI2 | CPUID_7_0_EBX_ERMS | CPUID_7_0_EBX_INVPCID | - CPUID_7_0_EBX_RTM, - .xlevel = 0x8000000A, - .model_id = "Intel Core Processor (Haswell)", - }, - { - .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_7_0_EBX_RTM; + xcc->xlevel = 0x8000000A; + pstrcpy(xcc->model_id, sizeof(xcc->model_id), + "Intel Core Processor (Haswell)"); +} + +static const TypeInfo haswell_cpu_type_info = { + .name = TYPE("Haswell"), + .parent = TYPE_X86_CPU, + .class_init = haswell_cpu_class_init, +}; + +static void opteron_g1_cpu_class_init(ObjectClass *oc, void *data) +{ + X86CPUClass *xcc = X86_CPU_CLASS(oc); + + xcc->level = 5; + xcc->vendor1 = CPUID_VENDOR_AMD_1; + xcc->vendor2 = CPUID_VENDOR_AMD_2; + xcc->vendor3 = CPUID_VENDOR_AMD_3; + xcc->family = 15; + xcc->model = 6; + xcc->stepping = 1; + xcc->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_DE | CPUID_FP87; + xcc->ext_features = CPUID_EXT_SSE3; + xcc->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_EXT2_TSC | CPUID_EXT2_PSE | CPUID_EXT2_DE | CPUID_EXT2_FPU; + xcc->xlevel = 0x80000008; + pstrcpy(xcc->model_id, sizeof(xcc->model_id), + "AMD Opteron 240 (Gen 1 Class Opteron)"); +} + +static const TypeInfo opteron_g1_cpu_type_info = { + .name = TYPE("Opteron_G1"), + .parent = TYPE_X86_CPU, + .class_init = opteron_g1_cpu_class_init, +}; + +static void opteron_g2_cpu_class_init(ObjectClass *oc, void *data) +{ + X86CPUClass *xcc = X86_CPU_CLASS(oc); + + xcc->level = 5; + xcc->vendor1 = CPUID_VENDOR_AMD_1; + xcc->vendor2 = CPUID_VENDOR_AMD_2; + xcc->vendor3 = CPUID_VENDOR_AMD_3; + xcc->family = 15; + xcc->model = 6; + xcc->stepping = 1; + xcc->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_DE | CPUID_FP87; + xcc->ext_features = CPUID_EXT_CX16 | CPUID_EXT_SSE3; + xcc->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_EXT2_DE | CPUID_EXT2_FPU; + xcc->ext3_features = CPUID_EXT3_SVM | CPUID_EXT3_LAHF_LM; + xcc->xlevel = 0x80000008; + pstrcpy(xcc->model_id, sizeof(xcc->model_id), + "AMD Opteron 22xx (Gen 2 Class Opteron)"); +} + +static const TypeInfo opteron_g2_cpu_type_info = { + .name = TYPE("Opteron_G2"), + .parent = TYPE_X86_CPU, + .class_init = opteron_g2_cpu_class_init, +}; + +static void opteron_g3_cpu_class_init(ObjectClass *oc, void *data) +{ + X86CPUClass *xcc = X86_CPU_CLASS(oc); + + xcc->level = 5; + xcc->vendor1 = CPUID_VENDOR_AMD_1; + xcc->vendor2 = CPUID_VENDOR_AMD_2; + xcc->vendor3 = CPUID_VENDOR_AMD_3; + xcc->family = 15; + xcc->model = 6; + xcc->stepping = 1; + xcc->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_DE | CPUID_FP87; + xcc->ext_features = CPUID_EXT_POPCNT | CPUID_EXT_CX16 | CPUID_EXT_MONITOR | + CPUID_EXT_SSE3; + xcc->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_EXT2_DE | CPUID_EXT2_FPU; + xcc->ext3_features = CPUID_EXT3_MISALIGNSSE | CPUID_EXT3_SSE4A | + CPUID_EXT3_ABM | CPUID_EXT3_SVM | CPUID_EXT3_LAHF_LM; + xcc->xlevel = 0x80000008; + pstrcpy(xcc->model_id, sizeof(xcc->model_id), + "AMD Opteron 23xx (Gen 3 Class Opteron)"); +} + +static const TypeInfo opteron_g3_cpu_type_info = { + .name = TYPE("Opteron_G3"), + .parent = TYPE_X86_CPU, + .class_init = opteron_g3_cpu_class_init, +}; + +static void opteron_g4_cpu_class_init(ObjectClass *oc, void *data) +{ + X86CPUClass *xcc = X86_CPU_CLASS(oc); + + xcc->level = 0xd; + xcc->vendor1 = CPUID_VENDOR_AMD_1; + xcc->vendor2 = CPUID_VENDOR_AMD_2; + xcc->vendor3 = CPUID_VENDOR_AMD_3; + xcc->family = 21; + xcc->model = 1; + xcc->stepping = 2; + xcc->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_DE | CPUID_FP87; + xcc->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_EXT_SSE3; + xcc->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_EXT2_TSC | CPUID_EXT2_PSE | CPUID_EXT2_DE | CPUID_EXT2_FPU; + xcc->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", - }, - { - .name = "Opteron_G5", - .level = 0xd, - .vendor1 = CPUID_VENDOR_AMD_1, - .vendor2 = CPUID_VENDOR_AMD_2, - .vendor3 = CPUID_VENDOR_AMD_3, - .family = 21, - .model = 2, - .stepping = 0, - .features = CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX | + CPUID_EXT3_LAHF_LM; + xcc->xlevel = 0x8000001A; + pstrcpy(xcc->model_id, sizeof(xcc->model_id), + "AMD Opteron 62xx class CPU"); +} + +static const TypeInfo opteron_g4_cpu_type_info = { + .name = TYPE("Opteron_G4"), + .parent = TYPE_X86_CPU, + .class_init = opteron_g4_cpu_class_init, +}; + +static void opteron_g5_cpu_class_init(ObjectClass *oc, void *data) +{ + X86CPUClass *xcc = X86_CPU_CLASS(oc); + + xcc->level = 0xd; + xcc->vendor1 = CPUID_VENDOR_AMD_1; + xcc->vendor2 = CPUID_VENDOR_AMD_2; + xcc->vendor3 = CPUID_VENDOR_AMD_3; + xcc->family = 21; + xcc->model = 2; + xcc->stepping = 0; + xcc->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_F16C | CPUID_EXT_AVX | CPUID_EXT_XSAVE | + CPUID_DE | CPUID_FP87; + xcc->ext_features = CPUID_EXT_F16C | CPUID_EXT_AVX | CPUID_EXT_XSAVE | CPUID_EXT_AES | CPUID_EXT_POPCNT | CPUID_EXT_SSE42 | CPUID_EXT_SSE41 | CPUID_EXT_CX16 | CPUID_EXT_FMA | - CPUID_EXT_SSSE3 | CPUID_EXT_PCLMULQDQ | CPUID_EXT_SSE3, - .ext2_features = CPUID_EXT2_LM | CPUID_EXT2_RDTSCP | + CPUID_EXT_SSSE3 | CPUID_EXT_PCLMULQDQ | CPUID_EXT_SSE3; + xcc->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_TBM | CPUID_EXT3_FMA4 | CPUID_EXT3_XOP | + CPUID_EXT2_TSC | CPUID_EXT2_PSE | CPUID_EXT2_DE | CPUID_EXT2_FPU; + xcc->ext3_features = CPUID_EXT3_TBM | 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 63xx class CPU", - }, + CPUID_EXT3_LAHF_LM; + xcc->xlevel = 0x8000001A; + pstrcpy(xcc->model_id, sizeof(xcc->model_id), + "AMD Opteron 63xx class CPU"); +} + +static const TypeInfo opteron_g5_cpu_type_info = { + .name = TYPE("Opteron_G5"), + .parent = TYPE_X86_CPU, + .class_init = opteron_g5_cpu_class_init, }; #ifdef CONFIG_KVM @@ -832,61 +1059,60 @@ static int cpu_x86_fill_model_id(char *str) } #endif -/* Fill a x86_def_t struct with information about the host CPU, and +#ifdef CONFIG_KVM + +/* Fill a CPU class with information about the host CPU, and * the CPU features supported by the host hardware + host kernel - * - * This function may be called only if KVM is enabled. */ -static void kvm_cpu_fill_host(x86_def_t *x86_cpu_def) +static void kvm_host_cpu_class_init(ObjectClass *oc, void *data) { -#ifdef CONFIG_KVM + X86CPUClass *xcc = X86_CPU_CLASS(oc); KVMState *s = kvm_state; uint32_t eax = 0, ebx = 0, ecx = 0, edx = 0; assert(kvm_enabled()); - x86_cpu_def->name = "host"; host_cpuid(0x0, 0, &eax, &ebx, &ecx, &edx); - x86_cpu_def->vendor1 = ebx; - x86_cpu_def->vendor2 = edx; - x86_cpu_def->vendor3 = ecx; + xcc->vendor1 = ebx; + xcc->vendor2 = edx; + xcc->vendor3 = ecx; host_cpuid(0x1, 0, &eax, &ebx, &ecx, &edx); - x86_cpu_def->family = ((eax >> 8) & 0x0F) + ((eax >> 20) & 0xFF); - x86_cpu_def->model = ((eax >> 4) & 0x0F) | ((eax & 0xF0000) >> 12); - x86_cpu_def->stepping = eax & 0x0F; + xcc->family = ((eax >> 8) & 0x0F) + ((eax >> 20) & 0xFF); + xcc->model = ((eax >> 4) & 0x0F) | ((eax & 0xF0000) >> 12); + xcc->stepping = eax & 0x0F; - x86_cpu_def->level = kvm_arch_get_supported_cpuid(s, 0x0, 0, R_EAX); - x86_cpu_def->features = kvm_arch_get_supported_cpuid(s, 0x1, 0, R_EDX); - x86_cpu_def->ext_features = kvm_arch_get_supported_cpuid(s, 0x1, 0, R_ECX); + xcc->level = kvm_arch_get_supported_cpuid(s, 0x0, 0, R_EAX); + xcc->features = kvm_arch_get_supported_cpuid(s, 0x1, 0, R_EDX); + xcc->ext_features = kvm_arch_get_supported_cpuid(s, 0x1, 0, R_ECX); - if (x86_cpu_def->level >= 7) { - x86_cpu_def->cpuid_7_0_ebx_features = + if (xcc->level >= 7) { + xcc->cpuid_7_0_ebx_features = kvm_arch_get_supported_cpuid(s, 0x7, 0, R_EBX); } else { - x86_cpu_def->cpuid_7_0_ebx_features = 0; + xcc->cpuid_7_0_ebx_features = 0; } - x86_cpu_def->xlevel = kvm_arch_get_supported_cpuid(s, 0x80000000, 0, R_EAX); - x86_cpu_def->ext2_features = + xcc->xlevel = kvm_arch_get_supported_cpuid(s, 0x80000000, 0, R_EAX); + xcc->ext2_features = kvm_arch_get_supported_cpuid(s, 0x80000001, 0, R_EDX); - x86_cpu_def->ext3_features = + xcc->ext3_features = kvm_arch_get_supported_cpuid(s, 0x80000001, 0, R_ECX); - cpu_x86_fill_model_id(x86_cpu_def->model_id); - x86_cpu_def->vendor_override = 0; + cpu_x86_fill_model_id(xcc->model_id); + xcc->vendor_override = 0; /* Call Centaur's CPUID instruction. */ - if (x86_cpu_def->vendor1 == CPUID_VENDOR_VIA_1 && - x86_cpu_def->vendor2 == CPUID_VENDOR_VIA_2 && - x86_cpu_def->vendor3 == CPUID_VENDOR_VIA_3) { + if (xcc->vendor1 == CPUID_VENDOR_VIA_1 && + xcc->vendor2 == CPUID_VENDOR_VIA_2 && + xcc->vendor3 == CPUID_VENDOR_VIA_3) { host_cpuid(0xC0000000, 0, &eax, &ebx, &ecx, &edx); eax = kvm_arch_get_supported_cpuid(s, 0xC0000000, 0, R_EAX); if (eax >= 0xC0000001) { /* Support VIA max extended level */ - x86_cpu_def->xlevel2 = eax; + xcc->xlevel2 = eax; host_cpuid(0xC0000001, 0, &eax, &ebx, &ecx, &edx); - x86_cpu_def->ext4_features = + xcc->ext4_features = kvm_arch_get_supported_cpuid(s, 0xC0000001, 0, R_EDX); } } @@ -897,10 +1123,17 @@ static void kvm_cpu_fill_host(x86_def_t *x86_cpu_def) * available on the host hardware. Just set all bits and mask out the * unsupported ones later. */ - x86_cpu_def->svm_features = -1; -#endif /* CONFIG_KVM */ + xcc->svm_features = -1; } +static const TypeInfo kvm_host_cpu_type_info = { + .name = TYPE("host"), + .parent = TYPE_X86_CPU, + .class_init = kvm_host_cpu_class_init, +}; + +#endif /* CONFIG_KVM */ + static int unavailable_host_feature(struct model_features_t *f, uint32_t mask) { int i; @@ -922,24 +1155,24 @@ static int unavailable_host_feature(struct model_features_t *f, uint32_t mask) * * This function may be called only if KVM is enabled. */ -static int kvm_check_features_against_host(x86_def_t *guest_def) +static int kvm_check_features_against_host(X86CPU *guest_cpu) { - x86_def_t host_def; + CPUX86State *guest_env = &guest_cpu->env; + X86CPUClass *host_xcc = X86_CPU_CLASS(object_class_by_name(TYPE("host"))); uint32_t mask; int rv, i; struct model_features_t ft[] = { - {&guest_def->features, &host_def.features, + {&guest_env->cpuid_features, &host_xcc->features, ~0, feature_name, 0x00000000}, - {&guest_def->ext_features, &host_def.ext_features, + {&guest_env->cpuid_ext_features, &host_xcc->ext_features, ~CPUID_EXT_HYPERVISOR, ext_feature_name, 0x00000001}, - {&guest_def->ext2_features, &host_def.ext2_features, + {&guest_env->cpuid_ext2_features, &host_xcc->ext2_features, ~PPRO_FEATURES, ext2_feature_name, 0x80000000}, - {&guest_def->ext3_features, &host_def.ext3_features, + {&guest_env->cpuid_ext3_features, &host_xcc->ext3_features, ~CPUID_EXT3_SVM, ext3_feature_name, 0x80000001}}; assert(kvm_enabled()); - kvm_cpu_fill_host(&host_def); for (rv = 0, i = 0; i < ARRAY_SIZE(ft); ++i) for (mask = 1; mask; mask <<= 1) if (ft[i].check_feat & mask && *ft[i].guest_feat & mask && @@ -1203,26 +1436,12 @@ static void x86_cpuid_set_tsc_freq(Object *obj, Visitor *v, void *opaque, cpu->env.tsc_khz = value / 1000; } -static int cpu_x86_find_by_name(x86_def_t *x86_cpu_def, const char *name) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(builtin_x86_defs); i++) { - x86_def_t *def = &builtin_x86_defs[i]; - if (strcmp(name, def->name) == 0) { - memcpy(x86_cpu_def, def, sizeof(*def)); - return 0; - } - } - - return -1; -} - /* Parse "+feature,-feature,feature=foo" CPU feature string */ -static int cpu_x86_parse_featurestr(x86_def_t *x86_cpu_def, char *features) +static int cpu_x86_parse_featurestr(X86CPU *cpu, char *features) { - unsigned int i; + CPUX86State *env = &cpu->env; + Error *error = NULL; char *featurestr; /* Single 'key=value" string being parsed */ /* Features to be added */ uint32_t plus_features = 0, plus_ext_features = 0; @@ -1259,27 +1478,39 @@ static int cpu_x86_parse_featurestr(x86_def_t *x86_cpu_def, char *features) if (!strcmp(featurestr, "family")) { char *err; numvalue = strtoul(val, &err, 0); - if (!*val || *err || numvalue > 0xff + 0xf) { + if (!*val || *err) { fprintf(stderr, "bad numerical value %s\n", val); goto error; } - x86_cpu_def->family = numvalue; + object_property_set_int(OBJECT(cpu), numvalue, "family", + &error); + if (error != NULL) { + goto error; + } } else if (!strcmp(featurestr, "model")) { char *err; numvalue = strtoul(val, &err, 0); - if (!*val || *err || numvalue > 0xff) { + if (!*val || *err) { fprintf(stderr, "bad numerical value %s\n", val); goto error; } - x86_cpu_def->model = numvalue; + object_property_set_int(OBJECT(cpu), numvalue, "model", + &error); + if (error != NULL) { + goto error; + } } else if (!strcmp(featurestr, "stepping")) { char *err; numvalue = strtoul(val, &err, 0); - if (!*val || *err || numvalue > 0xf) { + if (!*val || *err) { fprintf(stderr, "bad numerical value %s\n", val); goto error; } - x86_cpu_def->stepping = numvalue ; + object_property_set_int(OBJECT(cpu), numvalue, "stepping", + &error); + if (error != NULL) { + goto error; + } } else if (!strcmp(featurestr, "level")) { char *err; numvalue = strtoul(val, &err, 0); @@ -1287,7 +1518,11 @@ static int cpu_x86_parse_featurestr(x86_def_t *x86_cpu_def, char *features) fprintf(stderr, "bad numerical value %s\n", val); goto error; } - x86_cpu_def->level = numvalue; + object_property_set_int(OBJECT(cpu), numvalue, "level", + &error); + if (error != NULL) { + goto error; + } } else if (!strcmp(featurestr, "xlevel")) { char *err; numvalue = strtoul(val, &err, 0); @@ -1298,35 +1533,36 @@ static int cpu_x86_parse_featurestr(x86_def_t *x86_cpu_def, char *features) if (numvalue < 0x80000000) { numvalue += 0x80000000; } - x86_cpu_def->xlevel = numvalue; - } else if (!strcmp(featurestr, "vendor")) { - if (strlen(val) != 12) { - fprintf(stderr, "vendor string must be 12 chars long\n"); + object_property_set_int(OBJECT(cpu), numvalue, "xlevel", + &error); + if (error != NULL) { goto error; } - x86_cpu_def->vendor1 = 0; - x86_cpu_def->vendor2 = 0; - x86_cpu_def->vendor3 = 0; - for(i = 0; i < 4; i++) { - x86_cpu_def->vendor1 |= ((uint8_t)val[i ]) << (8 * i); - x86_cpu_def->vendor2 |= ((uint8_t)val[i + 4]) << (8 * i); - x86_cpu_def->vendor3 |= ((uint8_t)val[i + 8]) << (8 * i); + } else if (!strcmp(featurestr, "vendor")) { + object_property_set_str(OBJECT(cpu), val, "vendor", &error); + if (error != NULL) { + goto error; } - x86_cpu_def->vendor_override = 1; } else if (!strcmp(featurestr, "model_id")) { - pstrcpy(x86_cpu_def->model_id, sizeof(x86_cpu_def->model_id), - val); + object_property_set_str(OBJECT(cpu), val, "model-id", &error); + if (error != NULL) { + goto error; + } } else if (!strcmp(featurestr, "tsc_freq")) { int64_t tsc_freq; char *err; tsc_freq = strtosz_suffix_unit(val, &err, STRTOSZ_DEFSUFFIX_B, 1000); - if (tsc_freq < 0 || *err) { + if (*err) { fprintf(stderr, "bad numerical value %s\n", val); goto error; } - x86_cpu_def->tsc_khz = tsc_freq / 1000; + object_property_set_int(OBJECT(cpu), tsc_freq, + "tsc-frequency", &error); + if (error != NULL) { + goto error; + } } else if (!strcmp(featurestr, "hv_spinlocks")) { char *err; numvalue = strtoul(val, &err, 0); @@ -1353,27 +1589,32 @@ static int cpu_x86_parse_featurestr(x86_def_t *x86_cpu_def, char *features) } featurestr = strtok(NULL, ","); } - x86_cpu_def->features |= plus_features; - x86_cpu_def->ext_features |= plus_ext_features; - x86_cpu_def->ext2_features |= plus_ext2_features; - 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; + env->cpuid_features |= plus_features; + env->cpuid_ext_features |= plus_ext_features; + env->cpuid_ext2_features |= plus_ext2_features; + env->cpuid_ext3_features |= plus_ext3_features; + env->cpuid_kvm_features |= plus_kvm_features; + env->cpuid_svm_features |= plus_svm_features; + env->cpuid_7_0_ebx_features |= plus_7_0_ebx_features; + env->cpuid_features &= ~minus_features; + env->cpuid_ext_features &= ~minus_ext_features; + env->cpuid_ext2_features &= ~minus_ext2_features; + env->cpuid_ext3_features &= ~minus_ext3_features; + env->cpuid_kvm_features &= ~minus_kvm_features; + env->cpuid_svm_features &= ~minus_svm_features; + env->cpuid_7_0_ebx_features &= ~minus_7_0_ebx_features; if (check_cpuid && kvm_enabled()) { - if (kvm_check_features_against_host(x86_cpu_def) && enforce_cpuid) + if (kvm_check_features_against_host(cpu) && enforce_cpuid) { goto error; + } } return 0; error: + if (error != NULL) { + fprintf(stderr, "%s\n", error_get_pretty(error)); + error_free(error); + } return -1; } @@ -1407,23 +1648,60 @@ static void listflags(char *buf, int bufsize, uint32_t fbits, } } +static ObjectClass *x86_cpu_class_by_name(const char *cpu_model) +{ + ObjectClass *oc; + char *typename; + + oc = object_class_by_name(cpu_model); + if (oc != NULL && object_class_dynamic_cast(oc, TYPE_X86_CPU) != NULL) { + return oc; + } + + typename = g_strdup_printf(TYPE("%s"), cpu_model); + oc = object_class_by_name(typename); + g_free(typename); + if (oc != NULL && object_class_dynamic_cast(oc, TYPE_X86_CPU) != NULL) { + return oc; + } + + return NULL; +} + /* generate CPU information. */ + +typedef struct X86CPUListState { + fprintf_function cpu_fprintf; + FILE *file; +} X86CPUListState; + +static void x86_cpu_list_entry(gpointer data, gpointer user_data) +{ + ObjectClass *oc = data; + X86CPUClass *xcc = X86_CPU_CLASS(oc); + X86CPUListState *s = user_data; + char buf[256]; + + snprintf(buf, MIN(sizeof(buf), strlen(object_class_get_name(oc)) + - strlen("-" TYPE_X86_CPU) + 1), + "%s", object_class_get_name(oc)); + (*s->cpu_fprintf)(s->file, "x86 %16s %-48s\n", + buf, xcc->model_id); +} + void x86_cpu_list(FILE *f, fprintf_function cpu_fprintf) { - int i; + X86CPUListState s = { + .file = f, + .cpu_fprintf = cpu_fprintf, + }; + GSList *list; char buf[256]; - /* Force creation of CPU class */ - object_class_by_name(TYPE_X86_CPU); + list = object_class_get_list(TYPE_X86_CPU, false); + g_slist_foreach(list, x86_cpu_list_entry, &s); + g_slist_free(list); - for (i = 0; i < ARRAY_SIZE(builtin_x86_defs); i++) { - x86_def_t *def = &builtin_x86_defs[i]; - 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); @@ -1435,25 +1713,38 @@ void x86_cpu_list(FILE *f, fprintf_function cpu_fprintf) (*cpu_fprintf)(f, " %s\n", buf); } -CpuDefinitionInfoList *arch_query_cpu_definitions(Error **errp) -{ - CpuDefinitionInfoList *cpu_list = NULL; - int i; +typedef struct X86CPUDefsState { + CpuDefinitionInfoList *cpu_list; +} X86CPUDefsState; - for (i = 0; i < ARRAY_SIZE(builtin_x86_defs); i++) { - CpuDefinitionInfoList *entry; - CpuDefinitionInfo *info; +static void x86_cpu_defs_entry(gpointer data, gpointer user_data) +{ + ObjectClass *oc = data; + X86CPUDefsState *s = user_data; + CpuDefinitionInfoList *entry; + CpuDefinitionInfo *info; + + info = g_malloc0(sizeof(*info)); + info->name = g_strdup(object_class_get_name(oc)); + + entry = g_malloc0(sizeof(*entry)); + entry->value = info; + entry->next = s->cpu_list; + s->cpu_list = entry; +} - info = g_malloc0(sizeof(*info)); - info->name = g_strdup(builtin_x86_defs[i].name); +CpuDefinitionInfoList *arch_query_cpu_definitions(Error **errp) +{ + X86CPUDefsState s = { + .cpu_list = NULL, + }; + GSList *list; - entry = g_malloc0(sizeof(*entry)); - entry->value = info; - entry->next = cpu_list; - cpu_list = entry; - } + list = object_class_get_list(TYPE_X86_CPU, false); + g_slist_foreach(list, x86_cpu_defs_entry, &s); + g_slist_free(list); - return cpu_list; + return s.cpu_list; } #ifdef CONFIG_KVM @@ -1482,16 +1773,16 @@ static void filter_features_for_kvm(X86CPU *cpu) } #endif -int cpu_x86_register(X86CPU *cpu, const char *cpu_model) +X86CPU *cpu_x86_init(const char *cpu_model) { - CPUX86State *env = &cpu->env; - x86_def_t def1, *def = &def1; + X86CPU *cpu = NULL; + CPUX86State *env; + ObjectClass *oc; + X86CPUClass *xcc; Error *error = NULL; char *name, *features; gchar **model_pieces; - memset(def, 0, sizeof(*def)); - model_pieces = g_strsplit(cpu_model, ",", 2); if (!model_pieces[0]) { goto error; @@ -1499,43 +1790,45 @@ int cpu_x86_register(X86CPU *cpu, const char *cpu_model) name = model_pieces[0]; features = model_pieces[1]; - if (kvm_enabled() && strcmp(name, "host") == 0) { - kvm_cpu_fill_host(def); - } else { - if (cpu_x86_find_by_name(def, name) < 0) { - goto error; - } + if (!kvm_enabled() && strcmp(name, "host") == 0) { + goto error; } - - if (cpu_x86_parse_featurestr(def, features) < 0) { + oc = x86_cpu_class_by_name(name); + if (oc == NULL) { goto error; } - if (def->vendor1) { - env->cpuid_vendor1 = def->vendor1; - env->cpuid_vendor2 = def->vendor2; - env->cpuid_vendor3 = def->vendor3; + cpu = X86_CPU(object_new(object_class_get_name(oc))); + env = &cpu->env; + env->cpu_model_str = cpu_model; + xcc = X86_CPU_GET_CLASS(cpu); + + if (xcc->vendor1) { + env->cpuid_vendor1 = xcc->vendor1; + env->cpuid_vendor2 = xcc->vendor2; + env->cpuid_vendor3 = xcc->vendor3; } else { env->cpuid_vendor1 = CPUID_VENDOR_INTEL_1; env->cpuid_vendor2 = CPUID_VENDOR_INTEL_2; env->cpuid_vendor3 = CPUID_VENDOR_INTEL_3; } - env->cpuid_vendor_override = def->vendor_override; - object_property_set_int(OBJECT(cpu), def->level, "level", &error); - object_property_set_int(OBJECT(cpu), def->family, "family", &error); - object_property_set_int(OBJECT(cpu), def->model, "model", &error); - object_property_set_int(OBJECT(cpu), def->stepping, "stepping", &error); - env->cpuid_features = def->features; - env->cpuid_ext_features = def->ext_features; - env->cpuid_ext2_features = def->ext2_features; - env->cpuid_ext3_features = def->ext3_features; - object_property_set_int(OBJECT(cpu), def->xlevel, "xlevel", &error); - 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_features = def->cpuid_7_0_ebx_features; - env->cpuid_xlevel2 = def->xlevel2; - object_property_set_int(OBJECT(cpu), (int64_t)def->tsc_khz * 1000, + env->cpuid_vendor_override = xcc->vendor_override; + object_property_set_int(OBJECT(cpu), xcc->level, "level", &error); + object_property_set_int(OBJECT(cpu), xcc->family, "family", &error); + object_property_set_int(OBJECT(cpu), xcc->model, "model", &error); + object_property_set_int(OBJECT(cpu), xcc->stepping, "stepping", &error); + env->cpuid_features = xcc->features; + env->cpuid_ext_features = xcc->ext_features; + env->cpuid_ext2_features = xcc->ext2_features; + env->cpuid_ext3_features = xcc->ext3_features; + object_property_set_int(OBJECT(cpu), xcc->xlevel, "xlevel", &error); + env->cpuid_kvm_features = xcc->kvm_features; + env->cpuid_svm_features = xcc->svm_features; + env->cpuid_ext4_features = xcc->ext4_features; + env->cpuid_7_0_ebx_features = xcc->cpuid_7_0_ebx_features; + env->cpuid_xlevel2 = xcc->xlevel2; + object_property_set_int(OBJECT(cpu), (int64_t)xcc->tsc_khz * 1000, "tsc-frequency", &error); + object_property_set_str(OBJECT(cpu), xcc->model_id, "model-id", &error); /* On AMD CPUs, some CPUID[8000_0001].EDX bits must match the bits on * CPUID[1].EDX. @@ -1544,7 +1837,11 @@ int cpu_x86_register(X86CPU *cpu, const char *cpu_model) 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); + env->cpuid_ext2_features |= (xcc->features & CPUID_EXT2_AMD_ALIASES); + } + + if (cpu_x86_parse_featurestr(cpu, features) < 0) { + goto error; } if (!kvm_enabled()) { @@ -1562,7 +1859,13 @@ int cpu_x86_register(X86CPU *cpu, const char *cpu_model) filter_features_for_kvm(cpu); #endif } - object_property_set_str(OBJECT(cpu), def->model_id, "model-id", &error); + if (error) { + fprintf(stderr, "%s\n", error_get_pretty(error)); + error_free(error); + goto error; + } + + x86_cpu_realize(OBJECT(cpu), &error); if (error) { fprintf(stderr, "%s\n", error_get_pretty(error)); error_free(error); @@ -1570,10 +1873,13 @@ int cpu_x86_register(X86CPU *cpu, const char *cpu_model) } g_strfreev(model_pieces); - return 0; + return cpu; error: + if (cpu != NULL) { + object_delete(OBJECT(cpu)); + } g_strfreev(model_pieces); - return -1; + return NULL; } #if !defined(CONFIG_USER_ONLY) @@ -1585,30 +1891,6 @@ void cpu_clear_apic_feature(CPUX86State *env) #endif /* !CONFIG_USER_ONLY */ -/* Initialize list of CPU models, filling some non-static fields if necessary - */ -static void x86_cpudef_setup(void) -{ - int i, j; - static const char *model_with_versions[] = { "qemu32", "qemu64", "athlon" }; - - for (i = 0; i < ARRAY_SIZE(builtin_x86_defs); ++i) { - x86_def_t *def = &builtin_x86_defs[i]; - - /* 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], 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; - } - } - } -} - static void get_cpuid_vendor(CPUX86State *env, uint32_t *ebx, uint32_t *ecx, uint32_t *edx) { @@ -2140,8 +2422,6 @@ static void x86_cpu_common_class_init(ObjectClass *oc, void *data) xcc->parent_reset = cc->reset; cc->reset = x86_cpu_reset; - - x86_cpudef_setup(); } static const TypeInfo x86_cpu_type_info = { @@ -2149,7 +2429,7 @@ static const TypeInfo x86_cpu_type_info = { .parent = TYPE_CPU, .instance_size = sizeof(X86CPU), .instance_init = x86_cpu_initfn, - .abstract = false, + .abstract = true, .class_size = sizeof(X86CPUClass), .class_init = x86_cpu_common_class_init, }; @@ -2157,6 +2437,33 @@ static const TypeInfo x86_cpu_type_info = { static void x86_cpu_register_types(void) { type_register_static(&x86_cpu_type_info); + type_register_static(&qemu64_cpu_type_info); + type_register_static(&phenom_cpu_type_info); + type_register_static(&core2duo_cpu_type_info); + type_register_static(&kvm64_cpu_type_info); + type_register_static(&qemu32_cpu_type_info); + type_register_static(&kvm32_cpu_type_info); + type_register_static(&coreduo_cpu_type_info); + type_register_static(&i486_cpu_type_info); + type_register_static(&pentium_cpu_type_info); + type_register_static(&pentium2_cpu_type_info); + type_register_static(&pentium3_cpu_type_info); + type_register_static(&athlon_cpu_type_info); + type_register_static(&n270_cpu_type_info); + type_register_static(&conroe_cpu_type_info); + type_register_static(&penryn_cpu_type_info); + type_register_static(&nehalem_cpu_type_info); + type_register_static(&westmere_cpu_type_info); + type_register_static(&sandybridge_cpu_type_info); + type_register_static(&haswell_cpu_type_info); + type_register_static(&opteron_g1_cpu_type_info); + type_register_static(&opteron_g2_cpu_type_info); + type_register_static(&opteron_g3_cpu_type_info); + type_register_static(&opteron_g4_cpu_type_info); + type_register_static(&opteron_g5_cpu_type_info); +#ifdef CONFIG_KVM + type_register_static(&kvm_host_cpu_type_info); +#endif } type_init(x86_cpu_register_types) diff --git a/target-i386/helper.c b/target-i386/helper.c index bf206cf..47b53ed 100644 --- a/target-i386/helper.c +++ b/target-i386/helper.c @@ -1240,30 +1240,6 @@ int cpu_x86_get_descr_debug(CPUX86State *env, unsigned int selector, return 1; } -X86CPU *cpu_x86_init(const char *cpu_model) -{ - X86CPU *cpu; - CPUX86State *env; - Error *error = NULL; - - cpu = X86_CPU(object_new(TYPE_X86_CPU)); - env = &cpu->env; - env->cpu_model_str = cpu_model; - - if (cpu_x86_register(cpu, cpu_model) < 0) { - object_delete(OBJECT(cpu)); - return NULL; - } - - x86_cpu_realize(OBJECT(cpu), &error); - if (error) { - error_free(error); - object_delete(OBJECT(cpu)); - return NULL; - } - return cpu; -} - #if !defined(CONFIG_USER_ONLY) void do_cpu_init(X86CPU *cpu) {
TODO: sort classes for -cpu ?, generalize X86CPUListState, more testing Signed-off-by: Andreas Färber <afaerber@suse.de> Cc: Eduardo Habkost <ehabkost@redhat.com> Cc: Igor Mammedov <imammedo@redhat.com> --- target-i386/cpu-qom.h | 17 + target-i386/cpu.c | 1481 +++++++++++++++++++++++++++++-------------------- target-i386/helper.c | 24 - 3 Dateien geändert, 911 Zeilen hinzugefügt(+), 611 Zeilen entfernt(-)