qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [RFC qom-cpu v2 0/2] target-i386: X86CPU subclasses
@ 2012-12-10 22:59 Andreas Färber
  2012-12-10 22:59 ` [Qemu-devel] [RFC qom-cpu v2 1/2] target-i386: Convert CPU definitions into " Andreas Färber
  2012-12-10 22:59 ` [Qemu-devel] [RFC qom-cpu v2 2/2] target-i386: Turn Haswell into subclass of SandyBridge Andreas Färber
  0 siblings, 2 replies; 10+ messages in thread
From: Andreas Färber @ 2012-12-10 22:59 UTC (permalink / raw)
  To: qemu-devel; +Cc: blauwirbel, imammedo, ehabkost, anthony, Andreas Färber

Hello,

Had some long train rides today, so here's a new throw at X86CPU subclasses:
After having initially proposed a "minimal" conversion by reusing the
list/array of CPU definitions, public opinion seems to have shifted from
preferring initfns to preferring class_inits. Combined with per-type TypeInfos
this allows to create custom hierarchies to share data among CPU families.
Thereby I do what I have long tried to avoid: touching almost every line of
x86 CPU definitions with risk of merge conflicts. This conversion was done
100% manually and does not touch the feature flags apart from the assignment
and semicolon, hopefully manageable for review; otherwise suggestions welcome.

Although in this series only the CPU properties that I had prepared earlier
for this purpose get used, CPU feature properties still make sense for
management tools to inspect and modify bits of a CPU just created.

This mini-series is based on my latest cleanup proposals.

Regards,
Andreas

v1-> v2:
* Instead of turning x86_def_t into X86CPUInfo to initialize classes,
  drop it completely and register types manually with customizable TypeInfos
* Use new list facilities for printing -cpu ? models
* Adopt new name scheme suggested by Eduardo and ideas from my alpha series
* Keep short names in -cpu ? output for alignment reasons
* Merge cpu_x86_init() into cpu.c:cpu_x86_register()
* Append patch showing Haswell as subclass of SandyBridge

Cc: Eduardo Habkost <ehabkost@redhat.com>
Cc: Igor Mammedov <imammedo@redhat.com>
Cc: Blue Swirl <blauwirbel@gmail.com>
Cc: Anthony Liguori <anthony@codemonkey.ws>

Andreas Färber (2):
  target-i386: Convert CPU definitions into X86CPU subclasses
  target-i386: Turn Haswell into subclass of SandyBridge

 target-i386/cpu-qom.h |   17 +
 target-i386/cpu.c     | 1475 +++++++++++++++++++++++++++++--------------------
 target-i386/helper.c  |   24 -
 3 Dateien geändert, 898 Zeilen hinzugefügt(+), 618 Zeilen entfernt(-)

-- 
1.7.10.4

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [Qemu-devel] [RFC qom-cpu v2 1/2] target-i386: Convert CPU definitions into X86CPU subclasses
  2012-12-10 22:59 [Qemu-devel] [RFC qom-cpu v2 0/2] target-i386: X86CPU subclasses Andreas Färber
@ 2012-12-10 22:59 ` Andreas Färber
  2013-01-15  8:41   ` Igor Mammedov
  2012-12-10 22:59 ` [Qemu-devel] [RFC qom-cpu v2 2/2] target-i386: Turn Haswell into subclass of SandyBridge Andreas Färber
  1 sibling, 1 reply; 10+ messages in thread
From: Andreas Färber @ 2012-12-10 22:59 UTC (permalink / raw)
  To: qemu-devel; +Cc: blauwirbel, imammedo, ehabkost, anthony, Andreas Färber

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

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [Qemu-devel] [RFC qom-cpu v2 2/2] target-i386: Turn Haswell into subclass of SandyBridge
  2012-12-10 22:59 [Qemu-devel] [RFC qom-cpu v2 0/2] target-i386: X86CPU subclasses Andreas Färber
  2012-12-10 22:59 ` [Qemu-devel] [RFC qom-cpu v2 1/2] target-i386: Convert CPU definitions into " Andreas Färber
