diff --git a/hw/ppc/cpu-core.c b/hw/ppc/cpu-core.c
index ed0481f..f60646d 100644
--- a/hw/ppc/cpu-core.c
+++ b/hw/ppc/cpu-core.c
@@ -7,6 +7,8 @@
 
 #include "hw/qdev.h"
 #include "hw/ppc/cpu-core.h"
+#include "hw/boards.h"
+#include <sysemu/cpus.h>
 
 static int ppc_cpu_core_realize_child(Object *child, void *opaque)
 {
@@ -32,10 +34,25 @@ static void ppc_cpu_core_class_init(ObjectClass *oc, void *data)
     dc->realize = ppc_cpu_core_realize;
 }
 
+static void ppc_cpu_core_instance_init(Object *obj)
+{
+    int i;
+    PowerPCCPU *cpu = NULL;
+    MachineState *machine = MACHINE(qdev_get_machine());
+
+    for (i = 0; i < smp_threads; i++) {
+        cpu = POWERPC_CPU(cpu_ppc_create(TYPE_POWERPC_CPU, machine->cpu_model));
+        object_property_add_child(obj, "thread[*]", OBJECT(cpu), &error_abort);
+        object_unref(OBJECT(cpu));
+    }
+}
+
 static const TypeInfo ppc_cpu_core_type_info = {
     .name = TYPE_POWERPC_CPU_CORE,
     .parent = TYPE_DEVICE,
     .class_init = ppc_cpu_core_class_init,
+    .instance_init = ppc_cpu_core_instance_init,
+    .instance_size = sizeof(PowerPCCPUCore),
 };
 
 static void ppc_cpu_core_register_types(void)
diff --git a/hw/ppc/cpu-socket.c b/hw/ppc/cpu-socket.c
index 602a060..f901336 100644
--- a/hw/ppc/cpu-socket.c
+++ b/hw/ppc/cpu-socket.c
@@ -8,6 +8,7 @@
 #include "hw/qdev.h"
 #include "hw/ppc/cpu-socket.h"
 #include "sysemu/cpus.h"
+#include "cpu.h"
 
 static int ppc_cpu_socket_realize_child(Object *child, void *opaque)
 {
@@ -33,10 +34,24 @@ static void ppc_cpu_socket_class_init(ObjectClass *oc, void *data)
     dc->realize = ppc_cpu_socket_realize;
 }
 
+static void ppc_cpu_socket_instance_init(Object *obj)
+{
+    int i;
+    Object *core;
+
+    for (i = 0; i < smp_cores; i++) {
+        core = object_new(TYPE_POWERPC_CPU_CORE);
+        object_property_add_child(obj, "core[*]", core, &error_abort);
+        object_unref(core);
+    }
+}
+
 static const TypeInfo ppc_cpu_socket_type_info = {
     .name = TYPE_POWERPC_CPU_SOCKET,
     .parent = TYPE_CPU_SOCKET,
     .class_init = ppc_cpu_socket_class_init,
+    .instance_init = ppc_cpu_socket_instance_init,
+    .instance_size = sizeof(PowerPCCPUSocket),
 };
 
 static void ppc_cpu_socket_register_types(void)
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index 16b67f4..f52d38f 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -37,6 +37,7 @@
 #include "mmu-hash64.h"
 #include "qom/cpu.h"
 
+#include "hw/ppc/cpu-socket.h"
 #include "hw/boards.h"
 #include "hw/ppc/ppc.h"
 #include "hw/loader.h"
@@ -1469,7 +1470,6 @@ static void ppc_spapr_init(MachineState *machine)
     const char *kernel_cmdline = machine->kernel_cmdline;
     const char *initrd_filename = machine->initrd_filename;
     const char *boot_device = machine->boot_order;
-    PowerPCCPU *cpu;
     PCIHostState *phb;
     int i;
     MemoryRegion *sysmem = get_system_memory();
@@ -1484,6 +1484,8 @@ static void ppc_spapr_init(MachineState *machine)
     bool kernel_le = false;
     char *filename;
     int smt = kvmppc_smt_threads();
+    Object *socket;
+    int sockets;
 
     msi_supported = true;
 
@@ -1548,12 +1550,11 @@ static void ppc_spapr_init(MachineState *machine)
     if (machine->cpu_model == NULL) {
         machine->cpu_model = kvm_enabled() ? "host" : "POWER7";
     }
-    for (i = 0; i < smp_cpus; i++) {
-        cpu = cpu_ppc_init(machine->cpu_model);
-        if (cpu == NULL) {
-            fprintf(stderr, "Unable to find PowerPC CPU definition\n");
-            exit(1);
-        }
+
+    sockets = smp_cpus / smp_cores / smp_threads;
+    for (i = 0; i < sockets; i++) {
+        socket = object_new(TYPE_POWERPC_CPU_SOCKET);
+        object_property_set_bool(socket, true, "realized", &error_abort);
     }
 
     /* allocate RAM */
diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h
index abc3545..f15cc2c 100644
--- a/target-ppc/cpu.h
+++ b/target-ppc/cpu.h
@@ -1162,6 +1162,7 @@ do {                                            \
 
 /*****************************************************************************/
 PowerPCCPU *cpu_ppc_init(const char *cpu_model);
+CPUState *cpu_ppc_create(const char *typename, const char *cpu_model);
 void ppc_translate_init(void);
 void gen_update_current_nip(void *opaque);
 int cpu_ppc_exec (CPUPPCState *s);
diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index d74f4f0..a8716cf 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -9365,6 +9365,52 @@ static ObjectClass *ppc_cpu_class_by_name(const char *name)
     return NULL;
 }
 
+/*
+ * This is essentially same as cpu_generic_init() but without a set
+ * realize call.
+ */
+CPUState *cpu_ppc_create(const char *typename, const char *cpu_model)
+{
+    char *str, *name, *featurestr;
+    CPUState *cpu;
+    ObjectClass *oc;
+    CPUClass *cc;
+    Error *err = NULL;
+
+    str = g_strdup(cpu_model);
+    name = strtok(str, ",");
+
+    oc = cpu_class_by_name(typename, name);
+    if (oc == NULL) {
+        g_free(str);
+        return NULL;
+    }
+
+    cpu = CPU(object_new(object_class_get_name(oc)));
+    cc = CPU_GET_CLASS(cpu);
+
+    featurestr = strtok(NULL, ",");
+    cc->parse_features(cpu, featurestr, &err);
+    g_free(str);
+    if (err != NULL) {
+        goto out;
+    }
+
+out:
+    if (err != NULL) {
+        error_report("%s", error_get_pretty(err));
+        error_free(err);
+        object_unref(OBJECT(cpu));
+        return NULL;
+    }
+
+    return cpu;
+}
+
+/*
+ * TODO: This can be removed when all powerpc targets are converted to
+ * socket level CPU realization.
+ */
 PowerPCCPU *cpu_ppc_init(const char *cpu_model)
 {
     return POWERPC_CPU(cpu_generic_init(TYPE_POWERPC_CPU, cpu_model));
