diff mbox

[RFC,qom-cpu,v2,1/2] target-i386: Convert CPU definitions into X86CPU subclasses

Message ID 1355180372-6525-2-git-send-email-afaerber@suse.de
State New
Headers show

Commit Message

Andreas Färber Dec. 10, 2012, 10:59 p.m. UTC
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(-)

Comments

Igor Mammedov Jan. 15, 2013, 8:41 a.m. UTC | #1
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
Eduardo Habkost Jan. 15, 2013, 10:07 a.m. UTC | #2
On Tue, Jan 15, 2013 at 09:41:04AM +0100, Igor Mammedov wrote:
> On Mon, 10 Dec 2012 23:59:31 +0100
> Andreas Färber <afaerber@suse.de> wrote:
> 
> > TODO: sort classes for -cpu ?, generalize X86CPUListState, more testing
> > 
> > Signed-off-by: Andreas Färber <afaerber@suse.de>
> > Cc: Eduardo Habkost <ehabkost@redhat.com>
> > Cc: Igor Mammedov <imammedo@redhat.com>
[...]
> The patch is just renaming of the current builtin_x86_defs
> into a bunch of functions and polluting X86CPUClass
> with fields from the former x86_def_t.
> object_new() still creates a dummy cpu instance whose defaults
> are still manually copied from X86CPUClass instead of x86_def_t.
> 

That's a good thing, isn't it? It means the patch is easier to review.
:-)

No patch alone will do everything we want, because we want to do a lot.
We need to do it one step at a time.

(BTW, why are you looking at this RFC instead of the more recent one,
that I have sent on Jan 4? [that's very similar to this one])


> What's the point in having dummy sub-classes?
> How it can help in your CPU re-factoring?

It will help us to unify the CPU creation/realization code that's
duplicated over all the architectures.

It will give libvirt an easy mechanism to list the available CPU models
that won't require parsing help output (using "qom-list-types" QMP
command).

> 
> 
> On the other hand converting features to static properties first and
> then converting X86CPU to sub-classes, yields already initialized to
> defaults sub-class completely removing notion of x86_def_t and
> not polluting X86CPUClass with redundant fields.

I wouldn't disagree with this approach in principle, but I believe our
main problem today is lack of reviewer bandwidth. I learned the hard way
that trying to clean up everything before implementing something will
make sure the code takes forever to be reviewed.


> For example see following patches on
> https://github.com/imammedo/qemu/commits/x86-cpu-classes.Jan142013
> 
> e9fd18f qdev: extend DEFINE_GENERIC_PROP() to support default values
> c65eca9 qdev: make qdev_prop_find_bit return non const so prop default value could be modified
> 0311952 allow to expolit default value static props for model, family, stepping & vendor props
> 8b3080e target-i386: add helpers to change default values of static properties before object is created
> ed506d3 target-i386: prepare for subclasses to have its own instance of static properties definitions
> a48e252 target-i386: declare subclass for qemu64 cpu model
> 9c556c2 target-i386: move cpu_x86_init() & cpu_x86_register() into it and switch to subclasses. PS: implemended only for qemu64
> f5dbfe6 CPU_CLASS_NAME(qemu64) hack
> 00e15b8 target-i386: properties list are per subclass: do not set them in superclass to avoid defaults set by subclass be over-written
> 
> -- 
> Regards,
>   Igor
diff mbox

Patch

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)
 {