@ 2012-12-10 22:59 ` Andreas Färber
  2012-12-12 12:45   ` Eduardo Habkost
  1 sibling, 1 reply; 10+ messages in thread
From: Andreas Färber @ 2012-12-10 22:59 UTC (permalink / raw)
  To: qemu-devel; +Cc: blauwirbel, imammedo, ehabkost, anthony, Andreas Färber

  ehabkost: "When adding the Haswell CPU model, I intended to make it
  a superset of the features present on the SandyBridge model"

Inherit from SandyBridge to keep only the delta for Haswell.

Signed-off-by: Andreas Färber <afaerber@suse.de>
Cc: Eduardo Habkost <ehabkost@redhat.com>
---
 target-i386/cpu.c |   24 ++----------------------
 1 Datei geändert, 2 Zeilen hinzugefügt(+), 22 Zeilen entfernt(-)

diff --git a/target-i386/cpu.c b/target-i386/cpu.c
index c59c6a5..ffd160a 100644
--- a/target-i386/cpu.c
+++ b/target-i386/cpu.c
@@ -814,39 +814,19 @@ 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;
-    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;
-    xcc->ext2_features = CPUID_EXT2_LM | CPUID_EXT2_RDTSCP | CPUID_EXT2_NX |
-             CPUID_EXT2_SYSCALL;
-    xcc->ext3_features = CPUID_EXT3_LAHF_LM;
+    xcc->ext_features |= CPUID_EXT_FMA | CPUID_EXT_MOVBE | CPUID_EXT_PCID;
     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;
-    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,
+    .parent = TYPE("SandyBridge"),
     .class_init = haswell_cpu_class_init,
 };
 
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: [Qemu-devel] [RFC qom-cpu v2 2/2] target-i386: Turn Haswell into subclass of SandyBridge
  2012-12-10 22:59 ` [Qemu-devel] [RFC qom-cpu v2 2/2] target-i386: Turn Haswell into subclass of SandyBridge Andreas Färber
@ 2012-12-12 12:45   ` Eduardo Habkost
  2012-12-12 14:47     ` Andreas Färber
  0 siblings, 1 reply; 10+ messages in thread
From: Eduardo Habkost @ 2012-12-12 12:45 UTC (permalink / raw)
  To: Andreas Färber; +Cc: blauwirbel, imammedo, qemu-devel, anthony

On Mon, Dec 10, 2012 at 11:59:32PM +0100, Andreas Färber wrote:
>   ehabkost: "When adding the Haswell CPU model, I intended to make it
>   a superset of the features present on the SandyBridge model"
> 
> Inherit from SandyBridge to keep only the delta for Haswell.

Most CPUs have a superset of the features of their predecessors. Are you
simply using SandyBridge->Haswell as an example, or you think their
relationship is special somehow?

I believe we don't want to make externally-visible class inheritance,
but probably just reuse constans or init functions internally. A Haswell
CPU is not a type of SandyBridge CPU, it just happens to contain a
superset of the features present in SandyBridge.

I mean: Haswell also has a superset of features of 486, but we don't
want to make the hierarchy look like the following, do we?

- X86CPU
  -> X86IntelCPU
     -> 486
        -> pentium
           -> pentium2
              -> pentium3
                 -> Conroe
                    -> Penryn
                       -> Nehalem
                          -> Westmere
                             -> SandyBridge
                                -> Haswell

> 
> Signed-off-by: Andreas Färber <afaerber@suse.de>
> Cc: Eduardo Habkost <ehabkost@redhat.com>
> ---
>  target-i386/cpu.c |   24 ++----------------------
>  1 Datei geändert, 2 Zeilen hinzugefügt(+), 22 Zeilen entfernt(-)
> 
> diff --git a/target-i386/cpu.c b/target-i386/cpu.c
> index c59c6a5..ffd160a 100644
> --- a/target-i386/cpu.c
> +++ b/target-i386/cpu.c
> @@ -814,39 +814,19 @@ 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;
> -    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;
> -    xcc->ext2_features = CPUID_EXT2_LM | CPUID_EXT2_RDTSCP | CPUID_EXT2_NX |
> -             CPUID_EXT2_SYSCALL;
> -    xcc->ext3_features = CPUID_EXT3_LAHF_LM;
> +    xcc->ext_features |= CPUID_EXT_FMA | CPUID_EXT_MOVBE | CPUID_EXT_PCID;
>      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;
> -    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,
> +    .parent = TYPE("SandyBridge"),
>      .class_init = haswell_cpu_class_init,
>  };
>  
> -- 
> 1.7.10.4
> 

-- 
Eduardo

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [Qemu-devel] [RFC qom-cpu v2 2/2] target-i386: Turn Haswell into subclass of SandyBridge
  2012-12-12 12:45   ` Eduardo Habkost
