diff --git a/target-i386/cpu-qom.h b/target-i386/cpu-qom.h
index 722f11a..60c5c32 100644
--- a/target-i386/cpu-qom.h
+++ b/target-i386/cpu-qom.h
@@ -37,6 +37,9 @@
 #define X86_CPU_GET_CLASS(obj) \
     OBJECT_GET_CLASS(X86CPUClass, (obj), TYPE_X86_CPU)
 
+
+typedef struct X86CPUDefinition X86CPUDefinition;
+
 /**
  * X86CPUClass:
  * @parent_realize: The parent class' realize handler.
@@ -49,6 +52,16 @@ typedef struct X86CPUClass {
     CPUClass parent_class;
     /*< public >*/
 
+    /* CPU model definition
+     * Should be eventually replaced by subclass-specific property defaults
+     */
+    X86CPUDefinition *cpu_def;
+    /* CPU model requires KVM to be enabled */
+    bool kvm_required;
+    /* Optional description of CPU model.
+     * If unavailable, cpu_def->model_id is used */
+    const char *model_description;
+
     DeviceRealize parent_realize;
     void (*parent_reset)(CPUState *cpu);
 } X86CPUClass;
diff --git a/target-i386/cpu.c b/target-i386/cpu.c
index 6659527..bb72e5b 100644
--- a/target-i386/cpu.c
+++ b/target-i386/cpu.c
@@ -484,7 +484,10 @@ static void add_flagname_to_bitmaps(const char *flagname,
     }
 }
 
