Merge remote-tracking branch 'quintela/migration.next' into staging

# By Michael R. Hines (8) and others
# Via Juan Quintela
* quintela/migration.next:
  migration: add autoconvergence documentation
  Fix real mode guest segments dpl value in savevm
  Fix real mode guest migration
  rdma: account for the time spent in MIG_STATE_SETUP through QMP
  rdma: introduce MIG_STATE_NONE and change MIG_STATE_SETUP state transition
  rdma: allow state transitions between other states besides ACTIVE
  rdma: send pc.ram
  rdma: core logic
  rdma: introduce ram_handle_compressed()
  rdma: bugfix: ram_control_save_page()
  rdma: update documentation to reflect new unpin support

Message-id: 1374590725-14144-1-git-send-email-quintela@redhat.com
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
diff --git a/HACKING b/HACKING
index e73ac79..12fbc8a 100644
--- a/HACKING
+++ b/HACKING
@@ -40,8 +40,23 @@
 it would not be correct to store an actual guest physical address in a
 ram_addr_t.
 
-Use target_ulong (or abi_ulong) for CPU virtual addresses, however
-devices should not need to use target_ulong.
+For CPU virtual addresses there are several possible types.
+vaddr is the best type to use to hold a CPU virtual address in
+target-independent code. It is guaranteed to be large enough to hold a
+virtual address for any target, and it does not change size from target
+to target. It is always unsigned.
+target_ulong is a type the size of a virtual address on the CPU; this means
+it may be 32 or 64 bits depending on which target is being built. It should
+therefore be used only in target-specific code, and in some
+performance-critical built-per-target core code such as the TLB code.
+There is also a signed version, target_long.
+abi_ulong is for the *-user targets, and represents a type the size of
+'void *' in that target's ABI. (This may not be the same as the size of a
+full CPU virtual address in the case of target ABIs which use 32 bit pointers
+on 64 bit CPUs, like sparc32plus.) Definitions of structures that must match
+the target's ABI must use this type for anything that on the target is defined
+to be an 'unsigned long' or a pointer type.
+There is also a signed version, abi_long.
 
 Of course, take all of the above with a grain of salt.  If you're about
 to use some system interface that requires a type like size_t, pid_t or
diff --git a/bsd-user/main.c b/bsd-user/main.c
index 1e92552..f9246aa 100644
--- a/bsd-user/main.c
+++ b/bsd-user/main.c
@@ -643,7 +643,7 @@
             {
                 int sig;
 
-                sig = gdb_handlesig (env, TARGET_SIGTRAP);
+                sig = gdb_handlesig(cs, TARGET_SIGTRAP);
 #if 0
                 if (sig)
                   {
@@ -738,6 +738,7 @@
     struct image_info info1, *info = &info1;
     TaskState ts1, *ts = &ts1;
     CPUArchState *env;
+    CPUState *cpu;
     int optind;
     const char *r;
     int gdbstub_port = 0;
@@ -912,10 +913,11 @@
         fprintf(stderr, "Unable to find CPU definition\n");
         exit(1);
     }
+    cpu = ENV_GET_CPU(env);
 #if defined(TARGET_SPARC) || defined(TARGET_PPC)
-    cpu_reset(ENV_GET_CPU(env));
+    cpu_reset(cpu);
 #endif
-    thread_cpu = ENV_GET_CPU(env);
+    thread_cpu = cpu;
 
     if (getenv("QEMU_STRACE")) {
         do_strace = 1;
@@ -1134,7 +1136,7 @@
 
     if (gdbstub_port) {
         gdbserver_start (gdbstub_port);
-        gdb_handlesig(env, 0);
+        gdb_handlesig(cpu, 0);
     }
     cpu_loop(env);
     /* never exits */
diff --git a/cpu-exec.c b/cpu-exec.c
index 6c784a7..301be28 100644
--- a/cpu-exec.c
+++ b/cpu-exec.c
@@ -59,8 +59,14 @@
          * counter hit zero); we must restore the guest PC to the address
          * of the start of the TB.
          */
+        CPUClass *cc = CPU_GET_CLASS(cpu);
         TranslationBlock *tb = (TranslationBlock *)(next_tb & ~TB_EXIT_MASK);
-        cpu_pc_from_tb(env, tb);
+        if (cc->synchronize_from_tb) {
+            cc->synchronize_from_tb(cpu, tb);
+        } else {
+            assert(cc->set_pc);
+            cc->set_pc(cpu, tb->pc);
+        }
     }
     if ((next_tb & TB_EXIT_MASK) == TB_EXIT_REQUESTED) {
         /* We were asked to stop executing TBs (probably a pending
@@ -291,7 +297,7 @@
             for(;;) {
                 interrupt_request = cpu->interrupt_request;
                 if (unlikely(interrupt_request)) {
-                    if (unlikely(env->singlestep_enabled & SSTEP_NOIRQ)) {
+                    if (unlikely(cpu->singlestep_enabled & SSTEP_NOIRQ)) {
                         /* Mask out external interrupts for this step. */
                         interrupt_request &= ~CPU_INTERRUPT_SSTEP_MASK;
                     }
diff --git a/cpus.c b/cpus.c
index 2509eb5..ca6b886 100644
--- a/cpus.c
+++ b/cpus.c
@@ -1186,7 +1186,7 @@
         CPUArchState *env = cpu->env_ptr;
 
         qemu_clock_enable(vm_clock,
-                          (env->singlestep_enabled & SSTEP_NOTIMER) == 0);
+                          (cpu->singlestep_enabled & SSTEP_NOTIMER) == 0);
 
         if (cpu_can_run(cpu)) {
             r = tcg_cpu_exec(env);
@@ -1285,7 +1285,6 @@
 {
     FILE *f;
     uint32_t l;
-    CPUArchState *env;
     CPUState *cpu;
     uint8_t buf[1024];
 
@@ -1299,7 +1298,6 @@
                   "a CPU number");
         return;
     }
-    env = cpu->env_ptr;
 
     f = fopen(filename, "wb");
     if (!f) {
@@ -1311,7 +1309,7 @@
         l = sizeof(buf);
         if (l > size)
             l = size;
-        cpu_memory_rw_debug(env, addr, buf, l, 0);
+        cpu_memory_rw_debug(cpu, addr, buf, l, 0);
         if (fwrite(buf, 1, l, f) != l) {
             error_set(errp, QERR_IO_ERROR);
             goto exit;
diff --git a/disas.c b/disas.c
index e51127e..71007fb 100644
--- a/disas.c
+++ b/disas.c
@@ -39,7 +39,7 @@
 {
     CPUDebug *s = container_of(info, CPUDebug, info);
 
-    cpu_memory_rw_debug(s->env, memaddr, myaddr, length, 0);
+    cpu_memory_rw_debug(ENV_GET_CPU(s->env), memaddr, myaddr, length, 0);
     return 0;
 }
 
@@ -392,7 +392,7 @@
     if (monitor_disas_is_physical) {
         cpu_physical_memory_read(memaddr, myaddr, length);
     } else {
-        cpu_memory_rw_debug(s->env, memaddr,myaddr, length, 0);
+        cpu_memory_rw_debug(ENV_GET_CPU(s->env), memaddr, myaddr, length, 0);
     }
     return 0;
 }
diff --git a/exec.c b/exec.c
index c8658c6..7997002 100644
--- a/exec.c
+++ b/exec.c
@@ -415,14 +415,14 @@
 
 #if defined(TARGET_HAS_ICE)
 #if defined(CONFIG_USER_ONLY)
-static void breakpoint_invalidate(CPUArchState *env, target_ulong pc)
+static void breakpoint_invalidate(CPUState *cpu, target_ulong pc)
 {
     tb_invalidate_phys_page_range(pc, pc + 1, 0);
 }
 #else
-static void breakpoint_invalidate(CPUArchState *env, target_ulong pc)
+static void breakpoint_invalidate(CPUState *cpu, target_ulong pc)
 {
-    tb_invalidate_phys_addr(cpu_get_phys_page_debug(env, pc) |
+    tb_invalidate_phys_addr(cpu_get_phys_page_debug(cpu, pc) |
             (pc & ~TARGET_PAGE_MASK));
 }
 #endif
@@ -525,15 +525,17 @@
     bp->flags = flags;
 
     /* keep all GDB-injected breakpoints in front */
-    if (flags & BP_GDB)
+    if (flags & BP_GDB) {
         QTAILQ_INSERT_HEAD(&env->breakpoints, bp, entry);
-    else
+    } else {
         QTAILQ_INSERT_TAIL(&env->breakpoints, bp, entry);
+    }
 
-    breakpoint_invalidate(env, pc);
+    breakpoint_invalidate(ENV_GET_CPU(env), pc);
 
-    if (breakpoint)
+    if (breakpoint) {
         *breakpoint = bp;
+    }
     return 0;
 #else
     return -ENOSYS;
@@ -564,7 +566,7 @@
 #if defined(TARGET_HAS_ICE)
     QTAILQ_REMOVE(&env->breakpoints, breakpoint, entry);
 
-    breakpoint_invalidate(env, breakpoint->pc);
+    breakpoint_invalidate(ENV_GET_CPU(env), breakpoint->pc);
 
     g_free(breakpoint);
 #endif
@@ -585,14 +587,16 @@
 
 /* enable or disable single step mode. EXCP_DEBUG is returned by the
    CPU loop after each instruction */
-void cpu_single_step(CPUArchState *env, int enabled)
+void cpu_single_step(CPUState *cpu, int enabled)
 {
 #if defined(TARGET_HAS_ICE)
-    if (env->singlestep_enabled != enabled) {
-        env->singlestep_enabled = enabled;
-        if (kvm_enabled())
+    CPUArchState *env = cpu->env_ptr;
+
+    if (cpu->singlestep_enabled != enabled) {
+        cpu->singlestep_enabled = enabled;
+        if (kvm_enabled()) {
             kvm_update_guest_debug(env, 0);
-        else {
+        } else {
             /* must flush all the translated code to avoid inconsistencies */
             /* XXX: only flush what is necessary */
             tb_flush(env);
@@ -1831,7 +1835,7 @@
 
 /* physical memory access (slow version, mainly for debug) */
 #if defined(CONFIG_USER_ONLY)
-int cpu_memory_rw_debug(CPUArchState *env, target_ulong addr,
+int cpu_memory_rw_debug(CPUState *cpu, target_ulong addr,
                         uint8_t *buf, int len, int is_write)
 {
     int l, flags;
@@ -2602,7 +2606,7 @@
 }
 
 /* virtual memory access for debug (includes writing to ROM) */
-int cpu_memory_rw_debug(CPUArchState *env, target_ulong addr,
+int cpu_memory_rw_debug(CPUState *cpu, target_ulong addr,
                         uint8_t *buf, int len, int is_write)
 {
     int l;
@@ -2611,7 +2615,7 @@
 
     while (len > 0) {
         page = addr & TARGET_PAGE_MASK;
-        phys_addr = cpu_get_phys_page_debug(env, page);
+        phys_addr = cpu_get_phys_page_debug(cpu, page);
         /* if no physical page mapped, return an error */
         if (phys_addr == -1)
             return -1;
diff --git a/gdbstub.c b/gdbstub.c
index 0ee82a9..35ca7c2 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -42,15 +42,16 @@
 #include "sysemu/kvm.h"
 #include "qemu/bitops.h"
 
-#ifndef TARGET_CPU_MEMORY_RW_DEBUG
-static inline int target_memory_rw_debug(CPUArchState *env, target_ulong addr,
-                                         uint8_t *buf, int len, int is_write)
+static inline int target_memory_rw_debug(CPUState *cpu, target_ulong addr,
+                                         uint8_t *buf, int len, bool is_write)
 {
-    return cpu_memory_rw_debug(env, addr, buf, len, is_write);
+    CPUClass *cc = CPU_GET_CLASS(cpu);
+
+    if (cc->memory_rw_debug) {
+        return cc->memory_rw_debug(cpu, addr, buf, len, is_write);
+    }
+    return cpu_memory_rw_debug(cpu, addr, buf, len, is_write);
 }
-#else
-/* target_memory_rw_debug() defined in cpu.h */
-#endif
 
 enum {
     GDB_SIGNAL_0 = 0,
@@ -287,9 +288,9 @@
     RS_CHKSUM2,
 };
 typedef struct GDBState {
-    CPUArchState *c_cpu; /* current CPU for step/continue ops */
-    CPUArchState *g_cpu; /* current CPU for other ops */
-    CPUArchState *query_cpu; /* for q{f|s}ThreadInfo */
+    CPUState *c_cpu; /* current CPU for step/continue ops */
+    CPUState *g_cpu; /* current CPU for other ops */
+    CPUState *query_cpu; /* for q{f|s}ThreadInfo */
     enum RSState state; /* parsing state */
     char line_buf[MAX_PACKET_LENGTH];
     int line_buf_index;
@@ -1839,7 +1840,7 @@
         /* Generate the XML description for this CPU.  */
         if (!target_xml[0]) {
             GDBRegisterState *r;
-            CPUArchState *env = first_cpu->env_ptr;
+            CPUState *cpu = first_cpu;
 
             snprintf(target_xml, sizeof(target_xml),
                      "<?xml version=\"1.0\"?>"
@@ -1848,7 +1849,7 @@
                      "<xi:include href=\"%s\"/>",
                      GDB_CORE_XML);
 
-            for (r = env->gdb_regs; r; r = r->next) {
+            for (r = cpu->gdb_regs; r; r = r->next) {
                 pstrcat(target_xml, sizeof(target_xml), "<xi:include href=\"");
                 pstrcat(target_xml, sizeof(target_xml), r->xml);
                 pstrcat(target_xml, sizeof(target_xml), "\"/>");
@@ -1866,14 +1867,15 @@
 }
 #endif
 
-static int gdb_read_register(CPUArchState *env, uint8_t *mem_buf, int reg)
+static int gdb_read_register(CPUState *cpu, uint8_t *mem_buf, int reg)
 {
+    CPUArchState *env = cpu->env_ptr;
     GDBRegisterState *r;
 
     if (reg < NUM_CORE_REGS)
         return cpu_gdb_read_register(env, mem_buf, reg);
 
-    for (r = env->gdb_regs; r; r = r->next) {
+    for (r = cpu->gdb_regs; r; r = r->next) {
         if (r->base_reg <= reg && reg < r->base_reg + r->num_regs) {
             return r->get_reg(env, mem_buf, reg - r->base_reg);
         }
@@ -1881,14 +1883,15 @@
     return 0;
 }
 
-static int gdb_write_register(CPUArchState *env, uint8_t *mem_buf, int reg)
+static int gdb_write_register(CPUState *cpu, uint8_t *mem_buf, int reg)
 {
+    CPUArchState *env = cpu->env_ptr;
     GDBRegisterState *r;
 
     if (reg < NUM_CORE_REGS)
         return cpu_gdb_write_register(env, mem_buf, reg);
 
-    for (r = env->gdb_regs; r; r = r->next) {
+    for (r = cpu->gdb_regs; r; r = r->next) {
         if (r->base_reg <= reg && reg < r->base_reg + r->num_regs) {
             return r->set_reg(env, mem_buf, reg - r->base_reg);
         }
@@ -1903,15 +1906,15 @@
    gdb reading a CPU register, and set_reg is gdb modifying a CPU register.
  */
 
-void gdb_register_coprocessor(CPUArchState * env,
-                             gdb_reg_cb get_reg, gdb_reg_cb set_reg,
-                             int num_regs, const char *xml, int g_pos)
+void gdb_register_coprocessor(CPUState *cpu,
+                              gdb_reg_cb get_reg, gdb_reg_cb set_reg,
+                              int num_regs, const char *xml, int g_pos)
 {
     GDBRegisterState *s;
     GDBRegisterState **p;
     static int last_reg = NUM_CORE_REGS;
 
-    p = &env->gdb_regs;
+    p = &cpu->gdb_regs;
     while (*p) {
         /* Check for duplicates.  */
         if (strcmp((*p)->xml, xml) == 0)
@@ -1954,8 +1957,9 @@
     CPUArchState *env;
     int err = 0;
 
-    if (kvm_enabled())
+    if (kvm_enabled()) {
         return kvm_insert_breakpoint(gdbserver_state->c_cpu, addr, len, type);
+    }
 
     switch (type) {
     case GDB_BREAKPOINT_SW:
@@ -1991,8 +1995,9 @@
     CPUArchState *env;
     int err = 0;
 
-    if (kvm_enabled())
+    if (kvm_enabled()) {
         return kvm_remove_breakpoint(gdbserver_state->c_cpu, addr, len, type);
+    }
 
     switch (type) {
     case GDB_BREAKPOINT_SW:
@@ -2027,7 +2032,7 @@
     CPUArchState *env;
 
     if (kvm_enabled()) {
-        kvm_remove_all_breakpoints(ENV_GET_CPU(gdbserver_state->c_cpu));
+        kvm_remove_all_breakpoints(gdbserver_state->c_cpu);
         return;
     }
 
@@ -2042,49 +2047,22 @@
 
 static void gdb_set_cpu_pc(GDBState *s, target_ulong pc)
 {
-    cpu_synchronize_state(ENV_GET_CPU(s->c_cpu));
-#if defined(TARGET_I386)
-    s->c_cpu->eip = pc;
-#elif defined (TARGET_PPC)
-    s->c_cpu->nip = pc;
-#elif defined (TARGET_SPARC)
-    s->c_cpu->pc = pc;
-    s->c_cpu->npc = pc + 4;
-#elif defined (TARGET_ARM)
-    s->c_cpu->regs[15] = pc;
-#elif defined (TARGET_SH4)
-    s->c_cpu->pc = pc;
-#elif defined (TARGET_MIPS)
-    s->c_cpu->active_tc.PC = pc & ~(target_ulong)1;
-    if (pc & 1) {
-        s->c_cpu->hflags |= MIPS_HFLAG_M16;
-    } else {
-        s->c_cpu->hflags &= ~(MIPS_HFLAG_M16);
+    CPUState *cpu = s->c_cpu;
+    CPUClass *cc = CPU_GET_CLASS(cpu);
+
+    cpu_synchronize_state(cpu);
+    if (cc->set_pc) {
+        cc->set_pc(cpu, pc);
     }
-#elif defined (TARGET_MICROBLAZE)
-    s->c_cpu->sregs[SR_PC] = pc;
-#elif defined(TARGET_OPENRISC)
-    s->c_cpu->pc = pc;
-#elif defined (TARGET_CRIS)
-    s->c_cpu->pc = pc;
-#elif defined (TARGET_ALPHA)
-    s->c_cpu->pc = pc;
-#elif defined (TARGET_S390X)
-    s->c_cpu->psw.addr = pc;
-#elif defined (TARGET_LM32)
-    s->c_cpu->pc = pc;
-#elif defined(TARGET_XTENSA)
-    s->c_cpu->pc = pc;
-#endif
 }
 
-static CPUArchState *find_cpu(uint32_t thread_id)
+static CPUState *find_cpu(uint32_t thread_id)
 {
     CPUState *cpu;
 
     for (cpu = first_cpu; cpu != NULL; cpu = cpu->next_cpu) {
         if (cpu_index(cpu) == thread_id) {
-            return cpu->env_ptr;
+            return cpu;
         }
     }
 
@@ -2093,7 +2071,10 @@
 
 static int gdb_handle_packet(GDBState *s, const char *line_buf)
 {
+#ifdef TARGET_XTENSA
     CPUArchState *env;
+#endif
+    CPUState *cpu;
     const char *p;
     uint32_t thread;
     int ch, reg_size, type, res;
@@ -2111,7 +2092,7 @@
     case '?':
         /* TODO: Make this return the correct value for user-mode.  */
         snprintf(buf, sizeof(buf), "T%02xthread:%02x;", GDB_SIGNAL_TRAP,
-                 cpu_index(ENV_GET_CPU(s->c_cpu)));
+                 cpu_index(s->c_cpu));
         put_packet(s, buf);
         /* Remove all the breakpoints when this query is issued,
          * because gdb is doing and initial connect and the state
@@ -2173,12 +2154,12 @@
             }
             if (res) {
                 if (res_thread != -1 && res_thread != 0) {
-                    env = find_cpu(res_thread);
-                    if (env == NULL) {
+                    cpu = find_cpu(res_thread);
+                    if (cpu == NULL) {
                         put_packet(s, "E22");
                         break;
                     }
-                    s->c_cpu = env;
+                    s->c_cpu = cpu;
                 }
                 if (res == 's') {
                     cpu_single_step(s->c_cpu, sstep_flags);
@@ -2239,8 +2220,10 @@
         }
         break;
     case 'g':
-        cpu_synchronize_state(ENV_GET_CPU(s->g_cpu));
-        env = s->g_cpu;
+        cpu_synchronize_state(s->g_cpu);
+#ifdef TARGET_XTENSA
+        env = s->g_cpu->env_ptr;
+#endif
         len = 0;
         for (addr = 0; addr < num_g_regs; addr++) {
             reg_size = gdb_read_register(s->g_cpu, mem_buf + len, addr);
@@ -2250,8 +2233,10 @@
         put_packet(s, buf);
         break;
     case 'G':
-        cpu_synchronize_state(ENV_GET_CPU(s->g_cpu));
-        env = s->g_cpu;
+        cpu_synchronize_state(s->g_cpu);
+#ifdef TARGET_XTENSA
+        env = s->g_cpu->env_ptr;
+#endif
         registers = mem_buf;
         len = strlen(p) / 2;
         hextomem((uint8_t *)registers, p, len);
@@ -2267,7 +2252,7 @@
         if (*p == ',')
             p++;
         len = strtoull(p, NULL, 16);
-        if (target_memory_rw_debug(s->g_cpu, addr, mem_buf, len, 0) != 0) {
+        if (target_memory_rw_debug(s->g_cpu, addr, mem_buf, len, false) != 0) {
             put_packet (s, "E14");
         } else {
             memtohex(buf, mem_buf, len);
@@ -2282,7 +2267,8 @@
         if (*p == ':')
             p++;
         hextomem(mem_buf, p, len);
-        if (target_memory_rw_debug(s->g_cpu, addr, mem_buf, len, 1) != 0) {
+        if (target_memory_rw_debug(s->g_cpu, addr, mem_buf, len,
+                                   true) != 0) {
             put_packet(s, "E14");
         } else {
             put_packet(s, "OK");
@@ -2341,18 +2327,18 @@
             put_packet(s, "OK");
             break;
         }
-        env = find_cpu(thread);
-        if (env == NULL) {
+        cpu = find_cpu(thread);
+        if (cpu == NULL) {
             put_packet(s, "E22");
             break;
         }
         switch (type) {
         case 'c':
-            s->c_cpu = env;
+            s->c_cpu = cpu;
             put_packet(s, "OK");
             break;
         case 'g':
-            s->g_cpu = env;
+            s->g_cpu = cpu;
             put_packet(s, "OK");
             break;
         default:
@@ -2362,9 +2348,9 @@
         break;
     case 'T':
         thread = strtoull(p, (char **)&p, 16);
-        env = find_cpu(thread);
+        cpu = find_cpu(thread);
 
-        if (env != NULL) {
+        if (cpu != NULL) {
             put_packet(s, "OK");
         } else {
             put_packet(s, "E22");
@@ -2401,23 +2387,21 @@
             put_packet(s, "QC1");
             break;
         } else if (strcmp(p,"fThreadInfo") == 0) {
-            s->query_cpu = first_cpu->env_ptr;
+            s->query_cpu = first_cpu;
             goto report_cpuinfo;
         } else if (strcmp(p,"sThreadInfo") == 0) {
         report_cpuinfo:
             if (s->query_cpu) {
-                snprintf(buf, sizeof(buf), "m%x",
-                         cpu_index(ENV_GET_CPU(s->query_cpu)));
+                snprintf(buf, sizeof(buf), "m%x", cpu_index(s->query_cpu));
                 put_packet(s, buf);
-                s->query_cpu = ENV_GET_CPU(s->query_cpu)->next_cpu->env_ptr;
+                s->query_cpu = s->query_cpu->next_cpu;
             } else
                 put_packet(s, "l");
             break;
         } else if (strncmp(p,"ThreadExtraInfo,", 16) == 0) {
             thread = strtoull(p+16, (char **)&p, 16);
-            env = find_cpu(thread);
-            if (env != NULL) {
-                CPUState *cpu = ENV_GET_CPU(env);
+            cpu = find_cpu(thread);
+            if (cpu != NULL) {
                 cpu_synchronize_state(cpu);
                 len = snprintf((char *)mem_buf, sizeof(mem_buf),
                                "CPU#%d [%s]", cpu->cpu_index,
@@ -2429,7 +2413,8 @@
         }
 #ifdef CONFIG_USER_ONLY
         else if (strncmp(p, "Offsets", 7) == 0) {
-            TaskState *ts = s->c_cpu->opaque;
+            CPUArchState *env = s->c_cpu->env_ptr;
+            TaskState *ts = env->opaque;
 
             snprintf(buf, sizeof(buf),
                      "Text=" TARGET_ABI_FMT_lx ";Data=" TARGET_ABI_FMT_lx
@@ -2519,18 +2504,16 @@
 
 void gdb_set_stop_cpu(CPUState *cpu)
 {
-    CPUArchState *env = cpu->env_ptr;
-
-    gdbserver_state->c_cpu = env;
-    gdbserver_state->g_cpu = env;
+    gdbserver_state->c_cpu = cpu;
+    gdbserver_state->g_cpu = cpu;
 }
 
 #ifndef CONFIG_USER_ONLY
 static void gdb_vm_state_change(void *opaque, int running, RunState state)
 {
     GDBState *s = gdbserver_state;
-    CPUArchState *env = s->c_cpu;
-    CPUState *cpu = ENV_GET_CPU(env);
+    CPUArchState *env = s->c_cpu->env_ptr;
+    CPUState *cpu = s->c_cpu;
     char buf[256];
     const char *type;
     int ret;
@@ -2598,7 +2581,7 @@
     put_packet(s, buf);
 
     /* disable single step if it was enabled */
-    cpu_single_step(env, 0);
+    cpu_single_step(cpu, 0);
 }
 #endif
 
@@ -2668,7 +2651,7 @@
        is still in the running state, which can cause packets to be dropped
        and state transition 'T' packets to be sent while the syscall is still
        being processed.  */
-    cpu_exit(ENV_GET_CPU(s->c_cpu));
+    cpu_exit(s->c_cpu);
 #endif
 }
 
@@ -2789,66 +2772,67 @@
 }
 
 int
-gdb_handlesig (CPUArchState *env, int sig)
+gdb_handlesig(CPUState *cpu, int sig)
 {
-  GDBState *s;
-  char buf[256];
-  int n;
+    CPUArchState *env = cpu->env_ptr;
+    GDBState *s;
+    char buf[256];
+    int n;
 
-  s = gdbserver_state;
-  if (gdbserver_fd < 0 || s->fd < 0)
-    return sig;
-
-  /* disable single step if it was enabled */
-  cpu_single_step(env, 0);
-  tb_flush(env);
-
-  if (sig != 0)
-    {
-      snprintf(buf, sizeof(buf), "S%02x", target_signal_to_gdb (sig));
-      put_packet(s, buf);
+    s = gdbserver_state;
+    if (gdbserver_fd < 0 || s->fd < 0) {
+        return sig;
     }
-  /* put_packet() might have detected that the peer terminated the 
-     connection.  */
-  if (s->fd < 0)
-      return sig;
 
-  sig = 0;
-  s->state = RS_IDLE;
-  s->running_state = 0;
-  while (s->running_state == 0) {
-      n = read (s->fd, buf, 256);
-      if (n > 0)
-        {
-          int i;
+    /* disable single step if it was enabled */
+    cpu_single_step(cpu, 0);
+    tb_flush(env);
 
-          for (i = 0; i < n; i++)
-            gdb_read_byte (s, buf[i]);
+    if (sig != 0) {
+        snprintf(buf, sizeof(buf), "S%02x", target_signal_to_gdb(sig));
+        put_packet(s, buf);
+    }
+    /* put_packet() might have detected that the peer terminated the
+       connection.  */
+    if (s->fd < 0) {
+        return sig;
+    }
+
+    sig = 0;
+    s->state = RS_IDLE;
+    s->running_state = 0;
+    while (s->running_state == 0) {
+        n = read(s->fd, buf, 256);
+        if (n > 0) {
+            int i;
+
+            for (i = 0; i < n; i++) {
+                gdb_read_byte(s, buf[i]);
+            }
+        } else if (n == 0 || errno != EAGAIN) {
+            /* XXX: Connection closed.  Should probably wait for another
+               connection before continuing.  */
+            return sig;
         }
-      else if (n == 0 || errno != EAGAIN)
-        {
-          /* XXX: Connection closed.  Should probably wait for another
-             connection before continuing.  */
-          return sig;
-        }
-  }
-  sig = s->signal;
-  s->signal = 0;
-  return sig;
+    }
+    sig = s->signal;
+    s->signal = 0;
+    return sig;
 }
 
 /* Tell the remote gdb that the process has exited due to SIG.  */
 void gdb_signalled(CPUArchState *env, int sig)
 {
-  GDBState *s;
-  char buf[4];
+    GDBState *s;
+    char buf[4];
 
-  s = gdbserver_state;
-  if (gdbserver_fd < 0 || s->fd < 0)
-    return;
+    s = gdbserver_state;
+    if (gdbserver_fd < 0 || s->fd < 0) {
+        return;
+    }
 
-  snprintf(buf, sizeof(buf), "X%02x", target_signal_to_gdb (sig));
-  put_packet(s, buf);
+    snprintf(buf, sizeof(buf), "X%02x", target_signal_to_gdb(sig));
+    put_packet(s, buf);
 }
 
 static void gdb_accept(void)
@@ -2876,8 +2860,8 @@
     socket_set_nodelay(fd);
 
     s = g_malloc0(sizeof(GDBState));
-    s->c_cpu = first_cpu->env_ptr;
-    s->g_cpu = first_cpu->env_ptr;
+    s->c_cpu = first_cpu;
+    s->g_cpu = first_cpu;
     s->fd = fd;
     gdb_has_xml = 0;
 
@@ -3061,8 +3045,8 @@
         mon_chr = s->mon_chr;
         memset(s, 0, sizeof(GDBState));
     }
-    s->c_cpu = first_cpu->env_ptr;
-    s->g_cpu = first_cpu->env_ptr;
+    s->c_cpu = first_cpu;
+    s->g_cpu = first_cpu;
     s->chr = chr;
     s->state = chr ? RS_IDLE : RS_INACTIVE;
     s->mon_chr = mon_chr;
diff --git a/hw/acpi/piix4.c b/hw/acpi/piix4.c
index 948ea87..c885690 100644
--- a/hw/acpi/piix4.c
+++ b/hw/acpi/piix4.c
@@ -64,7 +64,9 @@
 } CPUStatus;
 
 typedef struct PIIX4PMState {
-    PCIDevice dev;
+    /*< private >*/
+    PCIDevice parent_obj;
+    /*< public >*/
 
     MemoryRegion io;
     MemoryRegion io_gpe;
@@ -96,6 +98,11 @@
     Notifier cpu_added_notifier;
 } PIIX4PMState;
 
+#define TYPE_PIIX4_PM "PIIX4_PM"
+
+#define PIIX4_PM(obj) \
+    OBJECT_CHECK(PIIX4PMState, (obj), TYPE_PIIX4_PM)
+
 static void piix4_acpi_system_hot_add_init(MemoryRegion *parent,
                                            PCIBus *bus, PIIX4PMState *s);
 
@@ -130,11 +137,12 @@
 static void apm_ctrl_changed(uint32_t val, void *arg)
 {
     PIIX4PMState *s = arg;
+    PCIDevice *d = PCI_DEVICE(s);
 
     /* ACPI specs 3.0, 4.7.2.5 */
     acpi_pm1_cnt_update(&s->ar, val == ACPI_ENABLE, val == ACPI_DISABLE);
 
-    if (s->dev.config[0x5b] & (1 << 1)) {
+    if (d->config[0x5b] & (1 << 1)) {
         if (s->smi_irq) {
             qemu_irq_raise(s->smi_irq);
         }
@@ -143,24 +151,27 @@
 
 static void pm_io_space_update(PIIX4PMState *s)
 {
+    PCIDevice *d = PCI_DEVICE(s);
     uint32_t pm_io_base;
 
-    pm_io_base = le32_to_cpu(*(uint32_t *)(s->dev.config + 0x40));
+    pm_io_base = le32_to_cpu(*(uint32_t *)(d->config + 0x40));
     pm_io_base &= 0xffc0;
 
     memory_region_transaction_begin();
-    memory_region_set_enabled(&s->io, s->dev.config[0x80] & 1);
+    memory_region_set_enabled(&s->io, d->config[0x80] & 1);
     memory_region_set_address(&s->io, pm_io_base);
     memory_region_transaction_commit();
 }
 
 static void smbus_io_space_update(PIIX4PMState *s)
 {
-    s->smb_io_base = le32_to_cpu(*(uint32_t *)(s->dev.config + 0x90));
+    PCIDevice *d = PCI_DEVICE(s);
+
+    s->smb_io_base = le32_to_cpu(*(uint32_t *)(d->config + 0x90));
     s->smb_io_base &= 0xffc0;
 
     memory_region_transaction_begin();
-    memory_region_set_enabled(&s->smb.io, s->dev.config[0xd2] & 1);
+    memory_region_set_enabled(&s->smb.io, d->config[0xd2] & 1);
     memory_region_set_address(&s->smb.io, s->smb_io_base);
     memory_region_transaction_commit();
 }
@@ -239,7 +250,7 @@
     int ret, i;
     uint16_t temp;
 
-    ret = pci_device_load(&s->dev, f);
+    ret = pci_device_load(PCI_DEVICE(s), f);
     if (ret < 0) {
         return ret;
     }
@@ -283,7 +294,7 @@
     .load_state_old = acpi_load_old,
     .post_load = vmstate_acpi_post_load,
     .fields      = (VMStateField []) {
-        VMSTATE_PCI_DEVICE(dev, PIIX4PMState),
+        VMSTATE_PCI_DEVICE(parent_obj, PIIX4PMState),
         VMSTATE_UINT16(ar.pm1.evt.sts, PIIX4PMState),
         VMSTATE_UINT16(ar.pm1.evt.en, PIIX4PMState),
         VMSTATE_UINT16(ar.pm1.cnt.cnt, PIIX4PMState),
@@ -300,7 +311,7 @@
 static void acpi_piix_eject_slot(PIIX4PMState *s, unsigned slots)
 {
     BusChild *kid, *next;
-    BusState *bus = qdev_get_parent_bus(&s->dev.qdev);
+    BusState *bus = qdev_get_parent_bus(DEVICE(s));
     int slot = ffs(slots) - 1;
     bool slot_free = true;
 
@@ -326,8 +337,7 @@
 
 static void piix4_update_hotplug(PIIX4PMState *s)
 {
-    PCIDevice *dev = &s->dev;
-    BusState *bus = qdev_get_parent_bus(&dev->qdev);
+    BusState *bus = qdev_get_parent_bus(DEVICE(s));
     BusChild *kid, *next;
 
     /* Execute any pending removes during reset */
@@ -355,7 +365,8 @@
 static void piix4_reset(void *opaque)
 {
     PIIX4PMState *s = opaque;
-    uint8_t *pci_conf = s->dev.config;
+    PCIDevice *d = PCI_DEVICE(s);
+    uint8_t *pci_conf = d->config;
 
     pci_conf[0x58] = 0;
     pci_conf[0x59] = 0;
@@ -383,10 +394,11 @@
 static void piix4_pm_machine_ready(Notifier *n, void *opaque)
 {
     PIIX4PMState *s = container_of(n, PIIX4PMState, machine_ready);
-    MemoryRegion *io_as = pci_address_space_io(&s->dev);
+    PCIDevice *d = PCI_DEVICE(s);
+    MemoryRegion *io_as = pci_address_space_io(d);
     uint8_t *pci_conf;
 
-    pci_conf = s->dev.config;
+    pci_conf = d->config;
     pci_conf[0x5f] = 0x10 |
         (memory_region_present(io_as, 0x378) ? 0x80 : 0);
     pci_conf[0x63] = 0x60;
@@ -396,10 +408,10 @@
 
 static int piix4_pm_initfn(PCIDevice *dev)
 {
-    PIIX4PMState *s = DO_UPCAST(PIIX4PMState, dev, dev);
+    PIIX4PMState *s = PIIX4_PM(dev);
     uint8_t *pci_conf;
 
-    pci_conf = s->dev.config;
+    pci_conf = dev->config;
     pci_conf[0x06] = 0x80;
     pci_conf[0x07] = 0x02;
     pci_conf[0x09] = 0x00;
@@ -419,7 +431,7 @@
     pci_conf[0x90] = s->smb_io_base | 1;
     pci_conf[0x91] = s->smb_io_base >> 8;
     pci_conf[0xd2] = 0x09;
-    pm_smbus_init(&s->dev.qdev, &s->smb);
+    pm_smbus_init(DEVICE(dev), &s->smb);
     memory_region_set_enabled(&s->smb.io, pci_conf[0xd2] & 1);
     memory_region_add_subregion(pci_address_space_io(dev),
                                 s->smb_io_base, &s->smb.io);
@@ -450,18 +462,18 @@
                        qemu_irq sci_irq, qemu_irq smi_irq,
                        int kvm_enabled, FWCfgState *fw_cfg)
 {
-    PCIDevice *dev;
+    DeviceState *dev;
     PIIX4PMState *s;
 
-    dev = pci_create(bus, devfn, "PIIX4_PM");
-    qdev_prop_set_uint32(&dev->qdev, "smb_io_base", smb_io_base);
+    dev = DEVICE(pci_create(bus, devfn, TYPE_PIIX4_PM));
+    qdev_prop_set_uint32(dev, "smb_io_base", smb_io_base);
 
-    s = DO_UPCAST(PIIX4PMState, dev, dev);
+    s = PIIX4_PM(dev);
     s->irq = sci_irq;
     s->smi_irq = smi_irq;
     s->kvm_enabled = kvm_enabled;
 
-    qdev_init_nofail(&dev->qdev);
+    qdev_init_nofail(dev);
 
     if (fw_cfg) {
         uint8_t suspend[6] = {128, 0, 0, 129, 128, 128};
@@ -501,7 +513,7 @@
 }
 
 static const TypeInfo piix4_pm_info = {
-    .name          = "PIIX4_PM",
+    .name          = TYPE_PIIX4_PM,
     .parent        = TYPE_PCI_DEVICE,
     .instance_size = sizeof(PIIX4PMState),
     .class_init    = piix4_pm_class_init,
@@ -679,7 +691,7 @@
                           "acpi-pci-hotplug", PCI_HOTPLUG_SIZE);
     memory_region_add_subregion(parent, PCI_HOTPLUG_ADDR,
                                 &s->io_pci);
-    pci_bus_hotplug(bus, piix4_device_hotplug, &s->dev.qdev);
+    pci_bus_hotplug(bus, piix4_device_hotplug, DEVICE(s));
 
     qemu_for_each_cpu(piix4_init_cpu_status, &s->gpe_cpu);
     memory_region_init_io(&s->io_cpu, OBJECT(s), &cpu_hotplug_ops, s,
@@ -705,8 +717,7 @@
 				PCIHotplugState state)
 {
     int slot = PCI_SLOT(dev->devfn);
-    PIIX4PMState *s = DO_UPCAST(PIIX4PMState, dev,
-                                PCI_DEVICE(qdev));
+    PIIX4PMState *s = PIIX4_PM(qdev);
 
     /* Don't send event when device is enabled during qemu machine creation:
      * it is present on boot, no hotplug event is necessary. We do send an
diff --git a/hw/block/fdc.c b/hw/block/fdc.c
index cdc00e5..d32f6ba 100644
--- a/hw/block/fdc.c
+++ b/hw/block/fdc.c
@@ -544,8 +544,14 @@
     uint8_t timer1;
 };
 
+#define TYPE_SYSBUS_FDC "sysbus-fdc"
+#define SYSBUS_FDC(obj) OBJECT_CHECK(FDCtrlSysBus, (obj), TYPE_SYSBUS_FDC)
+
 typedef struct FDCtrlSysBus {
-    SysBusDevice busdev;
+    /*< private >*/
+    SysBusDevice parent_obj;
+    /*< public >*/
+
     struct FDCtrl state;
 } FDCtrlSysBus;
 
@@ -773,7 +779,7 @@
 
 static void fdctrl_external_reset_sysbus(DeviceState *d)
 {
-    FDCtrlSysBus *sys = container_of(d, FDCtrlSysBus, busdev.qdev);
+    FDCtrlSysBus *sys = SYSBUS_FDC(d);
     FDCtrl *s = &sys->state;
 
     fdctrl_reset(s, 0);
@@ -1991,7 +1997,7 @@
 };
 
 /* Init functions */
-static int fdctrl_connect_drives(FDCtrl *fdctrl)
+static void fdctrl_connect_drives(FDCtrl *fdctrl, Error **errp)
 {
     unsigned int i;
     FDrive *drive;
@@ -2002,12 +2008,12 @@
 
         if (drive->bs) {
             if (bdrv_get_on_error(drive->bs, 0) != BLOCKDEV_ON_ERROR_ENOSPC) {
-                error_report("fdc doesn't support drive option werror");
-                return -1;
+                error_setg(errp, "fdc doesn't support drive option werror");
+                return;
             }
             if (bdrv_get_on_error(drive->bs, 1) != BLOCKDEV_ON_ERROR_REPORT) {
-                error_report("fdc doesn't support drive option rerror");
-                return -1;
+                error_setg(errp, "fdc doesn't support drive option rerror");
+                return;
             }
         }
 
@@ -2017,7 +2023,6 @@
             bdrv_set_dev_ops(drive->bs, &fdctrl_block_ops, drive);
         }
     }
-    return 0;
 }
 
 ISADevice *fdctrl_init_isa(ISABus *bus, DriveInfo **fds)
@@ -2047,10 +2052,11 @@
 {
     FDCtrl *fdctrl;
     DeviceState *dev;
+    SysBusDevice *sbd;
     FDCtrlSysBus *sys;
 
-    dev = qdev_create(NULL, "sysbus-fdc");
-    sys = DO_UPCAST(FDCtrlSysBus, busdev.qdev, dev);
+    dev = qdev_create(NULL, TYPE_SYSBUS_FDC);
+    sys = SYSBUS_FDC(dev);
     fdctrl = &sys->state;
     fdctrl->dma_chann = dma_chann; /* FIXME */
     if (fds[0]) {
@@ -2060,8 +2066,9 @@
         qdev_prop_set_drive_nofail(dev, "driveB", fds[1]->bdrv);
     }
     qdev_init_nofail(dev);
-    sysbus_connect_irq(&sys->busdev, 0, irq);
-    sysbus_mmio_map(&sys->busdev, 0, mmio_base);
+    sbd = SYS_BUS_DEVICE(dev);
+    sysbus_connect_irq(sbd, 0, irq);
+    sysbus_mmio_map(sbd, 0, mmio_base);
 }
 
 void sun4m_fdctrl_init(qemu_irq irq, hwaddr io_base,
@@ -2075,13 +2082,13 @@
         qdev_prop_set_drive_nofail(dev, "drive", fds[0]->bdrv);
     }
     qdev_init_nofail(dev);
-    sys = DO_UPCAST(FDCtrlSysBus, busdev.qdev, dev);
-    sysbus_connect_irq(&sys->busdev, 0, irq);
-    sysbus_mmio_map(&sys->busdev, 0, io_base);
+    sys = SYSBUS_FDC(dev);
+    sysbus_connect_irq(SYS_BUS_DEVICE(sys), 0, irq);
+    sysbus_mmio_map(SYS_BUS_DEVICE(sys), 0, io_base);
     *fdc_tc = qdev_get_gpio_in(dev, 0);
 }
 
-static int fdctrl_init_common(FDCtrl *fdctrl)
+static void fdctrl_realize_common(FDCtrl *fdctrl, Error **errp)
 {
     int i, j;
     static int command_tables_inited = 0;
@@ -2102,15 +2109,16 @@
     fdctrl->fifo = qemu_memalign(512, FD_SECTOR_LEN);
     fdctrl->fifo_size = 512;
     fdctrl->result_timer = qemu_new_timer_ns(vm_clock,
-                                          fdctrl_result_timer, fdctrl);
+                                             fdctrl_result_timer, fdctrl);
 
     fdctrl->version = 0x90; /* Intel 82078 controller */
     fdctrl->config = FD_CONFIG_EIS | FD_CONFIG_EFIFO; /* Implicit seek, polling & FIFO enabled */
     fdctrl->num_floppies = MAX_FD;
 
-    if (fdctrl->dma_chann != -1)
+    if (fdctrl->dma_chann != -1) {
         DMA_register_channel(fdctrl->dma_chann, &fdctrl_transfer_handler, fdctrl);
-    return fdctrl_connect_drives(fdctrl);
+    }
+    fdctrl_connect_drives(fdctrl, errp);
 }
 
 static const MemoryRegionPortio fdc_portio_list[] = {
@@ -2124,7 +2132,7 @@
     ISADevice *isadev = ISA_DEVICE(dev);
     FDCtrlISABus *isa = ISA_FDC(dev);
     FDCtrl *fdctrl = &isa->state;
-    int ret;
+    Error *err = NULL;
 
     isa_register_portio_list(isadev, isa->iobase, fdc_portio_list, fdctrl,
                              "fdc");
@@ -2133,9 +2141,9 @@
     fdctrl->dma_chann = isa->dma;
 
     qdev_set_legacy_instance_id(dev, isa->iobase, 2);
-    ret = fdctrl_init_common(fdctrl);
-    if (ret < 0) {
-        error_setg(errp, "Floppy init failed.");
+    fdctrl_realize_common(fdctrl, &err);
+    if (err != NULL) {
+        error_propagate(errp, err);
         return;
     }
 
@@ -2143,38 +2151,62 @@
     add_boot_device_path(isa->bootindexB, dev, "/floppy@1");
 }
 
-static int sysbus_fdc_init1(SysBusDevice *dev)
+static void sysbus_fdc_initfn(Object *obj)
 {
-    FDCtrlSysBus *sys = DO_UPCAST(FDCtrlSysBus, busdev, dev);
+    FDCtrlSysBus *sys = SYSBUS_FDC(obj);
     FDCtrl *fdctrl = &sys->state;
-    int ret;
 
-    memory_region_init_io(&fdctrl->iomem, OBJECT(sys), &fdctrl_mem_ops, fdctrl,
+    memory_region_init_io(&fdctrl->iomem, obj, &fdctrl_mem_ops, fdctrl,
                           "fdc", 0x08);
-    sysbus_init_mmio(dev, &fdctrl->iomem);
-    sysbus_init_irq(dev, &fdctrl->irq);
-    qdev_init_gpio_in(&dev->qdev, fdctrl_handle_tc, 1);
-    fdctrl->dma_chann = -1;
-
-    qdev_set_legacy_instance_id(&dev->qdev, 0 /* io */, 2); /* FIXME */
-    ret = fdctrl_init_common(fdctrl);
-
-    return ret;
 }
 
-static int sun4m_fdc_init1(SysBusDevice *dev)
+static void sysbus_fdc_realize(DeviceState *dev, Error **errp)
 {
-    FDCtrl *fdctrl = &(FROM_SYSBUS(FDCtrlSysBus, dev)->state);
+    FDCtrlSysBus *sys = SYSBUS_FDC(dev);
+    FDCtrl *fdctrl = &sys->state;
+    SysBusDevice *b = SYS_BUS_DEVICE(dev);
+    Error *err = NULL;
 
-    memory_region_init_io(&fdctrl->iomem, OBJECT(dev), &fdctrl_mem_strict_ops,
+    sysbus_init_mmio(b, &fdctrl->iomem);
+    sysbus_init_irq(b, &fdctrl->irq);
+    qdev_init_gpio_in(dev, fdctrl_handle_tc, 1);
+    fdctrl->dma_chann = -1;
+
+    qdev_set_legacy_instance_id(dev, 0 /* io */, 2); /* FIXME */
+    fdctrl_realize_common(fdctrl, &err);
+    if (err != NULL) {
+        error_propagate(errp, err);
+        return;
+    }
+}
+
+static void sun4m_fdc_initfn(Object *obj)
+{
+    FDCtrlSysBus *sys = SYSBUS_FDC(obj);
+    FDCtrl *fdctrl = &sys->state;
+
+    memory_region_init_io(&fdctrl->iomem, obj, &fdctrl_mem_strict_ops,
                           fdctrl, "fdctrl", 0x08);
-    sysbus_init_mmio(dev, &fdctrl->iomem);
-    sysbus_init_irq(dev, &fdctrl->irq);
-    qdev_init_gpio_in(&dev->qdev, fdctrl_handle_tc, 1);
+}
+
+static void sun4m_fdc_realize(DeviceState *dev, Error **errp)
+{
+    FDCtrlSysBus *sys = SYSBUS_FDC(dev);
+    FDCtrl *fdctrl = &sys->state;
+    SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
+    Error *err = NULL;
+
+    sysbus_init_mmio(sbd, &fdctrl->iomem);
+    sysbus_init_irq(sbd, &fdctrl->irq);
+    qdev_init_gpio_in(dev, fdctrl_handle_tc, 1);
 
     fdctrl->sun4m = 1;
-    qdev_set_legacy_instance_id(&dev->qdev, 0 /* io */, 2); /* FIXME */
-    return fdctrl_init_common(fdctrl);
+    qdev_set_legacy_instance_id(dev, 0 /* io */, 2); /* FIXME */
+    fdctrl_realize_common(fdctrl, &err);
+    if (err != NULL) {
+        error_propagate(errp, err);
+        return;
+    }
 }
 
 FDriveType isa_fdc_get_drive_type(ISADevice *fdc, int i)
@@ -2245,18 +2277,18 @@
 static void sysbus_fdc_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
-    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
 
-    k->init = sysbus_fdc_init1;
+    dc->realize = sysbus_fdc_realize;
     dc->reset = fdctrl_external_reset_sysbus;
     dc->vmsd = &vmstate_sysbus_fdc;
     dc->props = sysbus_fdc_properties;
 }
 
 static const TypeInfo sysbus_fdc_info = {
-    .name          = "sysbus-fdc",
+    .name          = TYPE_SYSBUS_FDC,
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(FDCtrlSysBus),
+    .instance_init = sysbus_fdc_initfn,
     .class_init    = sysbus_fdc_class_init,
 };
 
@@ -2268,9 +2300,8 @@
 static void sun4m_fdc_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
-    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
 
-    k->init = sun4m_fdc_init1;
+    dc->realize = sun4m_fdc_realize;
     dc->reset = fdctrl_external_reset_sysbus;
     dc->vmsd = &vmstate_sysbus_fdc;
     dc->props = sun4m_fdc_properties;
@@ -2280,6 +2311,7 @@
     .name          = "SUNW,fdtwo",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(FDCtrlSysBus),
+    .instance_init = sun4m_fdc_initfn,
     .class_init    = sun4m_fdc_class_init,
 };
 
diff --git a/hw/block/pflash_cfi01.c b/hw/block/pflash_cfi01.c
index 6898a25..2bcd731 100644
--- a/hw/block/pflash_cfi01.c
+++ b/hw/block/pflash_cfi01.c
@@ -60,8 +60,14 @@
 #define DPRINTF(fmt, ...) do { } while (0)
 #endif
 
+#define TYPE_CFI_PFLASH01 "cfi.pflash01"
+#define CFI_PFLASH01(obj) OBJECT_CHECK(pflash_t, (obj), TYPE_CFI_PFLASH01)
+
 struct pflash_t {
-    SysBusDevice busdev;
+    /*< private >*/
+    SysBusDevice parent_obj;
+    /*< public >*/
+
     BlockDriverState *bs;
     uint32_t nb_blocs;
     uint64_t sector_len;
@@ -563,9 +569,9 @@
     .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
-static int pflash_cfi01_init(SysBusDevice *dev)
+static void pflash_cfi01_realize(DeviceState *dev, Error **errp)
 {
-    pflash_t *pfl = FROM_SYSBUS(typeof(*pfl), dev);
+    pflash_t *pfl = CFI_PFLASH01(dev);
     uint64_t total_len;
     int ret;
 
@@ -584,7 +590,7 @@
         pfl->name, total_len);
     vmstate_register_ram(&pfl->mem, DEVICE(pfl));
     pfl->storage = memory_region_get_ram_ptr(&pfl->mem);
-    sysbus_init_mmio(dev, &pfl->mem);
+    sysbus_init_mmio(SYS_BUS_DEVICE(dev), &pfl->mem);
 
     if (pfl->bs) {
         /* read the initial flash content */
@@ -593,7 +599,8 @@
         if (ret < 0) {
             vmstate_unregister_ram(&pfl->mem, DEVICE(pfl));
             memory_region_destroy(&pfl->mem);
-            return 1;
+            error_setg(errp, "failed to read the initial flash content");
+            return;
         }
     }
 
@@ -690,8 +697,6 @@
     pfl->cfi_table[0x3c] = 0x00;
 
     pfl->cfi_table[0x3f] = 0x01; /* Number of protection fields */
-
-    return 0;
 }
 
 static Property pflash_cfi01_properties[] = {
@@ -711,16 +716,15 @@
 static void pflash_cfi01_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
-    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
 
-    k->init = pflash_cfi01_init;
+    dc->realize = pflash_cfi01_realize;
     dc->props = pflash_cfi01_properties;
     dc->vmsd = &vmstate_pflash;
 }
 
 
 static const TypeInfo pflash_cfi01_info = {
-    .name           = "cfi.pflash01",
+    .name           = TYPE_CFI_PFLASH01,
     .parent         = TYPE_SYS_BUS_DEVICE,
     .instance_size  = sizeof(struct pflash_t),
     .class_init     = pflash_cfi01_class_init,
@@ -741,10 +745,7 @@
                                 uint16_t id0, uint16_t id1,
                                 uint16_t id2, uint16_t id3, int be)
 {
-    DeviceState *dev = qdev_create(NULL, "cfi.pflash01");
-    SysBusDevice *busdev = SYS_BUS_DEVICE(dev);
-    pflash_t *pfl = (pflash_t *)object_dynamic_cast(OBJECT(dev),
-                                                    "cfi.pflash01");
+    DeviceState *dev = qdev_create(NULL, TYPE_CFI_PFLASH01);
 
     if (bs && qdev_prop_set_drive(dev, "drive", bs)) {
         abort();
@@ -760,8 +761,8 @@
     qdev_prop_set_string(dev, "name", name);
     qdev_init_nofail(dev);
 
-    sysbus_mmio_map(busdev, 0, base);
-    return pfl;
+    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base);
+    return CFI_PFLASH01(dev);
 }
 
 MemoryRegion *pflash_cfi01_get_memory(pflash_t *fl)
diff --git a/hw/block/pflash_cfi02.c b/hw/block/pflash_cfi02.c
index d6cd3da..9fc02e3 100644
--- a/hw/block/pflash_cfi02.c
+++ b/hw/block/pflash_cfi02.c
@@ -55,8 +55,14 @@
 
 #define PFLASH_LAZY_ROMD_THRESHOLD 42
 
+#define TYPE_CFI_PFLASH02 "cfi.pflash02"
+#define CFI_PFLASH02(obj) OBJECT_CHECK(pflash_t, (obj), TYPE_CFI_PFLASH02)
+
 struct pflash_t {
-    SysBusDevice busdev;
+    /*< private >*/
+    SysBusDevice parent_obj;
+    /*< public >*/
+
     BlockDriverState *bs;
     uint32_t sector_len;
     uint32_t nb_blocs;
@@ -586,9 +592,9 @@
     .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
-static int pflash_cfi02_init(SysBusDevice *dev)
+static void pflash_cfi02_realize(DeviceState *dev, Error **errp)
 {
-    pflash_t *pfl = FROM_SYSBUS(typeof(*pfl), dev);
+    pflash_t *pfl = CFI_PFLASH02(dev);
     uint32_t chip_len;
     int ret;
 
@@ -610,14 +616,16 @@
         /* read the initial flash content */
         ret = bdrv_read(pfl->bs, 0, pfl->storage, chip_len >> 9);
         if (ret < 0) {
-            g_free(pfl);
-            return 1;
+            vmstate_unregister_ram(&pfl->orig_mem, DEVICE(pfl));
+            memory_region_destroy(&pfl->orig_mem);
+            error_setg(errp, "failed to read the initial flash content");
+            return;
         }
     }
 
     pflash_setup_mappings(pfl);
     pfl->rom_mode = 1;
-    sysbus_init_mmio(dev, &pfl->mem);
+    sysbus_init_mmio(SYS_BUS_DEVICE(dev), &pfl->mem);
 
     if (pfl->bs) {
         pfl->ro = bdrv_is_read_only(pfl->bs);
@@ -706,8 +714,6 @@
 
     pfl->cfi_table[0x3b] = 0x00;
     pfl->cfi_table[0x3c] = 0x00;
-
-    return 0;
 }
 
 static Property pflash_cfi02_properties[] = {
@@ -730,14 +736,13 @@
 static void pflash_cfi02_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
-    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
 
-    k->init = pflash_cfi02_init;
+    dc->realize = pflash_cfi02_realize;
     dc->props = pflash_cfi02_properties;
 }
 
 static const TypeInfo pflash_cfi02_info = {
-    .name           = "cfi.pflash02",
+    .name           = TYPE_CFI_PFLASH02,
     .parent         = TYPE_SYS_BUS_DEVICE,
     .instance_size  = sizeof(struct pflash_t),
     .class_init     = pflash_cfi02_class_init,
@@ -760,10 +765,7 @@
                                 uint16_t unlock_addr0, uint16_t unlock_addr1,
                                 int be)
 {
-    DeviceState *dev = qdev_create(NULL, "cfi.pflash02");
-    SysBusDevice *busdev = SYS_BUS_DEVICE(dev);
-    pflash_t *pfl = (pflash_t *)object_dynamic_cast(OBJECT(dev),
-                                                    "cfi.pflash02");
+    DeviceState *dev = qdev_create(NULL, TYPE_CFI_PFLASH02);
 
     if (bs && qdev_prop_set_drive(dev, "drive", bs)) {
         abort();
@@ -782,6 +784,6 @@
     qdev_prop_set_string(dev, "name", name);
     qdev_init_nofail(dev);
 
-    sysbus_mmio_map(busdev, 0, base);
-    return pfl;
+    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base);
+    return CFI_PFLASH02(dev);
 }
diff --git a/hw/display/vmware_vga.c b/hw/display/vmware_vga.c
index 714908f..3536cde 100644
--- a/hw/display/vmware_vga.c
+++ b/hw/display/vmware_vga.c
@@ -81,8 +81,16 @@
     int redraw_fifo_first, redraw_fifo_last;
 };
 
+#define TYPE_VMWARE_SVGA "vmware-svga"
+
+#define VMWARE_SVGA(obj) \
+    OBJECT_CHECK(struct pci_vmsvga_state_s, (obj), TYPE_VMWARE_SVGA)
+
 struct pci_vmsvga_state_s {
-    PCIDevice card;
+    /*< private >*/
+    PCIDevice parent_obj;
+    /*< public >*/
+
     struct vmsvga_state_s chip;
     MemoryRegion io_bar;
 };
@@ -787,7 +795,7 @@
     case SVGA_REG_FB_START: {
         struct pci_vmsvga_state_s *pci_vmsvga
             = container_of(s, struct pci_vmsvga_state_s, chip);
-        ret = pci_get_bar_addr(&pci_vmsvga->card, 1);
+        ret = pci_get_bar_addr(PCI_DEVICE(pci_vmsvga), 1);
         break;
     }
 
@@ -823,7 +831,7 @@
     case SVGA_REG_MEM_START: {
         struct pci_vmsvga_state_s *pci_vmsvga
             = container_of(s, struct pci_vmsvga_state_s, chip);
-        ret = pci_get_bar_addr(&pci_vmsvga->card, 2);
+        ret = pci_get_bar_addr(PCI_DEVICE(pci_vmsvga), 2);
         break;
     }
 
@@ -1092,8 +1100,7 @@
 
 static void vmsvga_reset(DeviceState *dev)
 {
-    struct pci_vmsvga_state_s *pci =
-        DO_UPCAST(struct pci_vmsvga_state_s, card.qdev, dev);
+    struct pci_vmsvga_state_s *pci = VMWARE_SVGA(dev);
     struct vmsvga_state_s *s = &pci->chip;
 
     s->index = 0;
@@ -1172,7 +1179,7 @@
     .minimum_version_id = 0,
     .minimum_version_id_old = 0,
     .fields      = (VMStateField[]) {
-        VMSTATE_PCI_DEVICE(card, struct pci_vmsvga_state_s),
+        VMSTATE_PCI_DEVICE(parent_obj, struct pci_vmsvga_state_s),
         VMSTATE_STRUCT(chip, struct pci_vmsvga_state_s, 0,
                        vmstate_vmware_vga_internal, struct vmsvga_state_s),
         VMSTATE_END_OF_LIST()
@@ -1250,24 +1257,23 @@
 
 static int pci_vmsvga_initfn(PCIDevice *dev)
 {
-    struct pci_vmsvga_state_s *s =
-        DO_UPCAST(struct pci_vmsvga_state_s, card, dev);
+    struct pci_vmsvga_state_s *s = VMWARE_SVGA(dev);
 
-    s->card.config[PCI_CACHE_LINE_SIZE] = 0x08;         /* Cache line size */
-    s->card.config[PCI_LATENCY_TIMER] = 0x40;           /* Latency timer */
-    s->card.config[PCI_INTERRUPT_LINE] = 0xff;          /* End */
+    dev->config[PCI_CACHE_LINE_SIZE] = 0x08;
+    dev->config[PCI_LATENCY_TIMER] = 0x40;
+    dev->config[PCI_INTERRUPT_LINE] = 0xff;          /* End */
 
     memory_region_init_io(&s->io_bar, NULL, &vmsvga_io_ops, &s->chip,
                           "vmsvga-io", 0x10);
     memory_region_set_flush_coalesced(&s->io_bar);
-    pci_register_bar(&s->card, 0, PCI_BASE_ADDRESS_SPACE_IO, &s->io_bar);
+    pci_register_bar(dev, 0, PCI_BASE_ADDRESS_SPACE_IO, &s->io_bar);
 
     vmsvga_init(DEVICE(dev), &s->chip,
                 pci_address_space(dev), pci_address_space_io(dev));
 
-    pci_register_bar(&s->card, 1, PCI_BASE_ADDRESS_MEM_PREFETCH,
+    pci_register_bar(dev, 1, PCI_BASE_ADDRESS_MEM_PREFETCH,
                      &s->chip.vga.vram);
-    pci_register_bar(&s->card, 2, PCI_BASE_ADDRESS_MEM_PREFETCH,
+    pci_register_bar(dev, 2, PCI_BASE_ADDRESS_MEM_PREFETCH,
                      &s->chip.fifo_ram);
 
     if (!dev->rom_bar) {
@@ -1303,7 +1309,7 @@
 }
 
 static const TypeInfo vmsvga_info = {
-    .name          = "vmware-svga",
+    .name          = TYPE_VMWARE_SVGA,
     .parent        = TYPE_PCI_DEVICE,
     .instance_size = sizeof(struct pci_vmsvga_state_s),
     .class_init    = vmsvga_class_init,
diff --git a/hw/i2c/exynos4210_i2c.c b/hw/i2c/exynos4210_i2c.c
index 52bffa5..42f5e89 100644
--- a/hw/i2c/exynos4210_i2c.c
+++ b/hw/i2c/exynos4210_i2c.c
@@ -271,7 +271,7 @@
 };
 
 static const VMStateDescription exynos4210_i2c_vmstate = {
-    .name = TYPE_EXYNOS4_I2C,
+    .name = "exynos4210.i2c",
     .version_id = 1,
     .minimum_version_id = 1,
     .fields = (VMStateField[]) {
diff --git a/hw/i386/kvm/clock.c b/hw/i386/kvm/clock.c
index 1022d67..e89e2f7 100644
--- a/hw/i386/kvm/clock.c
+++ b/hw/i386/kvm/clock.c
@@ -22,8 +22,14 @@
 #include <linux/kvm.h>
 #include <linux/kvm_para.h>
 
+#define TYPE_KVM_CLOCK "kvmclock"
+#define KVM_CLOCK(obj) OBJECT_CHECK(KVMClockState, (obj), TYPE_KVM_CLOCK)
+
 typedef struct KVMClockState {
+    /*< private >*/
     SysBusDevice busdev;
+    /*< public >*/
+
     uint64_t clock;
     bool clock_valid;
 } KVMClockState;
@@ -85,12 +91,11 @@
     }
 }
 
-static int kvmclock_init(SysBusDevice *dev)
+static void kvmclock_realize(DeviceState *dev, Error **errp)
 {
-    KVMClockState *s = FROM_SYSBUS(KVMClockState, dev);
+    KVMClockState *s = KVM_CLOCK(dev);
 
     qemu_add_vm_change_state_handler(kvmclock_vm_state_change, s);
-    return 0;
 }
 
 static const VMStateDescription kvmclock_vmsd = {
@@ -107,15 +112,14 @@
 static void kvmclock_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
-    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
 
-    k->init = kvmclock_init;
+    dc->realize = kvmclock_realize;
     dc->no_user = 1;
     dc->vmsd = &kvmclock_vmsd;
 }
 
 static const TypeInfo kvmclock_info = {
-    .name          = "kvmclock",
+    .name          = TYPE_KVM_CLOCK,
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(KVMClockState),
     .class_init    = kvmclock_class_init,
@@ -129,7 +133,7 @@
     if (kvm_enabled() &&
         cpu->env.features[FEAT_KVM] & ((1ULL << KVM_FEATURE_CLOCKSOURCE) |
                                        (1ULL << KVM_FEATURE_CLOCKSOURCE2))) {
-        sysbus_create_simple("kvmclock", -1, NULL);
+        sysbus_create_simple(TYPE_KVM_CLOCK, -1, NULL);
     }
 }
 
diff --git a/hw/i386/kvmvapic.c b/hw/i386/kvmvapic.c
index ccd089a..a4506bc 100644
--- a/hw/i386/kvmvapic.c
+++ b/hw/i386/kvmvapic.c
@@ -146,6 +146,7 @@
 
 static int find_real_tpr_addr(VAPICROMState *s, CPUX86State *env)
 {
+    CPUState *cs = CPU(x86_env_get_cpu(env));
     hwaddr paddr;
     target_ulong addr;
 
@@ -158,7 +159,7 @@
      * virtual address space for the APIC mapping.
      */
     for (addr = 0xfffff000; addr >= 0x80000000; addr -= TARGET_PAGE_SIZE) {
-        paddr = cpu_get_phys_page_debug(env, addr);
+        paddr = cpu_get_phys_page_debug(cs, addr);
         if (paddr != APIC_DEFAULT_ADDRESS) {
             continue;
         }
@@ -187,9 +188,10 @@
          modrm_reg(opcode[1]) == instr->modrm_reg);
 }
 
-static int evaluate_tpr_instruction(VAPICROMState *s, CPUX86State *env,
+static int evaluate_tpr_instruction(VAPICROMState *s, X86CPU *cpu,
                                     target_ulong *pip, TPRAccess access)
 {
+    CPUState *cs = CPU(cpu);
     const TPRInstruction *instr;
     target_ulong ip = *pip;
     uint8_t opcode[2];
@@ -210,7 +212,7 @@
      * RSP, used by the patched instruction, is zero, so the guest gets a
      * double fault and dies.
      */
-    if (env->regs[R_ESP] == 0) {
+    if (cpu->env.regs[R_ESP] == 0) {
         return -1;
     }
 
@@ -225,7 +227,7 @@
             if (instr->access != access) {
                 continue;
             }
-            if (cpu_memory_rw_debug(env, ip - instr->length, opcode,
+            if (cpu_memory_rw_debug(cs, ip - instr->length, opcode,
                                     sizeof(opcode), 0) < 0) {
                 return -1;
             }
@@ -236,7 +238,7 @@
         }
         return -1;
     } else {
-        if (cpu_memory_rw_debug(env, ip, opcode, sizeof(opcode), 0) < 0) {
+        if (cpu_memory_rw_debug(cs, ip, opcode, sizeof(opcode), 0) < 0) {
             return -1;
         }
         for (i = 0; i < ARRAY_SIZE(tpr_instr); i++) {
@@ -253,7 +255,7 @@
      * Grab the virtual TPR address from the instruction
      * and update the cached values.
      */
-    if (cpu_memory_rw_debug(env, ip + instr->addr_offset,
+    if (cpu_memory_rw_debug(cs, ip + instr->addr_offset,
                             (void *)&real_tpr_addr,
                             sizeof(real_tpr_addr), 0) < 0) {
         return -1;
@@ -271,6 +273,7 @@
 
 static int update_rom_mapping(VAPICROMState *s, CPUX86State *env, target_ulong ip)
 {
+    CPUState *cs = CPU(x86_env_get_cpu(env));
     hwaddr paddr;
     uint32_t rom_state_vaddr;
     uint32_t pos, patch, offset;
@@ -287,7 +290,7 @@
 
     /* find out virtual address of the ROM */
     rom_state_vaddr = s->rom_state_paddr + (ip & 0xf0000000);
-    paddr = cpu_get_phys_page_debug(env, rom_state_vaddr);
+    paddr = cpu_get_phys_page_debug(cs, rom_state_vaddr);
     if (paddr == -1) {
         return -1;
     }
@@ -332,8 +335,9 @@
  * cannot be accessed or is considered invalid. This also ensures that we are
  * not patching the wrong guest.
  */
-static int get_kpcr_number(CPUX86State *env)
+static int get_kpcr_number(X86CPU *cpu)
 {
+    CPUX86State *env = &cpu->env;
     struct kpcr {
         uint8_t  fill1[0x1c];
         uint32_t self;
@@ -341,7 +345,7 @@
         uint8_t  number;
     } QEMU_PACKED kpcr;
 
-    if (cpu_memory_rw_debug(env, env->segs[R_FS].base,
+    if (cpu_memory_rw_debug(CPU(cpu), env->segs[R_FS].base,
                             (void *)&kpcr, sizeof(kpcr), 0) < 0 ||
         kpcr.self != env->segs[R_FS].base) {
         return -1;
@@ -349,9 +353,9 @@
     return kpcr.number;
 }
 
-static int vapic_enable(VAPICROMState *s, CPUX86State *env)
+static int vapic_enable(VAPICROMState *s, X86CPU *cpu)
 {
-    int cpu_number = get_kpcr_number(env);
+    int cpu_number = get_kpcr_number(cpu);
     hwaddr vapic_paddr;
     static const uint8_t enabled = 1;
 
@@ -362,26 +366,26 @@
         (((hwaddr)cpu_number) << VAPIC_CPU_SHIFT);
     cpu_physical_memory_rw(vapic_paddr + offsetof(VAPICState, enabled),
                            (void *)&enabled, sizeof(enabled), 1);
-    apic_enable_vapic(env->apic_state, vapic_paddr);
+    apic_enable_vapic(cpu->env.apic_state, vapic_paddr);
 
     s->state = VAPIC_ACTIVE;
 
     return 0;
 }
 
-static void patch_byte(CPUX86State *env, target_ulong addr, uint8_t byte)
+static void patch_byte(X86CPU *cpu, target_ulong addr, uint8_t byte)
 {
-    cpu_memory_rw_debug(env, addr, &byte, 1, 1);
+    cpu_memory_rw_debug(CPU(cpu), addr, &byte, 1, 1);
 }
 
-static void patch_call(VAPICROMState *s, CPUX86State *env, target_ulong ip,
+static void patch_call(VAPICROMState *s, X86CPU *cpu, target_ulong ip,
                        uint32_t target)
 {
     uint32_t offset;
 
     offset = cpu_to_le32(target - ip - 5);
-    patch_byte(env, ip, 0xe8); /* call near */
-    cpu_memory_rw_debug(env, ip + 1, (void *)&offset, sizeof(offset), 1);
+    patch_byte(cpu, ip, 0xe8); /* call near */
+    cpu_memory_rw_debug(CPU(cpu), ip + 1, (void *)&offset, sizeof(offset), 1);
 }
 
 static void patch_instruction(VAPICROMState *s, X86CPU *cpu, target_ulong ip)
@@ -409,32 +413,32 @@
 
     pause_all_vcpus();
 
-    cpu_memory_rw_debug(env, ip, opcode, sizeof(opcode), 0);
+    cpu_memory_rw_debug(cs, ip, opcode, sizeof(opcode), 0);
 
     switch (opcode[0]) {
     case 0x89: /* mov r32 to r/m32 */
-        patch_byte(env, ip, 0x50 + modrm_reg(opcode[1]));  /* push reg */
-        patch_call(s, env, ip + 1, handlers->set_tpr);
+        patch_byte(cpu, ip, 0x50 + modrm_reg(opcode[1]));  /* push reg */
+        patch_call(s, cpu, ip + 1, handlers->set_tpr);
         break;
     case 0x8b: /* mov r/m32 to r32 */
-        patch_byte(env, ip, 0x90);
-        patch_call(s, env, ip + 1, handlers->get_tpr[modrm_reg(opcode[1])]);
+        patch_byte(cpu, ip, 0x90);
+        patch_call(s, cpu, ip + 1, handlers->get_tpr[modrm_reg(opcode[1])]);
         break;
     case 0xa1: /* mov abs to eax */
-        patch_call(s, env, ip, handlers->get_tpr[0]);
+        patch_call(s, cpu, ip, handlers->get_tpr[0]);
         break;
     case 0xa3: /* mov eax to abs */
-        patch_call(s, env, ip, handlers->set_tpr_eax);
+        patch_call(s, cpu, ip, handlers->set_tpr_eax);
         break;
     case 0xc7: /* mov imm32, r/m32 (c7/0) */
-        patch_byte(env, ip, 0x68);  /* push imm32 */
-        cpu_memory_rw_debug(env, ip + 6, (void *)&imm32, sizeof(imm32), 0);
-        cpu_memory_rw_debug(env, ip + 1, (void *)&imm32, sizeof(imm32), 1);
-        patch_call(s, env, ip + 5, handlers->set_tpr);
+        patch_byte(cpu, ip, 0x68);  /* push imm32 */
+        cpu_memory_rw_debug(cs, ip + 6, (void *)&imm32, sizeof(imm32), 0);
+        cpu_memory_rw_debug(cs, ip + 1, (void *)&imm32, sizeof(imm32), 1);
+        patch_call(s, cpu, ip + 5, handlers->set_tpr);
         break;
     case 0xff: /* push r/m32 */
-        patch_byte(env, ip, 0x50); /* push eax */
-        patch_call(s, env, ip + 1, handlers->get_tpr_stack);
+        patch_byte(cpu, ip, 0x50); /* push eax */
+        patch_call(s, cpu, ip + 1, handlers->get_tpr_stack);
         break;
     default:
         abort();
@@ -458,16 +462,16 @@
 
     cpu_synchronize_state(cs);
 
-    if (evaluate_tpr_instruction(s, env, &ip, access) < 0) {
+    if (evaluate_tpr_instruction(s, cpu, &ip, access) < 0) {
         if (s->state == VAPIC_ACTIVE) {
-            vapic_enable(s, env);
+            vapic_enable(s, cpu);
         }
         return;
     }
     if (update_rom_mapping(s, env, ip) < 0) {
         return;
     }
-    if (vapic_enable(s, env) < 0) {
+    if (vapic_enable(s, cpu) < 0) {
         return;
     }
     patch_instruction(s, cpu, ip);
@@ -667,8 +671,8 @@
              * accurate.
              */
             pause_all_vcpus();
-            patch_byte(env, env->eip - 2, 0x66);
-            patch_byte(env, env->eip - 1, 0x90);
+            patch_byte(cpu, env->eip - 2, 0x66);
+            patch_byte(cpu, env->eip - 1, 0x90);
             resume_all_vcpus();
         }
 
@@ -681,7 +685,7 @@
         if (find_real_tpr_addr(s, env) < 0) {
             break;
         }
-        vapic_enable(s, env);
+        vapic_enable(s, cpu);
         break;
     default:
     case 4:
@@ -703,19 +707,18 @@
     .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
-static int vapic_init(SysBusDevice *dev)
+static void vapic_realize(DeviceState *dev, Error **errp)
 {
+    SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
     VAPICROMState *s = VAPIC(dev);
 
     memory_region_init_io(&s->io, OBJECT(s), &vapic_ops, s, "kvmvapic", 2);
-    sysbus_add_io(dev, VAPIC_IO_PORT, &s->io);
-    sysbus_init_ioports(dev, VAPIC_IO_PORT, 2);
+    sysbus_add_io(sbd, VAPIC_IO_PORT, &s->io);
+    sysbus_init_ioports(sbd, VAPIC_IO_PORT, 2);
 
     option_rom[nb_option_roms].name = "kvmvapic.bin";
     option_rom[nb_option_roms].bootindex = -1;
     nb_option_roms++;
-
-    return 0;
 }
 
 static void do_vapic_enable(void *data)
@@ -723,7 +726,7 @@
     VAPICROMState *s = data;
     X86CPU *cpu = X86_CPU(first_cpu);
 
-    vapic_enable(s, &cpu->env);
+    vapic_enable(s, cpu);
 }
 
 static int vapic_post_load(void *opaque, int version_id)
@@ -812,13 +815,12 @@
 
 static void vapic_class_init(ObjectClass *klass, void *data)
 {
-    SysBusDeviceClass *sc = SYS_BUS_DEVICE_CLASS(klass);
     DeviceClass *dc = DEVICE_CLASS(klass);
 
     dc->no_user = 1;
     dc->reset   = vapic_reset;
     dc->vmsd    = &vmstate_vapic;
-    sc->init    = vapic_init;
+    dc->realize = vapic_realize;
 }
 
 static const TypeInfo vapic_type = {
diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c
index 6f10246..0b1d2e3 100644
--- a/hw/i386/pc_q35.c
+++ b/hw/i386/pc_q35.c
@@ -60,6 +60,7 @@
     const char *boot_device = args->boot_device;
     ram_addr_t below_4g_mem_size, above_4g_mem_size;
     Q35PCIHost *q35_host;
+    PCIHostState *phb;
     PCIBus *host_bus;
     PCIDevice *lpc;
     BusState *idebus[MAX_SATA_PORTS];
@@ -139,7 +140,8 @@
     q35_host->mch.guest_info = guest_info;
     /* pci */
     qdev_init_nofail(DEVICE(q35_host));
-    host_bus = q35_host->host.pci.bus;
+    phb = PCI_HOST_BRIDGE(q35_host);
+    host_bus = phb->bus;
     /* create ISA bus */
     lpc = pci_create_simple_multifunction(host_bus, PCI_DEVFN(ICH9_LPC_DEV,
                                           ICH9_LPC_FUNC), true,
diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c
index 1d863b5..419adde 100644
--- a/hw/ide/ahci.c
+++ b/hw/ide/ahci.c
@@ -117,12 +117,13 @@
 
 static void ahci_irq_raise(AHCIState *s, AHCIDevice *dev)
 {
-    struct AHCIPCIState *d = container_of(s, AHCIPCIState, ahci);
+    AHCIPCIState *d = container_of(s, AHCIPCIState, ahci);
+    PCIDevice *pci_dev = PCI_DEVICE(d);
 
     DPRINTF(0, "raise irq\n");
 
-    if (msi_enabled(&d->card)) {
-        msi_notify(&d->card, 0);
+    if (msi_enabled(pci_dev)) {
+        msi_notify(pci_dev, 0);
     } else {
         qemu_irq_raise(s->irq);
     }
@@ -130,11 +131,11 @@
 
 static void ahci_irq_lower(AHCIState *s, AHCIDevice *dev)
 {
-    struct AHCIPCIState *d = container_of(s, AHCIPCIState, ahci);
+    AHCIPCIState *d = container_of(s, AHCIPCIState, ahci);
 
     DPRINTF(0, "lower irq\n");
 
-    if (!msi_enabled(&d->card)) {
+    if (!msi_enabled(PCI_DEVICE(d))) {
         qemu_irq_lower(s->irq);
     }
 }
@@ -1285,8 +1286,14 @@
     },
 };
 
+#define TYPE_SYSBUS_AHCI "sysbus-ahci"
+#define SYSBUS_AHCI(obj) OBJECT_CHECK(SysbusAHCIState, (obj), TYPE_SYSBUS_AHCI)
+
 typedef struct SysbusAHCIState {
-    SysBusDevice busdev;
+    /*< private >*/
+    SysBusDevice parent_obj;
+    /*< public >*/
+
     AHCIState ahci;
     uint32_t num_ports;
 } SysbusAHCIState;
@@ -1302,19 +1309,20 @@
 
 static void sysbus_ahci_reset(DeviceState *dev)
 {
-    SysbusAHCIState *s = DO_UPCAST(SysbusAHCIState, busdev.qdev, dev);
+    SysbusAHCIState *s = SYSBUS_AHCI(dev);
 
     ahci_reset(&s->ahci);
 }
 
-static int sysbus_ahci_init(SysBusDevice *dev)
+static void sysbus_ahci_realize(DeviceState *dev, Error **errp)
 {
-    SysbusAHCIState *s = FROM_SYSBUS(SysbusAHCIState, dev);
-    ahci_init(&s->ahci, &dev->qdev, NULL, s->num_ports);
+    SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
+    SysbusAHCIState *s = SYSBUS_AHCI(dev);
 
-    sysbus_init_mmio(dev, &s->ahci.mem);
-    sysbus_init_irq(dev, &s->ahci.irq);
-    return 0;
+    ahci_init(&s->ahci, dev, NULL, s->num_ports);
+
+    sysbus_init_mmio(sbd, &s->ahci.mem);
+    sysbus_init_irq(sbd, &s->ahci.irq);
 }
 
 static Property sysbus_ahci_properties[] = {
@@ -1324,17 +1332,16 @@
 
 static void sysbus_ahci_class_init(ObjectClass *klass, void *data)
 {
-    SysBusDeviceClass *sbc = SYS_BUS_DEVICE_CLASS(klass);
     DeviceClass *dc = DEVICE_CLASS(klass);
 
-    sbc->init = sysbus_ahci_init;
+    dc->realize = sysbus_ahci_realize;
     dc->vmsd = &vmstate_sysbus_ahci;
     dc->props = sysbus_ahci_properties;
     dc->reset = sysbus_ahci_reset;
 }
 
 static const TypeInfo sysbus_ahci_info = {
-    .name          = "sysbus-ahci",
+    .name          = TYPE_SYSBUS_AHCI,
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(SysbusAHCIState),
     .class_init    = sysbus_ahci_class_init,
diff --git a/hw/ide/ahci.h b/hw/ide/ahci.h
index 341a571..20e412c 100644
--- a/hw/ide/ahci.h
+++ b/hw/ide/ahci.h
@@ -301,10 +301,18 @@
 } AHCIState;
 
 typedef struct AHCIPCIState {
-    PCIDevice card;
+    /*< private >*/
+    PCIDevice parent_obj;
+    /*< public >*/
+
     AHCIState ahci;
 } AHCIPCIState;
 
+#define TYPE_ICH9_AHCI "ich9-ahci"
+
+#define ICH_AHCI(obj) \
+    OBJECT_CHECK(AHCIPCIState, (obj), TYPE_ICH9_AHCI)
+
 extern const VMStateDescription vmstate_ahci;
 
 #define VMSTATE_AHCI(_field, _state) {                               \
diff --git a/hw/ide/ich.c b/hw/ide/ich.c
index 6c0c0c2..4eb5488 100644
--- a/hw/ide/ich.c
+++ b/hw/ide/ich.c
@@ -84,7 +84,7 @@
     .unmigratable = 1, /* Still buggy under I/O load */
     .version_id = 1,
     .fields = (VMStateField []) {
-        VMSTATE_PCI_DEVICE(card, AHCIPCIState),
+        VMSTATE_PCI_DEVICE(parent_obj, AHCIPCIState),
         VMSTATE_AHCI(ahci, AHCIPCIState),
         VMSTATE_END_OF_LIST()
     },
@@ -92,7 +92,7 @@
 
 static void pci_ich9_reset(DeviceState *dev)
 {
-    struct AHCIPCIState *d = DO_UPCAST(struct AHCIPCIState, card.qdev, dev);
+    AHCIPCIState *d = ICH_AHCI(dev);
 
     ahci_reset(&d->ahci);
 }
@@ -102,34 +102,34 @@
     struct AHCIPCIState *d;
     int sata_cap_offset;
     uint8_t *sata_cap;
-    d = DO_UPCAST(struct AHCIPCIState, card, dev);
+    d = ICH_AHCI(dev);
 
-    ahci_init(&d->ahci, &dev->qdev, pci_get_address_space(dev), 6);
+    ahci_init(&d->ahci, DEVICE(dev), pci_get_address_space(dev), 6);
 
-    pci_config_set_prog_interface(d->card.config, AHCI_PROGMODE_MAJOR_REV_1);
+    pci_config_set_prog_interface(dev->config, AHCI_PROGMODE_MAJOR_REV_1);
 
-    d->card.config[PCI_CACHE_LINE_SIZE] = 0x08;  /* Cache line size */
-    d->card.config[PCI_LATENCY_TIMER]   = 0x00;  /* Latency timer */
-    pci_config_set_interrupt_pin(d->card.config, 1);
+    dev->config[PCI_CACHE_LINE_SIZE] = 0x08;  /* Cache line size */
+    dev->config[PCI_LATENCY_TIMER]   = 0x00;  /* Latency timer */
+    pci_config_set_interrupt_pin(dev->config, 1);
 
     /* XXX Software should program this register */
-    d->card.config[0x90]   = 1 << 6; /* Address Map Register - AHCI mode */
+    dev->config[0x90]   = 1 << 6; /* Address Map Register - AHCI mode */
 
     msi_init(dev, 0x50, 1, true, false);
-    d->ahci.irq = d->card.irq[0];
+    d->ahci.irq = dev->irq[0];
 
-    pci_register_bar(&d->card, ICH9_IDP_BAR, PCI_BASE_ADDRESS_SPACE_IO,
+    pci_register_bar(dev, ICH9_IDP_BAR, PCI_BASE_ADDRESS_SPACE_IO,
                      &d->ahci.idp);
-    pci_register_bar(&d->card, ICH9_MEM_BAR, PCI_BASE_ADDRESS_SPACE_MEMORY,
+    pci_register_bar(dev, ICH9_MEM_BAR, PCI_BASE_ADDRESS_SPACE_MEMORY,
                      &d->ahci.mem);
 
-    sata_cap_offset = pci_add_capability(&d->card, PCI_CAP_ID_SATA,
+    sata_cap_offset = pci_add_capability(dev, PCI_CAP_ID_SATA,
                                          ICH9_SATA_CAP_OFFSET, SATA_CAP_SIZE);
     if (sata_cap_offset < 0) {
         return sata_cap_offset;
     }
 
-    sata_cap = d->card.config + sata_cap_offset;
+    sata_cap = dev->config + sata_cap_offset;
     pci_set_word(sata_cap + SATA_CAP_REV, 0x10);
     pci_set_long(sata_cap + SATA_CAP_BAR,
                  (ICH9_IDP_BAR + 0x4) | (ICH9_IDP_INDEX_LOG2 << 4));
@@ -141,7 +141,7 @@
 static void pci_ich9_uninit(PCIDevice *dev)
 {
     struct AHCIPCIState *d;
-    d = DO_UPCAST(struct AHCIPCIState, card, dev);
+    d = ICH_AHCI(dev);
 
     msi_uninit(dev);
     ahci_uninit(&d->ahci);
@@ -163,7 +163,7 @@
 }
 
 static const TypeInfo ich_ahci_info = {
-    .name          = "ich9-ahci",
+    .name          = TYPE_ICH9_AHCI,
     .parent        = TYPE_PCI_DEVICE,
     .instance_size = sizeof(AHCIPCIState),
     .class_init    = ich_ahci_class_init,
diff --git a/hw/intc/ioapic_common.c b/hw/intc/ioapic_common.c
index 5c5bb3c..6b705c1 100644
--- a/hw/intc/ioapic_common.c
+++ b/hw/intc/ioapic_common.c
@@ -57,23 +57,22 @@
     return 0;
 }
 
-static int ioapic_init_common(SysBusDevice *dev)
+static void ioapic_common_realize(DeviceState *dev, Error **errp)
 {
     IOAPICCommonState *s = IOAPIC_COMMON(dev);
     IOAPICCommonClass *info;
     static int ioapic_no;
 
     if (ioapic_no >= MAX_IOAPICS) {
-        return -1;
+        error_setg(errp, "Only %d ioapics allowed", MAX_IOAPICS);
+        return;
     }
 
     info = IOAPIC_COMMON_GET_CLASS(s);
     info->init(s, ioapic_no);
 
-    sysbus_init_mmio(&s->busdev, &s->io_memory);
+    sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->io_memory);
     ioapic_no++;
-
-    return 0;
 }
 
 static const VMStateDescription vmstate_ioapic_common = {
@@ -95,10 +94,9 @@
 
 static void ioapic_common_class_init(ObjectClass *klass, void *data)
 {
-    SysBusDeviceClass *sc = SYS_BUS_DEVICE_CLASS(klass);
     DeviceClass *dc = DEVICE_CLASS(klass);
 
-    sc->init = ioapic_init_common;
+    dc->realize = ioapic_common_realize;
     dc->vmsd = &vmstate_ioapic_common;
     dc->no_user = 1;
 }
diff --git a/hw/isa/isa-bus.c b/hw/isa/isa-bus.c
index cfd610c..9e104eb 100644
--- a/hw/isa/isa-bus.c
+++ b/hw/isa/isa-bus.c
@@ -192,18 +192,10 @@
     }
 }
 
-static int isabus_bridge_init(SysBusDevice *dev)
-{
-    /* nothing */
-    return 0;
-}
-
 static void isabus_bridge_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
-    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
 
-    k->init = isabus_bridge_init;
     dc->fw_name = "isa";
     dc->no_user = 1;
 }
diff --git a/hw/misc/ivshmem.c b/hw/misc/ivshmem.c
index 3594b84..4a74856 100644
--- a/hw/misc/ivshmem.c
+++ b/hw/misc/ivshmem.c
@@ -48,6 +48,10 @@
 #define IVSHMEM_DPRINTF(fmt, ...)
 #endif
 
+#define TYPE_IVSHMEM "ivshmem"
+#define IVSHMEM(obj) \
+    OBJECT_CHECK(IVShmemState, (obj), TYPE_IVSHMEM)
+
 typedef struct Peer {
     int nb_eventfds;
     EventNotifier *eventfds;
@@ -59,7 +63,10 @@
 } EventfdEntry;
 
 typedef struct IVShmemState {
-    PCIDevice dev;
+    /*< private >*/
+    PCIDevice parent_obj;
+    /*< public >*/
+
     uint32_t intrmask;
     uint32_t intrstatus;
     uint32_t doorbell;
@@ -116,6 +123,7 @@
 /* accessing registers - based on rtl8139 */
 static void ivshmem_update_irq(IVShmemState *s, int val)
 {
+    PCIDevice *d = PCI_DEVICE(s);
     int isr;
     isr = (s->intrstatus & s->intrmask) & 0xffffffff;
 
@@ -125,7 +133,7 @@
            isr ? 1 : 0, s->intrstatus, s->intrmask);
     }
 
-    qemu_set_irq(s->dev.irq[0], (isr != 0));
+    qemu_set_irq(d->irq[0], (isr != 0));
 }
 
 static void ivshmem_IntrMask_write(IVShmemState *s, uint32_t val)
@@ -296,7 +304,7 @@
 
     /* if MSI is supported we need multiple interrupts */
     if (ivshmem_has_feature(s, IVSHMEM_MSI)) {
-        s->eventfd_table[vector].pdev = &s->dev;
+        s->eventfd_table[vector].pdev = PCI_DEVICE(s);
         s->eventfd_table[vector].vector = vector;
 
         qemu_chr_add_handlers(chr, ivshmem_can_receive, fake_irqfd,
@@ -341,11 +349,11 @@
 
     memory_region_init_ram_ptr(&s->ivshmem, OBJECT(s), "ivshmem.bar2",
                                s->ivshmem_size, ptr);
-    vmstate_register_ram(&s->ivshmem, &s->dev.qdev);
+    vmstate_register_ram(&s->ivshmem, DEVICE(s));
     memory_region_add_subregion(&s->bar, 0, &s->ivshmem);
 
     /* region for shared memory */
-    pci_register_bar(&s->dev, 2, s->ivshmem_attr, &s->bar);
+    pci_register_bar(PCI_DEVICE(s), 2, s->ivshmem_attr, &s->bar);
 }
 
 static void ivshmem_add_eventfd(IVShmemState *s, int posn, int i)
@@ -469,7 +477,7 @@
                                                             incoming_fd, 0);
         memory_region_init_ram_ptr(&s->ivshmem, OBJECT(s),
                                    "ivshmem.bar2", s->ivshmem_size, map_ptr);
-        vmstate_register_ram(&s->ivshmem, &s->dev.qdev);
+        vmstate_register_ram(&s->ivshmem, DEVICE(s));
 
         IVSHMEM_DPRINTF("guest h/w addr = %" PRIu64 ", size = %" PRIu64 "\n",
                          s->ivshmem_offset, s->ivshmem_size);
@@ -521,20 +529,21 @@
  * we just enable all vectors on init and after reset. */
 static void ivshmem_use_msix(IVShmemState * s)
 {
+    PCIDevice *d = PCI_DEVICE(s);
     int i;
 
-    if (!msix_present(&s->dev)) {
+    if (!msix_present(d)) {
         return;
     }
 
     for (i = 0; i < s->vectors; i++) {
-        msix_vector_use(&s->dev, i);
+        msix_vector_use(d, i);
     }
 }
 
 static void ivshmem_reset(DeviceState *d)
 {
-    IVShmemState *s = DO_UPCAST(IVShmemState, dev.qdev, d);
+    IVShmemState *s = IVSHMEM(d);
 
     s->intrstatus = 0;
     ivshmem_use_msix(s);
@@ -569,7 +578,7 @@
 
 static void ivshmem_setup_msi(IVShmemState * s)
 {
-    if (msix_init_exclusive_bar(&s->dev, s->vectors, 1)) {
+    if (msix_init_exclusive_bar(PCI_DEVICE(s), s->vectors, 1)) {
         IVSHMEM_DPRINTF("msix initialization failed\n");
         exit(1);
     }
@@ -585,12 +594,13 @@
 static void ivshmem_save(QEMUFile* f, void *opaque)
 {
     IVShmemState *proxy = opaque;
+    PCIDevice *pci_dev = PCI_DEVICE(proxy);
 
     IVSHMEM_DPRINTF("ivshmem_save\n");
-    pci_device_save(&proxy->dev, f);
+    pci_device_save(pci_dev, f);
 
     if (ivshmem_has_feature(proxy, IVSHMEM_MSI)) {
-        msix_save(&proxy->dev, f);
+        msix_save(pci_dev, f);
     } else {
         qemu_put_be32(f, proxy->intrstatus);
         qemu_put_be32(f, proxy->intrmask);
@@ -603,6 +613,7 @@
     IVSHMEM_DPRINTF("ivshmem_load\n");
 
     IVShmemState *proxy = opaque;
+    PCIDevice *pci_dev = PCI_DEVICE(proxy);
     int ret;
 
     if (version_id > 0) {
@@ -614,13 +625,13 @@
         return -EINVAL;
     }
 
-    ret = pci_device_load(&proxy->dev, f);
+    ret = pci_device_load(pci_dev, f);
     if (ret) {
         return ret;
     }
 
     if (ivshmem_has_feature(proxy, IVSHMEM_MSI)) {
-        msix_load(&proxy->dev, f);
+        msix_load(pci_dev, f);
 	ivshmem_use_msix(proxy);
     } else {
         proxy->intrstatus = qemu_get_be32(f);
@@ -639,7 +650,7 @@
 
 static int pci_ivshmem_init(PCIDevice *dev)
 {
-    IVShmemState *s = DO_UPCAST(IVShmemState, dev, dev);
+    IVShmemState *s = IVSHMEM(dev);
     uint8_t *pci_conf;
 
     if (s->sizearg == NULL)
@@ -648,7 +659,7 @@
         s->ivshmem_size = ivshmem_get_size(s);
     }
 
-    register_savevm(&s->dev.qdev, "ivshmem", 0, 0, ivshmem_save, ivshmem_load,
+    register_savevm(DEVICE(dev), "ivshmem", 0, 0, ivshmem_save, ivshmem_load,
                                                                         dev);
 
     /* IRQFD requires MSI */
@@ -678,7 +689,7 @@
         migrate_add_blocker(s->migration_blocker);
     }
 
-    pci_conf = s->dev.config;
+    pci_conf = dev->config;
     pci_conf[PCI_COMMAND] = PCI_COMMAND_IO | PCI_COMMAND_MEMORY;
 
     pci_config_set_interrupt_pin(pci_conf, 1);
@@ -689,7 +700,7 @@
                           "ivshmem-mmio", IVSHMEM_REG_BAR_SIZE);
 
     /* region for registers*/
-    pci_register_bar(&s->dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY,
+    pci_register_bar(dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY,
                      &s->ivshmem_mmio);
 
     memory_region_init(&s->bar, OBJECT(s), "ivshmem-bar2-container", s->ivshmem_size);
@@ -723,7 +734,7 @@
         /* allocate/initialize space for interrupt handling */
         s->peers = g_malloc0(s->nb_peers * sizeof(Peer));
 
-        pci_register_bar(&s->dev, 2, s->ivshmem_attr, &s->bar);
+        pci_register_bar(dev, 2, s->ivshmem_attr, &s->bar);
 
         s->eventfd_chr = g_malloc0(s->vectors * sizeof(CharDriverState *));
 
@@ -764,14 +775,14 @@
 
     }
 
-    s->dev.config_write = ivshmem_write_config;
+    dev->config_write = ivshmem_write_config;
 
     return 0;
 }
 
 static void pci_ivshmem_uninit(PCIDevice *dev)
 {
-    IVShmemState *s = DO_UPCAST(IVShmemState, dev, dev);
+    IVShmemState *s = IVSHMEM(dev);
 
     if (s->migration_blocker) {
         migrate_del_blocker(s->migration_blocker);
@@ -780,10 +791,10 @@
 
     memory_region_destroy(&s->ivshmem_mmio);
     memory_region_del_subregion(&s->bar, &s->ivshmem);
-    vmstate_unregister_ram(&s->ivshmem, &s->dev.qdev);
+    vmstate_unregister_ram(&s->ivshmem, DEVICE(dev));
     memory_region_destroy(&s->ivshmem);
     memory_region_destroy(&s->bar);
-    unregister_savevm(&dev->qdev, "ivshmem", s);
+    unregister_savevm(DEVICE(dev), "ivshmem", s);
 }
 
 static Property ivshmem_properties[] = {
@@ -813,7 +824,7 @@
 }
 
 static const TypeInfo ivshmem_info = {
-    .name          = "ivshmem",
+    .name          = TYPE_IVSHMEM,
     .parent        = TYPE_PCI_DEVICE,
     .instance_size = sizeof(IVShmemState),
     .class_init    = ivshmem_class_init,
diff --git a/hw/misc/pci-testdev.c b/hw/misc/pci-testdev.c
index 8b0b73f..d69ff33 100644
--- a/hw/misc/pci-testdev.c
+++ b/hw/misc/pci-testdev.c
@@ -76,13 +76,21 @@
 #define IOTEST_ACCESS_WIDTH (sizeof(uint8_t))
 
 typedef struct PCITestDevState {
-    PCIDevice dev;
+    /*< private >*/
+    PCIDevice parent_obj;
+    /*< public >*/
+
     MemoryRegion mmio;
     MemoryRegion portio;
     IOTest *tests;
     int current;
 } PCITestDevState;
 
+#define TYPE_PCI_TEST_DEV "pci-testdev"
+
+#define PCI_TEST_DEV(obj) \
+    OBJECT_CHECK(PCITestDevState, (obj), TYPE_PCI_TEST_DEV)
+
 #define IOTEST_IS_MEM(i) (strcmp(IOTEST_TYPE(i), "portio"))
 #define IOTEST_REGION(d, i) (IOTEST_IS_MEM(i) ?  &(d)->mmio : &(d)->portio)
 #define IOTEST_SIZE(i) (IOTEST_IS_MEM(i) ? IOTEST_MEMSIZE : IOTEST_IOSIZE)
@@ -227,12 +235,12 @@
 
 static int pci_testdev_init(PCIDevice *pci_dev)
 {
-    PCITestDevState *d = DO_UPCAST(PCITestDevState, dev, pci_dev);
+    PCITestDevState *d = PCI_TEST_DEV(pci_dev);
     uint8_t *pci_conf;
     char *name;
     int r, i;
 
-    pci_conf = d->dev.config;
+    pci_conf = pci_dev->config;
 
     pci_conf[PCI_INTERRUPT_PIN] = 0; /* no interrupt pin */
 
@@ -240,8 +248,8 @@
                           "pci-testdev-mmio", IOTEST_MEMSIZE * 2);
     memory_region_init_io(&d->portio, OBJECT(d), &pci_testdev_pio_ops, d,
                           "pci-testdev-portio", IOTEST_IOSIZE * 2);
-    pci_register_bar(&d->dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &d->mmio);
-    pci_register_bar(&d->dev, 1, PCI_BASE_ADDRESS_SPACE_IO, &d->portio);
+    pci_register_bar(pci_dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &d->mmio);
+    pci_register_bar(pci_dev, 1, PCI_BASE_ADDRESS_SPACE_IO, &d->portio);
 
     d->current = -1;
     d->tests = g_malloc0(IOTEST_MAX * sizeof *d->tests);
@@ -274,7 +282,7 @@
 static void
 pci_testdev_uninit(PCIDevice *dev)
 {
-    PCITestDevState *d = DO_UPCAST(PCITestDevState, dev, dev);
+    PCITestDevState *d = PCI_TEST_DEV(dev);
     int i;
 
     pci_testdev_reset(d);
@@ -291,7 +299,7 @@
 
 static void qdev_pci_testdev_reset(DeviceState *dev)
 {
-    PCITestDevState *d = DO_UPCAST(PCITestDevState, dev.qdev, dev);
+    PCITestDevState *d = PCI_TEST_DEV(dev);
     pci_testdev_reset(d);
 }
 
@@ -311,7 +319,7 @@
 }
 
 static const TypeInfo pci_testdev_info = {
-    .name          = "pci-testdev",
+    .name          = TYPE_PCI_TEST_DEV,
     .parent        = TYPE_PCI_DEVICE,
     .instance_size = sizeof(PCITestDevState),
     .class_init    = pci_testdev_class_init,
diff --git a/hw/net/e1000.c b/hw/net/e1000.c
index 5f04f13..b952d8d 100644
--- a/hw/net/e1000.c
+++ b/hw/net/e1000.c
@@ -85,7 +85,10 @@
 };
 
 typedef struct E1000State_st {
-    PCIDevice dev;
+    /*< private >*/
+    PCIDevice parent_obj;
+    /*< public >*/
+
     NICState *nic;
     NICConf conf;
     MemoryRegion mmio;
@@ -138,6 +141,11 @@
     uint32_t compat_flags;
 } E1000State;
 
+#define TYPE_E1000 "e1000"
+
+#define E1000(obj) \
+    OBJECT_CHECK(E1000State, (obj), TYPE_E1000)
+
 #define	defreg(x)	x = (E1000_##x>>2)
 enum {
     defreg(CTRL),	defreg(EECD),	defreg(EERD),	defreg(GPRC),
@@ -240,6 +248,8 @@
 static void
 set_interrupt_cause(E1000State *s, int index, uint32_t val)
 {
+    PCIDevice *d = PCI_DEVICE(s);
+
     if (val && (E1000_DEVID >= E1000_DEV_ID_82547EI_MOBILE)) {
         /* Only for 8257x */
         val |= E1000_ICR_INT_ASSERTED;
@@ -256,7 +266,7 @@
      */
     s->mac_reg[ICS] = val;
 
-    qemu_set_irq(s->dev.irq[0], (s->mac_reg[IMS] & s->mac_reg[ICR]) != 0);
+    qemu_set_irq(d->irq[0], (s->mac_reg[IMS] & s->mac_reg[ICR]) != 0);
 }
 
 static void
@@ -553,6 +563,7 @@
 static void
 process_tx_desc(E1000State *s, struct e1000_tx_desc *dp)
 {
+    PCIDevice *d = PCI_DEVICE(s);
     uint32_t txd_lower = le32_to_cpu(dp->lower.data);
     uint32_t dtype = txd_lower & (E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D);
     unsigned int split_size = txd_lower & 0xffff, bytes, sz, op;
@@ -610,7 +621,7 @@
                 bytes = msh - tp->size;
 
             bytes = MIN(sizeof(tp->data) - tp->size, bytes);
-            pci_dma_read(&s->dev, addr, tp->data + tp->size, bytes);
+            pci_dma_read(d, addr, tp->data + tp->size, bytes);
             sz = tp->size + bytes;
             if (sz >= tp->hdr_len && tp->size < tp->hdr_len) {
                 memmove(tp->header, tp->data, tp->hdr_len);
@@ -628,7 +639,7 @@
         DBGOUT(TXERR, "TCP segmentation error\n");
     } else {
         split_size = MIN(sizeof(tp->data) - tp->size, split_size);
-        pci_dma_read(&s->dev, addr, tp->data + tp->size, split_size);
+        pci_dma_read(d, addr, tp->data + tp->size, split_size);
         tp->size += split_size;
     }
 
@@ -647,6 +658,7 @@
 static uint32_t
 txdesc_writeback(E1000State *s, dma_addr_t base, struct e1000_tx_desc *dp)
 {
+    PCIDevice *d = PCI_DEVICE(s);
     uint32_t txd_upper, txd_lower = le32_to_cpu(dp->lower.data);
 
     if (!(txd_lower & (E1000_TXD_CMD_RS|E1000_TXD_CMD_RPS)))
@@ -654,7 +666,7 @@
     txd_upper = (le32_to_cpu(dp->upper.data) | E1000_TXD_STAT_DD) &
                 ~(E1000_TXD_STAT_EC | E1000_TXD_STAT_LC | E1000_TXD_STAT_TU);
     dp->upper.data = cpu_to_le32(txd_upper);
-    pci_dma_write(&s->dev, base + ((char *)&dp->upper - (char *)dp),
+    pci_dma_write(d, base + ((char *)&dp->upper - (char *)dp),
                   &dp->upper, sizeof(dp->upper));
     return E1000_ICR_TXDW;
 }
@@ -670,6 +682,7 @@
 static void
 start_xmit(E1000State *s)
 {
+    PCIDevice *d = PCI_DEVICE(s);
     dma_addr_t base;
     struct e1000_tx_desc desc;
     uint32_t tdh_start = s->mac_reg[TDH], cause = E1000_ICS_TXQE;
@@ -682,7 +695,7 @@
     while (s->mac_reg[TDH] != s->mac_reg[TDT]) {
         base = tx_desc_base(s) +
                sizeof(struct e1000_tx_desc) * s->mac_reg[TDH];
-        pci_dma_read(&s->dev, base, &desc, sizeof(desc));
+        pci_dma_read(d, base, &desc, sizeof(desc));
 
         DBGOUT(TX, "index %d: %p : %x %x\n", s->mac_reg[TDH],
                (void *)(intptr_t)desc.buffer_addr, desc.lower.data,
@@ -815,6 +828,7 @@
 e1000_receive(NetClientState *nc, const uint8_t *buf, size_t size)
 {
     E1000State *s = qemu_get_nic_opaque(nc);
+    PCIDevice *d = PCI_DEVICE(s);
     struct e1000_rx_desc desc;
     dma_addr_t base;
     unsigned int n, rdt;
@@ -874,7 +888,7 @@
             desc_size = s->rxbuf_size;
         }
         base = rx_desc_base(s) + sizeof(desc) * s->mac_reg[RDH];
-        pci_dma_read(&s->dev, base, &desc, sizeof(desc));
+        pci_dma_read(d, base, &desc, sizeof(desc));
         desc.special = vlan_special;
         desc.status |= (vlan_status | E1000_RXD_STAT_DD);
         if (desc.buffer_addr) {
@@ -883,7 +897,7 @@
                 if (copy_size > s->rxbuf_size) {
                     copy_size = s->rxbuf_size;
                 }
-                pci_dma_write(&s->dev, le64_to_cpu(desc.buffer_addr),
+                pci_dma_write(d, le64_to_cpu(desc.buffer_addr),
                               buf + desc_offset + vlan_offset, copy_size);
             }
             desc_offset += desc_size;
@@ -898,7 +912,7 @@
         } else { // as per intel docs; skip descriptors with null buf addr
             DBGOUT(RX, "Null RX descriptor!!\n");
         }
-        pci_dma_write(&s->dev, base, &desc, sizeof(desc));
+        pci_dma_write(d, base, &desc, sizeof(desc));
 
         if (++s->mac_reg[RDH] * sizeof(desc) >= s->mac_reg[RDLEN])
             s->mac_reg[RDH] = 0;
@@ -1184,7 +1198,7 @@
     .pre_save = e1000_pre_save,
     .post_load = e1000_post_load,
     .fields      = (VMStateField []) {
-        VMSTATE_PCI_DEVICE(dev, E1000State),
+        VMSTATE_PCI_DEVICE(parent_obj, E1000State),
         VMSTATE_UNUSED_TEST(is_version_1, 4), /* was instance id */
         VMSTATE_UNUSED(4), /* Was mmio_base.  */
         VMSTATE_UINT32(rxbuf_size, E1000State),
@@ -1298,7 +1312,7 @@
 static void
 pci_e1000_uninit(PCIDevice *dev)
 {
-    E1000State *d = DO_UPCAST(E1000State, dev, dev);
+    E1000State *d = E1000(dev);
 
     qemu_del_timer(d->autoneg_timer);
     qemu_free_timer(d->autoneg_timer);
@@ -1318,13 +1332,14 @@
 
 static int pci_e1000_init(PCIDevice *pci_dev)
 {
-    E1000State *d = DO_UPCAST(E1000State, dev, pci_dev);
+    DeviceState *dev = DEVICE(pci_dev);
+    E1000State *d = E1000(pci_dev);
     uint8_t *pci_conf;
     uint16_t checksum = 0;
     int i;
     uint8_t *macaddr;
 
-    pci_conf = d->dev.config;
+    pci_conf = pci_dev->config;
 
     /* TODO: RST# value should be 0, PCI spec 6.2.4 */
     pci_conf[PCI_CACHE_LINE_SIZE] = 0x10;
@@ -1333,9 +1348,9 @@
 
     e1000_mmio_setup(d);
 
-    pci_register_bar(&d->dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &d->mmio);
+    pci_register_bar(pci_dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &d->mmio);
 
-    pci_register_bar(&d->dev, 1, PCI_BASE_ADDRESS_SPACE_IO, &d->io);
+    pci_register_bar(pci_dev, 1, PCI_BASE_ADDRESS_SPACE_IO, &d->io);
 
     memmove(d->eeprom_data, e1000_eeprom_template,
         sizeof e1000_eeprom_template);
@@ -1349,11 +1364,11 @@
     d->eeprom_data[EEPROM_CHECKSUM_REG] = checksum;
 
     d->nic = qemu_new_nic(&net_e1000_info, &d->conf,
-                          object_get_typename(OBJECT(d)), d->dev.qdev.id, d);
+                          object_get_typename(OBJECT(d)), dev->id, d);
 
     qemu_format_nic_info_str(qemu_get_queue(d->nic), macaddr);
 
-    add_boot_device_path(d->conf.bootindex, &pci_dev->qdev, "/ethernet-phy@0");
+    add_boot_device_path(d->conf.bootindex, dev, "/ethernet-phy@0");
 
     d->autoneg_timer = qemu_new_timer_ms(vm_clock, e1000_autoneg_timer, d);
 
@@ -1362,7 +1377,7 @@
 
 static void qdev_e1000_reset(DeviceState *dev)
 {
-    E1000State *d = DO_UPCAST(E1000State, dev.qdev, dev);
+    E1000State *d = E1000(dev);
     e1000_reset(d);
 }
 
@@ -1392,7 +1407,7 @@
 }
 
 static const TypeInfo e1000_info = {
-    .name          = "e1000",
+    .name          = TYPE_E1000,
     .parent        = TYPE_PCI_DEVICE,
     .instance_size = sizeof(E1000State),
     .class_init    = e1000_class_init,
diff --git a/hw/net/pcnet-pci.c b/hw/net/pcnet-pci.c
index f4a5aef..6ef28f7 100644
--- a/hw/net/pcnet-pci.c
+++ b/hw/net/pcnet-pci.c
@@ -43,9 +43,16 @@
 //#define PCNET_DEBUG_TMD
 //#define PCNET_DEBUG_MATCH
 
+#define TYPE_PCI_PCNET "pcnet"
+
+#define PCI_PCNET(obj) \
+     OBJECT_CHECK(PCIPCNetState, (obj), TYPE_PCI_PCNET)
 
 typedef struct {
-    PCIDevice pci_dev;
+    /*< private >*/
+    PCIDevice parent_obj;
+    /*< public >*/
+
     PCNetState state;
     MemoryRegion io_bar;
 } PCIPCNetState;
@@ -236,7 +243,7 @@
     .minimum_version_id = 2,
     .minimum_version_id_old = 2,
     .fields      = (VMStateField []) {
-        VMSTATE_PCI_DEVICE(pci_dev, PCIPCNetState),
+        VMSTATE_PCI_DEVICE(parent_obj, PCIPCNetState),
         VMSTATE_STRUCT(state, PCIPCNetState, 0, vmstate_pcnet, PCNetState),
         VMSTATE_END_OF_LIST()
     }
@@ -273,7 +280,7 @@
 
 static void pci_pcnet_uninit(PCIDevice *dev)
 {
-    PCIPCNetState *d = DO_UPCAST(PCIPCNetState, pci_dev, dev);
+    PCIPCNetState *d = PCI_PCNET(dev);
 
     memory_region_destroy(&d->state.mmio);
     memory_region_destroy(&d->io_bar);
@@ -293,7 +300,7 @@
 
 static int pci_pcnet_init(PCIDevice *pci_dev)
 {
-    PCIPCNetState *d = DO_UPCAST(PCIPCNetState, pci_dev, pci_dev);
+    PCIPCNetState *d = PCI_PCNET(pci_dev);
     PCNetState *s = &d->state;
     uint8_t *pci_conf;
 
@@ -329,12 +336,12 @@
     s->phys_mem_write = pci_physical_memory_write;
     s->dma_opaque = pci_dev;
 
-    return pcnet_common_init(&pci_dev->qdev, s, &net_pci_pcnet_info);
+    return pcnet_common_init(DEVICE(pci_dev), s, &net_pci_pcnet_info);
 }
 
 static void pci_reset(DeviceState *dev)
 {
-    PCIPCNetState *d = DO_UPCAST(PCIPCNetState, pci_dev.qdev, dev);
+    PCIPCNetState *d = PCI_PCNET(dev);
 
     pcnet_h_reset(&d->state);
 }
@@ -362,7 +369,7 @@
 }
 
 static const TypeInfo pcnet_info = {
-    .name          = "pcnet",
+    .name          = TYPE_PCI_PCNET,
     .parent        = TYPE_PCI_DEVICE,
     .instance_size = sizeof(PCIPCNetState),
     .class_init    = pcnet_class_init,
diff --git a/hw/net/rtl8139.c b/hw/net/rtl8139.c
index a00ff58..6552034 100644
--- a/hw/net/rtl8139.c
+++ b/hw/net/rtl8139.c
@@ -92,6 +92,11 @@
 }
 #endif
 
+#define TYPE_RTL8139 "rtl8139"
+
+#define RTL8139(obj) \
+     OBJECT_CHECK(RTL8139State, (obj), TYPE_RTL8139)
+
 /* Symbolic offsets to registers. */
 enum RTL8139_registers {
     MAC0 = 0,        /* Ethernet hardware address. */
@@ -428,7 +433,10 @@
 static void RTL8139TallyCounters_clear(RTL8139TallyCounters* counters);
 
 typedef struct RTL8139State {
-    PCIDevice dev;
+    /*< private >*/
+    PCIDevice parent_obj;
+    /*< public >*/
+
     uint8_t phys[8]; /* mac address */
     uint8_t mult[8]; /* multicast mask array */
 
@@ -701,13 +709,14 @@
 
 static void rtl8139_update_irq(RTL8139State *s)
 {
+    PCIDevice *d = PCI_DEVICE(s);
     int isr;
     isr = (s->IntrStatus & s->IntrMask) & 0xffff;
 
     DPRINTF("Set IRQ to %d (%04x %04x)\n", isr ? 1 : 0, s->IntrStatus,
         s->IntrMask);
 
-    qemu_set_irq(s->dev.irq[0], (isr != 0));
+    qemu_set_irq(d->irq[0], (isr != 0));
 }
 
 static int rtl8139_RxWrap(RTL8139State *s)
@@ -738,6 +747,8 @@
 
 static void rtl8139_write_buffer(RTL8139State *s, const void *buf, int size)
 {
+    PCIDevice *d = PCI_DEVICE(s);
+
     if (s->RxBufAddr + size > s->RxBufferSize)
     {
         int wrapped = MOD2(s->RxBufAddr + size, s->RxBufferSize);
@@ -749,14 +760,14 @@
 
             if (size > wrapped)
             {
-                pci_dma_write(&s->dev, s->RxBuf + s->RxBufAddr,
+                pci_dma_write(d, s->RxBuf + s->RxBufAddr,
                               buf, size-wrapped);
             }
 
             /* reset buffer pointer */
             s->RxBufAddr = 0;
 
-            pci_dma_write(&s->dev, s->RxBuf + s->RxBufAddr,
+            pci_dma_write(d, s->RxBuf + s->RxBufAddr,
                           buf + (size-wrapped), wrapped);
 
             s->RxBufAddr = wrapped;
@@ -766,7 +777,7 @@
     }
 
     /* non-wrapping path or overwrapping enabled */
-    pci_dma_write(&s->dev, s->RxBuf + s->RxBufAddr, buf, size);
+    pci_dma_write(d, s->RxBuf + s->RxBufAddr, buf, size);
 
     s->RxBufAddr += size;
 }
@@ -809,6 +820,7 @@
 static ssize_t rtl8139_do_receive(NetClientState *nc, const uint8_t *buf, size_t size_, int do_interrupt)
 {
     RTL8139State *s = qemu_get_nic_opaque(nc);
+    PCIDevice *d = PCI_DEVICE(s);
     /* size is the length of the buffer passed to the driver */
     int size = size_;
     const uint8_t *dot1q_buf = NULL;
@@ -973,13 +985,13 @@
 
         uint32_t val, rxdw0,rxdw1,rxbufLO,rxbufHI;
 
-        pci_dma_read(&s->dev, cplus_rx_ring_desc, &val, 4);
+        pci_dma_read(d, cplus_rx_ring_desc, &val, 4);
         rxdw0 = le32_to_cpu(val);
-        pci_dma_read(&s->dev, cplus_rx_ring_desc+4, &val, 4);
+        pci_dma_read(d, cplus_rx_ring_desc+4, &val, 4);
         rxdw1 = le32_to_cpu(val);
-        pci_dma_read(&s->dev, cplus_rx_ring_desc+8, &val, 4);
+        pci_dma_read(d, cplus_rx_ring_desc+8, &val, 4);
         rxbufLO = le32_to_cpu(val);
-        pci_dma_read(&s->dev, cplus_rx_ring_desc+12, &val, 4);
+        pci_dma_read(d, cplus_rx_ring_desc+12, &val, 4);
         rxbufHI = le32_to_cpu(val);
 
         DPRINTF("+++ C+ mode RX descriptor %d %08x %08x %08x %08x\n",
@@ -1047,12 +1059,12 @@
 
         /* receive/copy to target memory */
         if (dot1q_buf) {
-            pci_dma_write(&s->dev, rx_addr, buf, 2 * ETHER_ADDR_LEN);
-            pci_dma_write(&s->dev, rx_addr + 2 * ETHER_ADDR_LEN,
+            pci_dma_write(d, rx_addr, buf, 2 * ETHER_ADDR_LEN);
+            pci_dma_write(d, rx_addr + 2 * ETHER_ADDR_LEN,
                           buf + 2 * ETHER_ADDR_LEN + VLAN_HLEN,
                           size - 2 * ETHER_ADDR_LEN);
         } else {
-            pci_dma_write(&s->dev, rx_addr, buf, size);
+            pci_dma_write(d, rx_addr, buf, size);
         }
 
         if (s->CpCmd & CPlusRxChkSum)
@@ -1062,7 +1074,7 @@
 
         /* write checksum */
         val = cpu_to_le32(crc32(0, buf, size_));
-        pci_dma_write(&s->dev, rx_addr+size, (uint8_t *)&val, 4);
+        pci_dma_write(d, rx_addr+size, (uint8_t *)&val, 4);
 
 /* first segment of received packet flag */
 #define CP_RX_STATUS_FS (1<<29)
@@ -1108,9 +1120,9 @@
 
         /* update ring data */
         val = cpu_to_le32(rxdw0);
-        pci_dma_write(&s->dev, cplus_rx_ring_desc, (uint8_t *)&val, 4);
+        pci_dma_write(d, cplus_rx_ring_desc, (uint8_t *)&val, 4);
         val = cpu_to_le32(rxdw1);
-        pci_dma_write(&s->dev, cplus_rx_ring_desc+4, (uint8_t *)&val, 4);
+        pci_dma_write(d, cplus_rx_ring_desc+4, (uint8_t *)&val, 4);
 
         /* update tally counter */
         ++s->tally_counters.RxOk;
@@ -1197,7 +1209,7 @@
 
 static void rtl8139_reset(DeviceState *d)
 {
-    RTL8139State *s = container_of(d, RTL8139State, dev.qdev);
+    RTL8139State *s = RTL8139(d);
     int i;
 
     /* restore MAC address */
@@ -1293,49 +1305,50 @@
 
 static void RTL8139TallyCounters_dma_write(RTL8139State *s, dma_addr_t tc_addr)
 {
+    PCIDevice *d = PCI_DEVICE(s);
     RTL8139TallyCounters *tally_counters = &s->tally_counters;
     uint16_t val16;
     uint32_t val32;
     uint64_t val64;
 
     val64 = cpu_to_le64(tally_counters->TxOk);
-    pci_dma_write(&s->dev, tc_addr + 0,     (uint8_t *)&val64, 8);
+    pci_dma_write(d, tc_addr + 0,     (uint8_t *)&val64, 8);
 
     val64 = cpu_to_le64(tally_counters->RxOk);
-    pci_dma_write(&s->dev, tc_addr + 8,     (uint8_t *)&val64, 8);
+    pci_dma_write(d, tc_addr + 8,     (uint8_t *)&val64, 8);
 
     val64 = cpu_to_le64(tally_counters->TxERR);
-    pci_dma_write(&s->dev, tc_addr + 16,    (uint8_t *)&val64, 8);
+    pci_dma_write(d, tc_addr + 16,    (uint8_t *)&val64, 8);
 
     val32 = cpu_to_le32(tally_counters->RxERR);
-    pci_dma_write(&s->dev, tc_addr + 24,    (uint8_t *)&val32, 4);
+    pci_dma_write(d, tc_addr + 24,    (uint8_t *)&val32, 4);
 
     val16 = cpu_to_le16(tally_counters->MissPkt);
-    pci_dma_write(&s->dev, tc_addr + 28,    (uint8_t *)&val16, 2);
+    pci_dma_write(d, tc_addr + 28,    (uint8_t *)&val16, 2);
 
     val16 = cpu_to_le16(tally_counters->FAE);
-    pci_dma_write(&s->dev, tc_addr + 30,    (uint8_t *)&val16, 2);
+    pci_dma_write(d, tc_addr + 30,    (uint8_t *)&val16, 2);
 
     val32 = cpu_to_le32(tally_counters->Tx1Col);
-    pci_dma_write(&s->dev, tc_addr + 32,    (uint8_t *)&val32, 4);
+    pci_dma_write(d, tc_addr + 32,    (uint8_t *)&val32, 4);
 
     val32 = cpu_to_le32(tally_counters->TxMCol);
-    pci_dma_write(&s->dev, tc_addr + 36,    (uint8_t *)&val32, 4);
+    pci_dma_write(d, tc_addr + 36,    (uint8_t *)&val32, 4);
 
     val64 = cpu_to_le64(tally_counters->RxOkPhy);
-    pci_dma_write(&s->dev, tc_addr + 40,    (uint8_t *)&val64, 8);
+    pci_dma_write(d, tc_addr + 40,    (uint8_t *)&val64, 8);
 
     val64 = cpu_to_le64(tally_counters->RxOkBrd);
-    pci_dma_write(&s->dev, tc_addr + 48,    (uint8_t *)&val64, 8);
+    pci_dma_write(d, tc_addr + 48,    (uint8_t *)&val64, 8);
 
     val32 = cpu_to_le32(tally_counters->RxOkMul);
-    pci_dma_write(&s->dev, tc_addr + 56,    (uint8_t *)&val32, 4);
+    pci_dma_write(d, tc_addr + 56,    (uint8_t *)&val32, 4);
 
     val16 = cpu_to_le16(tally_counters->TxAbt);
-    pci_dma_write(&s->dev, tc_addr + 60,    (uint8_t *)&val16, 2);
+    pci_dma_write(d, tc_addr + 60,    (uint8_t *)&val16, 2);
 
     val16 = cpu_to_le16(tally_counters->TxUndrn);
-    pci_dma_write(&s->dev, tc_addr + 62,    (uint8_t *)&val16, 2);
+    pci_dma_write(d, tc_addr + 62,    (uint8_t *)&val16, 2);
 }
 
 /* Loads values of tally counters from VM state file */
@@ -1364,6 +1377,8 @@
 
 static void rtl8139_ChipCmd_write(RTL8139State *s, uint32_t val)
 {
+    DeviceState *d = DEVICE(s);
+
     val &= 0xff;
 
     DPRINTF("ChipCmd write val=0x%08x\n", val);
@@ -1371,7 +1386,7 @@
     if (val & CmdReset)
     {
         DPRINTF("ChipCmd reset\n");
-        rtl8139_reset(&s->dev.qdev);
+        rtl8139_reset(d);
     }
     if (val & CmdRxEnb)
     {
@@ -1525,6 +1540,8 @@
 
 static void rtl8139_Cfg9346_write(RTL8139State *s, uint32_t val)
 {
+    DeviceState *d = DEVICE(s);
+
     val &= 0xff;
 
     DPRINTF("Cfg9346 write val=0x%02x\n", val);
@@ -1544,7 +1561,7 @@
     } else if (opmode == 0x40) {
         /* Reset.  */
         val = 0;
-        rtl8139_reset(&s->dev.qdev);
+        rtl8139_reset(d);
     }
 
     s->Cfg9346 = val;
@@ -1821,13 +1838,14 @@
 
     DPRINTF("+++ transmitting from descriptor %d\n", descriptor);
 
+    PCIDevice *d = PCI_DEVICE(s);
     int txsize = s->TxStatus[descriptor] & 0x1fff;
     uint8_t txbuffer[0x2000];
 
     DPRINTF("+++ transmit reading %d bytes from host memory at 0x%08x\n",
         txsize, s->TxAddr[descriptor]);
 
-    pci_dma_read(&s->dev, s->TxAddr[descriptor], txbuffer, txsize);
+    pci_dma_read(d, s->TxAddr[descriptor], txbuffer, txsize);
 
     /* Mark descriptor as transferred */
     s->TxStatus[descriptor] |= TxHostOwns;
@@ -1946,6 +1964,7 @@
         return 0 ;
     }
 
+    PCIDevice *d = PCI_DEVICE(s);
     int descriptor = s->currCPlusTxDesc;
 
     dma_addr_t cplus_tx_ring_desc = rtl8139_addr64(s->TxAddr[0], s->TxAddr[1]);
@@ -1959,13 +1978,13 @@
 
     uint32_t val, txdw0,txdw1,txbufLO,txbufHI;
 
-    pci_dma_read(&s->dev, cplus_tx_ring_desc,    (uint8_t *)&val, 4);
+    pci_dma_read(d, cplus_tx_ring_desc,    (uint8_t *)&val, 4);
     txdw0 = le32_to_cpu(val);
-    pci_dma_read(&s->dev, cplus_tx_ring_desc+4,  (uint8_t *)&val, 4);
+    pci_dma_read(d, cplus_tx_ring_desc+4,  (uint8_t *)&val, 4);
     txdw1 = le32_to_cpu(val);
-    pci_dma_read(&s->dev, cplus_tx_ring_desc+8,  (uint8_t *)&val, 4);
+    pci_dma_read(d, cplus_tx_ring_desc+8,  (uint8_t *)&val, 4);
     txbufLO = le32_to_cpu(val);
-    pci_dma_read(&s->dev, cplus_tx_ring_desc+12, (uint8_t *)&val, 4);
+    pci_dma_read(d, cplus_tx_ring_desc+12, (uint8_t *)&val, 4);
     txbufHI = le32_to_cpu(val);
 
     DPRINTF("+++ C+ mode TX descriptor %d %08x %08x %08x %08x\n", descriptor,
@@ -2072,7 +2091,7 @@
             DMA_ADDR_FMT" to offset %d\n", txsize, tx_addr,
             s->cplus_txbuffer_offset);
 
-    pci_dma_read(&s->dev, tx_addr,
+    pci_dma_read(d, tx_addr,
                  s->cplus_txbuffer + s->cplus_txbuffer_offset, txsize);
     s->cplus_txbuffer_offset += txsize;
 
@@ -2100,7 +2119,7 @@
 
     /* update ring data */
     val = cpu_to_le32(txdw0);
-    pci_dma_write(&s->dev, cplus_tx_ring_desc, (uint8_t *)&val, 4);
+    pci_dma_write(d, cplus_tx_ring_desc, (uint8_t *)&val, 4);
 
     /* Now decide if descriptor being processed is holding the last segment of packet */
     if (txdw0 & CP_TX_LS)
@@ -3273,7 +3292,7 @@
     .post_load = rtl8139_post_load,
     .pre_save  = rtl8139_pre_save,
     .fields      = (VMStateField []) {
-        VMSTATE_PCI_DEVICE(dev, RTL8139State),
+        VMSTATE_PCI_DEVICE(parent_obj, RTL8139State),
         VMSTATE_PARTIAL_BUFFER(phys, RTL8139State, 6),
         VMSTATE_BUFFER(mult, RTL8139State),
         VMSTATE_UINT32_ARRAY(TxStatus, RTL8139State, 4),
@@ -3439,7 +3458,7 @@
 
 static void pci_rtl8139_uninit(PCIDevice *dev)
 {
-    RTL8139State *s = DO_UPCAST(RTL8139State, dev, dev);
+    RTL8139State *s = RTL8139(dev);
 
     memory_region_destroy(&s->bar_io);
     memory_region_destroy(&s->bar_mem);
@@ -3477,10 +3496,11 @@
 
 static int pci_rtl8139_init(PCIDevice *dev)
 {
-    RTL8139State * s = DO_UPCAST(RTL8139State, dev, dev);
+    RTL8139State *s = RTL8139(dev);
+    DeviceState *d = DEVICE(dev);
     uint8_t *pci_conf;
 
-    pci_conf = s->dev.config;
+    pci_conf = dev->config;
     pci_conf[PCI_INTERRUPT_PIN] = 1;    /* interrupt pin A */
     /* TODO: start of capability list, but no capability
      * list bit in status register, and offset 0xdc seems unused. */
@@ -3490,8 +3510,8 @@
                           "rtl8139", 0x100);
     memory_region_init_io(&s->bar_mem, OBJECT(s), &rtl8139_mmio_ops, s,
                           "rtl8139", 0x100);
-    pci_register_bar(&s->dev, 0, PCI_BASE_ADDRESS_SPACE_IO, &s->bar_io);
-    pci_register_bar(&s->dev, 1, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->bar_mem);
+    pci_register_bar(dev, 0, PCI_BASE_ADDRESS_SPACE_IO, &s->bar_io);
+    pci_register_bar(dev, 1, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->bar_mem);
 
     qemu_macaddr_default_if_unset(&s->conf.macaddr);
 
@@ -3507,7 +3527,7 @@
     s->eeprom.contents[9] = s->conf.macaddr.a[4] | s->conf.macaddr.a[5] << 8;
 
     s->nic = qemu_new_nic(&net_rtl8139_info, &s->conf,
-                          object_get_typename(OBJECT(dev)), dev->qdev.id, s);
+                          object_get_typename(OBJECT(dev)), d->id, s);
     qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a);
 
     s->cplus_txbuffer = NULL;
@@ -3518,7 +3538,7 @@
     s->timer = qemu_new_timer_ns(vm_clock, rtl8139_timer, s);
     rtl8139_set_next_tctr_time(s, qemu_get_clock_ns(vm_clock));
 
-    add_boot_device_path(s->conf.bootindex, &dev->qdev, "/ethernet-phy@0");
+    add_boot_device_path(s->conf.bootindex, d, "/ethernet-phy@0");
 
     return 0;
 }
@@ -3546,7 +3566,7 @@
 }
 
 static const TypeInfo rtl8139_info = {
-    .name          = "rtl8139",
+    .name          = TYPE_RTL8139,
     .parent        = TYPE_PCI_DEVICE,
     .instance_size = sizeof(RTL8139State),
     .class_init    = rtl8139_class_init,
diff --git a/hw/nvram/fw_cfg.c b/hw/nvram/fw_cfg.c
index e455282..0a35015 100644
--- a/hw/nvram/fw_cfg.c
+++ b/hw/nvram/fw_cfg.c
@@ -35,6 +35,7 @@
 #define TYPE_FW_CFG "fw_cfg"
 #define FW_CFG_NAME "fw_cfg"
 #define FW_CFG_PATH "/machine/" FW_CFG_NAME
+#define FW_CFG(obj) OBJECT_CHECK(FWCfgState, (obj), TYPE_FW_CFG)
 
 typedef struct FWCfgEntry {
     uint32_t len;
@@ -44,7 +45,10 @@
 } FWCfgEntry;
 
 struct FWCfgState {
-    SysBusDevice busdev;
+    /*< private >*/
+    SysBusDevice parent_obj;
+    /*< public >*/
+
     MemoryRegion ctl_iomem, data_iomem, comb_iomem;
     uint32_t ctl_iobase, data_iobase;
     FWCfgEntry entries[2][FW_CFG_MAX_ENTRY];
@@ -326,7 +330,7 @@
 
 static void fw_cfg_reset(DeviceState *d)
 {
-    FWCfgState *s = DO_UPCAST(FWCfgState, busdev.qdev, d);
+    FWCfgState *s = FW_CFG(d);
 
     fw_cfg_select(s, 0);
 }
@@ -489,12 +493,12 @@
     SysBusDevice *d;
     FWCfgState *s;
 
-    dev = qdev_create(NULL, "fw_cfg");
+    dev = qdev_create(NULL, TYPE_FW_CFG);
     qdev_prop_set_uint32(dev, "ctl_iobase", ctl_port);
     qdev_prop_set_uint32(dev, "data_iobase", data_port);
     d = SYS_BUS_DEVICE(dev);
 
-    s = DO_UPCAST(FWCfgState, busdev.qdev, dev);
+    s = FW_CFG(dev);
 
     assert(!object_resolve_path(FW_CFG_PATH, NULL));
 
@@ -522,31 +526,38 @@
     return s;
 }
 
-static int fw_cfg_init1(SysBusDevice *dev)
+static void fw_cfg_initfn(Object *obj)
 {
-    FWCfgState *s = FROM_SYSBUS(FWCfgState, dev);
+    SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
+    FWCfgState *s = FW_CFG(obj);
 
     memory_region_init_io(&s->ctl_iomem, OBJECT(s), &fw_cfg_ctl_mem_ops, s,
                           "fwcfg.ctl", FW_CFG_SIZE);
-    sysbus_init_mmio(dev, &s->ctl_iomem);
+    sysbus_init_mmio(sbd, &s->ctl_iomem);
     memory_region_init_io(&s->data_iomem, OBJECT(s), &fw_cfg_data_mem_ops, s,
                           "fwcfg.data", FW_CFG_DATA_SIZE);
-    sysbus_init_mmio(dev, &s->data_iomem);
+    sysbus_init_mmio(sbd, &s->data_iomem);
     /* In case ctl and data overlap: */
     memory_region_init_io(&s->comb_iomem, OBJECT(s), &fw_cfg_comb_mem_ops, s,
                           "fwcfg", FW_CFG_SIZE);
+}
+
+static void fw_cfg_realize(DeviceState *dev, Error **errp)
+{
+    FWCfgState *s = FW_CFG(dev);
+    SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
+
 
     if (s->ctl_iobase + 1 == s->data_iobase) {
-        sysbus_add_io(dev, s->ctl_iobase, &s->comb_iomem);
+        sysbus_add_io(sbd, s->ctl_iobase, &s->comb_iomem);
     } else {
         if (s->ctl_iobase) {
-            sysbus_add_io(dev, s->ctl_iobase, &s->ctl_iomem);
+            sysbus_add_io(sbd, s->ctl_iobase, &s->ctl_iomem);
         }
         if (s->data_iobase) {
-            sysbus_add_io(dev, s->data_iobase, &s->data_iomem);
+            sysbus_add_io(sbd, s->data_iobase, &s->data_iomem);
         }
     }
-    return 0;
 }
 
 static Property fw_cfg_properties[] = {
@@ -557,16 +568,14 @@
 
 FWCfgState *fw_cfg_find(void)
 {
-    return OBJECT_CHECK(FWCfgState, object_resolve_path(FW_CFG_PATH, NULL),
-                        TYPE_FW_CFG);
+    return FW_CFG(object_resolve_path(FW_CFG_PATH, NULL));
 }
 
 static void fw_cfg_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
-    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
 
-    k->init = fw_cfg_init1;
+    dc->realize = fw_cfg_realize;
     dc->no_user = 1;
     dc->reset = fw_cfg_reset;
     dc->vmsd = &vmstate_fw_cfg;
@@ -577,6 +586,7 @@
     .name          = TYPE_FW_CFG,
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(FWCfgState),
+    .instance_init = fw_cfg_initfn,
     .class_init    = fw_cfg_class_init,
 };
 
diff --git a/hw/pci-host/piix.c b/hw/pci-host/piix.c
index 870e388..3908860 100644
--- a/hw/pci-host/piix.c
+++ b/hw/pci-host/piix.c
@@ -87,7 +87,10 @@
     OBJECT_CHECK(PCII440FXState, (obj), TYPE_I440FX_PCI_DEVICE)
 
 struct PCII440FXState {
-    PCIDevice dev;
+    /*< private >*/
+    PCIDevice parent_obj;
+    /*< public >*/
+
     MemoryRegion *system_memory;
     MemoryRegion *pci_address_space;
     MemoryRegion *ram_memory;
@@ -121,22 +124,24 @@
 static void i440fx_update_memory_mappings(PCII440FXState *d)
 {
     int i;
+    PCIDevice *pd = PCI_DEVICE(d);
 
     memory_region_transaction_begin();
     for (i = 0; i < 13; i++) {
         pam_update(&d->pam_regions[i], i,
-                   d->dev.config[I440FX_PAM + ((i + 1) / 2)]);
+                   pd->config[I440FX_PAM + ((i + 1) / 2)]);
     }
-    smram_update(&d->smram_region, d->dev.config[I440FX_SMRAM], d->smm_enabled);
+    smram_update(&d->smram_region, pd->config[I440FX_SMRAM], d->smm_enabled);
     memory_region_transaction_commit();
 }
 
 static void i440fx_set_smm(int val, void *arg)
 {
     PCII440FXState *d = arg;
+    PCIDevice *pd = PCI_DEVICE(d);
 
     memory_region_transaction_begin();
-    smram_set_smm(&d->smm_enabled, val, d->dev.config[I440FX_SMRAM],
+    smram_set_smm(&d->smm_enabled, val, pd->config[I440FX_SMRAM],
                   &d->smram_region);
     memory_region_transaction_commit();
 }
@@ -158,9 +163,10 @@
 static int i440fx_load_old(QEMUFile* f, void *opaque, int version_id)
 {
     PCII440FXState *d = opaque;
+    PCIDevice *pd = PCI_DEVICE(d);
     int ret, i;
 
-    ret = pci_device_load(&d->dev, f);
+    ret = pci_device_load(pd, f);
     if (ret < 0)
         return ret;
     i440fx_update_memory_mappings(d);
@@ -191,34 +197,39 @@
     .load_state_old = i440fx_load_old,
     .post_load = i440fx_post_load,
     .fields      = (VMStateField []) {
-        VMSTATE_PCI_DEVICE(dev, PCII440FXState),
+        VMSTATE_PCI_DEVICE(parent_obj, PCII440FXState),
         VMSTATE_UINT8(smm_enabled, PCII440FXState),
         VMSTATE_END_OF_LIST()
     }
 };
 
-static int i440fx_pcihost_initfn(SysBusDevice *dev)
+static void i440fx_pcihost_initfn(Object *obj)
+{
+    PCIHostState *s = PCI_HOST_BRIDGE(obj);
+
+    memory_region_init_io(&s->conf_mem, obj, &pci_host_conf_le_ops, s,
+                          "pci-conf-idx", 4);
+    memory_region_init_io(&s->data_mem, obj, &pci_host_data_le_ops, s,
+                          "pci-conf-data", 4);
+}
+
+static void i440fx_pcihost_realize(DeviceState *dev, Error **errp)
 {
     PCIHostState *s = PCI_HOST_BRIDGE(dev);
+    SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
 
-    memory_region_init_io(&s->conf_mem, OBJECT(dev), &pci_host_conf_le_ops, s,
-                          "pci-conf-idx", 4);
-    sysbus_add_io(dev, 0xcf8, &s->conf_mem);
-    sysbus_init_ioports(&s->busdev, 0xcf8, 4);
+    sysbus_add_io(sbd, 0xcf8, &s->conf_mem);
+    sysbus_init_ioports(sbd, 0xcf8, 4);
 
-    memory_region_init_io(&s->data_mem, OBJECT(dev), &pci_host_data_le_ops, s,
-                          "pci-conf-data", 4);
-    sysbus_add_io(dev, 0xcfc, &s->data_mem);
-    sysbus_init_ioports(&s->busdev, 0xcfc, 4);
-
-    return 0;
+    sysbus_add_io(sbd, 0xcfc, &s->data_mem);
+    sysbus_init_ioports(sbd, 0xcfc, 4);
 }
 
 static int i440fx_initfn(PCIDevice *dev)
 {
     PCII440FXState *d = I440FX_PCI_DEVICE(dev);
 
-    d->dev.config[I440FX_SMRAM] = 0x02;
+    dev->config[I440FX_SMRAM] = 0x02;
 
     cpu_smm_register(&i440fx_set_smm, d);
     return 0;
@@ -305,9 +316,10 @@
     *piix3_devfn = piix3->dev.devfn;
 
     ram_size = ram_size / 8 / 1024 / 1024;
-    if (ram_size > 255)
+    if (ram_size > 255) {
         ram_size = 255;
-    (*pi440fx_state)->dev.config[0x57]=ram_size;
+    }
+    d->config[0x57] = ram_size;
 
     i440fx_update_memory_mappings(f);
 
@@ -640,11 +652,10 @@
 static void i440fx_pcihost_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
-    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
     PCIHostBridgeClass *hc = PCI_HOST_BRIDGE_CLASS(klass);
 
     hc->root_bus_path = i440fx_pcihost_root_bus_path;
-    k->init = i440fx_pcihost_initfn;
+    dc->realize = i440fx_pcihost_realize;
     dc->fw_name = "pci";
     dc->no_user = 1;
 }
@@ -653,6 +664,7 @@
     .name          = "i440FX-pcihost",
     .parent        = TYPE_PCI_HOST_BRIDGE,
     .instance_size = sizeof(I440FXState),
+    .instance_init = i440fx_pcihost_initfn,
     .class_init    = i440fx_pcihost_class_init,
 };
 
diff --git a/hw/pci-host/q35.c b/hw/pci-host/q35.c
index 8c3ee53..6b1b3b7 100644
--- a/hw/pci-host/q35.c
+++ b/hw/pci-host/q35.c
@@ -34,33 +34,27 @@
  * Q35 host
  */
 
-static int q35_host_init(SysBusDevice *dev)
+static void q35_host_realize(DeviceState *dev, Error **errp)
 {
-    PCIBus *b;
-    PCIHostState *pci = FROM_SYSBUS(PCIHostState, dev);
-    Q35PCIHost *s = Q35_HOST_DEVICE(&dev->qdev);
+    PCIHostState *pci = PCI_HOST_BRIDGE(dev);
+    Q35PCIHost *s = Q35_HOST_DEVICE(dev);
+    SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
 
-    memory_region_init_io(&pci->conf_mem, OBJECT(pci), &pci_host_conf_le_ops, pci,
-                          "pci-conf-idx", 4);
-    sysbus_add_io(dev, MCH_HOST_BRIDGE_CONFIG_ADDR, &pci->conf_mem);
-    sysbus_init_ioports(&pci->busdev, MCH_HOST_BRIDGE_CONFIG_ADDR, 4);
+    sysbus_add_io(sbd, MCH_HOST_BRIDGE_CONFIG_ADDR, &pci->conf_mem);
+    sysbus_init_ioports(sbd, MCH_HOST_BRIDGE_CONFIG_ADDR, 4);
 
-    memory_region_init_io(&pci->data_mem, OBJECT(pci), &pci_host_data_le_ops, pci,
-                          "pci-conf-data", 4);
-    sysbus_add_io(dev, MCH_HOST_BRIDGE_CONFIG_DATA, &pci->data_mem);
-    sysbus_init_ioports(&pci->busdev, MCH_HOST_BRIDGE_CONFIG_DATA, 4);
+    sysbus_add_io(sbd, MCH_HOST_BRIDGE_CONFIG_DATA, &pci->data_mem);
+    sysbus_init_ioports(sbd, MCH_HOST_BRIDGE_CONFIG_DATA, 4);
 
-    if (pcie_host_init(&s->host) < 0) {
-        return -1;
+    if (pcie_host_init(PCIE_HOST_BRIDGE(s)) < 0) {
+        error_setg(errp, "failed to initialize pcie host");
+        return;
     }
-    b = pci_bus_new(&s->host.pci.busdev.qdev, "pcie.0",
-                    s->mch.pci_address_space, s->mch.address_space_io,
-                    0, TYPE_PCIE_BUS);
-    s->host.pci.bus = b;
-    qdev_set_parent_bus(DEVICE(&s->mch), BUS(b));
+    pci->bus = pci_bus_new(DEVICE(s), "pcie.0",
+                           s->mch.pci_address_space, s->mch.address_space_io,
+                           0, TYPE_PCIE_BUS);
+    qdev_set_parent_bus(DEVICE(&s->mch), BUS(pci->bus));
     qdev_init_nofail(DEVICE(&s->mch));
-
-    return 0;
 }
 
 static const char *q35_host_root_bus_path(PCIHostState *host_bridge,
@@ -71,7 +65,7 @@
 }
 
 static Property mch_props[] = {
-    DEFINE_PROP_UINT64("MCFG", Q35PCIHost, host.base_addr,
+    DEFINE_PROP_UINT64("MCFG", Q35PCIHost, parent_obj.base_addr,
                         MCH_HOST_BRIDGE_PCIEXBAR_DEFAULT),
     DEFINE_PROP_END_OF_LIST(),
 };
@@ -79,11 +73,10 @@
 static void q35_host_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
-    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
     PCIHostBridgeClass *hc = PCI_HOST_BRIDGE_CLASS(klass);
 
     hc->root_bus_path = q35_host_root_bus_path;
-    k->init = q35_host_init;
+    dc->realize = q35_host_realize;
     dc->props = mch_props;
     dc->fw_name = "pci";
 }
@@ -91,6 +84,12 @@
 static void q35_host_initfn(Object *obj)
 {
     Q35PCIHost *s = Q35_HOST_DEVICE(obj);
+    PCIHostState *phb = PCI_HOST_BRIDGE(obj);
+
+    memory_region_init_io(&phb->conf_mem, obj, &pci_host_conf_le_ops, phb,
+                          "pci-conf-idx", 4);
+    memory_region_init_io(&phb->data_mem, obj, &pci_host_data_le_ops, phb,
+                          "pci-conf-data", 4);
 
     object_initialize(&s->mch, TYPE_MCH_PCI_DEVICE);
     object_property_add_child(OBJECT(s), "mch", OBJECT(&s->mch), NULL);
@@ -113,10 +112,9 @@
 /* PCIe MMCFG */
 static void mch_update_pciexbar(MCHPCIState *mch)
 {
-    PCIDevice *pci_dev = &mch->d;
-    BusState *bus = qdev_get_parent_bus(&pci_dev->qdev);
-    DeviceState *qdev = bus->parent;
-    Q35PCIHost *s = Q35_HOST_DEVICE(qdev);
+    PCIDevice *pci_dev = PCI_DEVICE(mch);
+    BusState *bus = qdev_get_parent_bus(DEVICE(mch));
+    PCIExpressHost *pehb = PCIE_HOST_BRIDGE(bus->parent);
 
     uint64_t pciexbar;
     int enable;
@@ -148,18 +146,19 @@
         break;
     }
     addr = pciexbar & addr_mask;
-    pcie_host_mmcfg_update(&s->host, enable, addr, length);
+    pcie_host_mmcfg_update(pehb, enable, addr, length);
 }
 
 /* PAM */
 static void mch_update_pam(MCHPCIState *mch)
 {
+    PCIDevice *pd = PCI_DEVICE(mch);
     int i;
 
     memory_region_transaction_begin();
     for (i = 0; i < 13; i++) {
         pam_update(&mch->pam_regions[i], i,
-                   mch->d.config[MCH_HOST_BRIDGE_PAM0 + ((i + 1) / 2)]);
+                   pd->config[MCH_HOST_BRIDGE_PAM0 + ((i + 1) / 2)]);
     }
     memory_region_transaction_commit();
 }
@@ -167,8 +166,10 @@
 /* SMRAM */
 static void mch_update_smram(MCHPCIState *mch)
 {
+    PCIDevice *pd = PCI_DEVICE(mch);
+
     memory_region_transaction_begin();
-    smram_update(&mch->smram_region, mch->d.config[MCH_HOST_BRDIGE_SMRAM],
+    smram_update(&mch->smram_region, pd->config[MCH_HOST_BRDIGE_SMRAM],
                     mch->smm_enabled);
     memory_region_transaction_commit();
 }
@@ -176,9 +177,10 @@
 static void mch_set_smm(int smm, void *arg)
 {
     MCHPCIState *mch = arg;
+    PCIDevice *pd = PCI_DEVICE(mch);
 
     memory_region_transaction_begin();
-    smram_set_smm(&mch->smm_enabled, smm, mch->d.config[MCH_HOST_BRDIGE_SMRAM],
+    smram_set_smm(&mch->smm_enabled, smm, pd->config[MCH_HOST_BRDIGE_SMRAM],
                     &mch->smram_region);
     memory_region_transaction_commit();
 }
@@ -228,7 +230,7 @@
     .minimum_version_id_old = 1,
     .post_load = mch_post_load,
     .fields = (VMStateField []) {
-        VMSTATE_PCI_DEVICE(d, MCHPCIState),
+        VMSTATE_PCI_DEVICE(parent_obj, MCHPCIState),
         VMSTATE_UINT8(smm_enabled, MCHPCIState),
         VMSTATE_END_OF_LIST()
     }
diff --git a/hw/pci/pci-hotplug-old.c b/hw/pci/pci-hotplug-old.c
index 8077289..619fe47 100644
--- a/hw/pci/pci-hotplug-old.c
+++ b/hw/pci/pci-hotplug-old.c
@@ -127,7 +127,7 @@
     dinfo->unit = qemu_opt_get_number(dinfo->opts, "unit", -1);
     dinfo->bus = scsibus->busnr;
     scsidev = scsi_bus_legacy_add_drive(scsibus, dinfo->bdrv, dinfo->unit,
-                                        false, -1, NULL);
+                                        false, -1, NULL, NULL);
     if (!scsidev) {
         return -1;
     }
diff --git a/hw/scsi/esp-pci.c b/hw/scsi/esp-pci.c
index 8f97c5a..2ac21d4 100644
--- a/hw/scsi/esp-pci.c
+++ b/hw/scsi/esp-pci.c
@@ -31,6 +31,9 @@
 
 #define TYPE_AM53C974_DEVICE "am53c974"
 
+#define PCI_ESP(obj) \
+    OBJECT_CHECK(PCIESPState, (obj), TYPE_AM53C974_DEVICE)
+
 #define DMA_CMD   0x0
 #define DMA_STC   0x1
 #define DMA_SPA   0x2
@@ -57,7 +60,10 @@
 #define SBAC_STATUS 0x1000
 
 typedef struct PCIESPState {
-    PCIDevice dev;
+    /*< private >*/
+    PCIDevice parent_obj;
+    /*< public >*/
+
     MemoryRegion io;
     uint32_t dma_regs[8];
     uint32_t sbac;
@@ -257,7 +263,7 @@
         len = pci->dma_regs[DMA_WBC];
     }
 
-    pci_dma_rw(&pci->dev, addr, buf, len, dir);
+    pci_dma_rw(PCI_DEVICE(pci), addr, buf, len, dir);
 
     /* update status registers */
     pci->dma_regs[DMA_WBC] -= len;
@@ -288,7 +294,7 @@
 
 static void esp_pci_hard_reset(DeviceState *dev)
 {
-    PCIESPState *pci = DO_UPCAST(PCIESPState, dev.qdev, dev);
+    PCIESPState *pci = PCI_ESP(dev);
     esp_hard_reset(&pci->esp);
     pci->dma_regs[DMA_CMD] &= ~(DMA_CMD_DIR | DMA_CMD_INTE_D | DMA_CMD_INTE_P
                               | DMA_CMD_MDL | DMA_CMD_DIAG | DMA_CMD_MASK);
@@ -306,7 +312,7 @@
     .minimum_version_id = 0,
     .minimum_version_id_old = 0,
     .fields = (VMStateField[]) {
-        VMSTATE_PCI_DEVICE(dev, PCIESPState),
+        VMSTATE_PCI_DEVICE(parent_obj, PCIESPState),
         VMSTATE_BUFFER_UNSAFE(dma_regs, PCIESPState, 0, 8 * sizeof(uint32_t)),
         VMSTATE_STRUCT(esp, PCIESPState, 0, vmstate_esp, ESPState),
         VMSTATE_END_OF_LIST()
@@ -336,11 +342,13 @@
 
 static int esp_pci_scsi_init(PCIDevice *dev)
 {
-    PCIESPState *pci = DO_UPCAST(PCIESPState, dev, dev);
+    PCIESPState *pci = PCI_ESP(dev);
+    DeviceState *d = DEVICE(dev);
     ESPState *s = &pci->esp;
     uint8_t *pci_conf;
+    Error *err = NULL;
 
-    pci_conf = pci->dev.config;
+    pci_conf = dev->config;
 
     /* Interrupt pin A */
     pci_conf[PCI_INTERRUPT_PIN] = 0x01;
@@ -352,19 +360,23 @@
     memory_region_init_io(&pci->io, OBJECT(pci), &esp_pci_io_ops, pci,
                           "esp-io", 0x80);
 
-    pci_register_bar(&pci->dev, 0, PCI_BASE_ADDRESS_SPACE_IO, &pci->io);
-    s->irq = pci->dev.irq[0];
+    pci_register_bar(dev, 0, PCI_BASE_ADDRESS_SPACE_IO, &pci->io);
+    s->irq = dev->irq[0];
 
-    scsi_bus_new(&s->bus, &dev->qdev, &esp_pci_scsi_info, NULL);
-    if (!dev->qdev.hotplugged) {
-        return scsi_bus_legacy_handle_cmdline(&s->bus);
+    scsi_bus_new(&s->bus, d, &esp_pci_scsi_info, NULL);
+    if (!d->hotplugged) {
+        scsi_bus_legacy_handle_cmdline(&s->bus, &err);
+        if (err != NULL) {
+            error_free(err);
+            return -1;
+        }
     }
     return 0;
 }
 
 static void esp_pci_scsi_uninit(PCIDevice *d)
 {
-    PCIESPState *pci = DO_UPCAST(PCIESPState, dev, d);
+    PCIESPState *pci = PCI_ESP(d);
 
     memory_region_destroy(&pci->io);
 }
diff --git a/hw/scsi/esp.c b/hw/scsi/esp.c
index c6166c5..94639b8 100644
--- a/hw/scsi/esp.c
+++ b/hw/scsi/esp.c
@@ -578,8 +578,14 @@
     }
 };
 
+#define TYPE_ESP "esp"
+#define ESP(obj) OBJECT_CHECK(SysBusESPState, (obj), TYPE_ESP)
+
 typedef struct {
-    SysBusDevice busdev;
+    /*< private >*/
+    SysBusDevice parent_obj;
+    /*< public >*/
+
     MemoryRegion iomem;
     uint32_t it_shift;
     ESPState esp;
@@ -623,8 +629,8 @@
     SysBusESPState *sysbus;
     ESPState *esp;
 
-    dev = qdev_create(NULL, "esp");
-    sysbus = DO_UPCAST(SysBusESPState, busdev.qdev, dev);
+    dev = qdev_create(NULL, TYPE_ESP);
+    sysbus = ESP(dev);
     esp = &sysbus->esp;
     esp->dma_memory_read = dma_memory_read;
     esp->dma_memory_write = dma_memory_write;
@@ -652,8 +658,7 @@
 
 static void sysbus_esp_gpio_demux(void *opaque, int irq, int level)
 {
-    DeviceState *d = opaque;
-    SysBusESPState *sysbus = container_of(d, SysBusESPState, busdev.qdev);
+    SysBusESPState *sysbus = ESP(opaque);
     ESPState *s = &sysbus->esp;
 
     switch (irq) {
@@ -666,28 +671,34 @@
     }
 }
 
-static int sysbus_esp_init(SysBusDevice *dev)
+static void sysbus_esp_realize(DeviceState *dev, Error **errp)
 {
-    SysBusESPState *sysbus = FROM_SYSBUS(SysBusESPState, dev);
+    SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
+    SysBusESPState *sysbus = ESP(dev);
     ESPState *s = &sysbus->esp;
+    Error *err = NULL;
 
-    sysbus_init_irq(dev, &s->irq);
+    sysbus_init_irq(sbd, &s->irq);
     assert(sysbus->it_shift != -1);
 
     s->chip_id = TCHI_FAS100A;
     memory_region_init_io(&sysbus->iomem, OBJECT(sysbus), &sysbus_esp_mem_ops,
                           sysbus, "esp", ESP_REGS << sysbus->it_shift);
-    sysbus_init_mmio(dev, &sysbus->iomem);
+    sysbus_init_mmio(sbd, &sysbus->iomem);
 
-    qdev_init_gpio_in(&dev->qdev, sysbus_esp_gpio_demux, 2);
+    qdev_init_gpio_in(dev, sysbus_esp_gpio_demux, 2);
 
-    scsi_bus_new(&s->bus, &dev->qdev, &esp_scsi_info, NULL);
-    return scsi_bus_legacy_handle_cmdline(&s->bus);
+    scsi_bus_new(&s->bus, dev, &esp_scsi_info, NULL);
+    scsi_bus_legacy_handle_cmdline(&s->bus, &err);
+    if (err != NULL) {
+        error_propagate(errp, err);
+        return;
+    }
 }
 
 static void sysbus_esp_hard_reset(DeviceState *dev)
 {
-    SysBusESPState *sysbus = DO_UPCAST(SysBusESPState, busdev.qdev, dev);
+    SysBusESPState *sysbus = ESP(dev);
     esp_hard_reset(&sysbus->esp);
 }
 
@@ -705,15 +716,14 @@
 static void sysbus_esp_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
-    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
 
-    k->init = sysbus_esp_init;
+    dc->realize = sysbus_esp_realize;
     dc->reset = sysbus_esp_hard_reset;
     dc->vmsd = &vmstate_sysbus_esp_scsi;
 }
 
 static const TypeInfo sysbus_esp_info = {
-    .name          = "esp",
+    .name          = TYPE_ESP,
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(SysBusESPState),
     .class_init    = sysbus_esp_class_init,
diff --git a/hw/scsi/lsi53c895a.c b/hw/scsi/lsi53c895a.c
index 2c17ae5..776e31a 100644
--- a/hw/scsi/lsi53c895a.c
+++ b/hw/scsi/lsi53c895a.c
@@ -184,7 +184,10 @@
 } lsi_request;
 
 typedef struct {
-    PCIDevice dev;
+    /*< private >*/
+    PCIDevice parent_obj;
+    /*< public >*/
+
     MemoryRegion mmio_io;
     MemoryRegion ram_io;
     MemoryRegion io_io;
@@ -275,6 +278,11 @@
     uint32_t script_ram[2048];
 } LSIState;
 
+#define TYPE_LSI53C895A "lsi53c895a"
+
+#define LSI53C895A(obj) \
+    OBJECT_CHECK(LSIState, (obj), TYPE_LSI53C895A)
+
 static inline int lsi_irq_on_rsl(LSIState *s)
 {
     return (s->sien0 & LSI_SIST0_RSL) && (s->scid & LSI_SCID_RRE);
@@ -382,7 +390,7 @@
 {
     uint32_t buf;
 
-    pci_dma_read(&s->dev, addr, &buf, 4);
+    pci_dma_read(PCI_DEVICE(s), addr, &buf, 4);
     return cpu_to_le32(buf);
 }
 
@@ -393,6 +401,7 @@
 
 static void lsi_update_irq(LSIState *s)
 {
+    PCIDevice *d = PCI_DEVICE(s);
     int level;
     static int last_level;
     lsi_request *p;
@@ -424,7 +433,7 @@
                 level, s->dstat, s->sist1, s->sist0);
         last_level = level;
     }
-    qemu_set_irq(s->dev.irq[0], level);
+    qemu_set_irq(d->irq[0], level);
 
     if (!level && lsi_irq_on_rsl(s) && !(s->scntl1 & LSI_SCNTL1_CON)) {
         DPRINTF("Handled IRQs & disconnected, looking for pending "
@@ -520,6 +529,7 @@
 /* Initiate a SCSI layer data transfer.  */
 static void lsi_do_dma(LSIState *s, int out)
 {
+    PCIDevice *pci_dev;
     uint32_t count;
     dma_addr_t addr;
     SCSIDevice *dev;
@@ -531,6 +541,7 @@
         return;
     }
 
+    pci_dev = PCI_DEVICE(s);
     dev = s->current->req->dev;
     assert(dev);
 
@@ -556,9 +567,9 @@
     }
     /* ??? Set SFBR to first data byte.  */
     if (out) {
-        pci_dma_read(&s->dev, addr, s->current->dma_buf, count);
+        pci_dma_read(pci_dev, addr, s->current->dma_buf, count);
     } else {
-        pci_dma_write(&s->dev, addr, s->current->dma_buf, count);
+        pci_dma_write(pci_dev, addr, s->current->dma_buf, count);
     }
     s->current->dma_len -= count;
     if (s->current->dma_len == 0) {
@@ -653,7 +664,7 @@
 
 static void lsi_request_cancelled(SCSIRequest *req)
 {
-    LSIState *s = DO_UPCAST(LSIState, dev.qdev, req->bus->qbus.parent);
+    LSIState *s = LSI53C895A(req->bus->qbus.parent);
     lsi_request *p = req->hba_private;
 
     req->hba_private = NULL;
@@ -692,7 +703,7 @@
  /* Callback to indicate that the SCSI layer has completed a command.  */
 static void lsi_command_complete(SCSIRequest *req, uint32_t status, size_t resid)
 {
-    LSIState *s = DO_UPCAST(LSIState, dev.qdev, req->bus->qbus.parent);
+    LSIState *s = LSI53C895A(req->bus->qbus.parent);
     int out;
 
     out = (s->sstat1 & PHASE_MASK) == PHASE_DO;
@@ -717,7 +728,7 @@
  /* Callback to indicate that the SCSI layer has completed a transfer.  */
 static void lsi_transfer_data(SCSIRequest *req, uint32_t len)
 {
-    LSIState *s = DO_UPCAST(LSIState, dev.qdev, req->bus->qbus.parent);
+    LSIState *s = LSI53C895A(req->bus->qbus.parent);
     int out;
 
     assert(req->hba_private);
@@ -753,7 +764,7 @@
     DPRINTF("Send command len=%d\n", s->dbc);
     if (s->dbc > 16)
         s->dbc = 16;
-    pci_dma_read(&s->dev, s->dnad, buf, s->dbc);
+    pci_dma_read(PCI_DEVICE(s), s->dnad, buf, s->dbc);
     s->sfbr = buf[0];
     s->command_complete = 0;
 
@@ -804,7 +815,7 @@
     s->dbc = 1;
     status = s->status;
     s->sfbr = status;
-    pci_dma_write(&s->dev, s->dnad, &status, 1);
+    pci_dma_write(PCI_DEVICE(s), s->dnad, &status, 1);
     lsi_set_phase(s, PHASE_MI);
     s->msg_action = 1;
     lsi_add_msg_byte(s, 0); /* COMMAND COMPLETE */
@@ -818,7 +829,7 @@
     len = s->msg_len;
     if (len > s->dbc)
         len = s->dbc;
-    pci_dma_write(&s->dev, s->dnad, s->msg, len);
+    pci_dma_write(PCI_DEVICE(s), s->dnad, s->msg, len);
     /* Linux drivers rely on the last byte being in the SIDL.  */
     s->sidl = s->msg[len - 1];
     s->msg_len -= len;
@@ -850,7 +861,7 @@
 static uint8_t lsi_get_msgbyte(LSIState *s)
 {
     uint8_t data;
-    pci_dma_read(&s->dev, s->dnad, &data, 1);
+    pci_dma_read(PCI_DEVICE(s), s->dnad, &data, 1);
     s->dnad++;
     s->dbc--;
     return data;
@@ -996,14 +1007,15 @@
 #define LSI_BUF_SIZE 4096
 static void lsi_memcpy(LSIState *s, uint32_t dest, uint32_t src, int count)
 {
+    PCIDevice *d = PCI_DEVICE(s);
     int n;
     uint8_t buf[LSI_BUF_SIZE];
 
     DPRINTF("memcpy dest 0x%08x src 0x%08x count %d\n", dest, src, count);
     while (count) {
         n = (count > LSI_BUF_SIZE) ? LSI_BUF_SIZE : count;
-        pci_dma_read(&s->dev, src, buf, n);
-        pci_dma_write(&s->dev, dest, buf, n);
+        pci_dma_read(d, src, buf, n);
+        pci_dma_write(d, dest, buf, n);
         src += n;
         dest += n;
         count -= n;
@@ -1029,6 +1041,7 @@
 
 static void lsi_execute_script(LSIState *s)
 {
+    PCIDevice *pci_dev = PCI_DEVICE(s);
     uint32_t insn;
     uint32_t addr, addr_high;
     int opcode;
@@ -1071,7 +1084,7 @@
 
             /* 32-bit Table indirect */
             offset = sxt24(addr);
-            pci_dma_read(&s->dev, s->dsa + offset, buf, 8);
+            pci_dma_read(pci_dev, s->dsa + offset, buf, 8);
             /* byte count is stored in bits 0:23 only */
             s->dbc = cpu_to_le32(buf[0]) & 0xffffff;
             s->rbc = s->dbc;
@@ -1430,7 +1443,7 @@
             n = (insn & 7);
             reg = (insn >> 16) & 0xff;
             if (insn & (1 << 24)) {
-                pci_dma_read(&s->dev, addr, data, n);
+                pci_dma_read(pci_dev, addr, data, n);
                 DPRINTF("Load reg 0x%x size %d addr 0x%08x = %08x\n", reg, n,
                         addr, *(int *)data);
                 for (i = 0; i < n; i++) {
@@ -1441,7 +1454,7 @@
                 for (i = 0; i < n; i++) {
                     data[i] = lsi_reg_readb(s, reg + i);
                 }
-                pci_dma_write(&s->dev, addr, data, n);
+                pci_dma_write(pci_dev, addr, data, n);
             }
         }
     }
@@ -1726,7 +1739,7 @@
             lsi_execute_script(s);
         }
         if (val & LSI_ISTAT0_SRST) {
-            qdev_reset_all(&s->dev.qdev);
+            qdev_reset_all(DEVICE(s));
         }
         break;
     case 0x16: /* MBOX0 */
@@ -1960,7 +1973,7 @@
 
 static void lsi_scsi_reset(DeviceState *dev)
 {
-    LSIState *s = DO_UPCAST(LSIState, dev.qdev, dev);
+    LSIState *s = LSI53C895A(dev);
 
     lsi_soft_reset(s);
 }
@@ -1983,7 +1996,7 @@
     .minimum_version_id_old = 0,
     .pre_save = lsi_pre_save,
     .fields      = (VMStateField []) {
-        VMSTATE_PCI_DEVICE(dev, LSIState),
+        VMSTATE_PCI_DEVICE(parent_obj, LSIState),
 
         VMSTATE_INT32(carry, LSIState),
         VMSTATE_INT32(status, LSIState),
@@ -2061,7 +2074,7 @@
 
 static void lsi_scsi_uninit(PCIDevice *d)
 {
-    LSIState *s = DO_UPCAST(LSIState, dev, d);
+    LSIState *s = LSI53C895A(d);
 
     memory_region_destroy(&s->mmio_io);
     memory_region_destroy(&s->ram_io);
@@ -2080,10 +2093,12 @@
 
 static int lsi_scsi_init(PCIDevice *dev)
 {
-    LSIState *s = DO_UPCAST(LSIState, dev, dev);
+    LSIState *s = LSI53C895A(dev);
+    DeviceState *d = DEVICE(dev);
     uint8_t *pci_conf;
+    Error *err = NULL;
 
-    pci_conf = s->dev.config;
+    pci_conf = dev->config;
 
     /* PCI latency timer = 255 */
     pci_conf[PCI_LATENCY_TIMER] = 0xff;
@@ -2097,14 +2112,18 @@
     memory_region_init_io(&s->io_io, OBJECT(s), &lsi_io_ops, s,
                           "lsi-io", 256);
 
-    pci_register_bar(&s->dev, 0, PCI_BASE_ADDRESS_SPACE_IO, &s->io_io);
-    pci_register_bar(&s->dev, 1, 0, &s->mmio_io);
-    pci_register_bar(&s->dev, 2, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->ram_io);
+    pci_register_bar(dev, 0, PCI_BASE_ADDRESS_SPACE_IO, &s->io_io);
+    pci_register_bar(dev, 1, 0, &s->mmio_io);
+    pci_register_bar(dev, 2, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->ram_io);
     QTAILQ_INIT(&s->queue);
 
-    scsi_bus_new(&s->bus, &dev->qdev, &lsi_scsi_info, NULL);
-    if (!dev->qdev.hotplugged) {
-        return scsi_bus_legacy_handle_cmdline(&s->bus);
+    scsi_bus_new(&s->bus, d, &lsi_scsi_info, NULL);
+    if (!d->hotplugged) {
+        scsi_bus_legacy_handle_cmdline(&s->bus, &err);
+        if (err != NULL) {
+            error_free(err);
+            return -1;
+        }
     }
     return 0;
 }
@@ -2125,7 +2144,7 @@
 }
 
 static const TypeInfo lsi_info = {
-    .name          = "lsi53c895a",
+    .name          = TYPE_LSI53C895A,
     .parent        = TYPE_PCI_DEVICE,
     .instance_size = sizeof(LSIState),
     .class_init    = lsi_class_init,
diff --git a/hw/scsi/megasas.c b/hw/scsi/megasas.c
index 45d0c77..eb52164 100644
--- a/hw/scsi/megasas.c
+++ b/hw/scsi/megasas.c
@@ -70,7 +70,10 @@
 } MegasasCmd;
 
 typedef struct MegasasState {
-    PCIDevice dev;
+    /*< private >*/
+    PCIDevice parent_obj;
+    /*< public >*/
+
     MemoryRegion mmio_io;
     MemoryRegion port_io;
     MemoryRegion queue_io;
@@ -108,6 +111,11 @@
     SCSIBus bus;
 } MegasasState;
 
+#define TYPE_MEGASAS "megasas"
+
+#define MEGASAS(obj) \
+    OBJECT_CHECK(MegasasState, (obj), TYPE_MEGASAS)
+
 #define MEGASAS_INTR_DISABLED_MASK 0xFFFFFFFF
 
 static bool megasas_intr_enabled(MegasasState *s)
@@ -232,7 +240,7 @@
                                          MEGASAS_MAX_SGE);
         return iov_count;
     }
-    pci_dma_sglist_init(&cmd->qsg, &s->dev, iov_count);
+    pci_dma_sglist_init(&cmd->qsg, PCI_DEVICE(s), iov_count);
     for (i = 0; i < iov_count; i++) {
         dma_addr_t iov_pa, iov_size_p;
 
@@ -493,6 +501,7 @@
 
 static void megasas_complete_frame(MegasasState *s, uint64_t context)
 {
+    PCIDevice *pci_dev = PCI_DEVICE(s);
     int tail, queue_offset;
 
     /* Decrement busy count */
@@ -521,12 +530,12 @@
         /* Notify HBA */
         s->doorbell++;
         if (s->doorbell == 1) {
-            if (msix_enabled(&s->dev)) {
+            if (msix_enabled(pci_dev)) {
                 trace_megasas_msix_raise(0);
-                msix_notify(&s->dev, 0);
+                msix_notify(pci_dev, 0);
             } else {
                 trace_megasas_irq_raise();
-                qemu_irq_raise(s->dev.irq[0]);
+                qemu_irq_raise(pci_dev->irq[0]);
             }
         }
     } else {
@@ -628,7 +637,7 @@
     }
     iov_pa = megasas_sgl_get_addr(cmd, &cmd->frame->dcmd.sgl);
     iov_size = megasas_sgl_get_len(cmd, &cmd->frame->dcmd.sgl);
-    pci_dma_sglist_init(&cmd->qsg, &s->dev, 1);
+    pci_dma_sglist_init(&cmd->qsg, PCI_DEVICE(s), 1);
     qemu_sglist_add(&cmd->qsg, iov_pa, iov_size);
     cmd->iov_size = iov_size;
     return cmd->iov_size;
@@ -655,6 +664,7 @@
 
 static int megasas_ctrl_get_info(MegasasState *s, MegasasCmd *cmd)
 {
+    PCIDevice *pci_dev = PCI_DEVICE(s);
     struct mfi_ctrl_info info;
     size_t dcmd_size = sizeof(info);
     BusChild *kid;
@@ -705,11 +715,11 @@
     memcpy(info.image_component[0].build_date, __DATE__, 11);
     memcpy(info.image_component[0].build_time, __TIME__, 8);
     info.image_component_count = 1;
-    if (s->dev.has_rom) {
+    if (pci_dev->has_rom) {
         uint8_t biosver[32];
         uint8_t *ptr;
 
-        ptr = memory_region_get_ram_ptr(&s->dev.rom);
+        ptr = memory_region_get_ram_ptr(&pci_dev->rom);
         memcpy(biosver, ptr + 0x41, 31);
         memcpy(info.image_component[1].name, "BIOS", 4);
         memcpy(info.image_component[1].version, biosver,
@@ -1900,6 +1910,7 @@
                                uint64_t val, unsigned size)
 {
     MegasasState *s = opaque;
+    PCIDevice *pci_dev = PCI_DEVICE(s);
     uint64_t frame_addr;
     uint32_t frame_count;
     int i;
@@ -1923,9 +1934,9 @@
         break;
     case MFI_OMSK:
         s->intr_mask = val;
-        if (!megasas_intr_enabled(s) && !msix_enabled(&s->dev)) {
+        if (!megasas_intr_enabled(s) && !msix_enabled(pci_dev)) {
             trace_megasas_irq_lower();
-            qemu_irq_lower(s->dev.irq[0]);
+            qemu_irq_lower(pci_dev->irq[0]);
         }
         if (megasas_intr_enabled(s)) {
             trace_megasas_intr_enabled();
@@ -1939,9 +1950,9 @@
             /* Update reply queue pointer */
             trace_megasas_qf_update(s->reply_queue_head, s->busy);
             stl_le_phys(s->producer_pa, s->reply_queue_head);
-            if (!msix_enabled(&s->dev)) {
+            if (!msix_enabled(pci_dev)) {
                 trace_megasas_irq_lower();
-                qemu_irq_lower(s->dev.irq[0]);
+                qemu_irq_lower(pci_dev->irq[0]);
             }
         }
         break;
@@ -2039,7 +2050,7 @@
 
 static void megasas_scsi_reset(DeviceState *dev)
 {
-    MegasasState *s = DO_UPCAST(MegasasState, dev.qdev, dev);
+    MegasasState *s = MEGASAS(dev);
 
     megasas_soft_reset(s);
 }
@@ -2050,7 +2061,7 @@
     .minimum_version_id = 0,
     .minimum_version_id_old = 0,
     .fields      = (VMStateField[]) {
-        VMSTATE_PCI_DEVICE(dev, MegasasState),
+        VMSTATE_PCI_DEVICE(parent_obj, MegasasState),
 
         VMSTATE_INT32(fw_state, MegasasState),
         VMSTATE_INT32(intr_mask, MegasasState),
@@ -2064,10 +2075,10 @@
 
 static void megasas_scsi_uninit(PCIDevice *d)
 {
-    MegasasState *s = DO_UPCAST(MegasasState, dev, d);
+    MegasasState *s = MEGASAS(d);
 
 #ifdef USE_MSIX
-    msix_uninit(&s->dev, &s->mmio_io);
+    msix_uninit(d, &s->mmio_io);
 #endif
     memory_region_destroy(&s->mmio_io);
     memory_region_destroy(&s->port_io);
@@ -2087,11 +2098,13 @@
 
 static int megasas_scsi_init(PCIDevice *dev)
 {
-    MegasasState *s = DO_UPCAST(MegasasState, dev, dev);
+    DeviceState *d = DEVICE(dev);
+    MegasasState *s = MEGASAS(dev);
     uint8_t *pci_conf;
     int i, bar_type;
+    Error *err = NULL;
 
-    pci_conf = s->dev.config;
+    pci_conf = dev->config;
 
     /* PCI latency timer = 0 */
     pci_conf[PCI_LATENCY_TIMER] = 0;
@@ -2108,7 +2121,7 @@
 #ifdef USE_MSIX
     /* MSI-X support is currently broken */
     if (megasas_use_msix(s) &&
-        msix_init(&s->dev, 15, &s->mmio_io, 0, 0x2000)) {
+        msix_init(dev, 15, &s->mmio_io, 0, 0x2000)) {
         s->flags &= ~MEGASAS_MASK_USE_MSIX;
     }
 #else
@@ -2116,12 +2129,12 @@
 #endif
 
     bar_type = PCI_BASE_ADDRESS_SPACE_MEMORY | PCI_BASE_ADDRESS_MEM_TYPE_64;
-    pci_register_bar(&s->dev, 0, bar_type, &s->mmio_io);
-    pci_register_bar(&s->dev, 2, PCI_BASE_ADDRESS_SPACE_IO, &s->port_io);
-    pci_register_bar(&s->dev, 3, bar_type, &s->queue_io);
+    pci_register_bar(dev, 0, bar_type, &s->mmio_io);
+    pci_register_bar(dev, 2, PCI_BASE_ADDRESS_SPACE_IO, &s->port_io);
+    pci_register_bar(dev, 3, bar_type, &s->queue_io);
 
     if (megasas_use_msix(s)) {
-        msix_vector_use(&s->dev, 0);
+        msix_vector_use(dev, 0);
     }
 
     if (!s->sas_addr) {
@@ -2158,8 +2171,14 @@
         s->frames[i].state = s;
     }
 
-    scsi_bus_new(&s->bus, &dev->qdev, &megasas_scsi_info, NULL);
-    scsi_bus_legacy_handle_cmdline(&s->bus);
+    scsi_bus_new(&s->bus, DEVICE(dev), &megasas_scsi_info, NULL);
+    if (!d->hotplugged) {
+        scsi_bus_legacy_handle_cmdline(&s->bus, &err);
+        if (err != NULL) {
+            error_free(err);
+            return -1;
+        }
+    }
     return 0;
 }
 
@@ -2198,7 +2217,7 @@
 }
 
 static const TypeInfo megasas_info = {
-    .name  = "megasas",
+    .name  = TYPE_MEGASAS,
     .parent = TYPE_PCI_DEVICE,
     .instance_size = sizeof(MegasasState),
     .class_init = megasas_class_init,
diff --git a/hw/scsi/scsi-bus.c b/hw/scsi/scsi-bus.c
index a92b7c1..b5a863a 100644
--- a/hw/scsi/scsi-bus.c
+++ b/hw/scsi/scsi-bus.c
@@ -209,10 +209,11 @@
 /* handle legacy '-drive if=scsi,...' cmd line args */
 SCSIDevice *scsi_bus_legacy_add_drive(SCSIBus *bus, BlockDriverState *bdrv,
                                       int unit, bool removable, int bootindex,
-                                      const char *serial)
+                                      const char *serial, Error **errp)
 {
     const char *driver;
     DeviceState *dev;
+    Error *err = NULL;
 
     driver = bdrv_is_sg(bdrv) ? "scsi-generic" : "scsi-disk";
     dev = qdev_create(&bus->qbus, driver);
@@ -227,19 +228,25 @@
         qdev_prop_set_string(dev, "serial", serial);
     }
     if (qdev_prop_set_drive(dev, "drive", bdrv) < 0) {
+        error_setg(errp, "Setting drive property failed");
         qdev_free(dev);
         return NULL;
     }
-    if (qdev_init(dev) < 0)
+    object_property_set_bool(OBJECT(dev), true, "realized", &err);
+    if (err != NULL) {
+        error_propagate(errp, err);
+        qdev_free(dev);
         return NULL;
+    }
     return SCSI_DEVICE(dev);
 }
 
-int scsi_bus_legacy_handle_cmdline(SCSIBus *bus)
+void scsi_bus_legacy_handle_cmdline(SCSIBus *bus, Error **errp)
 {
     Location loc;
     DriveInfo *dinfo;
-    int res = 0, unit;
+    int unit;
+    Error *err = NULL;
 
     loc_push_none(&loc);
     for (unit = 0; unit <= bus->info->max_target; unit++) {
@@ -248,13 +255,14 @@
             continue;
         }
         qemu_opts_loc_restore(dinfo->opts);
-        if (!scsi_bus_legacy_add_drive(bus, dinfo->bdrv, unit, false, -1, NULL)) {
-            res = -1;
+        scsi_bus_legacy_add_drive(bus, dinfo->bdrv, unit, false, -1, NULL,
+                                  &err);
+        if (err != NULL) {
+            error_propagate(errp, err);
             break;
         }
     }
     loc_pop(&loc);
-    return res;
 }
 
 static int32_t scsi_invalid_field(SCSIRequest *req, uint8_t *buf)
diff --git a/hw/scsi/spapr_vscsi.c b/hw/scsi/spapr_vscsi.c
index e8978bf..55b44b9 100644
--- a/hw/scsi/spapr_vscsi.c
+++ b/hw/scsi/spapr_vscsi.c
@@ -912,12 +912,17 @@
 static int spapr_vscsi_init(VIOsPAPRDevice *dev)
 {
     VSCSIState *s = VIO_SPAPR_VSCSI_DEVICE(dev);
+    Error *err = NULL;
 
     dev->crq.SendFunc = vscsi_do_crq;
 
     scsi_bus_new(&s->bus, &dev->qdev, &vscsi_scsi_info, NULL);
     if (!dev->qdev.hotplugged) {
-        scsi_bus_legacy_handle_cmdline(&s->bus);
+        scsi_bus_legacy_handle_cmdline(&s->bus, &err);
+        if (err != NULL) {
+            error_free(err);
+            return -1;
+        }
     }
 
     return 0;
diff --git a/hw/scsi/virtio-scsi.c b/hw/scsi/virtio-scsi.c
index 712f0ad..42cb73b 100644
--- a/hw/scsi/virtio-scsi.c
+++ b/hw/scsi/virtio-scsi.c
@@ -619,6 +619,7 @@
     VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(vdev);
     VirtIOSCSI *s = VIRTIO_SCSI(vdev);
     static int virtio_scsi_id;
+    Error *err = NULL;
     int ret;
 
     ret = virtio_scsi_common_init(vs);
@@ -629,7 +630,11 @@
     scsi_bus_new(&s->bus, qdev, &virtio_scsi_scsi_info, vdev->bus_name);
 
     if (!qdev->hotplugged) {
-        scsi_bus_legacy_handle_cmdline(&s->bus);
+        scsi_bus_legacy_handle_cmdline(&s->bus, &err);
+        if (err != NULL) {
+            error_free(err);
+            return -1;
+        }
     }
 
     register_savevm(qdev, "virtio-scsi", virtio_scsi_id++, 1,
diff --git a/hw/scsi/vmw_pvscsi.c b/hw/scsi/vmw_pvscsi.c
index 97d3aa3..e1074e1 100644
--- a/hw/scsi/vmw_pvscsi.c
+++ b/hw/scsi/vmw_pvscsi.c
@@ -1136,7 +1136,7 @@
 }
 
 static const VMStateDescription vmstate_pvscsi = {
-    .name = TYPE_PVSCSI,
+    .name = "pvscsi",
     .version_id = 0,
     .minimum_version_id = 0,
     .minimum_version_id_old = 0,
@@ -1201,7 +1201,7 @@
 }
 
 static const TypeInfo pvscsi_info = {
-    .name          = "pvscsi",
+    .name          = TYPE_PVSCSI,
     .parent        = TYPE_PCI_DEVICE,
     .instance_size = sizeof(PVSCSIState),
     .class_init    = pvscsi_class_init,
diff --git a/hw/timer/hpet.c b/hw/timer/hpet.c
index 90bd584..648b383 100644
--- a/hw/timer/hpet.c
+++ b/hw/timer/hpet.c
@@ -42,6 +42,9 @@
 
 #define HPET_MSI_SUPPORT        0
 
+#define TYPE_HPET "hpet"
+#define HPET(obj) OBJECT_CHECK(HPETState, (obj), TYPE_HPET)
+
 struct HPETState;
 typedef struct HPETTimer {  /* timers */
     uint8_t tn;             /*timer number*/
@@ -59,7 +62,10 @@
 } HPETTimer;
 
 typedef struct HPETState {
-    SysBusDevice busdev;
+    /*< private >*/
+    SysBusDevice parent_obj;
+    /*< public >*/
+
     MemoryRegion iomem;
     uint64_t hpet_offset;
     qemu_irq irqs[HPET_NUM_IRQ_ROUTES];
@@ -634,7 +640,8 @@
 
 static void hpet_reset(DeviceState *d)
 {
-    HPETState *s = FROM_SYSBUS(HPETState, SYS_BUS_DEVICE(d));
+    HPETState *s = HPET(d);
+    SysBusDevice *sbd = SYS_BUS_DEVICE(d);
     int i;
 
     for (i = 0; i < s->num_timers; i++) {
@@ -657,7 +664,7 @@
     s->hpet_offset = 0ULL;
     s->config = 0ULL;
     hpet_cfg.hpet[s->hpet_id].event_timer_block_id = (uint32_t)s->capability;
-    hpet_cfg.hpet[s->hpet_id].address = SYS_BUS_DEVICE(d)->mmio[0].addr;
+    hpet_cfg.hpet[s->hpet_id].address = sbd->mmio[0].addr;
 
     /* to document that the RTC lowers its output on reset as well */
     s->rtc_irq_level = 0;
@@ -665,7 +672,7 @@
 
 static void hpet_handle_legacy_irq(void *opaque, int n, int level)
 {
-    HPETState *s = FROM_SYSBUS(HPETState, opaque);
+    HPETState *s = HPET(opaque);
 
     if (n == HPET_LEGACY_PIT_INT) {
         if (!hpet_in_legacy_mode(s)) {
@@ -679,9 +686,20 @@
     }
 }
 
-static int hpet_init(SysBusDevice *dev)
+static void hpet_init(Object *obj)
 {
-    HPETState *s = FROM_SYSBUS(HPETState, dev);
+    SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
+    HPETState *s = HPET(obj);
+
+    /* HPET Area */
+    memory_region_init_io(&s->iomem, obj, &hpet_ram_ops, s, "hpet", 0x400);
+    sysbus_init_mmio(sbd, &s->iomem);
+}
+
+static void hpet_realize(DeviceState *dev, Error **errp)
+{
+    SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
+    HPETState *s = HPET(dev);
     int i;
     HPETTimer *timer;
 
@@ -691,14 +709,14 @@
     }
 
     if (hpet_cfg.count == 8) {
-        fprintf(stderr, "Only 8 instances of HPET is allowed\n");
-        return -1;
+        error_setg(errp, "Only 8 instances of HPET is allowed");
+        return;
     }
 
     s->hpet_id = hpet_cfg.count++;
 
     for (i = 0; i < HPET_NUM_IRQ_ROUTES; i++) {
-        sysbus_init_irq(dev, &s->irqs[i]);
+        sysbus_init_irq(sbd, &s->irqs[i]);
     }
 
     if (s->num_timers < HPET_MIN_TIMERS) {
@@ -718,13 +736,8 @@
     s->capability |= (s->num_timers - 1) << HPET_ID_NUM_TIM_SHIFT;
     s->capability |= ((HPET_CLK_PERIOD) << 32);
 
-    qdev_init_gpio_in(&dev->qdev, hpet_handle_legacy_irq, 2);
-    qdev_init_gpio_out(&dev->qdev, &s->pit_enabled, 1);
-
-    /* HPET Area */
-    memory_region_init_io(&s->iomem, OBJECT(s), &hpet_ram_ops, s, "hpet", 0x400);
-    sysbus_init_mmio(dev, &s->iomem);
-    return 0;
+    qdev_init_gpio_in(dev, hpet_handle_legacy_irq, 2);
+    qdev_init_gpio_out(dev, &s->pit_enabled, 1);
 }
 
 static Property hpet_device_properties[] = {
@@ -736,9 +749,8 @@
 static void hpet_device_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
-    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
 
-    k->init = hpet_init;
+    dc->realize = hpet_realize;
     dc->no_user = 1;
     dc->reset = hpet_reset;
     dc->vmsd = &vmstate_hpet;
@@ -746,9 +758,10 @@
 }
 
 static const TypeInfo hpet_device_info = {
-    .name          = "hpet",
+    .name          = TYPE_HPET,
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(HPETState),
+    .instance_init = hpet_init,
     .class_init    = hpet_device_class_init,
 };
 
diff --git a/hw/timer/imx_epit.c b/hw/timer/imx_epit.c
index e24e0c4..117dc7b 100644
--- a/hw/timer/imx_epit.c
+++ b/hw/timer/imx_epit.c
@@ -370,7 +370,7 @@
 };
 
 static const VMStateDescription vmstate_imx_timer_epit = {
-    .name = TYPE_IMX_EPIT,
+    .name = "imx.epit",
     .version_id = 2,
     .minimum_version_id = 2,
     .minimum_version_id_old = 2,
diff --git a/hw/timer/imx_gpt.c b/hw/timer/imx_gpt.c
index 97fbebb..87db0e1 100644
--- a/hw/timer/imx_gpt.c
+++ b/hw/timer/imx_gpt.c
@@ -142,7 +142,7 @@
 } IMXGPTState;
 
 static const VMStateDescription vmstate_imx_timer_gpt = {
-    .name = TYPE_IMX_GPT,
+    .name = "imx.gpt",
     .version_id = 3,
     .minimum_version_id = 3,
     .minimum_version_id_old = 3,
diff --git a/hw/usb/ccid-card-passthru.c b/hw/usb/ccid-card-passthru.c
index 01c7e6f..5f01ff1 100644
--- a/hw/usb/ccid-card-passthru.c
+++ b/hw/usb/ccid-card-passthru.c
@@ -364,7 +364,7 @@
 }
 
 static VMStateDescription passthru_vmstate = {
-    .name = PASSTHRU_DEV_NAME,
+    .name = "ccid-card-passthru",
     .version_id = 1,
     .minimum_version_id = 1,
     .fields = (VMStateField[]) {
diff --git a/hw/usb/dev-smartcard-reader.c b/hw/usb/dev-smartcard-reader.c
index 125cc2c..b33eb25 100644
--- a/hw/usb/dev-smartcard-reader.c
+++ b/hw/usb/dev-smartcard-reader.c
@@ -1397,7 +1397,7 @@
 };
 
 static VMStateDescription ccid_vmstate = {
-    .name = CCID_DEV_NAME,
+    .name = "usb-ccid",
     .version_id = 1,
     .minimum_version_id = 1,
     .post_load = ccid_post_load,
diff --git a/hw/usb/dev-storage.c b/hw/usb/dev-storage.c
index fe914ab..1954811 100644
--- a/hw/usb/dev-storage.c
+++ b/hw/usb/dev-storage.c
@@ -595,6 +595,7 @@
     MSDState *s = DO_UPCAST(MSDState, dev, dev);
     BlockDriverState *bs = s->conf.bs;
     SCSIDevice *scsi_dev;
+    Error *err = NULL;
 
     if (!bs) {
         error_report("drive property not set");
@@ -619,7 +620,8 @@
     usb_desc_init(dev);
     scsi_bus_new(&s->bus, &s->dev.qdev, &usb_msd_scsi_info_storage, NULL);
     scsi_dev = scsi_bus_legacy_add_drive(&s->bus, bs, 0, !!s->removable,
-                                            s->conf.bootindex, dev->serial);
+                                         s->conf.bootindex, dev->serial,
+                                         &err);
     if (!scsi_dev) {
         return -1;
     }
diff --git a/hw/usb/hcd-ohci.c b/hw/usb/hcd-ohci.c
index a096ecf..2bab8ff 100644
--- a/hw/usb/hcd-ohci.c
+++ b/hw/usb/hcd-ohci.c
@@ -1843,51 +1843,61 @@
     return 0;
 }
 
+#define TYPE_PCI_OHCI "pci-ohci"
+#define PCI_OHCI(obj) OBJECT_CHECK(OHCIPCIState, (obj), TYPE_PCI_OHCI)
+
 typedef struct {
-    PCIDevice pci_dev;
+    /*< private >*/
+    PCIDevice parent_obj;
+    /*< public >*/
+
     OHCIState state;
     char *masterbus;
     uint32_t num_ports;
     uint32_t firstport;
 } OHCIPCIState;
 
-static int usb_ohci_initfn_pci(struct PCIDevice *dev)
+static int usb_ohci_initfn_pci(PCIDevice *dev)
 {
-    OHCIPCIState *ohci = DO_UPCAST(OHCIPCIState, pci_dev, dev);
+    OHCIPCIState *ohci = PCI_OHCI(dev);
 
-    ohci->pci_dev.config[PCI_CLASS_PROG] = 0x10; /* OHCI */
-    ohci->pci_dev.config[PCI_INTERRUPT_PIN] = 0x01; /* interrupt pin A */
+    dev->config[PCI_CLASS_PROG] = 0x10; /* OHCI */
+    dev->config[PCI_INTERRUPT_PIN] = 0x01; /* interrupt pin A */
 
-    if (usb_ohci_init(&ohci->state, &dev->qdev, ohci->num_ports, 0,
+    if (usb_ohci_init(&ohci->state, DEVICE(dev), ohci->num_ports, 0,
                       ohci->masterbus, ohci->firstport,
                       pci_get_address_space(dev)) != 0) {
         return -1;
     }
-    ohci->state.irq = ohci->pci_dev.irq[0];
+    ohci->state.irq = dev->irq[0];
 
-    /* TODO: avoid cast below by using dev */
-    pci_register_bar(&ohci->pci_dev, 0, 0, &ohci->state.mem);
+    pci_register_bar(dev, 0, 0, &ohci->state.mem);
     return 0;
 }
 
+#define TYPE_SYSBUS_OHCI "sysbus-ohci"
+#define SYSBUS_OHCI(obj) OBJECT_CHECK(OHCISysBusState, (obj), TYPE_SYSBUS_OHCI)
+
 typedef struct {
-    SysBusDevice busdev;
+    /*< private >*/
+    SysBusDevice parent_obj;
+    /*< public >*/
+
     OHCIState ohci;
     uint32_t num_ports;
     dma_addr_t dma_offset;
 } OHCISysBusState;
 
-static int ohci_init_pxa(SysBusDevice *dev)
+static void ohci_realize_pxa(DeviceState *dev, Error **errp)
 {
-    OHCISysBusState *s = FROM_SYSBUS(OHCISysBusState, dev);
+    OHCISysBusState *s = SYSBUS_OHCI(dev);
+    SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
 
     /* Cannot fail as we pass NULL for masterbus */
-    usb_ohci_init(&s->ohci, &dev->qdev, s->num_ports, s->dma_offset, NULL, 0,
+    usb_ohci_init(&s->ohci, dev, s->num_ports, s->dma_offset, NULL, 0,
                   &address_space_memory);
-    sysbus_init_irq(dev, &s->ohci.irq);
-    sysbus_init_mmio(dev, &s->ohci.mem);
-
-    return 0;
+    sysbus_init_irq(sbd, &s->ohci.irq);
+    sysbus_init_mmio(sbd, &s->ohci.mem);
 }
 
 static Property ohci_pci_properties[] = {
@@ -1912,7 +1922,7 @@
 }
 
 static const TypeInfo ohci_pci_info = {
-    .name          = "pci-ohci",
+    .name          = TYPE_PCI_OHCI,
     .parent        = TYPE_PCI_DEVICE,
     .instance_size = sizeof(OHCIPCIState),
     .class_init    = ohci_pci_class_init,
@@ -1927,15 +1937,14 @@
 static void ohci_sysbus_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
-    SysBusDeviceClass *sbc = SYS_BUS_DEVICE_CLASS(klass);
 
-    sbc->init = ohci_init_pxa;
+    dc->realize = ohci_realize_pxa;
     dc->desc = "OHCI USB Controller";
     dc->props = ohci_sysbus_properties;
 }
 
 static const TypeInfo ohci_sysbus_info = {
-    .name          = "sysbus-ohci",
+    .name          = TYPE_SYSBUS_OHCI,
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(OHCISysBusState),
     .class_init    = ohci_sysbus_class_init,
diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c
index d7a54fd..9ba3e3e 100644
--- a/hw/usb/hcd-xhci.c
+++ b/hw/usb/hcd-xhci.c
@@ -443,7 +443,10 @@
 } XHCIInterrupter;
 
 struct XHCIState {
-    PCIDevice pci_dev;
+    /*< private >*/
+    PCIDevice parent_obj;
+    /*< public >*/
+
     USBBus bus;
     qemu_irq irq;
     MemoryRegion mem;
@@ -482,6 +485,11 @@
     XHCIRing cmd_ring;
 };
 
+#define TYPE_XHCI "nec-usb-xhci"
+
+#define XHCI(obj) \
+    OBJECT_CHECK(XHCIState, (obj), TYPE_XHCI)
+
 typedef struct XHCIEvRingSeg {
     uint32_t addr_low;
     uint32_t addr_high;
@@ -654,7 +662,7 @@
 
     assert((len % sizeof(uint32_t)) == 0);
 
-    pci_dma_read(&xhci->pci_dev, addr, buf, len);
+    pci_dma_read(PCI_DEVICE(xhci), addr, buf, len);
 
     for (i = 0; i < (len / sizeof(uint32_t)); i++) {
         buf[i] = le32_to_cpu(buf[i]);
@@ -672,7 +680,7 @@
     for (i = 0; i < (len / sizeof(uint32_t)); i++) {
         tmp[i] = cpu_to_le32(buf[i]);
     }
-    pci_dma_write(&xhci->pci_dev, addr, tmp, len);
+    pci_dma_write(PCI_DEVICE(xhci), addr, tmp, len);
 }
 
 static XHCIPort *xhci_lookup_port(XHCIState *xhci, struct USBPort *uport)
@@ -699,10 +707,11 @@
 
 static void xhci_intx_update(XHCIState *xhci)
 {
+    PCIDevice *pci_dev = PCI_DEVICE(xhci);
     int level = 0;
 
-    if (msix_enabled(&xhci->pci_dev) ||
-        msi_enabled(&xhci->pci_dev)) {
+    if (msix_enabled(pci_dev) ||
+        msi_enabled(pci_dev)) {
         return;
     }
 
@@ -718,9 +727,10 @@
 
 static void xhci_msix_update(XHCIState *xhci, int v)
 {
+    PCIDevice *pci_dev = PCI_DEVICE(xhci);
     bool enabled;
 
-    if (!msix_enabled(&xhci->pci_dev)) {
+    if (!msix_enabled(pci_dev)) {
         return;
     }
 
@@ -731,17 +741,19 @@
 
     if (enabled) {
         trace_usb_xhci_irq_msix_use(v);
-        msix_vector_use(&xhci->pci_dev, v);
+        msix_vector_use(pci_dev, v);
         xhci->intr[v].msix_used = true;
     } else {
         trace_usb_xhci_irq_msix_unuse(v);
-        msix_vector_unuse(&xhci->pci_dev, v);
+        msix_vector_unuse(pci_dev, v);
         xhci->intr[v].msix_used = false;
     }
 }
 
 static void xhci_intr_raise(XHCIState *xhci, int v)
 {
+    PCIDevice *pci_dev = PCI_DEVICE(xhci);
+
     xhci->intr[v].erdp_low |= ERDP_EHB;
     xhci->intr[v].iman |= IMAN_IP;
     xhci->usbsts |= USBSTS_EINT;
@@ -754,15 +766,15 @@
         return;
     }
 
-    if (msix_enabled(&xhci->pci_dev)) {
+    if (msix_enabled(pci_dev)) {
         trace_usb_xhci_irq_msix(v);
-        msix_notify(&xhci->pci_dev, v);
+        msix_notify(pci_dev, v);
         return;
     }
 
-    if (msi_enabled(&xhci->pci_dev)) {
+    if (msi_enabled(pci_dev)) {
         trace_usb_xhci_irq_msi(v);
-        msi_notify(&xhci->pci_dev, v);
+        msi_notify(pci_dev, v);
         return;
     }
 
@@ -785,6 +797,7 @@
 
 static void xhci_write_event(XHCIState *xhci, XHCIEvent *event, int v)
 {
+    PCIDevice *pci_dev = PCI_DEVICE(xhci);
     XHCIInterrupter *intr = &xhci->intr[v];
     XHCITRB ev_trb;
     dma_addr_t addr;
@@ -803,7 +816,7 @@
                                ev_trb.status, ev_trb.control);
 
     addr = intr->er_start + TRB_SIZE*intr->er_ep_idx;
-    pci_dma_write(&xhci->pci_dev, addr, &ev_trb, TRB_SIZE);
+    pci_dma_write(pci_dev, addr, &ev_trb, TRB_SIZE);
 
     intr->er_ep_idx++;
     if (intr->er_ep_idx >= intr->er_size) {
@@ -950,9 +963,11 @@
 static TRBType xhci_ring_fetch(XHCIState *xhci, XHCIRing *ring, XHCITRB *trb,
                                dma_addr_t *addr)
 {
+    PCIDevice *pci_dev = PCI_DEVICE(xhci);
+
     while (1) {
         TRBType type;
-        pci_dma_read(&xhci->pci_dev, ring->dequeue, trb, TRB_SIZE);
+        pci_dma_read(pci_dev, ring->dequeue, trb, TRB_SIZE);
         trb->addr = ring->dequeue;
         trb->ccs = ring->ccs;
         le64_to_cpus(&trb->parameter);
@@ -985,6 +1000,7 @@
 
 static int xhci_ring_chain_length(XHCIState *xhci, const XHCIRing *ring)
 {
+    PCIDevice *pci_dev = PCI_DEVICE(xhci);
     XHCITRB trb;
     int length = 0;
     dma_addr_t dequeue = ring->dequeue;
@@ -994,7 +1010,7 @@
 
     while (1) {
         TRBType type;
-        pci_dma_read(&xhci->pci_dev, dequeue, &trb, TRB_SIZE);
+        pci_dma_read(pci_dev, dequeue, &trb, TRB_SIZE);
         le64_to_cpus(&trb.parameter);
         le32_to_cpus(&trb.status);
         le32_to_cpus(&trb.control);
@@ -1046,7 +1062,7 @@
         return;
     }
     dma_addr_t erstba = xhci_addr64(intr->erstba_low, intr->erstba_high);
-    pci_dma_read(&xhci->pci_dev, erstba, &seg, sizeof(seg));
+    pci_dma_read(PCI_DEVICE(xhci), erstba, &seg, sizeof(seg));
     le32_to_cpus(&seg.addr_low);
     le32_to_cpus(&seg.addr_high);
     le32_to_cpus(&seg.size);
@@ -1521,7 +1537,7 @@
     int i;
 
     xfer->int_req = false;
-    pci_dma_sglist_init(&xfer->sgl, &xhci->pci_dev, xfer->trb_count);
+    pci_dma_sglist_init(&xfer->sgl, PCI_DEVICE(xhci), xfer->trb_count);
     for (i = 0; i < xfer->trb_count; i++) {
         XHCITRB *trb = &xfer->trbs[i];
         dma_addr_t addr;
@@ -2106,7 +2122,7 @@
     assert(slotid >= 1 && slotid <= xhci->numslots);
 
     dcbaap = xhci_addr64(xhci->dcbaap_low, xhci->dcbaap_high);
-    poctx = ldq_le_pci_dma(&xhci->pci_dev, dcbaap + 8*slotid);
+    poctx = ldq_le_pci_dma(PCI_DEVICE(xhci), dcbaap + 8 * slotid);
     ictx = xhci_mask64(pictx);
     octx = xhci_mask64(poctx);
 
@@ -2427,7 +2443,7 @@
     /* TODO: actually implement real values here */
     bw_ctx[0] = 0;
     memset(&bw_ctx[1], 80, xhci->numports); /* 80% */
-    pci_dma_write(&xhci->pci_dev, ctx, bw_ctx, sizeof(bw_ctx));
+    pci_dma_write(PCI_DEVICE(xhci), ctx, bw_ctx, sizeof(bw_ctx));
 
     return CC_SUCCESS;
 }
@@ -2450,11 +2466,12 @@
 
 static void xhci_via_challenge(XHCIState *xhci, uint64_t addr)
 {
+    PCIDevice *pci_dev = PCI_DEVICE(xhci);
     uint32_t buf[8];
     uint32_t obuf[8];
     dma_addr_t paddr = xhci_mask64(addr);
 
-    pci_dma_read(&xhci->pci_dev, paddr, &buf, 32);
+    pci_dma_read(pci_dev, paddr, &buf, 32);
 
     memcpy(obuf, buf, sizeof(obuf));
 
@@ -2470,7 +2487,7 @@
         obuf[7] = obuf[2] ^ obuf[3] ^ 0x65866593;
     }
 
-    pci_dma_write(&xhci->pci_dev, paddr, &obuf, 32);
+    pci_dma_write(pci_dev, paddr, &obuf, 32);
 }
 
 static void xhci_process_commands(XHCIState *xhci)
@@ -2681,7 +2698,7 @@
 
 static void xhci_reset(DeviceState *dev)
 {
-    XHCIState *xhci = DO_UPCAST(XHCIState, pci_dev.qdev, dev);
+    XHCIState *xhci = XHCI(dev);
     int i;
 
     trace_usb_xhci_reset();
@@ -2926,6 +2943,7 @@
                             uint64_t val, unsigned size)
 {
     XHCIState *xhci = ptr;
+    DeviceState *d = DEVICE(ptr);
 
     trace_usb_xhci_oper_write(reg, val);
 
@@ -2939,7 +2957,7 @@
         xhci->usbcmd = val & 0xc0f;
         xhci_mfwrap_update(xhci);
         if (val & USBCMD_HCRST) {
-            xhci_reset(&xhci->pci_dev.qdev);
+            xhci_reset(d);
         }
         xhci_intx_update(xhci);
         break;
@@ -3265,8 +3283,9 @@
     .wakeup_endpoint = xhci_wakeup_endpoint,
 };
 
-static void usb_xhci_init(XHCIState *xhci, DeviceState *dev)
+static void usb_xhci_init(XHCIState *xhci)
 {
+    DeviceState *dev = DEVICE(xhci);
     XHCIPort *port;
     int i, usbports, speedmask;
 
@@ -3281,7 +3300,7 @@
     usbports = MAX(xhci->numports_2, xhci->numports_3);
     xhci->numports = xhci->numports_2 + xhci->numports_3;
 
-    usb_bus_new(&xhci->bus, &xhci_bus_ops, &xhci->pci_dev.qdev);
+    usb_bus_new(&xhci->bus, &xhci_bus_ops, dev);
 
     for (i = 0; i < usbports; i++) {
         speedmask = 0;
@@ -3313,14 +3332,14 @@
 {
     int i, ret;
 
-    XHCIState *xhci = DO_UPCAST(XHCIState, pci_dev, dev);
+    XHCIState *xhci = XHCI(dev);
 
-    xhci->pci_dev.config[PCI_CLASS_PROG] = 0x30;    /* xHCI */
-    xhci->pci_dev.config[PCI_INTERRUPT_PIN] = 0x01; /* interrupt pin 1 */
-    xhci->pci_dev.config[PCI_CACHE_LINE_SIZE] = 0x10;
-    xhci->pci_dev.config[0x60] = 0x30; /* release number */
+    dev->config[PCI_CLASS_PROG] = 0x30;    /* xHCI */
+    dev->config[PCI_INTERRUPT_PIN] = 0x01; /* interrupt pin 1 */
+    dev->config[PCI_CACHE_LINE_SIZE] = 0x10;
+    dev->config[0x60] = 0x30; /* release number */
 
-    usb_xhci_init(xhci, &dev->qdev);
+    usb_xhci_init(xhci);
 
     if (xhci->numintrs > MAXINTRS) {
         xhci->numintrs = MAXINTRS;
@@ -3340,7 +3359,7 @@
 
     xhci->mfwrap_timer = qemu_new_timer_ns(vm_clock, xhci_mfwrap_timer, xhci);
 
-    xhci->irq = xhci->pci_dev.irq[0];
+    xhci->irq = dev->irq[0];
 
     memory_region_init(&xhci->mem, OBJECT(xhci), "xhci", LEN_REGS);
     memory_region_init_io(&xhci->mem_cap, OBJECT(xhci), &xhci_cap_ops, xhci,
@@ -3366,18 +3385,18 @@
         memory_region_add_subregion(&xhci->mem, offset, &port->mem);
     }
 
-    pci_register_bar(&xhci->pci_dev, 0,
+    pci_register_bar(dev, 0,
                      PCI_BASE_ADDRESS_SPACE_MEMORY|PCI_BASE_ADDRESS_MEM_TYPE_64,
                      &xhci->mem);
 
-    ret = pcie_endpoint_cap_init(&xhci->pci_dev, 0xa0);
+    ret = pcie_endpoint_cap_init(dev, 0xa0);
     assert(ret >= 0);
 
     if (xhci->flags & (1 << XHCI_FLAG_USE_MSI)) {
-        msi_init(&xhci->pci_dev, 0x70, xhci->numintrs, true, false);
+        msi_init(dev, 0x70, xhci->numintrs, true, false);
     }
     if (xhci->flags & (1 << XHCI_FLAG_USE_MSI_X)) {
-        msix_init(&xhci->pci_dev, xhci->numintrs,
+        msix_init(dev, xhci->numintrs,
                   &xhci->mem, 0, OFF_MSIX_TABLE,
                   &xhci->mem, 0, OFF_MSIX_PBA,
                   0x90);
@@ -3389,6 +3408,7 @@
 static int usb_xhci_post_load(void *opaque, int version_id)
 {
     XHCIState *xhci = opaque;
+    PCIDevice *pci_dev = PCI_DEVICE(xhci);
     XHCISlot *slot;
     XHCIEPContext *epctx;
     dma_addr_t dcbaap, pctx;
@@ -3404,7 +3424,7 @@
             continue;
         }
         slot->ctx =
-            xhci_mask64(ldq_le_pci_dma(&xhci->pci_dev, dcbaap + 8*slotid));
+            xhci_mask64(ldq_le_pci_dma(pci_dev, dcbaap + 8 * slotid));
         xhci_dma_read_u32s(xhci, slot->ctx, slot_ctx, sizeof(slot_ctx));
         slot->uport = xhci_lookup_uport(xhci, slot_ctx);
         assert(slot->uport && slot->uport->dev);
@@ -3429,9 +3449,9 @@
 
     for (intr = 0; intr < xhci->numintrs; intr++) {
         if (xhci->intr[intr].msix_used) {
-            msix_vector_use(&xhci->pci_dev, intr);
+            msix_vector_use(pci_dev, intr);
         } else {
-            msix_vector_unuse(&xhci->pci_dev, intr);
+            msix_vector_unuse(pci_dev, intr);
         }
     }
 
@@ -3524,8 +3544,8 @@
     .version_id = 1,
     .post_load = usb_xhci_post_load,
     .fields = (VMStateField[]) {
-        VMSTATE_PCIE_DEVICE(pci_dev, XHCIState),
-        VMSTATE_MSIX(pci_dev, XHCIState),
+        VMSTATE_PCIE_DEVICE(parent_obj, XHCIState),
+        VMSTATE_MSIX(parent_obj, XHCIState),
 
         VMSTATE_STRUCT_VARRAY_UINT32(ports, XHCIState, numports, 1,
                                      vmstate_xhci_port, XHCIPort),
@@ -3581,7 +3601,7 @@
 }
 
 static const TypeInfo xhci_info = {
-    .name          = "nec-usb-xhci",
+    .name          = TYPE_XHCI,
     .parent        = TYPE_PCI_DEVICE,
     .instance_size = sizeof(XHCIState),
     .class_init    = xhci_class_init,
diff --git a/hw/xen/xen_platform.c b/hw/xen/xen_platform.c
index 15d7cf0..6a8ba7e 100644
--- a/hw/xen/xen_platform.c
+++ b/hw/xen/xen_platform.c
@@ -49,7 +49,10 @@
 #define PFFLAG_ROM_LOCK 1 /* Sets whether ROM memory area is RW or RO */
 
 typedef struct PCIXenPlatformState {
-    PCIDevice  pci_dev;
+    /*< private >*/
+    PCIDevice parent_obj;
+    /*< public >*/
+
     MemoryRegion fixed_io;
     MemoryRegion bar;
     MemoryRegion mmio_bar;
@@ -62,6 +65,10 @@
     int log_buffer_off;
 } PCIXenPlatformState;
 
+#define TYPE_XEN_PLATFORM "xen-platform"
+#define XEN_PLATFORM(obj) \
+    OBJECT_CHECK(PCIXenPlatformState, (obj), TYPE_XEN_PLATFORM)
+
 #define XEN_PLATFORM_IOPORT 0x10
 
 /* Send bytes to syslog */
@@ -88,7 +95,7 @@
     if (pci_get_word(d->config + PCI_CLASS_DEVICE) ==
             PCI_CLASS_NETWORK_ETHERNET
             && strcmp(d->name, "xen-pci-passthrough") != 0) {
-        qdev_free(&d->qdev);
+        qdev_free(DEVICE(d));
     }
 }
 
@@ -103,7 +110,7 @@
     if (pci_get_word(d->config + PCI_CLASS_DEVICE) ==
             PCI_CLASS_STORAGE_IDE
             && strcmp(d->name, "xen-pci-passthrough") != 0) {
-        qdev_unplug(&(d->qdev), NULL);
+        qdev_unplug(DEVICE(d), NULL);
     }
 }
 
@@ -117,7 +124,8 @@
     PCIXenPlatformState *s = opaque;
 
     switch (addr) {
-    case 0:
+    case 0: {
+        PCIDevice *pci_dev = PCI_DEVICE(s);
         /* Unplug devices.  Value is a bitmask of which devices to
            unplug, with bit 0 the IDE devices, bit 1 the network
            devices, and bit 2 the non-primary-master IDE devices. */
@@ -125,16 +133,17 @@
             DPRINTF("unplug disks\n");
             bdrv_drain_all();
             bdrv_flush_all();
-            pci_unplug_disks(s->pci_dev.bus);
+            pci_unplug_disks(pci_dev->bus);
         }
         if (val & UNPLUG_ALL_NICS) {
             DPRINTF("unplug nics\n");
-            pci_unplug_nics(s->pci_dev.bus);
+            pci_unplug_nics(pci_dev->bus);
         }
         if (val & UNPLUG_AUX_IDE_DISKS) {
             DPRINTF("unplug auxiliary disks not supported\n");
         }
         break;
+    }
     case 2:
         switch (val) {
         case 1:
@@ -368,7 +377,7 @@
     .minimum_version_id_old = 4,
     .post_load = xen_platform_post_load,
     .fields = (VMStateField []) {
-        VMSTATE_PCI_DEVICE(pci_dev, PCIXenPlatformState),
+        VMSTATE_PCI_DEVICE(parent_obj, PCIXenPlatformState),
         VMSTATE_UINT8(flags, PCIXenPlatformState),
         VMSTATE_END_OF_LIST()
     }
@@ -376,10 +385,10 @@
 
 static int xen_platform_initfn(PCIDevice *dev)
 {
-    PCIXenPlatformState *d = DO_UPCAST(PCIXenPlatformState, pci_dev, dev);
+    PCIXenPlatformState *d = XEN_PLATFORM(dev);
     uint8_t *pci_conf;
 
-    pci_conf = d->pci_dev.config;
+    pci_conf = dev->config;
 
     pci_set_word(pci_conf + PCI_COMMAND, PCI_COMMAND_IO | PCI_COMMAND_MEMORY);
 
@@ -388,11 +397,11 @@
     pci_conf[PCI_INTERRUPT_PIN] = 1;
 
     platform_ioport_bar_setup(d);
-    pci_register_bar(&d->pci_dev, 0, PCI_BASE_ADDRESS_SPACE_IO, &d->bar);
+    pci_register_bar(dev, 0, PCI_BASE_ADDRESS_SPACE_IO, &d->bar);
 
     /* reserve 16MB mmio address for share memory*/
     platform_mmio_setup(d);
-    pci_register_bar(&d->pci_dev, 1, PCI_BASE_ADDRESS_MEM_PREFETCH,
+    pci_register_bar(dev, 1, PCI_BASE_ADDRESS_MEM_PREFETCH,
                      &d->mmio_bar);
 
     platform_fixed_ioport_init(d);
@@ -402,7 +411,7 @@
 
 static void platform_reset(DeviceState *dev)
 {
-    PCIXenPlatformState *s = DO_UPCAST(PCIXenPlatformState, pci_dev.qdev, dev);
+    PCIXenPlatformState *s = XEN_PLATFORM(dev);
 
     platform_fixed_ioport_reset(s);
 }
@@ -425,7 +434,7 @@
 }
 
 static const TypeInfo xen_platform_info = {
-    .name          = "xen-platform",
+    .name          = TYPE_XEN_PLATFORM,
     .parent        = TYPE_PCI_DEVICE,
     .instance_size = sizeof(PCIXenPlatformState),
     .class_init    = xen_platform_class_init,
diff --git a/hw/xtensa/xtensa_lx60.c b/hw/xtensa/xtensa_lx60.c
index 075daf1..1138666 100644
--- a/hw/xtensa/xtensa_lx60.c
+++ b/hw/xtensa/xtensa_lx60.c
@@ -144,9 +144,11 @@
     memory_region_add_subregion(address_space, buffers, ram);
 }
 
-static uint64_t translate_phys_addr(void *env, uint64_t addr)
+static uint64_t translate_phys_addr(void *opaque, uint64_t addr)
 {
-    return cpu_get_phys_page_debug(env, addr);
+    XtensaCPU *cpu = opaque;
+
+    return cpu_get_phys_page_debug(CPU(cpu), addr);
 }
 
 static void lx60_reset(void *opaque)
@@ -252,7 +254,7 @@
         }
         uint64_t elf_entry;
         uint64_t elf_lowaddr;
-        int success = load_elf(kernel_filename, translate_phys_addr, env,
+        int success = load_elf(kernel_filename, translate_phys_addr, cpu,
                 &elf_entry, &elf_lowaddr, NULL, be, ELF_MACHINE, 0);
         if (success > 0) {
             env->pc = elf_entry;
diff --git a/hw/xtensa/xtensa_sim.c b/hw/xtensa/xtensa_sim.c
index a88707e..ea91162 100644
--- a/hw/xtensa/xtensa_sim.c
+++ b/hw/xtensa/xtensa_sim.c
@@ -32,9 +32,11 @@
 #include "exec/memory.h"
 #include "exec/address-spaces.h"
 
-static uint64_t translate_phys_addr(void *env, uint64_t addr)
+static uint64_t translate_phys_addr(void *opaque, uint64_t addr)
 {
-    return cpu_get_phys_page_debug(env, addr);
+    XtensaCPU *cpu = opaque;
+
+    return cpu_get_phys_page_debug(CPU(cpu), addr);
 }
 
 static void sim_reset(void *opaque)
@@ -88,10 +90,10 @@
         uint64_t elf_entry;
         uint64_t elf_lowaddr;
 #ifdef TARGET_WORDS_BIGENDIAN
-        int success = load_elf(kernel_filename, translate_phys_addr, env,
+        int success = load_elf(kernel_filename, translate_phys_addr, cpu,
                 &elf_entry, &elf_lowaddr, NULL, 1, ELF_MACHINE, 0);
 #else
-        int success = load_elf(kernel_filename, translate_phys_addr, env,
+        int success = load_elf(kernel_filename, translate_phys_addr, cpu,
                 &elf_entry, &elf_lowaddr, NULL, 0, ELF_MACHINE, 0);
 #endif
         if (success > 0) {
diff --git a/include/exec/cpu-all.h b/include/exec/cpu-all.h
index 5084202..f2800ec 100644
--- a/include/exec/cpu-all.h
+++ b/include/exec/cpu-all.h
@@ -22,6 +22,7 @@
 #include "qemu-common.h"
 #include "exec/cpu-common.h"
 #include "qemu/thread.h"
+#include "qom/cpu.h"
 
 /* some important defines:
  *
@@ -428,19 +429,8 @@
 void cpu_watchpoint_remove_by_ref(CPUArchState *env, CPUWatchpoint *watchpoint);
 void cpu_watchpoint_remove_all(CPUArchState *env, int mask);
 
-#define SSTEP_ENABLE  0x1  /* Enable simulated HW single stepping */
-#define SSTEP_NOIRQ   0x2  /* Do not use IRQ while single stepping */
-#define SSTEP_NOTIMER 0x4  /* Do not Timers while single stepping */
-
-void cpu_single_step(CPUArchState *env, int enabled);
-
 #if !defined(CONFIG_USER_ONLY)
 
-/* Return the physical page corresponding to a virtual one. Use it
-   only for debugging because no protection checks are done. Return -1
-   if no page found. */
-hwaddr cpu_get_phys_page_debug(CPUArchState *env, target_ulong addr);
-
 /* memory API */
 
 extern ram_addr_t ram_size;
@@ -494,7 +484,7 @@
 void qemu_mutex_unlock_ramlist(void);
 #endif /* !CONFIG_USER_ONLY */
 
-int cpu_memory_rw_debug(CPUArchState *env, target_ulong addr,
+int cpu_memory_rw_debug(CPUState *cpu, target_ulong addr,
                         uint8_t *buf, int len, int is_write);
 
 #endif /* CPU_ALL_H */
diff --git a/include/exec/cpu-defs.h b/include/exec/cpu-defs.h
index 39094b3..b5b93db 100644
--- a/include/exec/cpu-defs.h
+++ b/include/exec/cpu-defs.h
@@ -170,13 +170,10 @@
     /* from this point: preserved by CPU reset */                       \
     /* ice debug support */                                             \
     QTAILQ_HEAD(breakpoints_head, CPUBreakpoint) breakpoints;            \
-    int singlestep_enabled;                                             \
                                                                         \
     QTAILQ_HEAD(watchpoints_head, CPUWatchpoint) watchpoints;            \
     CPUWatchpoint *watchpoint_hit;                                      \
                                                                         \
-    struct GDBRegisterState *gdb_regs;                                  \
-                                                                        \
     /* Core interrupt code */                                           \
     sigjmp_buf jmp_env;                                                 \
     int exception_index;                                                \
diff --git a/include/exec/gdbstub.h b/include/exec/gdbstub.h
index ded4160..1bd00ae 100644
--- a/include/exec/gdbstub.h
+++ b/include/exec/gdbstub.h
@@ -11,7 +11,7 @@
 #define GDB_WATCHPOINT_ACCESS    4
 
 #ifdef NEED_CPU_H
-typedef void (*gdb_syscall_complete_cb)(CPUArchState *env,
+typedef void (*gdb_syscall_complete_cb)(CPUState *cpu,
                                         target_ulong ret, target_ulong err);
 
 void gdb_do_syscall(gdb_syscall_complete_cb cb, const char *fmt, ...);
@@ -20,13 +20,13 @@
 void gdb_exit(CPUArchState *, int);
 #ifdef CONFIG_USER_ONLY
 int gdb_queuesig (void);
-int gdb_handlesig (CPUArchState *, int);
+int gdb_handlesig(CPUState *, int);
 void gdb_signalled(CPUArchState *, int);
 void gdbserver_fork(CPUArchState *);
 #endif
 /* Get or set a register.  Returns the size of the register.  */
 typedef int (*gdb_reg_cb)(CPUArchState *env, uint8_t *buf, int reg);
-void gdb_register_coprocessor(CPUArchState *env,
+void gdb_register_coprocessor(CPUState *cpu,
                               gdb_reg_cb get_reg, gdb_reg_cb set_reg,
                               int num_regs, const char *xml, int g_pos);
 
diff --git a/include/exec/softmmu-semi.h b/include/exec/softmmu-semi.h
index 93798b9..8401f7d 100644
--- a/include/exec/softmmu-semi.h
+++ b/include/exec/softmmu-semi.h
@@ -13,14 +13,14 @@
 {
     uint32_t val;
 
-    cpu_memory_rw_debug(env, addr, (uint8_t *)&val, 4, 0);
+    cpu_memory_rw_debug(ENV_GET_CPU(env), addr, (uint8_t *)&val, 4, 0);
     return tswap32(val);
 }
 static inline uint32_t softmmu_tget8(CPUArchState *env, uint32_t addr)
 {
     uint8_t val;
 
-    cpu_memory_rw_debug(env, addr, &val, 1, 0);
+    cpu_memory_rw_debug(ENV_GET_CPU(env), addr, &val, 1, 0);
     return val;
 }
 
@@ -31,7 +31,7 @@
 static inline void softmmu_tput32(CPUArchState *env, uint32_t addr, uint32_t val)
 {
     val = tswap32(val);
-    cpu_memory_rw_debug(env, addr, (uint8_t *)&val, 4, 1);
+    cpu_memory_rw_debug(ENV_GET_CPU(env), addr, (uint8_t *)&val, 4, 1);
 }
 #define put_user_u32(arg, p) ({ softmmu_tput32(env, p, arg) ; 0; })
 #define put_user_ual(arg, p) put_user_u32(arg, p)
@@ -42,8 +42,9 @@
     uint8_t *p;
     /* TODO: Make this something that isn't fixed size.  */
     p = malloc(len);
-    if (p && copy)
-        cpu_memory_rw_debug(env, addr, p, len, 0);
+    if (p && copy) {
+        cpu_memory_rw_debug(ENV_GET_CPU(env), addr, p, len, 0);
+    }
     return p;
 }
 #define lock_user(type, p, len, copy) softmmu_lock_user(env, p, len, copy)
@@ -58,7 +59,7 @@
         return NULL;
     }
     do {
-        cpu_memory_rw_debug(env, addr, &c, 1, 0);
+        cpu_memory_rw_debug(ENV_GET_CPU(env), addr, &c, 1, 0);
         addr++;
         *(p++) = c;
     } while (c);
@@ -68,8 +69,9 @@
 static void softmmu_unlock_user(CPUArchState *env, void *p, target_ulong addr,
                                 target_ulong len)
 {
-    if (len)
-        cpu_memory_rw_debug(env, addr, p, len, 1);
+    if (len) {
+        cpu_memory_rw_debug(ENV_GET_CPU(env), addr, p, len, 1);
+    }
     free(p);
 }
 #define unlock_user(s, args, len) softmmu_unlock_user(env, s, args, len)
diff --git a/include/hw/pci-host/q35.h b/include/hw/pci-host/q35.h
index b083831..3cb631e 100644
--- a/include/hw/pci-host/q35.h
+++ b/include/hw/pci-host/q35.h
@@ -43,7 +43,10 @@
      OBJECT_CHECK(MCHPCIState, (obj), TYPE_MCH_PCI_DEVICE)
 
 typedef struct MCHPCIState {
-    PCIDevice d;
+    /*< private >*/
+    PCIDevice parent_obj;
+    /*< public >*/
+
     MemoryRegion *ram_memory;
     MemoryRegion *pci_address_space;
     MemoryRegion *system_memory;
@@ -59,7 +62,10 @@
 } MCHPCIState;
 
 typedef struct Q35PCIHost {
-    PCIExpressHost host;
+    /*< private >*/
+    PCIExpressHost parent_obj;
+    /*< public >*/
+
     MCHPCIState mch;
 } Q35PCIHost;
 
diff --git a/include/hw/scsi/scsi.h b/include/hw/scsi/scsi.h
index 9786e00..8786531 100644
--- a/include/hw/scsi/scsi.h
+++ b/include/hw/scsi/scsi.h
@@ -162,8 +162,8 @@
 
 SCSIDevice *scsi_bus_legacy_add_drive(SCSIBus *bus, BlockDriverState *bdrv,
                                       int unit, bool removable, int bootindex,
-                                      const char *serial);
-int scsi_bus_legacy_handle_cmdline(SCSIBus *bus);
+                                      const char *serial, Error **errp);
+void scsi_bus_legacy_handle_cmdline(SCSIBus *bus, Error **errp);
 
 /*
  * Predefined sense codes
diff --git a/include/hw/sysbus.h b/include/hw/sysbus.h
index 7c2e316..8c17165 100644
--- a/include/hw/sysbus.h
+++ b/include/hw/sysbus.h
@@ -23,8 +23,20 @@
 #define SYS_BUS_DEVICE_GET_CLASS(obj) \
      OBJECT_GET_CLASS(SysBusDeviceClass, (obj), TYPE_SYS_BUS_DEVICE)
 
+/**
+ * SysBusDeviceClass:
+ * @init: Callback function invoked when the #DeviceState.realized property
+ * is changed to %true. Deprecated, new types inheriting directly from
+ * TYPE_SYS_BUS_DEVICE should use #DeviceClass.realize instead, new leaf
+ * types should consult their respective parent type.
+ *
+ * SysBusDeviceClass is not overriding #DeviceClass.realize, so derived
+ * classes overriding it are not required to invoke its implementation.
+ */
 typedef struct SysBusDeviceClass {
+    /*< private >*/
     DeviceClass parent_class;
+    /*< public >*/
 
     int (*init)(SysBusDevice *dev);
 } SysBusDeviceClass;
diff --git a/include/qom/cpu.h b/include/qom/cpu.h
index dfd81a1..daf1835 100644
--- a/include/qom/cpu.h
+++ b/include/qom/cpu.h
@@ -30,6 +30,18 @@
 typedef int (*WriteCoreDumpFunction)(void *buf, size_t size, void *opaque);
 
 /**
+ * vaddr:
+ * Type wide enough to contain any #target_ulong virtual address.
+ */
+typedef uint64_t vaddr;
+#define VADDR_PRId PRId64
+#define VADDR_PRIu PRIu64
+#define VADDR_PRIo PRIo64
+#define VADDR_PRIx PRIx64
+#define VADDR_PRIX PRIX64
+#define VADDR_MAX UINT64_MAX
+
+/**
  * SECTION:cpu
  * @section_id: QEMU-cpu
  * @title: CPU Class
@@ -48,6 +60,8 @@
                                     bool is_write, bool is_exec, int opaque,
                                     unsigned size);
 
+struct TranslationBlock;
+
 /**
  * CPUClass:
  * @class_by_name: Callback to map -cpu command line model name to an
@@ -56,11 +70,16 @@
  * @reset_dump_flags: #CPUDumpFlags to use for reset logging.
  * @do_interrupt: Callback for interrupt handling.
  * @do_unassigned_access: Callback for unassigned access handling.
+ * @memory_rw_debug: Callback for GDB memory access.
  * @dump_state: Callback for dumping state.
  * @dump_statistics: Callback for dumping statistics.
  * @get_arch_id: Callback for getting architecture-dependent CPU ID.
  * @get_paging_enabled: Callback for inquiring whether paging is enabled.
  * @get_memory_mapping: Callback for obtaining the memory mappings.
+ * @set_pc: Callback for setting the Program Counter register.
+ * @synchronize_from_tb: Callback for synchronizing state from a TCG
+ * #TranslationBlock.
+ * @get_phys_page_debug: Callback for obtaining a physical address.
  * @vmsd: State description for migration.
  *
  * Represents a CPU family or model.
@@ -76,6 +95,8 @@
     int reset_dump_flags;
     void (*do_interrupt)(CPUState *cpu);
     CPUUnassignedAccess do_unassigned_access;
+    int (*memory_rw_debug)(CPUState *cpu, vaddr addr,
+                           uint8_t *buf, int len, bool is_write);
     void (*dump_state)(CPUState *cpu, FILE *f, fprintf_function cpu_fprintf,
                        int flags);
     void (*dump_statistics)(CPUState *cpu, FILE *f,
@@ -84,6 +105,9 @@
     bool (*get_paging_enabled)(const CPUState *cpu);
     void (*get_memory_mapping)(CPUState *cpu, MemoryMappingList *list,
                                Error **errp);
+    void (*set_pc)(CPUState *cpu, vaddr value);
+    void (*synchronize_from_tb)(CPUState *cpu, struct TranslationBlock *tb);
+    hwaddr (*get_phys_page_debug)(CPUState *cpu, vaddr addr);
 
     const struct VMStateDescription *vmsd;
     int (*write_elf64_note)(WriteCoreDumpFunction f, CPUState *cpu,
@@ -114,8 +138,10 @@
  * @stopped: Indicates the CPU has been artificially stopped.
  * @tcg_exit_req: Set to force TCG to stop executing linked TBs for this
  *           CPU and return to its top level loop.
+ * @singlestep_enabled: Flags for single-stepping.
  * @env_ptr: Pointer to subclass-specific CPUArchState field.
  * @current_tb: Currently executing TB.
+ * @gdb_regs: Additional GDB registers.
  * @next_cpu: Next CPU sharing TB cache.
  * @kvm_fd: vCPU file descriptor for KVM.
  *
@@ -146,9 +172,11 @@
     volatile sig_atomic_t exit_request;
     volatile sig_atomic_t tcg_exit_req;
     uint32_t interrupt_request;
+    int singlestep_enabled;
 
     void *env_ptr; /* CPUArchState */
     struct TranslationBlock *current_tb;
+    struct GDBRegisterState *gdb_regs;
     CPUState *next_cpu;
 
     int kvm_fd;
@@ -259,6 +287,25 @@
 void cpu_dump_statistics(CPUState *cpu, FILE *f, fprintf_function cpu_fprintf,
                          int flags);
 
+#ifndef CONFIG_USER_ONLY
+/**
+ * cpu_get_phys_page_debug:
+ * @cpu: The CPU to obtain the physical page address for.
+ * @addr: The virtual address.
+ *
+ * Obtains the physical page corresponding to a virtual one.
+ * Use it only for debugging because no protection checks are done.
+ *
+ * Returns: Corresponding physical page address or -1 if no page found.
+ */
+static inline hwaddr cpu_get_phys_page_debug(CPUState *cpu, vaddr addr)
+{
+    CPUClass *cc = CPU_GET_CLASS(cpu);
+
+    return cc->get_phys_page_debug(cpu, addr);
+}
+#endif
+
 /**
  * cpu_reset:
  * @cpu: The CPU whose state is to be reset.
@@ -277,59 +324,6 @@
 ObjectClass *cpu_class_by_name(const char *typename, const char *cpu_model);
 
 /**
- * cpu_class_set_vmsd:
- * @cc: CPU class
- * @value: Value to set. Unused for %CONFIG_USER_ONLY.
- *
- * Sets #VMStateDescription for @cc.
- *
- * The @value argument is intentionally discarded for the non-softmmu targets
- * to avoid linker errors or excessive preprocessor usage. If this behavior
- * is undesired, you should assign #CPUClass.vmsd directly instead.
- */
-#ifndef CONFIG_USER_ONLY
-static inline void cpu_class_set_vmsd(CPUClass *cc,
-                                      const struct VMStateDescription *value)
-{
-    cc->vmsd = value;
-}
-#else
-#define cpu_class_set_vmsd(cc, value) ((cc)->vmsd = NULL)
-#endif
-
-#ifndef CONFIG_USER_ONLY
-static inline void cpu_class_set_do_unassigned_access(CPUClass *cc,
-                                                      CPUUnassignedAccess value)
-{
-    cc->do_unassigned_access = value;
-}
-#else
-#define cpu_class_set_do_unassigned_access(cc, value) \
-    ((cc)->do_unassigned_access = NULL)
-#endif
-
-/**
- * device_class_set_vmsd:
- * @dc: Device class
- * @value: Value to set. Unused for %CONFIG_USER_ONLY.
- *
- * Sets #VMStateDescription for @dc.
- *
- * The @value argument is intentionally discarded for the non-softmmu targets
- * to avoid linker errors or excessive preprocessor usage. If this behavior
- * is undesired, you should assign #DeviceClass.vmsd directly instead.
- */
-#ifndef CONFIG_USER_ONLY
-static inline void device_class_set_vmsd(DeviceClass *dc,
-                                         const struct VMStateDescription *value)
-{
-    dc->vmsd = value;
-}
-#else
-#define device_class_set_vmsd(dc, value) ((dc)->vmsd = NULL)
-#endif
-
-/**
  * qemu_cpu_has_work:
  * @cpu: The vCPU to check.
  *
@@ -489,6 +483,19 @@
  */
 void qemu_init_vcpu(CPUState *cpu);
 
+#define SSTEP_ENABLE  0x1  /* Enable simulated HW single stepping */
+#define SSTEP_NOIRQ   0x2  /* Do not use IRQ while single stepping */
+#define SSTEP_NOTIMER 0x4  /* Do not Timers while single stepping */
+
+/**
+ * cpu_single_step:
+ * @cpu: CPU to the flags for.
+ * @enabled: Flags to enable.
+ *
+ * Enables or disables single-stepping for @cpu.
+ */
+void cpu_single_step(CPUState *cpu, int enabled);
+
 #ifdef CONFIG_SOFTMMU
 extern const struct VMStateDescription vmstate_cpu_common;
 #else
diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h
index 1e08a85..f8ac448 100644
--- a/include/sysemu/kvm.h
+++ b/include/sysemu/kvm.h
@@ -169,9 +169,9 @@
 void kvm_setup_guest_memory(void *start, size_t size);
 void kvm_flush_coalesced_mmio_buffer(void);
 
-int kvm_insert_breakpoint(CPUArchState *env, target_ulong addr,
+int kvm_insert_breakpoint(CPUState *cpu, target_ulong addr,
                           target_ulong len, int type);
-int kvm_remove_breakpoint(CPUArchState *env, target_ulong addr,
+int kvm_remove_breakpoint(CPUState *cpu, target_ulong addr,
                           target_ulong len, int type);
 void kvm_remove_all_breakpoints(CPUState *cpu);
 int kvm_update_guest_debug(CPUArchState *env, unsigned long reinject_trap);
diff --git a/kvm-all.c b/kvm-all.c
index 232c39a..4fb4ccb 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -1890,7 +1890,7 @@
 
     data.dbg.control = reinject_trap;
 
-    if (env->singlestep_enabled) {
+    if (cpu->singlestep_enabled) {
         data.dbg.control |= KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_SINGLESTEP;
     }
     kvm_arch_update_guest_debug(cpu, &data.dbg);
@@ -1900,10 +1900,9 @@
     return data.err;
 }
 
-int kvm_insert_breakpoint(CPUArchState *env, target_ulong addr,
+int kvm_insert_breakpoint(CPUState *cpu, target_ulong addr,
                           target_ulong len, int type)
 {
-    CPUState *cpu = ENV_GET_CPU(env);
     struct kvm_sw_breakpoint *bp;
     int err;
 
@@ -1946,10 +1945,9 @@
     return 0;
 }
 
-int kvm_remove_breakpoint(CPUArchState *env, target_ulong addr,
+int kvm_remove_breakpoint(CPUState *cpu, target_ulong addr,
                           target_ulong len, int type)
 {
-    CPUState *cpu = ENV_GET_CPU(env);
     struct kvm_sw_breakpoint *bp;
     int err;
 
@@ -2022,13 +2020,13 @@
     return -EINVAL;
 }
 
-int kvm_insert_breakpoint(CPUArchState *env, target_ulong addr,
+int kvm_insert_breakpoint(CPUState *cpu, target_ulong addr,
                           target_ulong len, int type)
 {
     return -EINVAL;
 }
 
-int kvm_remove_breakpoint(CPUArchState *env, target_ulong addr,
+int kvm_remove_breakpoint(CPUState *cpu, target_ulong addr,
                           target_ulong len, int type)
 {
     return -EINVAL;
diff --git a/kvm-stub.c b/kvm-stub.c
index 370c837..7b2233a 100644
--- a/kvm-stub.c
+++ b/kvm-stub.c
@@ -83,13 +83,13 @@
     return -ENOSYS;
 }
 
-int kvm_insert_breakpoint(CPUArchState *env, target_ulong addr,
+int kvm_insert_breakpoint(CPUState *cpu, target_ulong addr,
                           target_ulong len, int type)
 {
     return -EINVAL;
 }
 
-int kvm_remove_breakpoint(CPUArchState *env, target_ulong addr,
+int kvm_remove_breakpoint(CPUState *cpu, target_ulong addr,
                           target_ulong len, int type)
 {
     return -EINVAL;
diff --git a/linux-user/cpu-uname.c b/linux-user/cpu-uname.c
index 59cd647..cc713e6 100644
--- a/linux-user/cpu-uname.c
+++ b/linux-user/cpu-uname.c
@@ -55,12 +55,14 @@
     return "x86-64";
 #elif defined(TARGET_I386)
     /* see arch/x86/kernel/cpu/bugs.c: check_bugs(), 386, 486, 586, 686 */
-    uint32_t cpuid_version = ((CPUX86State *)cpu_env)->cpuid_version;
-    int family = ((cpuid_version >> 8) & 0x0f) + ((cpuid_version >> 20) & 0xff);
-    if (family == 4)
+    CPUState *cpu = ENV_GET_CPU((CPUX86State *)cpu_env);
+    int family = object_property_get_int(OBJECT(cpu), "family", NULL);
+    if (family == 4) {
         return "i486";
-    if (family == 5)
+    }
+    if (family == 5) {
         return "i586";
+    }
     return "i686";
 #else
     /* default is #define-d in each arch/ subdir */
diff --git a/linux-user/main.c b/linux-user/main.c
index 99c3b3f..f6a3aad 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -312,6 +312,7 @@
 
 void cpu_loop(CPUX86State *env)
 {
+    CPUState *cs = CPU(x86_env_get_cpu(env));
     int trapnr;
     abi_ulong pc;
     target_siginfo_t info;
@@ -443,7 +444,7 @@
             {
                 int sig;
 
-                sig = gdb_handlesig (env, TARGET_SIGTRAP);
+                sig = gdb_handlesig(cs, TARGET_SIGTRAP);
                 if (sig)
                   {
                     info.si_signo = sig;
@@ -875,7 +876,7 @@
             {
                 int sig;
 
-                sig = gdb_handlesig (env, TARGET_SIGTRAP);
+                sig = gdb_handlesig(cs, TARGET_SIGTRAP);
                 if (sig)
                   {
                     info.si_signo = sig;
@@ -966,7 +967,7 @@
             {
                 int sig;
 
-                sig = gdb_handlesig(env, TARGET_SIGTRAP);
+                sig = gdb_handlesig(cs, TARGET_SIGTRAP);
                 if (sig) {
                     info.si_signo = sig;
                     info.si_errno = 0;
@@ -1233,7 +1234,7 @@
             {
                 int sig;
 
-                sig = gdb_handlesig (env, TARGET_SIGTRAP);
+                sig = gdb_handlesig(cs, TARGET_SIGTRAP);
                 if (sig)
                   {
                     info.si_signo = sig;
@@ -1764,7 +1765,7 @@
             {
                 int sig;
 
-                sig = gdb_handlesig(env, TARGET_SIGTRAP);
+                sig = gdb_handlesig(cs, TARGET_SIGTRAP);
                 if (sig) {
                     info.si_signo = sig;
                     info.si_errno = 0;
@@ -2315,7 +2316,7 @@
             {
                 int sig;
 
-                sig = gdb_handlesig (env, TARGET_SIGTRAP);
+                sig = gdb_handlesig(cs, TARGET_SIGTRAP);
                 if (sig)
                   {
                     info.si_signo = sig;
@@ -2475,7 +2476,7 @@
             break;
         }
         if (gdbsig) {
-            gdb_handlesig(env, gdbsig);
+            gdb_handlesig(cs, gdbsig);
             if (gdbsig != TARGET_SIGTRAP) {
                 exit(1);
             }
@@ -2518,7 +2519,7 @@
             {
                 int sig;
 
-                sig = gdb_handlesig (env, TARGET_SIGTRAP);
+                sig = gdb_handlesig(cs, TARGET_SIGTRAP);
                 if (sig)
                   {
                     info.si_signo = sig;
@@ -2586,7 +2587,7 @@
             {
                 int sig;
 
-                sig = gdb_handlesig (env, TARGET_SIGTRAP);
+                sig = gdb_handlesig(cs, TARGET_SIGTRAP);
                 if (sig)
                   {
                     info.si_signo = sig;
@@ -2686,7 +2687,7 @@
             {
                 int sig;
 
-                sig = gdb_handlesig (env, TARGET_SIGTRAP);
+                sig = gdb_handlesig(cs, TARGET_SIGTRAP);
                 if (sig)
                   {
                     info.si_signo = sig;
@@ -2779,7 +2780,7 @@
             {
                 int sig;
 
-                sig = gdb_handlesig (env, TARGET_SIGTRAP);
+                sig = gdb_handlesig(cs, TARGET_SIGTRAP);
                 if (sig)
                   {
                     info.si_signo = sig;
@@ -3006,7 +3007,7 @@
             }
             break;
         case EXCP_DEBUG:
-            info.si_signo = gdb_handlesig (env, TARGET_SIGTRAP);
+            info.si_signo = gdb_handlesig(cs, TARGET_SIGTRAP);
             if (info.si_signo) {
                 env->lock_addr = -1;
                 info.si_errno = 0;
@@ -3059,7 +3060,7 @@
             break;
 
         case EXCP_DEBUG:
-            sig = gdb_handlesig(env, TARGET_SIGTRAP);
+            sig = gdb_handlesig(cs, TARGET_SIGTRAP);
             if (sig) {
                 n = TARGET_TRAP_BRKPT;
                 goto do_signal_pc;
@@ -3541,6 +3542,7 @@
     struct linux_binprm bprm;
     TaskState *ts;
     CPUArchState *env;
+    CPUState *cpu;
     int optind;
     char **target_environ, **wrk;
     char **target_argv;
@@ -3637,11 +3639,12 @@
         fprintf(stderr, "Unable to find CPU definition\n");
         exit(1);
     }
+    cpu = ENV_GET_CPU(env);
 #if defined(TARGET_SPARC) || defined(TARGET_PPC)
-    cpu_reset(ENV_GET_CPU(env));
+    cpu_reset(cpu);
 #endif
 
-    thread_cpu = ENV_GET_CPU(env);
+    thread_cpu = cpu;
 
     if (getenv("QEMU_STRACE")) {
         do_strace = 1;
@@ -4076,7 +4079,7 @@
                     gdbstub_port);
             exit(1);
         }
-        gdb_handlesig(env, 0);
+        gdb_handlesig(cpu, 0);
     }
     cpu_loop(env);
     /* never exits */
diff --git a/linux-user/signal.c b/linux-user/signal.c
index d0727be..a5e8906 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -5386,6 +5386,7 @@
 
 void process_pending_signals(CPUArchState *cpu_env)
 {
+    CPUState *cpu = ENV_GET_CPU(cpu_env);
     int sig;
     abi_ulong handler;
     sigset_t set, old_set;
@@ -5419,7 +5420,7 @@
     if (!k->first)
         k->pending = 0;
 
-    sig = gdb_handlesig (cpu_env, sig);
+    sig = gdb_handlesig(cpu, sig);
     if (!sig) {
         sa = NULL;
         handler = TARGET_SIG_IGN;
diff --git a/monitor.c b/monitor.c
index 6db2ba4..5dc0aa9 100644
--- a/monitor.c
+++ b/monitor.c
@@ -1164,7 +1164,7 @@
             cpu_physical_memory_read(addr, buf, l);
         } else {
             env = mon_get_cpu();
-            if (cpu_memory_rw_debug(env, addr, buf, l, 0) < 0) {
+            if (cpu_memory_rw_debug(ENV_GET_CPU(env), addr, buf, l, 0) < 0) {
                 monitor_printf(mon, " Cannot access memory\n");
                 break;
             }
diff --git a/target-alpha/cpu-qom.h b/target-alpha/cpu-qom.h
index 60125b1..b2eeba3 100644
--- a/target-alpha/cpu-qom.h
+++ b/target-alpha/cpu-qom.h
@@ -81,5 +81,6 @@
 void alpha_cpu_do_interrupt(CPUState *cpu);
 void alpha_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
                           int flags);
+hwaddr alpha_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
 
 #endif
diff --git a/target-alpha/cpu.c b/target-alpha/cpu.c
index 2670805..c8c8c2c 100644
--- a/target-alpha/cpu.c
+++ b/target-alpha/cpu.c
@@ -24,6 +24,13 @@
 #include "migration/vmstate.h"
 
 
+static void alpha_cpu_set_pc(CPUState *cs, vaddr value)
+{
+    AlphaCPU *cpu = ALPHA_CPU(cs);
+
+    cpu->env.pc = value;
+}
+
 static void alpha_cpu_realizefn(DeviceState *dev, Error **errp)
 {
     AlphaCPUClass *acc = ALPHA_CPU_GET_CLASS(dev);
@@ -263,8 +270,12 @@
     cc->class_by_name = alpha_cpu_class_by_name;
     cc->do_interrupt = alpha_cpu_do_interrupt;
     cc->dump_state = alpha_cpu_dump_state;
-    cpu_class_set_do_unassigned_access(cc, alpha_cpu_unassigned_access);
-    device_class_set_vmsd(dc, &vmstate_alpha_cpu);
+    cc->set_pc = alpha_cpu_set_pc;
+#ifndef CONFIG_USER_ONLY
+    cc->do_unassigned_access = alpha_cpu_unassigned_access;
+    cc->get_phys_page_debug = alpha_cpu_get_phys_page_debug;
+    dc->vmsd = &vmstate_alpha_cpu;
+#endif
 }
 
 static const TypeInfo alpha_cpu_type_info = {
diff --git a/target-alpha/cpu.h b/target-alpha/cpu.h
index 066f032..c85dc6e 100644
--- a/target-alpha/cpu.h
+++ b/target-alpha/cpu.h
@@ -515,9 +515,4 @@
 
 #include "exec/exec-all.h"
 
-static inline void cpu_pc_from_tb(CPUAlphaState *env, TranslationBlock *tb)
-{
-    env->pc = tb->pc;
-}
-
 #endif /* !defined (__CPU_ALPHA_H__) */
diff --git a/target-alpha/helper.c b/target-alpha/helper.c
index ff57dd6..fc61bb0 100644
--- a/target-alpha/helper.c
+++ b/target-alpha/helper.c
@@ -315,12 +315,13 @@
     return ret;
 }
 
-hwaddr cpu_get_phys_page_debug(CPUAlphaState *env, target_ulong addr)
+hwaddr alpha_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
 {
+    AlphaCPU *cpu = ALPHA_CPU(cs);
     target_ulong phys;
     int prot, fail;
 
-    fail = get_physical_address(env, addr, 0, 0, &phys, &prot);
+    fail = get_physical_address(&cpu->env, addr, 0, 0, &phys, &prot);
     return (fail >= 0 ? -1 : phys);
 }
 
diff --git a/target-alpha/translate.c b/target-alpha/translate.c
index 5558b72..0efd559 100644
--- a/target-alpha/translate.c
+++ b/target-alpha/translate.c
@@ -38,7 +38,6 @@
 typedef struct DisasContext DisasContext;
 struct DisasContext {
     struct TranslationBlock *tb;
-    CPUAlphaState *env;
     uint64_t pc;
     int mem_idx;
 
@@ -46,6 +45,11 @@
     int tb_rm;
     /* Current flush-to-zero setting for this TB.  */
     int tb_ftz;
+
+    /* implver value for this CPU.  */
+    int implver;
+
+    bool singlestep_enabled;
 };
 
 /* Return values from translate_one, indicating the state of the TB.
@@ -380,7 +384,7 @@
     /* Check for the dest on the same page as the start of the TB.  We
        also want to suppress goto_tb in the case of single-steping and IO.  */
     return (((ctx->tb->pc ^ dest) & TARGET_PAGE_MASK) == 0
-            && !ctx->env->singlestep_enabled
+            && !ctx->singlestep_enabled
             && !(ctx->tb->cflags & CF_LAST_IO));
 }
 
@@ -2248,8 +2252,9 @@
             break;
         case 0x6C:
             /* IMPLVER */
-            if (rc != 31)
-                tcg_gen_movi_i64(cpu_ir[rc], ctx->env->implver);
+            if (rc != 31) {
+                tcg_gen_movi_i64(cpu_ir[rc], ctx->implver);
+            }
             break;
         default:
             goto invalid_opc;
@@ -3383,6 +3388,7 @@
                                                   TranslationBlock *tb,
                                                   bool search_pc)
 {
+    CPUState *cs = CPU(cpu);
     CPUAlphaState *env = &cpu->env;
     DisasContext ctx, *ctxp = &ctx;
     target_ulong pc_start;
@@ -3398,9 +3404,10 @@
     gen_opc_end = tcg_ctx.gen_opc_buf + OPC_MAX_SIZE;
 
     ctx.tb = tb;
-    ctx.env = env;
     ctx.pc = pc_start;
     ctx.mem_idx = cpu_mmu_index(env);
+    ctx.implver = env->implver;
+    ctx.singlestep_enabled = cs->singlestep_enabled;
 
     /* ??? Every TB begins with unset rounding mode, to be initialized on
        the first fp insn of the TB.  Alternately we could define a proper
@@ -3457,7 +3464,7 @@
                 || tcg_ctx.gen_opc_ptr >= gen_opc_end
                 || num_insns >= max_insns
                 || singlestep
-                || env->singlestep_enabled)) {
+                || ctx.singlestep_enabled)) {
             ret = EXIT_PC_STALE;
         }
     } while (ret == NO_EXIT);
@@ -3474,7 +3481,7 @@
         tcg_gen_movi_i64(cpu_pc, ctx.pc);
         /* FALLTHRU */
     case EXIT_PC_UPDATED:
-        if (env->singlestep_enabled) {
+        if (ctx.singlestep_enabled) {
             gen_excp_1(EXCP_DEBUG, 0);
         } else {
             tcg_gen_exit_tb(0);
diff --git a/target-arm/arm-semi.c b/target-arm/arm-semi.c
index 5f01bca..ee469c4 100644
--- a/target-arm/arm-semi.c
+++ b/target-arm/arm-semi.c
@@ -122,8 +122,10 @@
 static target_ulong syscall_err;
 #endif
 
-static void arm_semi_cb(CPUARMState *env, target_ulong ret, target_ulong err)
+static void arm_semi_cb(CPUState *cs, target_ulong ret, target_ulong err)
 {
+    ARMCPU *cpu = ARM_CPU(cs);
+    CPUARMState *env = &cpu->env;
 #ifdef CONFIG_USER_ONLY
     TaskState *ts = env->opaque;
 #endif
@@ -152,12 +154,14 @@
     }
 }
 
-static void arm_semi_flen_cb(CPUARMState *env, target_ulong ret, target_ulong err)
+static void arm_semi_flen_cb(CPUState *cs, target_ulong ret, target_ulong err)
 {
+    ARMCPU *cpu = ARM_CPU(cs);
+    CPUARMState *env = &cpu->env;
     /* The size is always stored in big-endian order, extract
        the value. We assume the size always fit in 32 bits.  */
     uint32_t size;
-    cpu_memory_rw_debug(env, env->regs[13]-64+32, (uint8_t *)&size, 4, 0);
+    cpu_memory_rw_debug(cs, env->regs[13]-64+32, (uint8_t *)&size, 4, 0);
     env->regs[0] = be32_to_cpu(size);
 #ifdef CONFIG_USER_ONLY
     ((TaskState *)env->opaque)->swi_errno = err;
diff --git a/target-arm/cpu-qom.h b/target-arm/cpu-qom.h
index 48ba605..02162c9 100644
--- a/target-arm/cpu-qom.h
+++ b/target-arm/cpu-qom.h
@@ -147,4 +147,6 @@
 void arm_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
                         int flags);
 
+hwaddr arm_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
+
 #endif
diff --git a/target-arm/cpu.c b/target-arm/cpu.c
index 9f1696f..d3906a4 100644
--- a/target-arm/cpu.c
+++ b/target-arm/cpu.c
@@ -25,6 +25,13 @@
 #endif
 #include "sysemu/sysemu.h"
 
+static void arm_cpu_set_pc(CPUState *cs, vaddr value)
+{
+    ARMCPU *cpu = ARM_CPU(cs);
+
+    cpu->env.regs[15] = value;
+}
+
 static void cp_reg_reset(gpointer key, gpointer value, gpointer opaque)
 {
     /* Reset a single ARMCPRegInfo register */
@@ -816,7 +823,11 @@
     cc->class_by_name = arm_cpu_class_by_name;
     cc->do_interrupt = arm_cpu_do_interrupt;
     cc->dump_state = arm_cpu_dump_state;
-    cpu_class_set_vmsd(cc, &vmstate_arm_cpu);
+    cc->set_pc = arm_cpu_set_pc;
+#ifndef CONFIG_USER_ONLY
+    cc->get_phys_page_debug = arm_cpu_get_phys_page_debug;
+    cc->vmsd = &vmstate_arm_cpu;
+#endif
 }
 
 static void cpu_register(const ARMCPUInfo *info)
diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index c798b27..b2dc494 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -797,11 +797,6 @@
 
 #include "exec/exec-all.h"
 
-static inline void cpu_pc_from_tb(CPUARMState *env, TranslationBlock *tb)
-{
-    env->regs[15] = tb->pc;
-}
-
 /* Load an instruction and return it in the standard little-endian order */
 static inline uint32_t arm_ldl_code(CPUARMState *env, uint32_t addr,
                                     bool do_swap)
diff --git a/target-arm/helper.c b/target-arm/helper.c
index aeae024..b0c3ca1 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -1513,16 +1513,17 @@
 
 void arm_cpu_register_gdb_regs_for_features(ARMCPU *cpu)
 {
+    CPUState *cs = CPU(cpu);
     CPUARMState *env = &cpu->env;
 
     if (arm_feature(env, ARM_FEATURE_NEON)) {
-        gdb_register_coprocessor(env, vfp_gdb_get_reg, vfp_gdb_set_reg,
+        gdb_register_coprocessor(cs, vfp_gdb_get_reg, vfp_gdb_set_reg,
                                  51, "arm-neon.xml", 0);
     } else if (arm_feature(env, ARM_FEATURE_VFP3)) {
-        gdb_register_coprocessor(env, vfp_gdb_get_reg, vfp_gdb_set_reg,
+        gdb_register_coprocessor(cs, vfp_gdb_get_reg, vfp_gdb_set_reg,
                                  35, "arm-vfp3.xml", 0);
     } else if (arm_feature(env, ARM_FEATURE_VFP)) {
-        gdb_register_coprocessor(env, vfp_gdb_get_reg, vfp_gdb_set_reg,
+        gdb_register_coprocessor(cs, vfp_gdb_get_reg, vfp_gdb_set_reg,
                                  19, "arm-vfp.xml", 0);
     }
 }
@@ -2762,17 +2763,19 @@
     return 1;
 }
 
-hwaddr cpu_get_phys_page_debug(CPUARMState *env, target_ulong addr)
+hwaddr arm_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
 {
+    ARMCPU *cpu = ARM_CPU(cs);
     hwaddr phys_addr;
     target_ulong page_size;
     int prot;
     int ret;
 
-    ret = get_phys_addr(env, addr, 0, 0, &phys_addr, &prot, &page_size);
+    ret = get_phys_addr(&cpu->env, addr, 0, 0, &phys_addr, &prot, &page_size);
 
-    if (ret != 0)
+    if (ret != 0) {
         return -1;
+    }
 
     return phys_addr;
 }
diff --git a/target-arm/translate.c b/target-arm/translate.c
index 7b50c8c..6db4c50 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -9911,6 +9911,7 @@
                                                   TranslationBlock *tb,
                                                   bool search_pc)
 {
+    CPUState *cs = CPU(cpu);
     CPUARMState *env = &cpu->env;
     DisasContext dc1, *dc = &dc1;
     CPUBreakpoint *bp;
@@ -9930,7 +9931,7 @@
 
     dc->is_jmp = DISAS_NEXT;
     dc->pc = pc_start;
-    dc->singlestep_enabled = env->singlestep_enabled;
+    dc->singlestep_enabled = cs->singlestep_enabled;
     dc->condjmp = 0;
     dc->thumb = ARM_TBFLAG_THUMB(tb->flags);
     dc->bswap_code = ARM_TBFLAG_BSWAP_CODE(tb->flags);
@@ -10080,7 +10081,7 @@
          * ensures prefetch aborts occur at the right place.  */
         num_insns ++;
     } while (!dc->is_jmp && tcg_ctx.gen_opc_ptr < gen_opc_end &&
-             !env->singlestep_enabled &&
+             !cs->singlestep_enabled &&
              !singlestep &&
              dc->pc < next_page_start &&
              num_insns < max_insns);
@@ -10097,7 +10098,7 @@
     /* At this stage dc->condjmp will only be set when the skipped
        instruction was a conditional branch or trap, and the PC has
        already been written.  */
-    if (unlikely(env->singlestep_enabled)) {
+    if (unlikely(cs->singlestep_enabled)) {
         /* Make sure the pc is updated, and raise a debug exception.  */
         if (dc->condjmp) {
             gen_set_condexec(dc);
diff --git a/target-cris/cpu-qom.h b/target-cris/cpu-qom.h
index af7d14d..d7baf07 100644
--- a/target-cris/cpu-qom.h
+++ b/target-cris/cpu-qom.h
@@ -79,4 +79,6 @@
 void cris_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
                          int flags);
 
+hwaddr cris_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
+
 #endif
diff --git a/target-cris/cpu.c b/target-cris/cpu.c
index 2abb57f..ba095e7 100644
--- a/target-cris/cpu.c
+++ b/target-cris/cpu.c
@@ -26,6 +26,13 @@
 #include "mmu.h"
 
 
+static void cris_cpu_set_pc(CPUState *cs, vaddr value)
+{
+    CRISCPU *cpu = CRIS_CPU(cs);
+
+    cpu->env.pc = value;
+}
+
 /* CPUClass::reset() */
 static void cris_cpu_reset(CPUState *s)
 {
@@ -247,6 +254,10 @@
     cc->class_by_name = cris_cpu_class_by_name;
     cc->do_interrupt = cris_cpu_do_interrupt;
     cc->dump_state = cris_cpu_dump_state;
+    cc->set_pc = cris_cpu_set_pc;
+#ifndef CONFIG_USER_ONLY
+    cc->get_phys_page_debug = cris_cpu_get_phys_page_debug;
+#endif
 }
 
 static const TypeInfo cris_cpu_type_info = {
diff --git a/target-cris/cpu.h b/target-cris/cpu.h
index c12a8ca..4b9fc4c 100644
--- a/target-cris/cpu.h
+++ b/target-cris/cpu.h
@@ -279,8 +279,4 @@
 
 #include "exec/exec-all.h"
 
-static inline void cpu_pc_from_tb(CPUCRISState *env, TranslationBlock *tb)
-{
-    env->pc = tb->pc;
-}
 #endif
diff --git a/target-cris/helper.c b/target-cris/helper.c
index aba7537..d274b38 100644
--- a/target-cris/helper.c
+++ b/target-cris/helper.c
@@ -255,16 +255,17 @@
           env->pregs[PR_ERP]);
 }
 
-hwaddr cpu_get_phys_page_debug(CPUCRISState * env, target_ulong addr)
+hwaddr cris_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
 {
+    CRISCPU *cpu = CRIS_CPU(cs);
     uint32_t phy = addr;
     struct cris_mmu_result res;
     int miss;
 
-    miss = cris_mmu_translate(&res, env, addr, 0, 0, 1);
+    miss = cris_mmu_translate(&res, &cpu->env, addr, 0, 0, 1);
     /* If D TLB misses, try I TLB.  */
     if (miss) {
-        miss = cris_mmu_translate(&res, env, addr, 2, 0, 1);
+        miss = cris_mmu_translate(&res, &cpu->env, addr, 2, 0, 1);
     }
 
     if (!miss) {
diff --git a/target-cris/translate.c b/target-cris/translate.c
index 1de9743..2a4beeb 100644
--- a/target-cris/translate.c
+++ b/target-cris/translate.c
@@ -3165,6 +3165,7 @@
 gen_intermediate_code_internal(CRISCPU *cpu, TranslationBlock *tb,
                                bool search_pc)
 {
+    CPUState *cs = CPU(cpu);
     CPUCRISState *env = &cpu->env;
     uint16_t *gen_opc_end;
     uint32_t pc_start;
@@ -3197,7 +3198,7 @@
     dc->is_jmp = DISAS_NEXT;
     dc->ppc = pc_start;
     dc->pc = pc_start;
-    dc->singlestep_enabled = env->singlestep_enabled;
+    dc->singlestep_enabled = cs->singlestep_enabled;
     dc->flags_uptodate = 1;
     dc->flagx_known = 1;
     dc->flags_x = tb->flags & X_FLAG;
@@ -3337,7 +3338,7 @@
 
         /* If we are rexecuting a branch due to exceptions on
            delay slots dont break.  */
-        if (!(tb->pc & 1) && env->singlestep_enabled) {
+        if (!(tb->pc & 1) && cs->singlestep_enabled) {
             break;
         }
     } while (!dc->is_jmp && !dc->cpustate_changed
@@ -3370,7 +3371,7 @@
 
     cris_evaluate_flags(dc);
 
-    if (unlikely(env->singlestep_enabled)) {
+    if (unlikely(cs->singlestep_enabled)) {
         if (dc->is_jmp == DISAS_NEXT) {
             tcg_gen_movi_tl(env_pc, npc);
         }
diff --git a/target-i386/cpu-qom.h b/target-i386/cpu-qom.h
index 7e55e5f..d928562 100644
--- a/target-i386/cpu-qom.h
+++ b/target-i386/cpu-qom.h
@@ -104,4 +104,6 @@
 void x86_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
                         int flags);
 
+hwaddr x86_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
+
 #endif
diff --git a/target-i386/cpu.c b/target-i386/cpu.c
index e3f75a8..cd350cb 100644
--- a/target-i386/cpu.c
+++ b/target-i386/cpu.c
@@ -2506,6 +2506,20 @@
     return cpu->env.cr[0] & CR0_PG_MASK;
 }
 
+static void x86_cpu_set_pc(CPUState *cs, vaddr value)
+{
+    X86CPU *cpu = X86_CPU(cs);
+
+    cpu->env.eip = value;
+}
+
+static void x86_cpu_synchronize_from_tb(CPUState *cs, TranslationBlock *tb)
+{
+    X86CPU *cpu = X86_CPU(cs);
+
+    cpu->env.eip = tb->pc - tb->cs_base;
+}
+
 static void x86_cpu_common_class_init(ObjectClass *oc, void *data)
 {
     X86CPUClass *xcc = X86_CPU_CLASS(oc);
@@ -2522,16 +2536,19 @@
 
     cc->do_interrupt = x86_cpu_do_interrupt;
     cc->dump_state = x86_cpu_dump_state;
+    cc->set_pc = x86_cpu_set_pc;
+    cc->synchronize_from_tb = x86_cpu_synchronize_from_tb;
     cc->get_arch_id = x86_cpu_get_arch_id;
     cc->get_paging_enabled = x86_cpu_get_paging_enabled;
 #ifndef CONFIG_USER_ONLY
     cc->get_memory_mapping = x86_cpu_get_memory_mapping;
+    cc->get_phys_page_debug = x86_cpu_get_phys_page_debug;
     cc->write_elf64_note = x86_cpu_write_elf64_note;
     cc->write_elf64_qemunote = x86_cpu_write_elf64_qemunote;
     cc->write_elf32_note = x86_cpu_write_elf32_note;
     cc->write_elf32_qemunote = x86_cpu_write_elf32_qemunote;
+    cc->vmsd = &vmstate_x86_cpu;
 #endif
-    cpu_class_set_vmsd(cc, &vmstate_x86_cpu);
 }
 
 static const TypeInfo x86_cpu_type_info = {
diff --git a/target-i386/cpu.h b/target-i386/cpu.h
index 2d005b3..cedefdc 100644
--- a/target-i386/cpu.h
+++ b/target-i386/cpu.h
@@ -1148,11 +1148,6 @@
 
 #include "exec/exec-all.h"
 
-static inline void cpu_pc_from_tb(CPUX86State *env, TranslationBlock *tb)
-{
-    env->eip = tb->pc - tb->cs_base;
-}
-
 static inline void cpu_get_tb_cpu_state(CPUX86State *env, target_ulong *pc,
                                         target_ulong *cs_base, int *flags)
 {
diff --git a/target-i386/helper.c b/target-i386/helper.c
index d6f43d7..bf3e2ac 100644
--- a/target-i386/helper.c
+++ b/target-i386/helper.c
@@ -363,7 +363,7 @@
 
         cpu_fprintf(f, "Code=");
         for (i = 0; i < DUMP_CODE_BYTES_TOTAL; i++) {
-            if (cpu_memory_rw_debug(env, base - offs + i, &code, 1, 0) == 0) {
+            if (cpu_memory_rw_debug(cs, base - offs + i, &code, 1, 0) == 0) {
                 snprintf(codestr, sizeof(codestr), "%02x", code);
             } else {
                 snprintf(codestr, sizeof(codestr), "??");
@@ -884,8 +884,10 @@
     return 1;
 }
 
-hwaddr cpu_get_phys_page_debug(CPUX86State *env, target_ulong addr)
+hwaddr x86_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
 {
+    X86CPU *cpu = X86_CPU(cs);
+    CPUX86State *env = &cpu->env;
     target_ulong pde_addr, pte_addr;
     uint64_t pte;
     hwaddr paddr;
@@ -1258,6 +1260,8 @@
                             target_ulong *base, unsigned int *limit,
                             unsigned int *flags)
 {
+    X86CPU *cpu = x86_env_get_cpu(env);
+    CPUState *cs = CPU(cpu);
     SegmentCache *dt;
     target_ulong ptr;
     uint32_t e1, e2;
@@ -1270,8 +1274,8 @@
     index = selector & ~7;
     ptr = dt->base + index;
     if ((index + 7) > dt->limit
-        || cpu_memory_rw_debug(env, ptr, (uint8_t *)&e1, sizeof(e1), 0) != 0
-        || cpu_memory_rw_debug(env, ptr+4, (uint8_t *)&e2, sizeof(e2), 0) != 0)
+        || cpu_memory_rw_debug(cs, ptr, (uint8_t *)&e1, sizeof(e1), 0) != 0
+        || cpu_memory_rw_debug(cs, ptr+4, (uint8_t *)&e2, sizeof(e2), 0) != 0)
         return 0;
 
     *base = ((e1 >> 16) | ((e2 & 0xff) << 16) | (e2 & 0xff000000));
diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index 8315489..3c9d10a 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -1594,6 +1594,7 @@
 
 static int kvm_guest_debug_workarounds(X86CPU *cpu)
 {
+    CPUState *cs = CPU(cpu);
     CPUX86State *env = &cpu->env;
     int ret = 0;
     unsigned long reinject_trap = 0;
@@ -1616,7 +1617,7 @@
      * reinject them via SET_GUEST_DEBUG.
      */
     if (reinject_trap ||
-        (!kvm_has_robust_singlestep() && env->singlestep_enabled)) {
+        (!kvm_has_robust_singlestep() && cs->singlestep_enabled)) {
         ret = kvm_update_guest_debug(env, reinject_trap);
     }
     return ret;
@@ -1931,25 +1932,23 @@
     return 1;
 }
 
-int kvm_arch_insert_sw_breakpoint(CPUState *cpu, struct kvm_sw_breakpoint *bp)
+int kvm_arch_insert_sw_breakpoint(CPUState *cs, struct kvm_sw_breakpoint *bp)
 {
-    CPUX86State *env = &X86_CPU(cpu)->env;
     static const uint8_t int3 = 0xcc;
 
-    if (cpu_memory_rw_debug(env, bp->pc, (uint8_t *)&bp->saved_insn, 1, 0) ||
-        cpu_memory_rw_debug(env, bp->pc, (uint8_t *)&int3, 1, 1)) {
+    if (cpu_memory_rw_debug(cs, bp->pc, (uint8_t *)&bp->saved_insn, 1, 0) ||
+        cpu_memory_rw_debug(cs, bp->pc, (uint8_t *)&int3, 1, 1)) {
         return -EINVAL;
     }
     return 0;
 }
 
-int kvm_arch_remove_sw_breakpoint(CPUState *cpu, struct kvm_sw_breakpoint *bp)
+int kvm_arch_remove_sw_breakpoint(CPUState *cs, struct kvm_sw_breakpoint *bp)
 {
-    CPUX86State *env = &X86_CPU(cpu)->env;
     uint8_t int3;
 
-    if (cpu_memory_rw_debug(env, bp->pc, &int3, 1, 0) || int3 != 0xcc ||
-        cpu_memory_rw_debug(env, bp->pc, (uint8_t *)&bp->saved_insn, 1, 1)) {
+    if (cpu_memory_rw_debug(cs, bp->pc, &int3, 1, 0) || int3 != 0xcc ||
+        cpu_memory_rw_debug(cs, bp->pc, (uint8_t *)&bp->saved_insn, 1, 1)) {
         return -EINVAL;
     }
     return 0;
@@ -2042,13 +2041,14 @@
 static int kvm_handle_debug(X86CPU *cpu,
                             struct kvm_debug_exit_arch *arch_info)
 {
+    CPUState *cs = CPU(cpu);
     CPUX86State *env = &cpu->env;
     int ret = 0;
     int n;
 
     if (arch_info->exception == 1) {
         if (arch_info->dr6 & (1 << 14)) {
-            if (env->singlestep_enabled) {
+            if (cs->singlestep_enabled) {
                 ret = EXCP_DEBUG;
             }
         } else {
diff --git a/target-i386/translate.c b/target-i386/translate.c
index 6550c27..065a9d3 100644
--- a/target-i386/translate.c
+++ b/target-i386/translate.c
@@ -8255,6 +8255,7 @@
                                                   TranslationBlock *tb,
                                                   bool search_pc)
 {
+    CPUState *cs = CPU(cpu);
     CPUX86State *env = &cpu->env;
     DisasContext dc1, *dc = &dc1;
     target_ulong pc_ptr;
@@ -8281,7 +8282,7 @@
     dc->cpl = (flags >> HF_CPL_SHIFT) & 3;
     dc->iopl = (flags >> IOPL_SHIFT) & 3;
     dc->tf = (flags >> TF_SHIFT) & 1;
-    dc->singlestep_enabled = env->singlestep_enabled;
+    dc->singlestep_enabled = cs->singlestep_enabled;
     dc->cc_op = CC_OP_DYNAMIC;
     dc->cc_op_dirty = false;
     dc->cs_base = cs_base;
@@ -8302,7 +8303,7 @@
     dc->code64 = (flags >> HF_CS64_SHIFT) & 1;
 #endif
     dc->flags = flags;
-    dc->jmp_opt = !(dc->tf || env->singlestep_enabled ||
+    dc->jmp_opt = !(dc->tf || cs->singlestep_enabled ||
                     (flags & HF_INHIBIT_IRQ_MASK)
 #ifndef CONFIG_SOFTMMU
                     || (flags & HF_SOFTMMU_MASK)
diff --git a/target-lm32/cpu-qom.h b/target-lm32/cpu-qom.h
index e3bb619..9e27329 100644
--- a/target-lm32/cpu-qom.h
+++ b/target-lm32/cpu-qom.h
@@ -78,5 +78,6 @@
 void lm32_cpu_do_interrupt(CPUState *cpu);
 void lm32_cpu_dump_state(CPUState *cpu, FILE *f, fprintf_function cpu_fprintf,
                          int flags);
+hwaddr lm32_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
 
 #endif
diff --git a/target-lm32/cpu.c b/target-lm32/cpu.c
index 04327ac..ce55e48 100644
--- a/target-lm32/cpu.c
+++ b/target-lm32/cpu.c
@@ -22,6 +22,13 @@
 #include "qemu-common.h"
 
 
+static void lm32_cpu_set_pc(CPUState *cs, vaddr value)
+{
+    LM32CPU *cpu = LM32_CPU(cs);
+
+    cpu->env.pc = value;
+}
+
 /* CPUClass::reset() */
 static void lm32_cpu_reset(CPUState *s)
 {
@@ -79,7 +86,11 @@
 
     cc->do_interrupt = lm32_cpu_do_interrupt;
     cc->dump_state = lm32_cpu_dump_state;
-    cpu_class_set_vmsd(cc, &vmstate_lm32_cpu);
+    cc->set_pc = lm32_cpu_set_pc;
+#ifndef CONFIG_USER_ONLY
+    cc->get_phys_page_debug = lm32_cpu_get_phys_page_debug;
+    cc->vmsd = &vmstate_lm32_cpu;
+#endif
 }
 
 static const TypeInfo lm32_cpu_type_info = {
diff --git a/target-lm32/cpu.h b/target-lm32/cpu.h
index 856bdc7..dbfe043 100644
--- a/target-lm32/cpu.h
+++ b/target-lm32/cpu.h
@@ -232,9 +232,4 @@
 
 #include "exec/exec-all.h"
 
-static inline void cpu_pc_from_tb(CPULM32State *env, TranslationBlock *tb)
-{
-    env->pc = tb->pc;
-}
-
 #endif
diff --git a/target-lm32/helper.c b/target-lm32/helper.c
index 615b44e..15bc615 100644
--- a/target-lm32/helper.c
+++ b/target-lm32/helper.c
@@ -37,10 +37,12 @@
     return 0;
 }
 
-hwaddr cpu_get_phys_page_debug(CPULM32State *env, target_ulong addr)
+hwaddr lm32_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
 {
+    LM32CPU *cpu = LM32_CPU(cs);
+
     addr &= TARGET_PAGE_MASK;
-    if (env->flags & LM32_FLAG_IGNORE_MSB) {
+    if (cpu->env.flags & LM32_FLAG_IGNORE_MSB) {
         return addr & 0x7fffffff;
     } else {
         return addr;
diff --git a/target-lm32/translate.c b/target-lm32/translate.c
index ed12f50..1247287 100644
--- a/target-lm32/translate.c
+++ b/target-lm32/translate.c
@@ -1015,6 +1015,7 @@
 void gen_intermediate_code_internal(LM32CPU *cpu,
                                     TranslationBlock *tb, bool search_pc)
 {
+    CPUState *cs = CPU(cpu);
     CPULM32State *env = &cpu->env;
     struct DisasContext ctx, *dc = &ctx;
     uint16_t *gen_opc_end;
@@ -1032,7 +1033,7 @@
 
     dc->is_jmp = DISAS_NEXT;
     dc->pc = pc_start;
-    dc->singlestep_enabled = env->singlestep_enabled;
+    dc->singlestep_enabled = cs->singlestep_enabled;
     dc->nr_nops = 0;
 
     if (pc_start & 3) {
@@ -1077,7 +1078,7 @@
 
     } while (!dc->is_jmp
          && tcg_ctx.gen_opc_ptr < gen_opc_end
-         && !env->singlestep_enabled
+         && !cs->singlestep_enabled
          && !singlestep
          && (dc->pc < next_page_start)
          && num_insns < max_insns);
@@ -1086,7 +1087,7 @@
         gen_io_end();
     }
 
-    if (unlikely(env->singlestep_enabled)) {
+    if (unlikely(cs->singlestep_enabled)) {
         if (dc->is_jmp == DISAS_NEXT) {
             tcg_gen_movi_tl(cpu_pc, dc->pc);
         }
diff --git a/target-m68k/cpu-qom.h b/target-m68k/cpu-qom.h
index 858bf30..7115707 100644
--- a/target-m68k/cpu-qom.h
+++ b/target-m68k/cpu-qom.h
@@ -73,5 +73,6 @@
 void m68k_cpu_do_interrupt(CPUState *cpu);
 void m68k_cpu_dump_state(CPUState *cpu, FILE *f, fprintf_function cpu_fprintf,
                          int flags);
+hwaddr m68k_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
 
 #endif
diff --git a/target-m68k/cpu.c b/target-m68k/cpu.c
index 1b6ef66..988f476 100644
--- a/target-m68k/cpu.c
+++ b/target-m68k/cpu.c
@@ -23,6 +23,13 @@
 #include "migration/vmstate.h"
 
 
+static void m68k_cpu_set_pc(CPUState *cs, vaddr value)
+{
+    M68kCPU *cpu = M68K_CPU(cs);
+
+    cpu->env.pc = value;
+}
+
 static void m68k_set_feature(CPUM68KState *env, int feature)
 {
     env->features |= (1u << feature);
@@ -182,6 +189,10 @@
     cc->class_by_name = m68k_cpu_class_by_name;
     cc->do_interrupt = m68k_cpu_do_interrupt;
     cc->dump_state = m68k_cpu_dump_state;
+    cc->set_pc = m68k_cpu_set_pc;
+#ifndef CONFIG_USER_ONLY
+    cc->get_phys_page_debug = m68k_cpu_get_phys_page_debug;
+#endif
     dc->vmsd = &vmstate_m68k_cpu;
 }
 
diff --git a/target-m68k/cpu.h b/target-m68k/cpu.h
index 9fdf89e..cfd6846 100644
--- a/target-m68k/cpu.h
+++ b/target-m68k/cpu.h
@@ -260,9 +260,4 @@
 
 #include "exec/exec-all.h"
 
-static inline void cpu_pc_from_tb(CPUM68KState *env, TranslationBlock *tb)
-{
-    env->pc = tb->pc;
-}
-
 #endif
diff --git a/target-m68k/helper.c b/target-m68k/helper.c
index 54fa419..00a7a08 100644
--- a/target-m68k/helper.c
+++ b/target-m68k/helper.c
@@ -121,10 +121,11 @@
 
 void m68k_cpu_init_gdb(M68kCPU *cpu)
 {
+    CPUState *cs = CPU(cpu);
     CPUM68KState *env = &cpu->env;
 
     if (m68k_feature(env, M68K_FEATURE_CF_FPU)) {
-        gdb_register_coprocessor(env, fpu_gdb_get_reg, fpu_gdb_set_reg,
+        gdb_register_coprocessor(cs, fpu_gdb_get_reg, fpu_gdb_set_reg,
                                  11, "cf-fp.xml", 18);
     }
     /* TODO: Add [E]MAC registers.  */
@@ -290,7 +291,7 @@
 /* MMU */
 
 /* TODO: This will need fixing once the MMU is implemented.  */
-hwaddr cpu_get_phys_page_debug(CPUM68KState *env, target_ulong addr)
+hwaddr m68k_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
 {
     return addr;
 }
diff --git a/target-m68k/m68k-semi.c b/target-m68k/m68k-semi.c
index 239fadb..94c4983 100644
--- a/target-m68k/m68k-semi.c
+++ b/target-m68k/m68k-semi.c
@@ -161,8 +161,11 @@
 
 static int m68k_semi_is_fseek;
 
-static void m68k_semi_cb(CPUM68KState *env, target_ulong ret, target_ulong err)
+static void m68k_semi_cb(CPUState *cs, target_ulong ret, target_ulong err)
 {
+    M68kCPU *cpu = M68K_CPU(cs);
+    CPUM68KState *env = &cpu->env;
+
     if (m68k_semi_is_fseek) {
         /* FIXME: We've already lost the high bits of the fseek
            return value.  */
diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index 2d73af5..d562eeb 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -2974,6 +2974,7 @@
 gen_intermediate_code_internal(M68kCPU *cpu, TranslationBlock *tb,
                                bool search_pc)
 {
+    CPUState *cs = CPU(cpu);
     CPUM68KState *env = &cpu->env;
     DisasContext dc1, *dc = &dc1;
     uint16_t *gen_opc_end;
@@ -2995,7 +2996,7 @@
     dc->is_jmp = DISAS_NEXT;
     dc->pc = pc_start;
     dc->cc_op = CC_OP_DYNAMIC;
-    dc->singlestep_enabled = env->singlestep_enabled;
+    dc->singlestep_enabled = cs->singlestep_enabled;
     dc->fpcr = env->fpcr;
     dc->user = (env->sr & SR_S) == 0;
     dc->is_mem = 0;
@@ -3038,14 +3039,14 @@
 	disas_m68k_insn(env, dc);
         num_insns++;
     } while (!dc->is_jmp && tcg_ctx.gen_opc_ptr < gen_opc_end &&
-             !env->singlestep_enabled &&
+             !cs->singlestep_enabled &&
              !singlestep &&
              (pc_offset) < (TARGET_PAGE_SIZE - 32) &&
              num_insns < max_insns);
 
     if (tb->cflags & CF_LAST_IO)
         gen_io_end();
-    if (unlikely(env->singlestep_enabled)) {
+    if (unlikely(cs->singlestep_enabled)) {
         /* Make sure the pc is updated, and raise a debug exception.  */
         if (!dc->is_jmp) {
             gen_flush_cc_op(dc);
diff --git a/target-microblaze/cpu-qom.h b/target-microblaze/cpu-qom.h
index ec2b989..1318a36 100644
--- a/target-microblaze/cpu-qom.h
+++ b/target-microblaze/cpu-qom.h
@@ -74,5 +74,6 @@
 void mb_cpu_do_interrupt(CPUState *cs);
 void mb_cpu_dump_state(CPUState *cpu, FILE *f, fprintf_function cpu_fprintf,
                        int flags);
+hwaddr mb_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
 
 #endif
diff --git a/target-microblaze/cpu.c b/target-microblaze/cpu.c
index dce1c7e..9f10c8c 100644
--- a/target-microblaze/cpu.c
+++ b/target-microblaze/cpu.c
@@ -26,6 +26,13 @@
 #include "migration/vmstate.h"
 
 
+static void mb_cpu_set_pc(CPUState *cs, vaddr value)
+{
+    MicroBlazeCPU *cpu = MICROBLAZE_CPU(cs);
+
+    cpu->env.sregs[SR_PC] = value;
+}
+
 /* CPUClass::reset() */
 static void mb_cpu_reset(CPUState *s)
 {
@@ -133,7 +140,11 @@
 
     cc->do_interrupt = mb_cpu_do_interrupt;
     cc->dump_state = mb_cpu_dump_state;
-    cpu_class_set_do_unassigned_access(cc, mb_cpu_unassigned_access);
+    cc->set_pc = mb_cpu_set_pc;
+#ifndef CONFIG_USER_ONLY
+    cc->do_unassigned_access = mb_cpu_unassigned_access;
+    cc->get_phys_page_debug = mb_cpu_get_phys_page_debug;
+#endif
     dc->vmsd = &vmstate_mb_cpu;
     dc->props = mb_properties;
 }
diff --git a/target-microblaze/cpu.h b/target-microblaze/cpu.h
index 6c35475..7508cf5 100644
--- a/target-microblaze/cpu.h
+++ b/target-microblaze/cpu.h
@@ -365,9 +365,4 @@
 
 #include "exec/exec-all.h"
 
-static inline void cpu_pc_from_tb(CPUMBState *env, TranslationBlock *tb)
-{
-    env->sregs[SR_PC] = tb->pc;
-}
-
 #endif
diff --git a/target-microblaze/helper.c b/target-microblaze/helper.c
index c6c96d4..4fa9ce9 100644
--- a/target-microblaze/helper.c
+++ b/target-microblaze/helper.c
@@ -265,8 +265,10 @@
     }
 }
 
-hwaddr cpu_get_phys_page_debug(CPUMBState * env, target_ulong addr)
+hwaddr mb_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
 {
+    MicroBlazeCPU *cpu = MICROBLAZE_CPU(cs);
+    CPUMBState *env = &cpu->env;
     target_ulong vaddr, paddr = 0;
     struct microblaze_mmu_lookup lu;
     unsigned int hit;
diff --git a/target-microblaze/translate.c b/target-microblaze/translate.c
index eba255b..cd43577 100644
--- a/target-microblaze/translate.c
+++ b/target-microblaze/translate.c
@@ -1741,6 +1741,7 @@
 gen_intermediate_code_internal(MicroBlazeCPU *cpu, TranslationBlock *tb,
                                bool search_pc)
 {
+    CPUState *cs = CPU(cpu);
     CPUMBState *env = &cpu->env;
     uint16_t *gen_opc_end;
     uint32_t pc_start;
@@ -1766,7 +1767,7 @@
         dc->jmp = JMP_INDIRECT;
     }
     dc->pc = pc_start;
-    dc->singlestep_enabled = env->singlestep_enabled;
+    dc->singlestep_enabled = cs->singlestep_enabled;
     dc->cpustate_changed = 0;
     dc->abort_at_next_insn = 0;
     dc->nr_nops = 0;
@@ -1859,8 +1860,9 @@
                 break;
             }
         }
-        if (env->singlestep_enabled)
+        if (cs->singlestep_enabled) {
             break;
+        }
     } while (!dc->is_jmp && !dc->cpustate_changed
          && tcg_ctx.gen_opc_ptr < gen_opc_end
                  && !singlestep
@@ -1887,7 +1889,7 @@
     }
     t_sync_flags(dc);
 
-    if (unlikely(env->singlestep_enabled)) {
+    if (unlikely(cs->singlestep_enabled)) {
         TCGv_i32 tmp = tcg_const_i32(EXCP_DEBUG);
 
         if (dc->is_jmp != DISAS_JUMP) {
diff --git a/target-mips/cpu-qom.h b/target-mips/cpu-qom.h
index 654744a..7c8e616 100644
--- a/target-mips/cpu-qom.h
+++ b/target-mips/cpu-qom.h
@@ -77,5 +77,6 @@
 void mips_cpu_do_interrupt(CPUState *cpu);
 void mips_cpu_dump_state(CPUState *cpu, FILE *f, fprintf_function cpu_fprintf,
                          int flags);
+hwaddr mips_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
 
 #endif
diff --git a/target-mips/cpu.c b/target-mips/cpu.c
index 60a3faf..4834c86 100644
--- a/target-mips/cpu.c
+++ b/target-mips/cpu.c
@@ -22,6 +22,29 @@
 #include "qemu-common.h"
 
 
+static void mips_cpu_set_pc(CPUState *cs, vaddr value)
+{
+    MIPSCPU *cpu = MIPS_CPU(cs);
+    CPUMIPSState *env = &cpu->env;
+
+    env->active_tc.PC = value & ~(target_ulong)1;
+    if (value & 1) {
+        env->hflags |= MIPS_HFLAG_M16;
+    } else {
+        env->hflags &= ~(MIPS_HFLAG_M16);
+    }
+}
+
+static void mips_cpu_synchronize_from_tb(CPUState *cs, TranslationBlock *tb)
+{
+    MIPSCPU *cpu = MIPS_CPU(cs);
+    CPUMIPSState *env = &cpu->env;
+
+    env->active_tc.PC = tb->pc;
+    env->hflags &= ~MIPS_HFLAG_BMASK;
+    env->hflags |= tb->flags & MIPS_HFLAG_BMASK;
+}
+
 /* CPUClass::reset() */
 static void mips_cpu_reset(CPUState *s)
 {
@@ -75,7 +98,12 @@
 
     cc->do_interrupt = mips_cpu_do_interrupt;
     cc->dump_state = mips_cpu_dump_state;
-    cpu_class_set_do_unassigned_access(cc, mips_cpu_unassigned_access);
+    cc->set_pc = mips_cpu_set_pc;
+    cc->synchronize_from_tb = mips_cpu_synchronize_from_tb;
+#ifndef CONFIG_USER_ONLY
+    cc->do_unassigned_access = mips_cpu_unassigned_access;
+    cc->get_phys_page_debug = mips_cpu_get_phys_page_debug;
+#endif
 }
 
 static const TypeInfo mips_cpu_type_info = {
diff --git a/target-mips/cpu.h b/target-mips/cpu.h
index 7ffd2e3..a29c82f 100644
--- a/target-mips/cpu.h
+++ b/target-mips/cpu.h
@@ -732,13 +732,6 @@
 
 #include "exec/exec-all.h"
 
-static inline void cpu_pc_from_tb(CPUMIPSState *env, TranslationBlock *tb)
-{
-    env->active_tc.PC = tb->pc;
-    env->hflags &= ~MIPS_HFLAG_BMASK;
-    env->hflags |= tb->flags & MIPS_HFLAG_BMASK;
-}
-
 static inline void compute_hflags(CPUMIPSState *env)
 {
     env->hflags &= ~(MIPS_HFLAG_COP1X | MIPS_HFLAG_64 | MIPS_HFLAG_CP0 |
diff --git a/target-mips/helper.c b/target-mips/helper.c
index 6983b92..6feef7b 100644
--- a/target-mips/helper.c
+++ b/target-mips/helper.c
@@ -254,13 +254,16 @@
 }
 
 #if !defined(CONFIG_USER_ONLY)
-hwaddr cpu_get_phys_page_debug(CPUMIPSState *env, target_ulong addr)
+hwaddr mips_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
 {
+    MIPSCPU *cpu = MIPS_CPU(cs);
     hwaddr phys_addr;
     int prot;
 
-    if (get_physical_address(env, &phys_addr, &prot, addr, 0, ACCESS_INT) != 0)
+    if (get_physical_address(&cpu->env, &phys_addr, &prot, addr, 0,
+                             ACCESS_INT) != 0) {
         return -1;
+    }
     return phys_addr;
 }
 #endif
diff --git a/target-mips/translate.c b/target-mips/translate.c
index 8246c20..877f8df 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -15543,6 +15543,7 @@
 gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb,
                                bool search_pc)
 {
+    CPUState *cs = CPU(cpu);
     CPUMIPSState *env = &cpu->env;
     DisasContext ctx;
     target_ulong pc_start;
@@ -15561,7 +15562,7 @@
     gen_opc_end = tcg_ctx.gen_opc_buf + OPC_MAX_SIZE;
     ctx.pc = pc_start;
     ctx.saved_pc = -1;
-    ctx.singlestep_enabled = env->singlestep_enabled;
+    ctx.singlestep_enabled = cs->singlestep_enabled;
     ctx.insn_flags = env->insn_flags;
     ctx.tb = tb;
     ctx.bstate = BS_NONE;
@@ -15637,8 +15638,9 @@
            This is what GDB expects and is consistent with what the
            hardware does (e.g. if a delay slot instruction faults, the
            reported PC is the PC of the branch).  */
-        if (env->singlestep_enabled && (ctx.hflags & MIPS_HFLAG_BMASK) == 0)
+        if (cs->singlestep_enabled && (ctx.hflags & MIPS_HFLAG_BMASK) == 0) {
             break;
+        }
 
         if ((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0)
             break;
@@ -15653,9 +15655,10 @@
         if (singlestep)
             break;
     }
-    if (tb->cflags & CF_LAST_IO)
+    if (tb->cflags & CF_LAST_IO) {
         gen_io_end();
-    if (env->singlestep_enabled && ctx.bstate != BS_BRANCH) {
+    }
+    if (cs->singlestep_enabled && ctx.bstate != BS_BRANCH) {
         save_cpu_state(&ctx, ctx.bstate == BS_NONE);
         gen_helper_0e0i(raise_exception, EXCP_DEBUG);
     } else {
diff --git a/target-moxie/cpu.c b/target-moxie/cpu.c
index 92ca594..6550be5 100644
--- a/target-moxie/cpu.c
+++ b/target-moxie/cpu.c
@@ -22,6 +22,13 @@
 #include "migration/vmstate.h"
 #include "machine.h"
 
+static void moxie_cpu_set_pc(CPUState *cs, vaddr value)
+{
+    MoxieCPU *cpu = MOXIE_CPU(cs);
+
+    cpu->env.pc = value;
+}
+
 static void moxie_cpu_reset(CPUState *s)
 {
     MoxieCPU *cpu = MOXIE_CPU(s);
@@ -93,7 +100,11 @@
 
     cc->do_interrupt = moxie_cpu_do_interrupt;
     cc->dump_state = moxie_cpu_dump_state;
-    cpu_class_set_vmsd(cc, &vmstate_moxie_cpu);
+    cc->set_pc = moxie_cpu_set_pc;
+#ifndef CONFIG_USER_ONLY
+    cc->get_phys_page_debug = moxie_cpu_get_phys_page_debug;
+    cc->vmsd = &vmstate_moxie_cpu;
+#endif
 }
 
 static void moxielite_initfn(Object *obj)
diff --git a/target-moxie/cpu.h b/target-moxie/cpu.h
index 72d02c2..5ce14b5 100644
--- a/target-moxie/cpu.h
+++ b/target-moxie/cpu.h
@@ -118,6 +118,7 @@
 void moxie_cpu_do_interrupt(CPUState *cs);
 void moxie_cpu_dump_state(CPUState *cpu, FILE *f,
                           fprintf_function cpu_fprintf, int flags);
+hwaddr moxie_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
 void moxie_translate_init(void);
 int cpu_moxie_signal_handler(int host_signum, void *pinfo,
                              void *puc);
@@ -143,11 +144,6 @@
 #include "exec/cpu-all.h"
 #include "exec/exec-all.h"
 
-static inline void cpu_pc_from_tb(CPUMoxieState *env, TranslationBlock *tb)
-{
-    env->pc = tb->pc;
-}
-
 static inline void cpu_get_tb_cpu_state(CPUMoxieState *env, target_ulong *pc,
                                         target_ulong *cs_base, int *flags)
 {
diff --git a/target-moxie/helper.c b/target-moxie/helper.c
index ea0788f..b12e4ff 100644
--- a/target-moxie/helper.c
+++ b/target-moxie/helper.c
@@ -118,11 +118,6 @@
     return 1;
 }
 
-hwaddr cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
-{
-    return addr;
-}
-
 #else /* !CONFIG_USER_ONLY */
 
 int cpu_moxie_handle_mmu_fault(CPUMoxieState *env, target_ulong address,
@@ -162,12 +157,14 @@
     }
 }
 
-hwaddr cpu_get_phys_page_debug(CPUMoxieState *env, target_ulong addr)
+hwaddr moxie_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
 {
+    MoxieCPU *cpu = MOXIE_CPU(cs);
     uint32_t phy = addr;
     MoxieMMUResult res;
     int miss;
-    miss = moxie_mmu_translate(&res, env, addr, 0, 0);
+
+    miss = moxie_mmu_translate(&res, &cpu->env, addr, 0, 0);
     if (!miss) {
         phy = res.phy;
     }
diff --git a/target-moxie/translate.c b/target-moxie/translate.c
index 664d359..8cc0bb7 100644
--- a/target-moxie/translate.c
+++ b/target-moxie/translate.c
@@ -824,6 +824,7 @@
 gen_intermediate_code_internal(MoxieCPU *cpu, TranslationBlock *tb,
                                bool search_pc)
 {
+    CPUState *cs = CPU(cpu);
     DisasContext ctx;
     target_ulong pc_start;
     uint16_t *gen_opc_end;
@@ -871,7 +872,7 @@
         ctx.pc += decode_opc(cpu, &ctx);
         num_insns++;
 
-        if (env->singlestep_enabled) {
+        if (cs->singlestep_enabled) {
             break;
         }
 
@@ -880,7 +881,7 @@
         }
     } while (ctx.bstate == BS_NONE && tcg_ctx.gen_opc_ptr < gen_opc_end);
 
-    if (env->singlestep_enabled) {
+    if (cs->singlestep_enabled) {
         tcg_gen_movi_tl(cpu_pc, ctx.pc);
         gen_helper_debug(cpu_env);
     } else {
diff --git a/target-openrisc/cpu.c b/target-openrisc/cpu.c
index 6d40f1b..3da5a7a 100644
--- a/target-openrisc/cpu.c
+++ b/target-openrisc/cpu.c
@@ -20,6 +20,13 @@
 #include "cpu.h"
 #include "qemu-common.h"
 
+static void openrisc_cpu_set_pc(CPUState *cs, vaddr value)
+{
+    OpenRISCCPU *cpu = OPENRISC_CPU(cs);
+
+    cpu->env.pc = value;
+}
+
 /* CPUClass::reset() */
 static void openrisc_cpu_reset(CPUState *s)
 {
@@ -146,7 +153,11 @@
     cc->class_by_name = openrisc_cpu_class_by_name;
     cc->do_interrupt = openrisc_cpu_do_interrupt;
     cc->dump_state = openrisc_cpu_dump_state;
-    device_class_set_vmsd(dc, &vmstate_openrisc_cpu);
+    cc->set_pc = openrisc_cpu_set_pc;
+#ifndef CONFIG_USER_ONLY
+    cc->get_phys_page_debug = openrisc_cpu_get_phys_page_debug;
+    dc->vmsd = &vmstate_openrisc_cpu;
+#endif
 }
 
 static void cpu_register(const OpenRISCCPUInfo *info)
diff --git a/target-openrisc/cpu.h b/target-openrisc/cpu.h
index 0aff8f2..3ddb767 100644
--- a/target-openrisc/cpu.h
+++ b/target-openrisc/cpu.h
@@ -349,6 +349,7 @@
 void openrisc_cpu_do_interrupt(CPUState *cpu);
 void openrisc_cpu_dump_state(CPUState *cpu, FILE *f,
                              fprintf_function cpu_fprintf, int flags);
+hwaddr openrisc_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
 void openrisc_translate_init(void);
 int cpu_openrisc_handle_mmu_fault(CPUOpenRISCState *env,
                                   target_ulong address,
@@ -428,9 +429,4 @@
     return env->pc;
 }
 
-static inline void cpu_pc_from_tb(CPUOpenRISCState *env, TranslationBlock *tb)
-{
-    env->pc = tb->pc;
-}
-
 #endif /* CPU_OPENRISC_H */
diff --git a/target-openrisc/mmu.c b/target-openrisc/mmu.c
index d354e1f..57f5616 100644
--- a/target-openrisc/mmu.c
+++ b/target-openrisc/mmu.c
@@ -219,12 +219,11 @@
 #endif
 
 #ifndef CONFIG_USER_ONLY
-hwaddr cpu_get_phys_page_debug(CPUOpenRISCState *env,
-                                           target_ulong addr)
+hwaddr openrisc_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
 {
+    OpenRISCCPU *cpu = OPENRISC_CPU(cs);
     hwaddr phys_addr;
     int prot;
-    OpenRISCCPU *cpu = openrisc_env_get_cpu(env);
 
     if (cpu_openrisc_get_phys_addr(cpu, &phys_addr, &prot, addr, 0)) {
         return -1;
diff --git a/target-openrisc/translate.c b/target-openrisc/translate.c
index f222834..a6050ba 100644
--- a/target-openrisc/translate.c
+++ b/target-openrisc/translate.c
@@ -1662,6 +1662,7 @@
                                                   TranslationBlock *tb,
                                                   int search_pc)
 {
+    CPUState *cs = CPU(cpu);
     struct DisasContext ctx, *dc = &ctx;
     uint16_t *gen_opc_end;
     uint32_t pc_start;
@@ -1681,7 +1682,7 @@
     dc->mem_idx = cpu_mmu_index(&cpu->env);
     dc->synced_flags = dc->tb_flags = tb->flags;
     dc->delayed_branch = !!(dc->tb_flags & D_FLAG);
-    dc->singlestep_enabled = cpu->env.singlestep_enabled;
+    dc->singlestep_enabled = cs->singlestep_enabled;
     if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
         qemu_log("-----------------------------------------\n");
         log_cpu_state(CPU(cpu), 0);
@@ -1743,7 +1744,7 @@
         }
     } while (!dc->is_jmp
              && tcg_ctx.gen_opc_ptr < gen_opc_end
-             && !cpu->env.singlestep_enabled
+             && !cs->singlestep_enabled
              && !singlestep
              && (dc->pc < next_page_start)
              && num_insns < max_insns);
@@ -1755,7 +1756,7 @@
         dc->is_jmp = DISAS_UPDATE;
         tcg_gen_movi_tl(cpu_pc, dc->pc);
     }
-    if (unlikely(cpu->env.singlestep_enabled)) {
+    if (unlikely(cs->singlestep_enabled)) {
         if (dc->is_jmp == DISAS_NEXT) {
             tcg_gen_movi_tl(cpu_pc, dc->pc);
         }
diff --git a/target-ppc/cpu-qom.h b/target-ppc/cpu-qom.h
index 7132599..3341c51 100644
--- a/target-ppc/cpu-qom.h
+++ b/target-ppc/cpu-qom.h
@@ -105,5 +105,6 @@
                         int flags);
 void ppc_cpu_dump_statistics(CPUState *cpu, FILE *f,
                              fprintf_function cpu_fprintf, int flags);
+hwaddr ppc_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
 
 #endif
diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h
index 7a7b1bf..6f51e1f 100644
--- a/target-ppc/cpu.h
+++ b/target-ppc/cpu.h
@@ -2144,11 +2144,6 @@
 
 #include "exec/exec-all.h"
 
-static inline void cpu_pc_from_tb(CPUPPCState *env, TranslationBlock *tb)
-{
-    env->nip = tb->pc;
-}
-
 void dump_mmu(FILE *f, fprintf_function cpu_fprintf, CPUPPCState *env);
 
 #endif /* !defined (__CPU_PPC_H__) */
diff --git a/target-ppc/mmu_helper.c b/target-ppc/mmu_helper.c
index 77102c4..5dd4e05 100644
--- a/target-ppc/mmu_helper.c
+++ b/target-ppc/mmu_helper.c
@@ -1409,8 +1409,10 @@
     return ret;
 }
 
-hwaddr cpu_get_phys_page_debug(CPUPPCState *env, target_ulong addr)
+hwaddr ppc_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
 {
+    PowerPCCPU *cpu = POWERPC_CPU(cs);
+    CPUPPCState *env = &cpu->env;
     mmu_ctx_t ctx;
 
     switch (env->mmu_model) {
diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index eb96272..f07d70d 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -9730,6 +9730,7 @@
                                                   TranslationBlock *tb,
                                                   bool search_pc)
 {
+    CPUState *cs = CPU(cpu);
     CPUPPCState *env = &cpu->env;
     DisasContext ctx, *ctxp = &ctx;
     opc_handler_t **table, *handler;
@@ -9770,8 +9771,9 @@
         ctx.singlestep_enabled = 0;
     if ((env->flags & POWERPC_FLAG_BE) && msr_be)
         ctx.singlestep_enabled |= CPU_BRANCH_STEP;
-    if (unlikely(env->singlestep_enabled))
+    if (unlikely(cs->singlestep_enabled)) {
         ctx.singlestep_enabled |= GDBSTUB_SINGLE_STEP;
+    }
 #if defined (DO_SINGLE_STEP) && 0
     /* Single step trace mode */
     msr_se = 1;
@@ -9873,7 +9875,7 @@
                      ctx.exception != POWERPC_EXCP_BRANCH)) {
             gen_exception(ctxp, POWERPC_EXCP_TRACE);
         } else if (unlikely(((ctx.nip & (TARGET_PAGE_SIZE - 1)) == 0) ||
-                            (env->singlestep_enabled) ||
+                            (cs->singlestep_enabled) ||
                             singlestep ||
                             num_insns >= max_insns)) {
             /* if we reach a page boundary or are single stepping, stop
@@ -9887,7 +9889,7 @@
     if (ctx.exception == POWERPC_EXCP_NONE) {
         gen_goto_tb(&ctx, 0, ctx.nip);
     } else if (ctx.exception != POWERPC_EXCP_BRANCH) {
-        if (unlikely(env->singlestep_enabled)) {
+        if (unlikely(cs->singlestep_enabled)) {
             gen_debug_exception(ctxp);
         }
         /* Generate the return instruction */
diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index 79bfcd8..0b0844f 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -7804,8 +7804,8 @@
 
 static void ppc_cpu_realizefn(DeviceState *dev, Error **errp)
 {
+    CPUState *cs = CPU(dev);
     PowerPCCPU *cpu = POWERPC_CPU(dev);
-    CPUPPCState *env = &cpu->env;
     PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
     Error *local_err = NULL;
 #if !defined(CONFIG_USER_ONLY)
@@ -7849,15 +7849,15 @@
     init_ppc_proc(cpu);
 
     if (pcc->insns_flags & PPC_FLOAT) {
-        gdb_register_coprocessor(env, gdb_get_float_reg, gdb_set_float_reg,
+        gdb_register_coprocessor(cs, gdb_get_float_reg, gdb_set_float_reg,
                                  33, "power-fpu.xml", 0);
     }
     if (pcc->insns_flags & PPC_ALTIVEC) {
-        gdb_register_coprocessor(env, gdb_get_avr_reg, gdb_set_avr_reg,
+        gdb_register_coprocessor(cs, gdb_get_avr_reg, gdb_set_avr_reg,
                                  34, "power-altivec.xml", 0);
     }
     if (pcc->insns_flags & PPC_SPE) {
-        gdb_register_coprocessor(env, gdb_get_spe_reg, gdb_set_spe_reg,
+        gdb_register_coprocessor(cs, gdb_get_spe_reg, gdb_set_spe_reg,
                                  34, "power-spe.xml", 0);
     }
 
@@ -7865,6 +7865,7 @@
 
 #if defined(PPC_DUMP_CPU)
     {
+        CPUPPCState *env = &cpu->env;
         const char *mmu_model, *excp_model, *bus_model;
         switch (env->mmu_model) {
         case POWERPC_MMU_32B:
@@ -8016,10 +8017,10 @@
             printf("                        none\n");
         printf("    Time-base/decrementer clock source: %s\n",
                env->flags & POWERPC_FLAG_RTC_CLK ? "RTC clock" : "bus clock");
+        dump_ppc_insns(env);
+        dump_ppc_sprs(env);
+        fflush(stdout);
     }
-    dump_ppc_insns(env);
-    dump_ppc_sprs(env);
-    fflush(stdout);
 #endif
 }
 
@@ -8322,6 +8323,13 @@
     return cpu_list;
 }
 
+static void ppc_cpu_set_pc(CPUState *cs, vaddr value)
+{
+    PowerPCCPU *cpu = POWERPC_CPU(cs);
+
+    cpu->env.nip = value;
+}
+
 /* CPUClass::reset() */
 static void ppc_cpu_reset(CPUState *s)
 {
@@ -8449,6 +8457,10 @@
     cc->do_interrupt = ppc_cpu_do_interrupt;
     cc->dump_state = ppc_cpu_dump_state;
     cc->dump_statistics = ppc_cpu_dump_statistics;
+    cc->set_pc = ppc_cpu_set_pc;
+#ifndef CONFIG_USER_ONLY
+    cc->get_phys_page_debug = ppc_cpu_get_phys_page_debug;
+#endif
 }
 
 static const TypeInfo ppc_cpu_type_info = {
diff --git a/target-s390x/cpu-qom.h b/target-s390x/cpu-qom.h
index 4c091e3..a4fe8fb 100644
--- a/target-s390x/cpu-qom.h
+++ b/target-s390x/cpu-qom.h
@@ -74,5 +74,6 @@
 void s390_cpu_do_interrupt(CPUState *cpu);
 void s390_cpu_dump_state(CPUState *cpu, FILE *f, fprintf_function cpu_fprintf,
                          int flags);
+hwaddr s390_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
 
 #endif
diff --git a/target-s390x/cpu.c b/target-s390x/cpu.c
index 1ef2fc0..cb89d1a 100644
--- a/target-s390x/cpu.c
+++ b/target-s390x/cpu.c
@@ -58,6 +58,13 @@
 }
 #endif
 
+static void s390_cpu_set_pc(CPUState *cs, vaddr value)
+{
+    S390CPU *cpu = S390_CPU(cs);
+
+    cpu->env.psw.addr = value;
+}
+
 /* CPUClass::reset() */
 static void s390_cpu_reset(CPUState *s)
 {
@@ -165,6 +172,10 @@
 
     cc->do_interrupt = s390_cpu_do_interrupt;
     cc->dump_state = s390_cpu_dump_state;
+    cc->set_pc = s390_cpu_set_pc;
+#ifndef CONFIG_USER_ONLY
+    cc->get_phys_page_debug = s390_cpu_get_phys_page_debug;
+#endif
     dc->vmsd = &vmstate_s390_cpu;
 }
 
diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h
index 6462688..65bef86 100644
--- a/target-s390x/cpu.h
+++ b/target-s390x/cpu.h
@@ -1041,11 +1041,6 @@
         (env->psw.mask & PSW_MASK_EXT);
 }
 
-static inline void cpu_pc_from_tb(CPUS390XState *env, TranslationBlock* tb)
-{
-    env->psw.addr = tb->pc;
-}
-
 /* fpu_helper.c */
 uint32_t set_cc_nz_f32(float32 v);
 uint32_t set_cc_nz_f64(float64 v);
diff --git a/target-s390x/helper.c b/target-s390x/helper.c
index b425054..61abfd7 100644
--- a/target-s390x/helper.c
+++ b/target-s390x/helper.c
@@ -417,9 +417,10 @@
     return 0;
 }
 
-hwaddr cpu_get_phys_page_debug(CPUS390XState *env,
-                                           target_ulong vaddr)
+hwaddr s390_cpu_get_phys_page_debug(CPUState *cs, vaddr vaddr)
 {
+    S390CPU *cpu = S390_CPU(cs);
+    CPUS390XState *env = &cpu->env;
     target_ulong raddr;
     int prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
     int old_exc = env->exception_index;
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index cba7b87..1fb76c5 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -4740,6 +4740,7 @@
                                                   TranslationBlock *tb,
                                                   bool search_pc)
 {
+    CPUState *cs = CPU(cpu);
     CPUS390XState *env = &cpu->env;
     DisasContext dc;
     target_ulong pc_start;
@@ -4761,7 +4762,7 @@
     dc.tb = tb;
     dc.pc = pc_start;
     dc.cc_op = CC_OP_DYNAMIC;
-    do_debug = dc.singlestep_enabled = env->singlestep_enabled;
+    do_debug = dc.singlestep_enabled = cs->singlestep_enabled;
 
     gen_opc_end = tcg_ctx.gen_opc_buf + OPC_MAX_SIZE;
 
@@ -4818,7 +4819,7 @@
                 || tcg_ctx.gen_opc_ptr >= gen_opc_end
                 || num_insns >= max_insns
                 || singlestep
-                || env->singlestep_enabled)) {
+                || cs->singlestep_enabled)) {
             status = EXIT_PC_STALE;
         }
     } while (status == NO_EXIT);
diff --git a/target-sh4/cpu-qom.h b/target-sh4/cpu-qom.h
index c229a9a..7c9160b 100644
--- a/target-sh4/cpu-qom.h
+++ b/target-sh4/cpu-qom.h
@@ -86,5 +86,6 @@
 void superh_cpu_do_interrupt(CPUState *cpu);
 void superh_cpu_dump_state(CPUState *cpu, FILE *f,
                            fprintf_function cpu_fprintf, int flags);
+hwaddr superh_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
 
 #endif
diff --git a/target-sh4/cpu.c b/target-sh4/cpu.c
index 03487eb..51a7757 100644
--- a/target-sh4/cpu.c
+++ b/target-sh4/cpu.c
@@ -24,6 +24,21 @@
 #include "migration/vmstate.h"
 
 
+static void superh_cpu_set_pc(CPUState *cs, vaddr value)
+{
+    SuperHCPU *cpu = SUPERH_CPU(cs);
+
+    cpu->env.pc = value;
+}
+
+static void superh_cpu_synchronize_from_tb(CPUState *cs, TranslationBlock *tb)
+{
+    SuperHCPU *cpu = SUPERH_CPU(cs);
+
+    cpu->env.pc = tb->pc;
+    cpu->env.flags = tb->flags;
+}
+
 /* CPUClass::reset() */
 static void superh_cpu_reset(CPUState *s)
 {
@@ -269,6 +284,11 @@
     cc->class_by_name = superh_cpu_class_by_name;
     cc->do_interrupt = superh_cpu_do_interrupt;
     cc->dump_state = superh_cpu_dump_state;
+    cc->set_pc = superh_cpu_set_pc;
+    cc->synchronize_from_tb = superh_cpu_synchronize_from_tb;
+#ifndef CONFIG_USER_ONLY
+    cc->get_phys_page_debug = superh_cpu_get_phys_page_debug;
+#endif
     dc->vmsd = &vmstate_sh_cpu;
 }
 
diff --git a/target-sh4/cpu.h b/target-sh4/cpu.h
index c8df18b..276d295 100644
--- a/target-sh4/cpu.h
+++ b/target-sh4/cpu.h
@@ -359,10 +359,4 @@
 
 #include "exec/exec-all.h"
 
-static inline void cpu_pc_from_tb(CPUSH4State *env, TranslationBlock *tb)
-{
-    env->pc = tb->pc;
-    env->flags = tb->flags;
-}
-
 #endif				/* _CPU_SH4_H */
diff --git a/target-sh4/helper.c b/target-sh4/helper.c
index cb6a2d2..9ac2825 100644
--- a/target-sh4/helper.c
+++ b/target-sh4/helper.c
@@ -508,12 +508,13 @@
     return 0;
 }
 
-hwaddr cpu_get_phys_page_debug(CPUSH4State * env, target_ulong addr)
+hwaddr superh_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
 {
+    SuperHCPU *cpu = SUPERH_CPU(cs);
     target_ulong physical;
     int prot;
 
-    get_physical_address(env, &physical, &prot, addr, 0, 0);
+    get_physical_address(&cpu->env, &physical, &prot, addr, 0, 0);
     return physical;
 }
 
diff --git a/target-sh4/translate.c b/target-sh4/translate.c
index 2fbe668..59f3d47 100644
--- a/target-sh4/translate.c
+++ b/target-sh4/translate.c
@@ -1849,6 +1849,7 @@
 gen_intermediate_code_internal(SuperHCPU *cpu, TranslationBlock *tb,
                                bool search_pc)
 {
+    CPUState *cs = CPU(cpu);
     CPUSH4State *env = &cpu->env;
     DisasContext ctx;
     target_ulong pc_start;
@@ -1868,7 +1869,7 @@
        so assume it is a dynamic branch.  */
     ctx.delayed_pc = -1; /* use delayed pc from env pointer */
     ctx.tb = tb;
-    ctx.singlestep_enabled = env->singlestep_enabled;
+    ctx.singlestep_enabled = cs->singlestep_enabled;
     ctx.features = env->features;
     ctx.has_movcal = (ctx.flags & TB_FLAG_PENDING_MOVCA);
 
@@ -1914,8 +1915,9 @@
 	ctx.pc += 2;
 	if ((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0)
 	    break;
-	if (env->singlestep_enabled)
+        if (cs->singlestep_enabled) {
 	    break;
+        }
         if (num_insns >= max_insns)
             break;
         if (singlestep)
@@ -1923,7 +1925,7 @@
     }
     if (tb->cflags & CF_LAST_IO)
         gen_io_end();
-    if (env->singlestep_enabled) {
+    if (cs->singlestep_enabled) {
         tcg_gen_movi_i32(cpu_pc, ctx.pc);
         gen_helper_debug(cpu_env);
     } else {
diff --git a/target-sparc/cpu-qom.h b/target-sparc/cpu-qom.h
index 033a5b5..39d975b 100644
--- a/target-sparc/cpu-qom.h
+++ b/target-sparc/cpu-qom.h
@@ -78,5 +78,6 @@
 void sparc_cpu_do_interrupt(CPUState *cpu);
 void sparc_cpu_dump_state(CPUState *cpu, FILE *f,
                           fprintf_function cpu_fprintf, int flags);
+hwaddr sparc_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
 
 #endif
diff --git a/target-sparc/cpu.c b/target-sparc/cpu.c
index 87c3a50..d1d0339 100644
--- a/target-sparc/cpu.c
+++ b/target-sparc/cpu.c
@@ -723,6 +723,22 @@
     cpu_fprintf(f, "\n");
 }
 
+static void sparc_cpu_set_pc(CPUState *cs, vaddr value)
+{
+    SPARCCPU *cpu = SPARC_CPU(cs);
+
+    cpu->env.pc = value;
+    cpu->env.npc = value + 4;
+}
+
+static void sparc_cpu_synchronize_from_tb(CPUState *cs, TranslationBlock *tb)
+{
+    SPARCCPU *cpu = SPARC_CPU(cs);
+
+    cpu->env.pc = tb->pc;
+    cpu->env.npc = tb->cs_base;
+}
+
 static void sparc_cpu_realizefn(DeviceState *dev, Error **errp)
 {
     SPARCCPUClass *scc = SPARC_CPU_GET_CLASS(dev);
@@ -766,7 +782,15 @@
 
     cc->do_interrupt = sparc_cpu_do_interrupt;
     cc->dump_state = sparc_cpu_dump_state;
-    cpu_class_set_do_unassigned_access(cc, sparc_cpu_unassigned_access);
+#if !defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY)
+    cc->memory_rw_debug = sparc_cpu_memory_rw_debug;
+#endif
+    cc->set_pc = sparc_cpu_set_pc;
+    cc->synchronize_from_tb = sparc_cpu_synchronize_from_tb;
+#ifndef CONFIG_USER_ONLY
+    cc->do_unassigned_access = sparc_cpu_unassigned_access;
+    cc->get_phys_page_debug = sparc_cpu_get_phys_page_debug;
+#endif
 }
 
 static const TypeInfo sparc_cpu_type_info = {
diff --git a/target-sparc/cpu.h b/target-sparc/cpu.h
index 41b014a..41194ec 100644
--- a/target-sparc/cpu.h
+++ b/target-sparc/cpu.h
@@ -526,9 +526,8 @@
 void dump_mmu(FILE *f, fprintf_function cpu_fprintf, CPUSPARCState *env);
 
 #if !defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY)
-int target_memory_rw_debug(CPUSPARCState *env, target_ulong addr,
-                           uint8_t *buf, int len, int is_write);
-#define TARGET_CPU_MEMORY_RW_DEBUG
+int sparc_cpu_memory_rw_debug(CPUState *cpu, vaddr addr,
+                              uint8_t *buf, int len, bool is_write);
 #endif
 
 
@@ -759,10 +758,4 @@
 
 #include "exec/exec-all.h"
 
-static inline void cpu_pc_from_tb(CPUSPARCState *env, TranslationBlock *tb)
-{
-    env->pc = tb->pc;
-    env->npc = tb->cs_base;
-}
-
 #endif
diff --git a/target-sparc/mmu_helper.c b/target-sparc/mmu_helper.c
index 740cbe8..ef12a0a 100644
--- a/target-sparc/mmu_helper.c
+++ b/target-sparc/mmu_helper.c
@@ -310,6 +310,7 @@
 
 void dump_mmu(FILE *f, fprintf_function cpu_fprintf, CPUSPARCState *env)
 {
+    CPUState *cs = CPU(sparc_env_get_cpu(env));
     target_ulong va, va1, va2;
     unsigned int n, m, o;
     hwaddr pde_ptr, pa;
@@ -322,20 +323,20 @@
     for (n = 0, va = 0; n < 256; n++, va += 16 * 1024 * 1024) {
         pde = mmu_probe(env, va, 2);
         if (pde) {
-            pa = cpu_get_phys_page_debug(env, va);
+            pa = cpu_get_phys_page_debug(cs, va);
             (*cpu_fprintf)(f, "VA: " TARGET_FMT_lx ", PA: " TARGET_FMT_plx
                            " PDE: " TARGET_FMT_lx "\n", va, pa, pde);
             for (m = 0, va1 = va; m < 64; m++, va1 += 256 * 1024) {
                 pde = mmu_probe(env, va1, 1);
                 if (pde) {
-                    pa = cpu_get_phys_page_debug(env, va1);
+                    pa = cpu_get_phys_page_debug(cs, va1);
                     (*cpu_fprintf)(f, " VA: " TARGET_FMT_lx ", PA: "
                                    TARGET_FMT_plx " PDE: " TARGET_FMT_lx "\n",
                                    va1, pa, pde);
                     for (o = 0, va2 = va1; o < 64; o++, va2 += 4 * 1024) {
                         pde = mmu_probe(env, va2, 0);
                         if (pde) {
-                            pa = cpu_get_phys_page_debug(env, va2);
+                            pa = cpu_get_phys_page_debug(cs, va2);
                             (*cpu_fprintf)(f, "  VA: " TARGET_FMT_lx ", PA: "
                                            TARGET_FMT_plx " PTE: "
                                            TARGET_FMT_lx "\n",
@@ -352,9 +353,12 @@
  * reads (and only reads) in stack frames as if windows were flushed. We assume
  * that the sparc ABI is followed.
  */
-int target_memory_rw_debug(CPUSPARCState *env, target_ulong addr,
-                           uint8_t *buf, int len, int is_write)
+int sparc_cpu_memory_rw_debug(CPUState *cs, vaddr address,
+                              uint8_t *buf, int len, bool is_write)
 {
+    SPARCCPU *cpu = SPARC_CPU(cs);
+    CPUSPARCState *env = &cpu->env;
+    target_ulong addr = address;
     int i;
     int len1;
     int cwp = env->cwp;
@@ -389,7 +393,7 @@
             /* Handle access before this window.  */
             if (addr < fp) {
                 len1 = fp - addr;
-                if (cpu_memory_rw_debug(env, addr, buf, len1, is_write) != 0) {
+                if (cpu_memory_rw_debug(cs, addr, buf, len1, is_write) != 0) {
                     return -1;
                 }
                 addr += len1;
@@ -425,7 +429,7 @@
             }
         }
     }
-    return cpu_memory_rw_debug(env, addr, buf, len, is_write);
+    return cpu_memory_rw_debug(cs, addr, buf, len, is_write);
 }
 
 #else /* !TARGET_SPARC64 */
@@ -833,8 +837,10 @@
 }
 #endif
 
-hwaddr cpu_get_phys_page_debug(CPUSPARCState *env, target_ulong addr)
+hwaddr sparc_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
 {
+    SPARCCPU *cpu = SPARC_CPU(cs);
+    CPUSPARCState *env = &cpu->env;
     hwaddr phys_addr;
     int mmu_idx = cpu_mmu_index(env);
     MemoryRegionSection section;
diff --git a/target-sparc/translate.c b/target-sparc/translate.c
index 5e771e5..093e0e2 100644
--- a/target-sparc/translate.c
+++ b/target-sparc/translate.c
@@ -5223,6 +5223,7 @@
                                                   TranslationBlock *tb,
                                                   bool spc)
 {
+    CPUState *cs = CPU(cpu);
     CPUSPARCState *env = &cpu->env;
     target_ulong pc_start, last_pc;
     uint16_t *gen_opc_end;
@@ -5244,7 +5245,7 @@
     dc->def = env->def;
     dc->fpu_enabled = tb_fpu_enabled(tb->flags);
     dc->address_mask_32bit = tb_am_enabled(tb->flags);
-    dc->singlestep = (env->singlestep_enabled || singlestep);
+    dc->singlestep = (cs->singlestep_enabled || singlestep);
     gen_opc_end = tcg_ctx.gen_opc_buf + OPC_MAX_SIZE;
 
     num_insns = 0;
diff --git a/target-unicore32/cpu-qom.h b/target-unicore32/cpu-qom.h
index 350d480..f727760 100644
--- a/target-unicore32/cpu-qom.h
+++ b/target-unicore32/cpu-qom.h
@@ -63,5 +63,6 @@
 void uc32_cpu_do_interrupt(CPUState *cpu);
 void uc32_cpu_dump_state(CPUState *cpu, FILE *f,
                          fprintf_function cpu_fprintf, int flags);
+hwaddr uc32_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
 
 #endif
diff --git a/target-unicore32/cpu.c b/target-unicore32/cpu.c
index 6572f01..46813e5 100644
--- a/target-unicore32/cpu.c
+++ b/target-unicore32/cpu.c
@@ -16,6 +16,13 @@
 #include "qemu-common.h"
 #include "migration/vmstate.h"
 
+static void uc32_cpu_set_pc(CPUState *cs, vaddr value)
+{
+    UniCore32CPU *cpu = UNICORE32_CPU(cs);
+
+    cpu->env.regs[31] = value;
+}
+
 static inline void set_feature(CPUUniCore32State *env, int feature)
 {
     env->features |= feature;
@@ -131,6 +138,10 @@
     cc->class_by_name = uc32_cpu_class_by_name;
     cc->do_interrupt = uc32_cpu_do_interrupt;
     cc->dump_state = uc32_cpu_dump_state;
+    cc->set_pc = uc32_cpu_set_pc;
+#ifndef CONFIG_USER_ONLY
+    cc->get_phys_page_debug = uc32_cpu_get_phys_page_debug;
+#endif
     dc->vmsd = &vmstate_uc32_cpu;
 }
 
diff --git a/target-unicore32/cpu.h b/target-unicore32/cpu.h
index d4be525..967511e 100644
--- a/target-unicore32/cpu.h
+++ b/target-unicore32/cpu.h
@@ -146,11 +146,6 @@
 #include "cpu-qom.h"
 #include "exec/exec-all.h"
 
-static inline void cpu_pc_from_tb(CPUUniCore32State *env, TranslationBlock *tb)
-{
-    env->regs[31] = tb->pc;
-}
-
 static inline void cpu_get_tb_cpu_state(CPUUniCore32State *env, target_ulong *pc,
                                         target_ulong *cs_base, int *flags)
 {
diff --git a/target-unicore32/softmmu.c b/target-unicore32/softmmu.c
index eadaeb1..1e13a85 100644
--- a/target-unicore32/softmmu.c
+++ b/target-unicore32/softmmu.c
@@ -261,9 +261,10 @@
     return ret;
 }
 
-hwaddr cpu_get_phys_page_debug(CPUUniCore32State *env,
-        target_ulong addr)
+hwaddr uc32_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
 {
-    cpu_abort(env, "%s not supported yet\n", __func__);
+    UniCore32CPU *cpu = UNICORE32_CPU(cs);
+
+    cpu_abort(&cpu->env, "%s not supported yet\n", __func__);
     return addr;
 }
diff --git a/target-unicore32/translate.c b/target-unicore32/translate.c
index d85185d..68be1c6 100644
--- a/target-unicore32/translate.c
+++ b/target-unicore32/translate.c
@@ -1879,6 +1879,7 @@
 static inline void gen_intermediate_code_internal(UniCore32CPU *cpu,
         TranslationBlock *tb, bool search_pc)
 {
+    CPUState *cs = CPU(cpu);
     CPUUniCore32State *env = &cpu->env;
     DisasContext dc1, *dc = &dc1;
     CPUBreakpoint *bp;
@@ -1900,7 +1901,7 @@
 
     dc->is_jmp = DISAS_NEXT;
     dc->pc = pc_start;
-    dc->singlestep_enabled = env->singlestep_enabled;
+    dc->singlestep_enabled = cs->singlestep_enabled;
     dc->condjmp = 0;
     cpu_F0s = tcg_temp_new_i32();
     cpu_F1s = tcg_temp_new_i32();
@@ -1971,7 +1972,7 @@
          * ensures prefetch aborts occur at the right place.  */
         num_insns++;
     } while (!dc->is_jmp && tcg_ctx.gen_opc_ptr < gen_opc_end &&
-             !env->singlestep_enabled &&
+             !cs->singlestep_enabled &&
              !singlestep &&
              dc->pc < next_page_start &&
              num_insns < max_insns);
@@ -1988,7 +1989,7 @@
     /* At this stage dc->condjmp will only be set when the skipped
        instruction was a conditional branch or trap, and the PC has
        already been written.  */
-    if (unlikely(env->singlestep_enabled)) {
+    if (unlikely(cs->singlestep_enabled)) {
         /* Make sure the pc is updated, and raise a debug exception.  */
         if (dc->condjmp) {
             if (dc->is_jmp == DISAS_SYSCALL) {
diff --git a/target-xtensa/cpu-qom.h b/target-xtensa/cpu-qom.h
index 31e7498..b9896f2 100644
--- a/target-xtensa/cpu-qom.h
+++ b/target-xtensa/cpu-qom.h
@@ -83,5 +83,6 @@
 void xtensa_cpu_do_interrupt(CPUState *cpu);
 void xtensa_cpu_dump_state(CPUState *cpu, FILE *f,
                            fprintf_function cpu_fprintf, int flags);
+hwaddr xtensa_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
 
 #endif
diff --git a/target-xtensa/cpu.c b/target-xtensa/cpu.c
index 0488984..d2bcfc6 100644
--- a/target-xtensa/cpu.c
+++ b/target-xtensa/cpu.c
@@ -33,6 +33,13 @@
 #include "migration/vmstate.h"
 
 
+static void xtensa_cpu_set_pc(CPUState *cs, vaddr value)
+{
+    XtensaCPU *cpu = XTENSA_CPU(cs);
+
+    cpu->env.pc = value;
+}
+
 /* CPUClass::reset() */
 static void xtensa_cpu_reset(CPUState *s)
 {
@@ -100,6 +107,10 @@
 
     cc->do_interrupt = xtensa_cpu_do_interrupt;
     cc->dump_state = xtensa_cpu_dump_state;
+    cc->set_pc = xtensa_cpu_set_pc;
+#ifndef CONFIG_USER_ONLY
+    cc->get_phys_page_debug = xtensa_cpu_get_phys_page_debug;
+#endif
     dc->vmsd = &vmstate_xtensa_cpu;
 }
 
diff --git a/target-xtensa/cpu.h b/target-xtensa/cpu.h
index 6c9fc35..a8f02f6 100644
--- a/target-xtensa/cpu.h
+++ b/target-xtensa/cpu.h
@@ -522,9 +522,4 @@
     return env->pending_irq_level;
 }
 
-static inline void cpu_pc_from_tb(CPUXtensaState *env, TranslationBlock *tb)
-{
-    env->pc = tb->pc;
-}
-
 #endif
diff --git a/target-xtensa/helper.c b/target-xtensa/helper.c
index 6f613c66..de6cc3b 100644
--- a/target-xtensa/helper.c
+++ b/target-xtensa/helper.c
@@ -108,17 +108,18 @@
     }
 }
 
-hwaddr cpu_get_phys_page_debug(CPUXtensaState *env, target_ulong addr)
+hwaddr xtensa_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
 {
+    XtensaCPU *cpu = XTENSA_CPU(cs);
     uint32_t paddr;
     uint32_t page_size;
     unsigned access;
 
-    if (xtensa_get_physical_addr(env, false, addr, 0, 0,
+    if (xtensa_get_physical_addr(&cpu->env, false, addr, 0, 0,
                 &paddr, &page_size, &access) == 0) {
         return paddr;
     }
-    if (xtensa_get_physical_addr(env, false, addr, 2, 0,
+    if (xtensa_get_physical_addr(&cpu->env, false, addr, 2, 0,
                 &paddr, &page_size, &access) == 0) {
         return paddr;
     }
diff --git a/target-xtensa/translate.c b/target-xtensa/translate.c
index e4cf828..e692329 100644
--- a/target-xtensa/translate.c
+++ b/target-xtensa/translate.c
@@ -2879,6 +2879,7 @@
 void gen_intermediate_code_internal(XtensaCPU *cpu,
                                     TranslationBlock *tb, bool search_pc)
 {
+    CPUState *cs = CPU(cpu);
     CPUXtensaState *env = &cpu->env;
     DisasContext dc;
     int insn_count = 0;
@@ -2894,7 +2895,7 @@
     }
 
     dc.config = env->config;
-    dc.singlestep_enabled = env->singlestep_enabled;
+    dc.singlestep_enabled = cs->singlestep_enabled;
     dc.tb = tb;
     dc.pc = pc_start;
     dc.ring = tb->flags & XTENSA_TBFLAG_RING_MASK;
@@ -2917,7 +2918,7 @@
 
     gen_tb_start();
 
-    if (env->singlestep_enabled && env->exception_taken) {
+    if (cs->singlestep_enabled && env->exception_taken) {
         env->exception_taken = 0;
         tcg_gen_movi_i32(cpu_pc, dc.pc);
         gen_exception(&dc, EXCP_DEBUG);
@@ -2970,7 +2971,7 @@
         if (dc.icount) {
             tcg_gen_mov_i32(cpu_SR[ICOUNT], dc.next_icount);
         }
-        if (env->singlestep_enabled) {
+        if (cs->singlestep_enabled) {
             tcg_gen_movi_i32(cpu_pc, dc.pc);
             gen_exception(&dc, EXCP_DEBUG);
             break;
diff --git a/target-xtensa/xtensa-semi.c b/target-xtensa/xtensa-semi.c
index 5fe0361..424253d 100644
--- a/target-xtensa/xtensa-semi.c
+++ b/target-xtensa/xtensa-semi.c
@@ -152,6 +152,7 @@
 
 void HELPER(simcall)(CPUXtensaState *env)
 {
+    CPUState *cs = CPU(xtensa_env_get_cpu(env));
     uint32_t *regs = env->regs;
 
     switch (regs[2]) {
@@ -169,8 +170,7 @@
             uint32_t len = regs[5];
 
             while (len > 0) {
-                hwaddr paddr =
-                    cpu_get_phys_page_debug(env, vaddr);
+                hwaddr paddr = cpu_get_phys_page_debug(cs, vaddr);
                 uint32_t page_left =
                     TARGET_PAGE_SIZE - (vaddr & (TARGET_PAGE_SIZE - 1));
                 uint32_t io_sz = page_left < len ? page_left : len;
@@ -204,8 +204,8 @@
             int i;
 
             for (i = 0; i < ARRAY_SIZE(name); ++i) {
-                rc = cpu_memory_rw_debug(
-                        env, regs[3] + i, (uint8_t *)name + i, 1, 0);
+                rc = cpu_memory_rw_debug(cs, regs[3] + i,
+                                         (uint8_t *)name + i, 1, 0);
                 if (rc != 0 || name[i] == 0) {
                     break;
                 }
@@ -249,7 +249,7 @@
             FD_SET(fd, &fdset);
 
             if (target_tv) {
-                cpu_memory_rw_debug(env, target_tv,
+                cpu_memory_rw_debug(cs, target_tv,
                         (uint8_t *)target_tvv, sizeof(target_tvv), 0);
                 tv.tv_sec = (int32_t)tswap32(target_tvv[0]);
                 tv.tv_usec = (int32_t)tswap32(target_tvv[1]);
@@ -284,8 +284,8 @@
             };
 
             argv.argptr[0] = tswap32(regs[3] + offsetof(struct Argv, text));
-            cpu_memory_rw_debug(
-                    env, regs[3], (uint8_t *)&argv, sizeof(argv), 1);
+            cpu_memory_rw_debug(cs,
+                                regs[3], (uint8_t *)&argv, sizeof(argv), 1);
         }
         break;