@ 2012-12-12 14:47     ` Andreas Färber
  2012-12-12 15:05       ` Eduardo Habkost
  0 siblings, 1 reply; 10+ messages in thread
From: Andreas Färber @ 2012-12-12 14:47 UTC (permalink / raw)
  To: Eduardo Habkost
  Cc: blauwirbel, imammedo, qemu-devel, Anthony Liguori, Paolo Bonzini

Am 12.12.2012 13:45, schrieb Eduardo Habkost:
> On Mon, Dec 10, 2012 at 11:59:32PM +0100, Andreas Färber wrote:
>>   ehabkost: "When adding the Haswell CPU model, I intended to make it
>>   a superset of the features present on the SandyBridge model"
>>
>> Inherit from SandyBridge to keep only the delta for Haswell.
> 
> Most CPUs have a superset of the features of their predecessors. Are you
> simply using SandyBridge->Haswell as an example, or you think their
> relationship is special somehow?
> 
> I believe we don't want to make externally-visible class inheritance,
> but probably just reuse constans or init functions internally. A Haswell
> CPU is not a type of SandyBridge CPU, it just happens to contain a
> superset of the features present in SandyBridge.
> 
> I mean: Haswell also has a superset of features of 486, but we don't
> want to make the hierarchy look like the following, do we?

I don't see why we would want to use a #define-based inheritence as
suggested for the PPRO when we have QOM. QOM inheritence reduces lines
of code significantly compared to just taking the values from elsewhere.

For the Haswell you said what I quoted, for the other models I said I
need your or someone's help to verify whether a hierarchy such as below
is semantically right or just a coincidence. I was at least considering
an abstract intel-/amd-*-cpu to avoid repeating the three value
assignments over and over.

At this time I believe the parents of a type are not (yet) exposed via
QMP, just the "type" string property.

Andreas

> - X86CPU
>   -> X86IntelCPU
>      -> 486
>         -> pentium
>            -> pentium2
>               -> pentium3
>                  -> Conroe
>                     -> Penryn
>                        -> Nehalem
>                           -> Westmere
>                              -> SandyBridge
>                                 -> Haswell