-typedef struct X86CPUDefinition {
+/* CPU model definition data that was not converted to QOM per-subclass
+ * property defaults yet.
+ */
+struct X86CPUDefinition {
     const char *name;
     uint32_t level;
     uint32_t xlevel;
@@ -497,7 +500,7 @@ typedef struct X86CPUDefinition {
     FeatureWordArray features;
     char model_id[48];
     bool cache_info_passthrough;
-} X86CPUDefinition;
+};
 
 #define I486_FEATURES (CPUID_FP87 | CPUID_VME | CPUID_PSE)
 #define PENTIUM_FEATURES (I486_FEATURES | CPUID_DE | CPUID_TSC | \
@@ -547,8 +550,29 @@ typedef struct X86CPUDefinition {
           CPUID_7_0_EBX_ERMS, CPUID_7_0_EBX_INVPCID, CPUID_7_0_EBX_RTM,
           CPUID_7_0_EBX_RDSEED */
 
-/* built-in CPU model definitions
+/* CPU class name definitions: */
+
+#define X86_CPU_CLASS_SUFFIX "-" TYPE_X86_CPU
+#define CPU_CLASS_NAME(name) (name X86_CPU_CLASS_SUFFIX)
+
+/* Return class name for a given CPU model name
+ * Caller is responsible for freeing the returned string.
  */
+static char *x86_cpu_class_name(const char *model_name)
+{
+    return g_strdup_printf(CPU_CLASS_NAME("%s"), model_name);
+}
+
+/* Return X86CPUClass for a CPU model name */
+static X86CPUClass *x86_cpu_class_by_name(const char *name)
+{
+    X86CPUClass *cc;
+    char *class_name = x86_cpu_class_name(name);
+    cc =  X86_CPU_CLASS(object_class_by_name(class_name));
+    g_free(class_name);
+    return cc;
+}
+
 static X86CPUDefinition builtin_x86_defs[] = {
     {
         .name = "qemu64",
@@ -1093,6 +1117,33 @@ static X86CPUDefinition builtin_x86_defs[] = {
     },
 };
 
+static void x86_cpu_class_init_cpudef(ObjectClass *oc, void *data)
+{
+    X86CPUDefinition *cpudef = data;
+    X86CPUClass *xcc = X86_CPU_CLASS(oc);
+    xcc->cpu_def = cpudef;
+}
+
+static void x86_register_cpudef_classes(void)
+{
+    int i;
+    for (i = 0; i < ARRAY_SIZE(builtin_x86_defs); i++) {
+        X86CPUDefinition *def = &builtin_x86_defs[i];
+        char *class_name = x86_cpu_class_name(def->name);
+        TypeInfo ti = {
+            .name = class_name,
+            .parent = TYPE_X86_CPU,
+            .instance_size = sizeof(X86CPU),
+            .abstract = false,
+            .class_size = sizeof(X86CPUClass),
+            .class_init = x86_cpu_class_init_cpudef,
+            .class_data = def,
+        };
+        type_register(&ti);
+        g_free(class_name);
+    }
+}
+
 /**
  * x86_cpu_compat_set_features:
  * @cpu_model: CPU model name to be changed. If NULL, all CPU models are changed
@@ -1134,44 +1185,74 @@ static int cpu_x86_fill_model_id(char *str)
     return 0;
 }
 
-/* Fill a X86CPUDefinition struct with information about the host CPU, and
- * the CPU features supported by the host hardware + host kernel
+static X86CPUDefinition host_cpudef;
+
+/* class_init for the "host" CPU model
  *
- * This function may be called only if KVM is enabled.
+ * This function may be called before KVM is initialized.
  */
-static void kvm_cpu_fill_host(X86CPUDefinition *x86_cpu_def)
+static void x86_cpu_class_init_host(ObjectClass *oc, void *data)
 {
-    KVMState *s = kvm_state;
+    X86CPUClass *xcc = X86_CPU_CLASS(oc);
     uint32_t eax = 0, ebx = 0, ecx = 0, edx = 0;
 
-    assert(kvm_enabled());
+    xcc->kvm_required = true;
 
-    x86_cpu_def->name = "host";
-    x86_cpu_def->cache_info_passthrough = true;
     host_cpuid(0x0, 0, &eax, &ebx, &ecx, &edx);
-    x86_cpu_vendor_words2str(x86_cpu_def->vendor, ebx, edx, ecx);
+    x86_cpu_vendor_words2str(host_cpudef.vendor, ebx, edx, 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;
+    host_cpudef.family = ((eax >> 8) & 0x0F) + ((eax >> 20) & 0xFF);
+    host_cpudef.model = ((eax >> 4) & 0x0F) | ((eax & 0xF0000) >> 12);
+    host_cpudef.stepping = eax & 0x0F;
+
+    cpu_x86_fill_model_id(host_cpudef.model_id);
+
+    xcc->cpu_def = &host_cpudef;
+    xcc->model_description =
+        "KVM processor with all supported host features "
+        "(only available in KVM mode)";
+
+    host_cpudef.cache_info_passthrough = true;
 
-    x86_cpu_def->level = kvm_arch_get_supported_cpuid(s, 0x0, 0, R_EAX);
-    x86_cpu_def->xlevel = kvm_arch_get_supported_cpuid(s, 0x80000000, 0, R_EAX);
-    x86_cpu_def->xlevel2 =
-        kvm_arch_get_supported_cpuid(s, 0xC0000000, 0, R_EAX);
+    /* level, xlevel, xlevel2, and the feature words are initialized on
+     * instance_init, because they require KVM to be initialized.
+     */
+}
+
+static void x86_cpu_instance_init_host(Object *obj)
+{
+    X86CPU *cpu = X86_CPU(obj);
+    CPUX86State *env = &cpu->env;
+    KVMState *s = kvm_state;
+
+    assert(kvm_enabled());
 
-    cpu_x86_fill_model_id(x86_cpu_def->model_id);
+    env->cpuid_level = kvm_arch_get_supported_cpuid(s, 0x0, 0, R_EAX);
+    env->cpuid_xlevel = kvm_arch_get_supported_cpuid(s, 0x80000000, 0, R_EAX);
+    env->cpuid_xlevel2 = kvm_arch_get_supported_cpuid(s, 0xC0000000, 0, R_EAX);
 
     FeatureWord w;
     for (w = 0; w < FEATURE_WORDS; w++) {
         FeatureWordInfo *wi = &feature_word_info[w];
-        x86_cpu_def->features[w] =
+        env->features[w] =
             kvm_arch_get_supported_cpuid(s, wi->cpuid_eax, wi->cpuid_ecx,
                                          wi->cpuid_reg);
     }
+    object_property_set_bool(OBJECT(cpu), true, "pmu", &error_abort);
 }
 
+
+static const TypeInfo x86_cpu_host_type_info = {
+    .name = CPU_CLASS_NAME("host"),
+    .parent = TYPE_X86_CPU,
+    .instance_size = sizeof(X86CPU),
+    .instance_init = x86_cpu_instance_init_host,
+    .abstract = false,
+    .class_size = sizeof(X86CPUClass),
+    .class_init = x86_cpu_class_init_host,
+};
+
 static int unavailable_host_feature(FeatureWordInfo *f, uint32_t mask)
 {
     int i;
@@ -1582,32 +1663,6 @@ static PropertyInfo qdev_prop_spinlocks = {
     .set   = x86_set_hv_spinlocks,
 };
 
-static int cpu_x86_find_by_name(X86CPU *cpu, X86CPUDefinition *x86_cpu_def,
-                                const char *name)
-{
-    X86CPUDefinition *def;
-    int i;
-
-    if (name == NULL) {
-        return -1;
-    }
-    if (kvm_enabled() && strcmp(name, "host") == 0) {
-        kvm_cpu_fill_host(x86_cpu_def);
-        object_property_set_bool(OBJECT(cpu), true, "pmu", &error_abort);
-        return 0;
-    }
-
-    for (i = 0; i < ARRAY_SIZE(builtin_x86_defs); i++) {
-        def = &builtin_x86_defs[i];
-        if (strcmp(name, def->name) == 0) {
-            memcpy(x86_cpu_def, def, sizeof(*def));
-            return 0;
-        }
-    }
-
-    return -1;
-}
-
 /* Convert all '_' in a feature string option name to '-', to make feature
  * name conform to QOM property naming rule, which uses '-' instead of '_'.
  */
@@ -1817,19 +1872,11 @@ static void filter_features_for_kvm(X86CPU *cpu)
     }
 }
 
-/* Load CPU definition for a given CPU model name
+/* Load data from X86CPUDefinition
  */
-static void x86_cpu_load_def(X86CPU *cpu, const char *name, Error **errp)
+static void x86_cpu_load_def(X86CPU *cpu, X86CPUDefinition *def, Error **errp)
 {
     CPUX86State *env = &cpu->env;
-    X86CPUDefinition def1, *def = &def1;
-
-    memset(def, 0, sizeof(*def));
-
-    if (cpu_x86_find_by_name(cpu, def, name) < 0) {
-        error_setg(errp, "Unable to find CPU definition: %s", name);
-        return;
-    }
 
     object_property_set_int(OBJECT(cpu), def->level, "level", errp);
     object_property_set_int(OBJECT(cpu), def->family, "family", errp);
@@ -1881,7 +1928,6 @@ X86CPU *cpu_x86_create(const char *cpu_model, DeviceState *icc_bridge,
     X86CPU *cpu = NULL;
     gchar **model_pieces;
     char *name, *features;
-    char *typename;
     Error *error = NULL;
 
     model_pieces = g_strsplit(cpu_model, ",", 2);
@@ -1892,12 +1938,19 @@ X86CPU *cpu_x86_create(const char *cpu_model, DeviceState *icc_bridge,
     name = model_pieces[0];
     features = model_pieces[1];
 
-    cpu = X86_CPU(object_new(TYPE_X86_CPU));
-    x86_cpu_load_def(cpu, name, &error);
-    if (error) {
+    X86CPUClass *cc = x86_cpu_class_by_name(name);
+    if (!cc) {
+        error_setg(&error, "Unable to find CPU definition: %s", name);
+        goto out;
+     }
+
+    if (cc->kvm_required && !kvm_enabled()) {
+        error_setg(&error, "CPU model '%s' requires KVM", name);
         goto out;
     }
 
+    cpu = X86_CPU(object_new(object_class_get_name(OBJECT_CLASS(cc))));
+
 #ifndef CONFIG_USER_ONLY
     if (icc_bridge == NULL) {
         error_setg(&error, "Invalid icc-bridge value");
@@ -1907,14 +1960,6 @@ X86CPU *cpu_x86_create(const char *cpu_model, DeviceState *icc_bridge,
     object_unref(OBJECT(cpu));
 #endif
 
-    /* Emulate per-model subclasses for global properties */
-    typename = g_strdup_printf("%s-" TYPE_X86_CPU, name);
-    qdev_prop_set_globals_for_type(DEVICE(cpu), typename, &error);
-    g_free(typename);
-    if (error) {
-        goto out;
-    }
-
     cpu_x86_parse_featurestr(cpu, features, &error);
     if (error) {
         goto out;
@@ -1923,8 +1968,10 @@ X86CPU *cpu_x86_create(const char *cpu_model, DeviceState *icc_bridge,
 out:
     if (error != NULL) {
         error_propagate(errp, error);
-        object_unref(OBJECT(cpu));
-        cpu = NULL;
+        if (cpu) {
+            object_unref(OBJECT(cpu));
+            cpu = NULL;
+        }
     }
     g_strfreev(model_pieces);
     return cpu;
@@ -2615,6 +2662,7 @@ static void x86_cpu_initfn(Object *obj)
 {
     CPUState *cs = CPU(obj);
     X86CPU *cpu = X86_CPU(obj);
+    X86CPUClass *xcc = X86_CPU_GET_CLASS(cpu);
     CPUX86State *env = &cpu->env;
     static int inited;
 
@@ -2666,6 +2714,9 @@ static void x86_cpu_initfn(Object *obj)
         cpu_set_debug_excp_handler(breakpoint_handler);
 #endif
     }
+
+    X86CPUDefinition *def = xcc->cpu_def;
+    x86_cpu_load_def(cpu, def, &error_abort);
 }
 
 static int64_t x86_cpu_get_arch_id(CPUState *cs)
@@ -2748,7 +2799,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,
 };
@@ -2756,6 +2807,8 @@ static const TypeInfo x86_cpu_type_info = {
 static void x86_cpu_register_types(void)
 {
     type_register_static(&x86_cpu_type_info);
+    x86_register_cpudef_classes();
+    type_register_static(&x86_cpu_host_type_info);
 }
 
 type_init(x86_cpu_register_types)