-- 
SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 Nürnberg, Germany
GF: Jeff Hawn, Jennifer Guild, Felix Imendörffer; HRB 16746 AG Nürnberg

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [Qemu-devel] [RFC qom-cpu v2 2/2] target-i386: Turn Haswell into subclass of SandyBridge
  2012-12-12 14:47     ` Andreas Färber
@ 2012-12-12 15:05       ` Eduardo Habkost
  2012-12-12 17:29         ` Andreas Färber
  0 siblings, 1 reply; 10+ messages in thread
From: Eduardo Habkost @ 2012-12-12 15:05 UTC (permalink / raw)
  To: Andreas Färber
  Cc: blauwirbel, imammedo, qemu-devel, Anthony Liguori, Paolo Bonzini

On Wed, Dec 12, 2012 at 03:47:49PM +0100, Andreas Färber wrote:
> Am 12.12.2012 13:45, schrieb Eduardo Habkost:
> > On Mon, Dec 10, 2012 at 11:59:32PM +0100, Andreas Färber wrote:
> >>   ehabkost: "When adding the Haswell CPU model, I intended to make it
> >>   a superset of the features present on the SandyBridge model"
> >>
> >> Inherit from SandyBridge to keep only the delta for Haswell.
> > 
> > Most CPUs have a superset of the features of their predecessors. Are you
> > simply using SandyBridge->Haswell as an example, or you think their
> > relationship is special somehow?
> > 
> > I believe we don't want to make externally-visible class inheritance,
> > but probably just reuse constans or init functions internally. A Haswell
> > CPU is not a type of SandyBridge CPU, it just happens to contain a
> > superset of the features present in SandyBridge.
> > 
> > I mean: Haswell also has a superset of features of 486, but we don't
> > want to make the hierarchy look like the following, do we?
> 
> I don't see why we would want to use a #define-based inheritence as
> suggested for the PPRO when we have QOM. QOM inheritence reduces lines
> of code significantly compared to just taking the values from elsewhere.

The reuse doesn't need to be #define-based (although maybe a
#define-based approach would work too), it could be function-call-based.

> 
> For the Haswell you said what I quoted, for the other models I said I
> need your or someone's help to verify whether a hierarchy such as below
> is semantically right or just a coincidence. I was at least considering
> an abstract intel-/amd-*-cpu to avoid repeating the three value
> assignments over and over.

Creating X86IntelCPU and X86AMDCPU classes make sense to me, because
Haswell is a kind of Intel CPu. Making Haswell a subclass of 486 (like
below) wouldn't.

> 
> At this time I believe the parents of a type are not (yet) exposed via
> QMP, just the "type" string property.

Even if they are not exposed externally, it's a confusing usage of
inheritance for me. I mean: a Haswell CPU is not a type of 486 CPU, it's
simply a different kind of CPU that happens to have a superset of the
486 features.

> 
> Andreas
> 
> > - X86CPU
> >   -> X86IntelCPU
> >      -> 486
> >         -> pentium
> >            -> pentium2
> >               -> pentium3
> >                  -> Conroe
> >                     -> Penryn
> >                        -> Nehalem
> >                           -> Westmere
> >                              -> SandyBridge
> >                                 -> Haswell
> 
> -- 
> SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 Nürnberg, Germany
> GF: Jeff Hawn, Jennifer Guild, Felix Imendörffer; HRB 16746 AG Nürnberg

-- 
Eduardo

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [Qemu-devel] [RFC qom-cpu v2 2/2] target-i386: Turn Haswell into subclass of SandyBridge
  2012-12-12 15:05       ` Eduardo Habkost
@ 2012-12-12 17:29         ` Andreas Färber
  2012-12-12 18:21           ` Alexander Graf
  0 siblings, 1 reply; 10+ messages in thread
From: Andreas Färber @ 2012-12-12 17:29 UTC (permalink / raw)
  To: Eduardo Habkost
  Cc: qemu-devel, Alexander Graf, blauwirbel, Paul Brook,
	Anthony Liguori, Paolo Bonzini, imammedo

Am 12.12.2012 16:05, schrieb Eduardo Habkost:
> On Wed, Dec 12, 2012 at 03:47:49PM +0100, Andreas Färber wrote:
>> Am 12.12.2012 13:45, schrieb Eduardo Habkost:
>>> On Mon, Dec 10, 2012 at 11:59:32PM +0100, Andreas Färber wrote:
>>>>   ehabkost: "When adding the Haswell CPU model, I intended to make it
>>>>   a superset of the features present on the SandyBridge model"
>>>>
>>>> Inherit from SandyBridge to keep only the delta for Haswell.
>>>
>>> Most CPUs have a superset of the features of their predecessors. Are you
>>> simply using SandyBridge->Haswell as an example, or you think their
>>> relationship is special somehow?
>>>
>>> I believe we don't want to make externally-visible class inheritance,
>>> but probably just reuse constans or init functions internally. A Haswell
>>> CPU is not a type of SandyBridge CPU, it just happens to contain a
>>> superset of the features present in SandyBridge.
>>>
>>> I mean: Haswell also has a superset of features of 486, but we don't
>>> want to make the hierarchy look like the following, do we?
>>
>> I don't see why we would want to use a #define-based inheritence as
>> suggested for the PPRO when we have QOM. QOM inheritence reduces lines
>> of code significantly compared to just taking the values from elsewhere.
> 
> The reuse doesn't need to be #define-based (although maybe a
> #define-based approach would work too), it could be function-call-based.
> 
>>
>> For the Haswell you said what I quoted, for the other models I said I
>> need your or someone's help to verify whether a hierarchy such as below
>> is semantically right or just a coincidence. I was at least considering
>> an abstract intel-/amd-*-cpu to avoid repeating the three value
>> assignments over and over.
> 
> Creating X86IntelCPU and X86AMDCPU classes make sense to me, because
> Haswell is a kind of Intel CPu. Making Haswell a subclass of 486 (like
> below) wouldn't.
> 
>>
>> At this time I believe the parents of a type are not (yet) exposed via
>> QMP, just the "type" string property.
> 
> Even if they are not exposed externally, it's a confusing usage of
> inheritance for me. I mean: a Haswell CPU is not a type of 486 CPU, it's
> simply a different kind of CPU that happens to have a superset of the
> 486 features.

I concur with your is-a argument. My patch took a pragmatic approach.

I'd like to wait for some more review comments on how to share code
between models then - I remember Paul, Anthony and Alex discussing the
x86 models a while back on IRC, CC'ing. (Summary: reading CPU models
from config files has been dropped, we only have built-in models left -
now how to design name-class mappings below X86CPU)

Andreas

>>> - X86CPU
>>>   -> X86IntelCPU
>>>      -> 486
>>>         -> pentium
>>>            -> pentium2
>>>               -> pentium3
>>>                  -> Conroe
>>>                     -> Penryn
>>>                        -> Nehalem
>>>                           -> Westmere
>>>                              -> SandyBridge
>>>                                 -> Haswell

-- 
SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 Nürnberg, Germany
GF: Jeff Hawn, Jennifer Guild, Felix Imendörffer; HRB 16746 AG Nürnberg

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [Qemu-devel] [RFC qom-cpu v2 2/2] target-i386: Turn Haswell into subclass of SandyBridge
  2012-12-12 17:29         ` Andreas Färber
@ 2012-12-12 18:21           ` Alexander Graf
  0 siblings, 0 replies; 10+ messages in thread
From: Alexander Graf @ 2012-12-12 18:21 UTC (permalink / raw)
  To: Andreas Färber
  Cc: Eduardo Habkost, qemu-devel, blauwirbel, Paul Brook,
	Anthony Liguori, Paolo Bonzini, imammedo

On 12/12/2012 06:29 PM, Andreas Färber wrote:
> Am 12.12.2012 16:05, schrieb Eduardo Habkost:
>> On Wed, Dec 12, 2012 at 03:47:49PM +0100, Andreas Färber wrote:
>>> Am 12.12.2012 13:45, schrieb Eduardo Habkost:
>>>> On Mon, Dec 10, 2012 at 11:59:32PM +0100, Andreas Färber wrote:
>>>>>    ehabkost: "When adding the Haswell CPU model, I intended to make it
>>>>>    a superset of the features present on the SandyBridge model"
>>>>>
>>>>> Inherit from SandyBridge to keep only the delta for Haswell.
>>>> Most CPUs have a superset of the features of their predecessors. Are you
>>>> simply using SandyBridge->Haswell as an example, or you think their
>>>> relationship is special somehow?
>>>>
>>>> I believe we don't want to make externally-visible class inheritance,
>>>> but probably just reuse constans or init functions internally. A Haswell
>>>> CPU is not a type of SandyBridge CPU, it just happens to contain a
>>>> superset of the features present in SandyBridge.
>>>>
>>>> I mean: Haswell also has a superset of features of 486, but we don't
>>>> want to make the hierarchy look like the following, do we?
>>> I don't see why we would want to use a #define-based inheritence as
>>> suggested for the PPRO when we have QOM. QOM inheritence reduces lines
>>> of code significantly compared to just taking the values from elsewhere.
>> The reuse doesn't need to be #define-based (although maybe a
>> #define-based approach would work too), it could be function-call-based.
>>
>>> For the Haswell you said what I quoted, for the other models I said I
>>> need your or someone's help to verify whether a hierarchy such as below
>>> is semantically right or just a coincidence. I was at least considering
>>> an abstract intel-/amd-*-cpu to avoid repeating the three value
>>> assignments over and over.
>> Creating X86IntelCPU and X86AMDCPU classes make sense to me, because
>> Haswell is a kind of Intel CPu. Making Haswell a subclass of 486 (like
>> below) wouldn't.
>>
>>> At this time I believe the parents of a type are not (yet) exposed via
>>> QMP, just the "type" string property.
>> Even if they are not exposed externally, it's a confusing usage of
>> inheritance for me. I mean: a Haswell CPU is not a type of 486 CPU, it's
>> simply a different kind of CPU that happens to have a superset of the
>> 486 features.
> I concur with your is-a argument. My patch took a pragmatic approach.

Considering that x86 is very straight forward in its CPU definitions, I 
think we can easily make this a flat model based on CPUID features + a 
few variables.

If you really want to model something, I would rather say

386
   -> 386SX
   -> 386DX
opteron-G3
   -> phenom-9550
   -> phenom-9560

Any inheritance above that level sounds excessive to me.


Alex

> I'd like to wait for some more review comments on how to share code
> between models then - I remember Paul, Anthony and Alex discussing the
> x86 models a while back on IRC, CC'ing. (Summary: reading CPU models
> from config files has been dropped, we only have built-in models left -
> now how to design name-class mappings below X86CPU)
>
> Andreas
>
>>>> - X86CPU
>>>>    ->  X86IntelCPU
>>>>       ->  486
>>>>          ->  pentium
>>>>             ->  pentium2
>>>>                ->  pentium3
>>>>                   ->  Conroe
>>>>                      ->  Penryn
>>>>                         ->  Nehalem
>>>>                            ->  Westmere
>>>>                               ->  SandyBridge
>>>>                                  ->  Haswell

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [Qemu-devel] [RFC qom-cpu v2 1/2] target-i386: Convert CPU definitions into X86CPU subclasses
  2012-12-10 22:59 ` [Qemu-devel] [RFC qom-cpu v2 1/2] target-i386: Convert CPU definitions into " Andreas Färber
@ 2013-01-15  8:41   ` Igor Mammedov
  2013-01-15 10:07     ` Eduardo Habkost
  0 siblings, 1 reply; 10+ messages in thread
From: Igor Mammedov @ 2013-01-15  8:41 UTC (permalink / raw)
  To: Andreas Färber; +Cc: blauwirbel, qemu-devel, anthony, ehabkost

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

-- 
Regards,
  Igor

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [Qemu-devel] [RFC qom-cpu v2 1/2] target-i386: Convert CPU definitions into X86CPU subclasses
  2013-01-15  8:41   ` Igor Mammedov
@ 2013-01-15 10:07     ` Eduardo Habkost
  0 siblings, 0 replies; 10+ messages in thread
From: Eduardo Habkost @ 2013-01-15 10:07 UTC (permalink / raw)
  To: Igor Mammedov
  Cc: blauwirbel, libvir-list, Andreas Färber, anthony, qemu-devel

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

-- 
Eduardo

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2013-01-15 10:06 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-12-10 22:59 [Qemu-devel] [RFC qom-cpu v2 0/2] target-i386: X86CPU subclasses Andreas Färber
2012-12-10 22:59 ` [Qemu-devel] [RFC qom-cpu v2 1/2] target-i386: Convert CPU definitions into " Andreas Färber
2013-01-15  8:41   ` Igor Mammedov
2013-01-15 10:07     ` Eduardo Habkost
2012-12-10 22:59 ` [Qemu-devel] [RFC qom-cpu v2 2/2] target-i386: Turn Haswell into subclass of SandyBridge Andreas Färber
2012-12-12 12:45   ` Eduardo Habkost
2012-12-12 14:47     ` Andreas Färber
2012-12-12 15:05       ` Eduardo Habkost
2012-12-12 17:29         ` Andreas Färber
2012-12-12 18:21           ` Alexander Graf

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).