summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--MAINTAINERS2
-rw-r--r--accel/kvm/kvm-all.c7
-rw-r--r--accel/stubs/kvm-stub.c5
-rw-r--r--dump/dump.c19
-rw-r--r--hmp-commands.hx8
-rw-r--r--hw/char/sh_serial.c236
-rw-r--r--hw/char/trace-events4
-rw-r--r--hw/core/gpio.c197
-rw-r--r--hw/core/hotplug-stubs.c34
-rw-r--r--hw/core/machine-smp.c181
-rw-r--r--hw/core/machine.c199
-rw-r--r--hw/core/meson.build35
-rw-r--r--hw/core/qdev-hotplug.c73
-rw-r--r--hw/core/qdev.c234
-rw-r--r--hw/i386/xen/xen-hvm.c4
-rw-r--r--hw/intc/sh_intc.c547
-rw-r--r--hw/intc/trace-events8
-rw-r--r--hw/pci-host/sh_pci.c10
-rw-r--r--hw/sh4/r2d.c69
-rw-r--r--hw/sh4/sh7750.c637
-rw-r--r--hw/sh4/sh7750_regnames.c148
-rw-r--r--hw/sh4/sh7750_regs.h1600
-rw-r--r--hw/sh4/shix.c12
-rw-r--r--hw/sh4/trace-events3
-rw-r--r--hw/sh4/trace.h1
-rw-r--r--hw/timer/sh_timer.c151
-rw-r--r--hw/timer/trace-events5
-rw-r--r--hw/vfio/common.c7
-rw-r--r--hw/vfio/pci.c19
-rw-r--r--hw/virtio/virtio-mem.c92
-rw-r--r--include/exec/memory.h41
-rw-r--r--include/exec/ram_addr.h13
-rw-r--r--include/hw/boards.h17
-rw-r--r--include/hw/core/cpu.h1
-rw-r--r--include/hw/sh4/sh.h19
-rw-r--r--include/hw/sh4/sh_intc.h2
-rw-r--r--include/hw/virtio/virtio-mem.h3
-rw-r--r--include/migration/blocker.h16
-rw-r--r--include/sysemu/kvm.h1
-rw-r--r--meson.build5
-rw-r--r--migration/dirtyrate.c367
-rw-r--r--migration/dirtyrate.h19
-rw-r--r--migration/migration.c30
-rw-r--r--migration/postcopy-ram.c40
-rw-r--r--migration/ram.c182
-rw-r--r--migration/ram.h1
-rw-r--r--migration/rdma.c138
-rw-r--r--migration/trace-events2
-rw-r--r--pc-bios/openbios-ppcbin696912 -> 696912 bytes
-rw-r--r--pc-bios/openbios-sparc32bin382048 -> 382048 bytes
-rw-r--r--pc-bios/openbios-sparc64bin1593408 -> 1593408 bytes
-rw-r--r--python/qemu/aqmp/__init__.py12
-rw-r--r--python/qemu/aqmp/legacy.py138
-rw-r--r--python/qemu/machine/machine.py85
-rwxr-xr-xpython/tests/iotests-mypy.sh4
-rwxr-xr-xpython/tests/iotests-pylint.sh4
-rw-r--r--qapi/migration.json48
m---------roms/openbios0
-rwxr-xr-xscripts/simplebench/bench_block_job.py3
-rw-r--r--softmmu/memory.c43
-rw-r--r--softmmu/qdev-monitor.c11
-rw-r--r--softmmu/trace-events1
-rwxr-xr-xtests/qemu-iotests/0407
-rwxr-xr-xtests/qemu-iotests/2182
-rwxr-xr-xtests/qemu-iotests/2552
-rwxr-xr-xtests/qemu-iotests/297109
-rwxr-xr-xtests/qemu-iotests/30013
-rw-r--r--tests/qemu-iotests/iotests.py20
-rw-r--r--tests/qemu-iotests/linters.py105
-rw-r--r--tests/qemu-iotests/mypy.ini12
-rw-r--r--tests/qemu-iotests/pylintrc16
-rwxr-xr-xtests/qemu-iotests/tests/mirror-top-perms17
-rw-r--r--tests/unit/meson.build1
-rw-r--r--tests/unit/test-smp-parse.c594
74 files changed, 4247 insertions, 2444 deletions
diff --git a/MAINTAINERS b/MAINTAINERS
index 894dc43105..310a9512ea 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1623,6 +1623,7 @@ F: cpu.c
 F: hw/core/cpu.c
 F: hw/core/machine-qmp-cmds.c
 F: hw/core/machine.c
+F: hw/core/machine-smp.c
 F: hw/core/null-machine.c
 F: hw/core/numa.c
 F: hw/cpu/cluster.c
@@ -1632,6 +1633,7 @@ F: include/hw/boards.h
 F: include/hw/core/cpu.h
 F: include/hw/cpu/cluster.h
 F: include/sysemu/numa.h
+F: tests/unit/test-smp-parse.c
 T: git https://gitlab.com/ehabkost/qemu.git machine-next
 
 Xtensa Machines
diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c
index db8d83b137..eecd8031cf 100644
--- a/accel/kvm/kvm-all.c
+++ b/accel/kvm/kvm-all.c
@@ -469,6 +469,7 @@ int kvm_init_vcpu(CPUState *cpu, Error **errp)
     cpu->kvm_fd = ret;
     cpu->kvm_state = s;
     cpu->vcpu_dirty = true;
+    cpu->dirty_pages = 0;
 
     mmap_size = kvm_ioctl(s, KVM_GET_VCPU_MMAP_SIZE, 0);
     if (mmap_size < 0) {
@@ -743,6 +744,7 @@ static uint32_t kvm_dirty_ring_reap_one(KVMState *s, CPUState *cpu)
         count++;
     }
     cpu->kvm_fetch_index = fetch;
+    cpu->dirty_pages += count;
 
     return count;
 }
@@ -2296,6 +2298,11 @@ bool kvm_vcpu_id_is_valid(int vcpu_id)
     return vcpu_id >= 0 && vcpu_id < kvm_max_vcpu_id(s);
 }
 
+bool kvm_dirty_ring_enabled(void)
+{
+    return kvm_state->kvm_dirty_ring_size ? true : false;
+}
+
 static int kvm_init(MachineState *ms)
 {
     MachineClass *mc = MACHINE_GET_CLASS(ms);
diff --git a/accel/stubs/kvm-stub.c b/accel/stubs/kvm-stub.c
index 5b1d00a222..5319573e00 100644
--- a/accel/stubs/kvm-stub.c
+++ b/accel/stubs/kvm-stub.c
@@ -147,4 +147,9 @@ bool kvm_arm_supports_user_irq(void)
 {
     return false;
 }
+
+bool kvm_dirty_ring_enabled(void)
+{
+    return false;
+}
 #endif
diff --git a/dump/dump.c b/dump/dump.c
index ab625909f3..662d0a62cd 100644
--- a/dump/dump.c
+++ b/dump/dump.c
@@ -29,6 +29,7 @@
 #include "qemu/error-report.h"
 #include "qemu/main-loop.h"
 #include "hw/misc/vmcoreinfo.h"
+#include "migration/blocker.h"
 
 #ifdef TARGET_X86_64
 #include "win_dump.h"
@@ -47,6 +48,8 @@
 
 #define MAX_GUEST_NOTE_SIZE (1 << 20) /* 1MB should be enough */
 
+static Error *dump_migration_blocker;
+
 #define ELF_NOTE_SIZE(hdr_size, name_size, desc_size)   \
     ((DIV_ROUND_UP((hdr_size), 4) +                     \
       DIV_ROUND_UP((name_size), 4) +                    \
@@ -101,6 +104,7 @@ static int dump_cleanup(DumpState *s)
             qemu_mutex_unlock_iothread();
         }
     }
+    migrate_del_blocker(dump_migration_blocker);
 
     return 0;
 }
@@ -2005,6 +2009,21 @@ void qmp_dump_guest_memory(bool paging, const char *file,
         return;
     }
 
+    if (!dump_migration_blocker) {
+        error_setg(&dump_migration_blocker,
+                   "Live migration disabled: dump-guest-memory in progress");
+    }
+
+    /*
+     * Allows even for -only-migratable, but forbid migration during the
+     * process of dump guest memory.
+     */
+    if (migrate_add_blocker_internal(dump_migration_blocker, errp)) {
+        /* Remember to release the fd before passing it over to dump state */
+        close(fd);
+        return;
+    }
+
     s = &dump_state_global;
     dump_state_prepare(s);
 
diff --git a/hmp-commands.hx b/hmp-commands.hx
index cf723c69ac..3a5aeba3fe 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -1737,8 +1737,10 @@ ERST
 
     {
         .name       = "calc_dirty_rate",
-        .args_type  = "second:l,sample_pages_per_GB:l?",
-        .params     = "second [sample_pages_per_GB]",
-        .help       = "start a round of guest dirty rate measurement",
+        .args_type  = "dirty_ring:-r,dirty_bitmap:-b,second:l,sample_pages_per_GB:l?",
+        .params     = "[-r] [-b] second [sample_pages_per_GB]",
+        .help       = "start a round of guest dirty rate measurement (using -r to"
+                      "\n\t\t\t specify dirty ring as the method of calculation and"
+                      "\n\t\t\t -b to specify dirty bitmap as method of calculation)",
         .cmd        = hmp_calc_dirty_rate,
     },
diff --git a/hw/char/sh_serial.c b/hw/char/sh_serial.c
index 167f4d8cb9..355886ee3a 100644
--- a/hw/char/sh_serial.c
+++ b/hw/char/sh_serial.c
@@ -26,13 +26,17 @@
  */
 
 #include "qemu/osdep.h"
+#include "hw/sysbus.h"
 #include "hw/irq.h"
+#include "hw/qdev-core.h"
+#include "hw/qdev-properties.h"
+#include "hw/qdev-properties-system.h"
 #include "hw/sh4/sh.h"
 #include "chardev/char-fe.h"
 #include "qapi/error.h"
 #include "qemu/timer.h"
-
-//#define DEBUG_SERIAL
+#include "qemu/log.h"
+#include "trace.h"
 
 #define SH_SERIAL_FLAG_TEND (1 << 0)
 #define SH_SERIAL_FLAG_TDE  (1 << 1)
@@ -42,10 +46,10 @@
 
 #define SH_RX_FIFO_LENGTH (16)
 
-typedef struct {
-    MemoryRegion iomem;
-    MemoryRegion iomem_p4;
-    MemoryRegion iomem_a7;
+OBJECT_DECLARE_SIMPLE_TYPE(SHSerialState, SH_SERIAL)
+
+struct SHSerialState {
+    SysBusDevice parent;
     uint8_t smr;
     uint8_t brr;
     uint8_t scr;
@@ -59,13 +63,12 @@ typedef struct {
     uint8_t rx_tail;
     uint8_t rx_head;
 
-    int freq;
-    int feat;
+    uint8_t feat;
     int flags;
     int rtrg;
 
     CharBackend chr;
-    QEMUTimer *fifo_timeout_timer;
+    QEMUTimer fifo_timeout_timer;
     uint64_t etu; /* Elementary Time Unit (ns) */
 
     qemu_irq eri;
@@ -73,9 +76,13 @@ typedef struct {
     qemu_irq txi;
     qemu_irq tei;
     qemu_irq bri;
-} sh_serial_state;
+};
+
+typedef struct {} SHSerialStateClass;
 
-static void sh_serial_clear_fifo(sh_serial_state * s)
+OBJECT_DEFINE_TYPE(SHSerialState, sh_serial, SH_SERIAL, SYS_BUS_DEVICE)
+
+static void sh_serial_clear_fifo(SHSerialState *s)
 {
     memset(s->rx_fifo, 0, SH_RX_FIFO_LENGTH);
     s->rx_cnt = 0;
@@ -86,14 +93,12 @@ static void sh_serial_clear_fifo(sh_serial_state * s)
 static void sh_serial_write(void *opaque, hwaddr offs,
                             uint64_t val, unsigned size)
 {
-    sh_serial_state *s = opaque;
+    SHSerialState *s = opaque;
+    DeviceState *d = DEVICE(s);
     unsigned char ch;
 
-#ifdef DEBUG_SERIAL
-    printf("sh_serial: write offs=0x%02x val=0x%02x\n",
-           offs, val);
-#endif
-    switch(offs) {
+    trace_sh_serial_write(d->id, size, offs, val);
+    switch (offs) {
     case 0x00: /* SMR */
         s->smr = val & ((s->feat & SH_SERIAL_FEAT_SCIF) ? 0x7b : 0xff);
         return;
@@ -103,8 +108,9 @@ static void sh_serial_write(void *opaque, hwaddr offs,
     case 0x08: /* SCR */
         /* TODO : For SH7751, SCIF mask should be 0xfb. */
         s->scr = val & ((s->feat & SH_SERIAL_FEAT_SCIF) ? 0xfa : 0xff);
-        if (!(val & (1 << 5)))
+        if (!(val & (1 << 5))) {
             s->flags |= SH_SERIAL_FLAG_TEND;
+        }
         if ((s->feat & SH_SERIAL_FEAT_SCIF) && s->txi) {
             qemu_set_irq(s->txi, val & (1 << 7));
         }
@@ -115,8 +121,10 @@ static void sh_serial_write(void *opaque, hwaddr offs,
     case 0x0c: /* FTDR / TDR */
         if (qemu_chr_fe_backend_connected(&s->chr)) {
             ch = val;
-            /* XXX this blocks entire thread. Rewrite to use
-             * qemu_chr_fe_write and background I/O callbacks */
+            /*
+             * XXX this blocks entire thread. Rewrite to use
+             * qemu_chr_fe_write and background I/O callbacks
+             */
             qemu_chr_fe_write_all(&s->chr, &ch, 1);
         }
         s->dr = val;
@@ -129,18 +137,23 @@ static void sh_serial_write(void *opaque, hwaddr offs,
 #endif
     }
     if (s->feat & SH_SERIAL_FEAT_SCIF) {
-        switch(offs) {
+        switch (offs) {
         case 0x10: /* FSR */
-            if (!(val & (1 << 6)))
+            if (!(val & (1 << 6))) {
                 s->flags &= ~SH_SERIAL_FLAG_TEND;
-            if (!(val & (1 << 5)))
+            }
+            if (!(val & (1 << 5))) {
                 s->flags &= ~SH_SERIAL_FLAG_TDE;
-            if (!(val & (1 << 4)))
+            }
+            if (!(val & (1 << 4))) {
                 s->flags &= ~SH_SERIAL_FLAG_BRK;
-            if (!(val & (1 << 1)))
+            }
+            if (!(val & (1 << 1))) {
                 s->flags &= ~SH_SERIAL_FLAG_RDF;
-            if (!(val & (1 << 0)))
+            }
+            if (!(val & (1 << 0))) {
                 s->flags &= ~SH_SERIAL_FLAG_DR;
+            }
 
             if (!(val & (1 << 1)) || !(val & (1 << 0))) {
                 if (s->rxi) {
@@ -176,9 +189,8 @@ static void sh_serial_write(void *opaque, hwaddr offs,
         case 0x24: /* LSR */
             return;
         }
-    }
-    else {
-        switch(offs) {
+    } else {
+        switch (offs) {
 #if 0
         case 0x0c:
             ret = s->dr;
@@ -192,20 +204,20 @@ static void sh_serial_write(void *opaque, hwaddr offs,
             return;
         }
     }
-
-    fprintf(stderr, "sh_serial: unsupported write to 0x%02"
-            HWADDR_PRIx "\n", offs);
-    abort();
+    qemu_log_mask(LOG_GUEST_ERROR,
+                  "%s: unsupported write to 0x%02" HWADDR_PRIx "\n",
+                  __func__, offs);
 }
 
 static uint64_t sh_serial_read(void *opaque, hwaddr offs,
                                unsigned size)
 {
-    sh_serial_state *s = opaque;
-    uint32_t ret = ~0;
+    SHSerialState *s = opaque;
+    DeviceState *d = DEVICE(s);
+    uint32_t ret = UINT32_MAX;
 
 #if 0
-    switch(offs) {
+    switch (offs) {
     case 0x00:
         ret = s->smr;
         break;
@@ -221,7 +233,7 @@ static uint64_t sh_serial_read(void *opaque, hwaddr offs,
     }
 #endif
     if (s->feat & SH_SERIAL_FEAT_SCIF) {
-        switch(offs) {
+        switch (offs) {
         case 0x00: /* SMR */
             ret = s->smr;
             break;
@@ -230,29 +242,37 @@ static uint64_t sh_serial_read(void *opaque, hwaddr offs,
             break;
         case 0x10: /* FSR */
             ret = 0;
-            if (s->flags & SH_SERIAL_FLAG_TEND)
+            if (s->flags & SH_SERIAL_FLAG_TEND) {
                 ret |= (1 << 6);
-            if (s->flags & SH_SERIAL_FLAG_TDE)
+            }
+            if (s->flags & SH_SERIAL_FLAG_TDE) {
                 ret |= (1 << 5);
-            if (s->flags & SH_SERIAL_FLAG_BRK)
+            }
+            if (s->flags & SH_SERIAL_FLAG_BRK) {
                 ret |= (1 << 4);
-            if (s->flags & SH_SERIAL_FLAG_RDF)
+            }
+            if (s->flags & SH_SERIAL_FLAG_RDF) {
                 ret |= (1 << 1);
-            if (s->flags & SH_SERIAL_FLAG_DR)
+            }
+            if (s->flags & SH_SERIAL_FLAG_DR) {
                 ret |= (1 << 0);
+            }
 
-            if (s->scr & (1 << 5))
+            if (s->scr & (1 << 5)) {
                 s->flags |= SH_SERIAL_FLAG_TDE | SH_SERIAL_FLAG_TEND;
+            }
 
             break;
         case 0x14:
             if (s->rx_cnt > 0) {
                 ret = s->rx_fifo[s->rx_tail++];
                 s->rx_cnt--;
-                if (s->rx_tail == SH_RX_FIFO_LENGTH)
+                if (s->rx_tail == SH_RX_FIFO_LENGTH) {
                     s->rx_tail = 0;
-                if (s->rx_cnt < s->rtrg)
+                }
+                if (s->rx_cnt < s->rtrg) {
                     s->flags &= ~SH_SERIAL_FLAG_RDF;
+                }
             }
             break;
         case 0x18:
@@ -268,9 +288,8 @@ static uint64_t sh_serial_read(void *opaque, hwaddr offs,
             ret = 0;
             break;
         }
-    }
-    else {
-        switch(offs) {
+    } else {
+        switch (offs) {
 #if 0
         case 0x0c:
             ret = s->dr;
@@ -287,40 +306,39 @@ static uint64_t sh_serial_read(void *opaque, hwaddr offs,
             break;
         }
     }
-#ifdef DEBUG_SERIAL
-    printf("sh_serial: read offs=0x%02x val=0x%x\n",
-           offs, ret);
-#endif
+    trace_sh_serial_read(d->id, size, offs, ret);
 
-    if (ret & ~((1 << 16) - 1)) {
-        fprintf(stderr, "sh_serial: unsupported read from 0x%02"
-                HWADDR_PRIx "\n", offs);
-        abort();
+    if (ret > UINT16_MAX) {
+        qemu_log_mask(LOG_GUEST_ERROR,
+                      "%s: unsupported read from 0x%02" HWADDR_PRIx "\n",
+                      __func__, offs);
+        ret = 0;
     }
 
     return ret;
 }
 
-static int sh_serial_can_receive(sh_serial_state *s)
+static int sh_serial_can_receive(SHSerialState *s)
 {
     return s->scr & (1 << 4);
 }
 
-static void sh_serial_receive_break(sh_serial_state *s)
+static void sh_serial_receive_break(SHSerialState *s)
 {
-    if (s->feat & SH_SERIAL_FEAT_SCIF)
+    if (s->feat & SH_SERIAL_FEAT_SCIF) {
         s->sr |= (1 << 4);
+    }
 }
 
 static int sh_serial_can_receive1(void *opaque)
 {
-    sh_serial_state *s = opaque;
+    SHSerialState *s = opaque;
     return sh_serial_can_receive(s);
 }
 
 static void sh_serial_timeout_int(void *opaque)
 {
-    sh_serial_state *s = opaque;
+    SHSerialState *s = opaque;
 
     s->flags |= SH_SERIAL_FLAG_RDF;
     if (s->scr & (1 << 6) && s->rxi) {
@@ -330,7 +348,7 @@ static void sh_serial_timeout_int(void *opaque)
 
 static void sh_serial_receive1(void *opaque, const uint8_t *buf, int size)
 {
-    sh_serial_state *s = opaque;
+    SHSerialState *s = opaque;
 
     if (s->feat & SH_SERIAL_FEAT_SCIF) {
         int i;
@@ -344,11 +362,11 @@ static void sh_serial_receive1(void *opaque, const uint8_t *buf, int size)
                 if (s->rx_cnt >= s->rtrg) {
                     s->flags |= SH_SERIAL_FLAG_RDF;
                     if (s->scr & (1 << 6) && s->rxi) {
-                        timer_del(s->fifo_timeout_timer);
+                        timer_del(&s->fifo_timeout_timer);
                         qemu_set_irq(s->rxi, 1);
                     }
                 } else {
-                    timer_mod(s->fifo_timeout_timer,
+                    timer_mod(&s->fifo_timeout_timer,
                         qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + 15 * s->etu);
                 }
             }
@@ -360,9 +378,10 @@ static void sh_serial_receive1(void *opaque, const uint8_t *buf, int size)
 
 static void sh_serial_event(void *opaque, QEMUChrEvent event)
 {
-    sh_serial_state *s = opaque;
-    if (event == CHR_EVENT_BREAK)
+    SHSerialState *s = opaque;
+    if (event == CHR_EVENT_BREAK) {
         sh_serial_receive_break(s);
+    }
 }
 
 static const MemoryRegionOps sh_serial_ops = {
@@ -371,20 +390,10 @@ static const MemoryRegionOps sh_serial_ops = {
     .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
-void sh_serial_init(MemoryRegion *sysmem,
-                    hwaddr base, int feat,
-                    uint32_t freq, Chardev *chr,
-                    qemu_irq eri_source,
-                    qemu_irq rxi_source,
-                    qemu_irq txi_source,
-                    qemu_irq tei_source,
-                    qemu_irq bri_source)
+static void sh_serial_reset(DeviceState *dev)
 {
-    sh_serial_state *s;
+    SHSerialState *s = SH_SERIAL(dev);
 
-    s = g_malloc0(sizeof(sh_serial_state));
-
-    s->feat = feat;
     s->flags = SH_SERIAL_FLAG_TEND | SH_SERIAL_FLAG_TDE;
     s->rtrg = 1;
 
@@ -393,39 +402,64 @@ void sh_serial_init(MemoryRegion *sysmem,
     s->scr = 1 << 5; /* pretend that TX is enabled so early printk works */
     s->sptr = 0;
 
-    if (feat & SH_SERIAL_FEAT_SCIF) {
+    if (s->feat & SH_SERIAL_FEAT_SCIF) {
         s->fcr = 0;
-    }
-    else {
+    } else {
         s->dr = 0xff;
     }
 
     sh_serial_clear_fifo(s);
+}
 
-    memory_region_init_io(&s->iomem, NULL, &sh_serial_ops, s,
-                          "serial", 0x100000000ULL);
-
-    memory_region_init_alias(&s->iomem_p4, NULL, "serial-p4", &s->iomem,
-                             0, 0x28);
-    memory_region_add_subregion(sysmem, P4ADDR(base), &s->iomem_p4);
-
-    memory_region_init_alias(&s->iomem_a7, NULL, "serial-a7", &s->iomem,
-                             0, 0x28);
-    memory_region_add_subregion(sysmem, A7ADDR(base), &s->iomem_a7);
-
-    if (chr) {
-        qemu_chr_fe_init(&s->chr, chr, &error_abort);
+static void sh_serial_realize(DeviceState *d, Error **errp)
+{
+    SHSerialState *s = SH_SERIAL(d);
+    MemoryRegion *iomem = g_malloc(sizeof(*iomem));
+
+    assert(d->id);
+    memory_region_init_io(iomem, OBJECT(d), &sh_serial_ops, s, d->id, 0x28);
+    sysbus_init_mmio(SYS_BUS_DEVICE(d), iomem);
+    qdev_init_gpio_out_named(d, &s->eri, "eri", 1);
+    qdev_init_gpio_out_named(d, &s->rxi, "rxi", 1);
+    qdev_init_gpio_out_named(d, &s->txi, "txi", 1);
+    qdev_init_gpio_out_named(d, &s->tei, "tei", 1);
+    qdev_init_gpio_out_named(d, &s->bri, "bri", 1);
+
+    if (qemu_chr_fe_backend_connected(&s->chr)) {
         qemu_chr_fe_set_handlers(&s->chr, sh_serial_can_receive1,
                                  sh_serial_receive1,
                                  sh_serial_event, NULL, s, NULL, true);
     }
 
-    s->fifo_timeout_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL,
-                                         sh_serial_timeout_int, s);
+    timer_init_ns(&s->fifo_timeout_timer, QEMU_CLOCK_VIRTUAL,
+                  sh_serial_timeout_int, s);
     s->etu = NANOSECONDS_PER_SECOND / 9600;
-    s->eri = eri_source;
-    s->rxi = rxi_source;
-    s->txi = txi_source;
-    s->tei = tei_source;
-    s->bri = bri_source;
+}
+
+static void sh_serial_finalize(Object *obj)
+{
+    SHSerialState *s = SH_SERIAL(obj);
+
+    timer_del(&s->fifo_timeout_timer);
+}
+
+static void sh_serial_init(Object *obj)
+{
+}
+
+static Property sh_serial_properties[] = {
+    DEFINE_PROP_CHR("chardev", SHSerialState, chr),
+    DEFINE_PROP_UINT8("features", SHSerialState, feat, 0),
+    DEFINE_PROP_END_OF_LIST()
+};
+
+static void sh_serial_class_init(ObjectClass *oc, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(oc);
+
+    device_class_set_props(dc, sh_serial_properties);
+    dc->realize = sh_serial_realize;
+    dc->reset = sh_serial_reset;
+    /* Reason: part of SuperH CPU/SoC, needs to be wired up */
+    dc->user_creatable = false;
 }
diff --git a/hw/char/trace-events b/hw/char/trace-events
index b774832af4..2ecb36232e 100644
--- a/hw/char/trace-events
+++ b/hw/char/trace-events
@@ -101,3 +101,7 @@ exynos_uart_rx_timeout(uint32_t channel, uint32_t stat, uint32_t intsp) "UART%d:
 
 # cadence_uart.c
 cadence_uart_baudrate(unsigned baudrate) "baudrate %u"
+
+# sh_serial.c
+sh_serial_read(char *id, unsigned size, uint64_t offs, uint64_t val) " %s size %d offs 0x%02" PRIx64 " -> 0x%02" PRIx64
+sh_serial_write(char *id, unsigned size, uint64_t offs, uint64_t val) "%s size %d offs 0x%02" PRIx64 " <- 0x%02" PRIx64
diff --git a/hw/core/gpio.c b/hw/core/gpio.c
new file mode 100644
index 0000000000..8e6b4f5edf
--- /dev/null
+++ b/hw/core/gpio.c
@@ -0,0 +1,197 @@
+/*
+ * qdev GPIO helpers
+ *
+ *  Copyright (c) 2009 CodeSourcery
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "qemu/osdep.h"
+#include "hw/qdev-core.h"
+#include "hw/irq.h"
+#include "qapi/error.h"
+
+static NamedGPIOList *qdev_get_named_gpio_list(DeviceState *dev,
+                                               const char *name)
+{
+    NamedGPIOList *ngl;
+
+    QLIST_FOREACH(ngl, &dev->gpios, node) {
+        /* NULL is a valid and matchable name. */
+        if (g_strcmp0(name, ngl->name) == 0) {
+            return ngl;
+        }
+    }
+
+    ngl = g_malloc0(sizeof(*ngl));
+    ngl->name = g_strdup(name);
+    QLIST_INSERT_HEAD(&dev->gpios, ngl, node);
+    return ngl;
+}
+
+void qdev_init_gpio_in_named_with_opaque(DeviceState *dev,
+                                         qemu_irq_handler handler,
+                                         void *opaque,
+                                         const char *name, int n)
+{
+    int i;
+    NamedGPIOList *gpio_list = qdev_get_named_gpio_list(dev, name);
+
+    assert(gpio_list->num_out == 0 || !name);
+    gpio_list->in = qemu_extend_irqs(gpio_list->in, gpio_list->num_in, handler,
+                                     opaque, n);
+
+    if (!name) {
+        name = "unnamed-gpio-in";
+    }
+    for (i = gpio_list->num_in; i < gpio_list->num_in + n; i++) {
+        gchar *propname = g_strdup_printf("%s[%u]", name, i);
+
+        object_property_add_child(OBJECT(dev), propname,
+                                  OBJECT(gpio_list->in[i]));
+        g_free(propname);
+    }
+
+    gpio_list->num_in += n;
+}
+
+void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n)
+{
+    qdev_init_gpio_in_named(dev, handler, NULL, n);
+}
+
+void qdev_init_gpio_out_named(DeviceState *dev, qemu_irq *pins,
+                              const char *name, int n)
+{
+    int i;
+    NamedGPIOList *gpio_list = qdev_get_named_gpio_list(dev, name);
+
+    assert(gpio_list->num_in == 0 || !name);
+
+    if (!name) {
+        name = "unnamed-gpio-out";
+    }
+    memset(pins, 0, sizeof(*pins) * n);
+    for (i = 0; i < n; ++i) {
+        gchar *propname = g_strdup_printf("%s[%u]", name,
+                                          gpio_list->num_out + i);
+
+        object_property_add_link(OBJECT(dev), propname, TYPE_IRQ,
+                                 (Object **)&pins[i],
+                                 object_property_allow_set_link,
+                                 OBJ_PROP_LINK_STRONG);
+        g_free(propname);
+    }
+    gpio_list->num_out += n;
+}
+
+void qdev_init_gpio_out(DeviceState *dev, qemu_irq *pins, int n)
+{
+    qdev_init_gpio_out_named(dev, pins, NULL, n);
+}
+
+qemu_irq qdev_get_gpio_in_named(DeviceState *dev, const char *name, int n)
+{
+    NamedGPIOList *gpio_list = qdev_get_named_gpio_list(dev, name);
+
+    assert(n >= 0 && n < gpio_list->num_in);
+    return gpio_list->in[n];
+}
+
+qemu_irq qdev_get_gpio_in(DeviceState *dev, int n)
+{
+    return qdev_get_gpio_in_named(dev, NULL, n);
+}
+
+void qdev_connect_gpio_out_named(DeviceState *dev, const char *name, int n,
+                                 qemu_irq pin)
+{
+    char *propname = g_strdup_printf("%s[%d]",
+                                     name ? name : "unnamed-gpio-out", n);
+    if (pin && !OBJECT(pin)->parent) {
+        /* We need a name for object_property_set_link to work */
+        object_property_add_child(container_get(qdev_get_machine(),
+                                                "/unattached"),
+                                  "non-qdev-gpio[*]", OBJECT(pin));
+    }
+    object_property_set_link(OBJECT(dev), propname, OBJECT(pin), &error_abort);
+    g_free(propname);
+}
+
+qemu_irq qdev_get_gpio_out_connector(DeviceState *dev, const char *name, int n)
+{
+    g_autofree char *propname = g_strdup_printf("%s[%d]",
+                                     name ? name : "unnamed-gpio-out", n);
+
+    qemu_irq ret = (qemu_irq)object_property_get_link(OBJECT(dev), propname,
+                                                      NULL);
+
+    return ret;
+}
+
+/* disconnect a GPIO output, returning the disconnected input (if any) */
+
+static qemu_irq qdev_disconnect_gpio_out_named(DeviceState *dev,
+                                               const char *name, int n)
+{
+    char *propname = g_strdup_printf("%s[%d]",
+                                     name ? name : "unnamed-gpio-out", n);
+
+    qemu_irq ret = (qemu_irq)object_property_get_link(OBJECT(dev), propname,
+                                                      NULL);
+    if (ret) {
+        object_property_set_link(OBJECT(dev), propname, NULL, NULL);
+    }
+    g_free(propname);
+    return ret;
+}
+
+qemu_irq qdev_intercept_gpio_out(DeviceState *dev, qemu_irq icpt,
+                                 const char *name, int n)
+{
+    qemu_irq disconnected = qdev_disconnect_gpio_out_named(dev, name, n);
+    qdev_connect_gpio_out_named(dev, name, n, icpt);
+    return disconnected;
+}
+
+void qdev_connect_gpio_out(DeviceState *dev, int n, qemu_irq pin)
+{
+    qdev_connect_gpio_out_named(dev, NULL, n, pin);
+}
+
+void qdev_pass_gpios(DeviceState *dev, DeviceState *container,
+                     const char *name)
+{
+    int i;
+    NamedGPIOList *ngl = qdev_get_named_gpio_list(dev, name);
+
+    for (i = 0; i < ngl->num_in; i++) {
+        const char *nm = ngl->name ? ngl->name : "unnamed-gpio-in";
+        char *propname = g_strdup_printf("%s[%d]", nm, i);
+
+        object_property_add_alias(OBJECT(container), propname,
+                                  OBJECT(dev), propname);
+        g_free(propname);
+    }
+    for (i = 0; i < ngl->num_out; i++) {
+        const char *nm = ngl->name ? ngl->name : "unnamed-gpio-out";
+        char *propname = g_strdup_printf("%s[%d]", nm, i);
+
+        object_property_add_alias(OBJECT(container), propname,
+                                  OBJECT(dev), propname);
+        g_free(propname);
+    }
+    QLIST_REMOVE(ngl, node);
+    QLIST_INSERT_HEAD(&container->gpios, ngl, node);
+}
diff --git a/hw/core/hotplug-stubs.c b/hw/core/hotplug-stubs.c
new file mode 100644
index 0000000000..7aadaa29bd
--- /dev/null
+++ b/hw/core/hotplug-stubs.c
@@ -0,0 +1,34 @@
+/*
+ * Hotplug handler stubs
+ *
+ * Copyright (c) Red Hat
+ *
+ * Authors:
+ *  Philippe Mathieu-Daudé <philmd@redhat.com>,
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+#include "qemu/osdep.h"
+#include "hw/qdev-core.h"
+
+HotplugHandler *qdev_get_hotplug_handler(DeviceState *dev)
+{
+    return NULL;
+}
+
+void hotplug_handler_pre_plug(HotplugHandler *plug_handler,
+                              DeviceState *plugged_dev,
+                              Error **errp)
+{
+    g_assert_not_reached();
+}
+
+void hotplug_handler_plug(HotplugHandler *plug_handler,
+                          DeviceState *plugged_dev,
+                          Error **errp)
+{
+    g_assert_not_reached();
+}
diff --git a/hw/core/machine-smp.c b/hw/core/machine-smp.c
new file mode 100644
index 0000000000..116a0cbbfa
--- /dev/null
+++ b/hw/core/machine-smp.c
@@ -0,0 +1,181 @@
+/*
+ * QEMU Machine core (related to -smp parsing)
+ *
+ * Copyright (c) 2021 Huawei Technologies Co., Ltd
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License,
+ * or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "qemu/osdep.h"
+#include "hw/boards.h"
+#include "qapi/error.h"
+
+/*
+ * Report information of a machine's supported CPU topology hierarchy.
+ * Topology members will be ordered from the largest to the smallest
+ * in the string.
+ */
+static char *cpu_hierarchy_to_string(MachineState *ms)
+{
+    MachineClass *mc = MACHINE_GET_CLASS(ms);
+    GString *s = g_string_new(NULL);
+
+    g_string_append_printf(s, "sockets (%u)", ms->smp.sockets);
+
+    if (mc->smp_props.dies_supported) {
+        g_string_append_printf(s, " * dies (%u)", ms->smp.dies);
+    }
+
+    g_string_append_printf(s, " * cores (%u)", ms->smp.cores);
+    g_string_append_printf(s, " * threads (%u)", ms->smp.threads);
+
+    return g_string_free(s, false);
+}
+
+/*
+ * smp_parse - Generic function used to parse the given SMP configuration
+ *
+ * Any missing parameter in "cpus/maxcpus/sockets/cores/threads" will be
+ * automatically computed based on the provided ones.
+ *
+ * In the calculation of omitted sockets/cores/threads: we prefer sockets
+ * over cores over threads before 6.2, while preferring cores over sockets
+ * over threads since 6.2.
+ *
+ * In the calculation of cpus/maxcpus: When both maxcpus and cpus are omitted,
+ * maxcpus will be computed from the given parameters and cpus will be set
+ * equal to maxcpus. When only one of maxcpus and cpus is given then the
+ * omitted one will be set to its given counterpart's value. Both maxcpus and
+ * cpus may be specified, but maxcpus must be equal to or greater than cpus.
+ *
+ * For compatibility, apart from the parameters that will be computed, newly
+ * introduced topology members which are likely to be target specific should
+ * be directly set as 1 if they are omitted (e.g. dies for PC since 4.1).
+ */
+void smp_parse(MachineState *ms, SMPConfiguration *config, Error **errp)
+{
+    MachineClass *mc = MACHINE_GET_CLASS(ms);
+    unsigned cpus    = config->has_cpus ? config->cpus : 0;
+    unsigned sockets = config->has_sockets ? config->sockets : 0;
+    unsigned dies    = config->has_dies ? config->dies : 0;
+    unsigned cores   = config->has_cores ? config->cores : 0;
+    unsigned threads = config->has_threads ? config->threads : 0;
+    unsigned maxcpus = config->has_maxcpus ? config->maxcpus : 0;
+
+    /*
+     * Specified CPU topology parameters must be greater than zero,
+     * explicit configuration like "cpus=0" is not allowed.
+     */
+    if ((config->has_cpus && config->cpus == 0) ||
+        (config->has_sockets && config->sockets == 0) ||
+        (config->has_dies && config->dies == 0) ||
+        (config->has_cores && config->cores == 0) ||
+        (config->has_threads && config->threads == 0) ||
+        (config->has_maxcpus && config->maxcpus == 0)) {
+        warn_report("Deprecated CPU topology (considered invalid): "
+                    "CPU topology parameters must be greater than zero");
+    }
+
+    /*
+     * If not supported by the machine, a topology parameter must be
+     * omitted or specified equal to 1.
+     */
+    if (!mc->smp_props.dies_supported && dies > 1) {
+        error_setg(errp, "dies not supported by this machine's CPU topology");
+        return;
+    }
+
+    dies = dies > 0 ? dies : 1;
+
+    /* compute missing values based on the provided ones */
+    if (cpus == 0 && maxcpus == 0) {
+        sockets = sockets > 0 ? sockets : 1;
+        cores = cores > 0 ? cores : 1;
+        threads = threads > 0 ? threads : 1;
+    } else {
+        maxcpus = maxcpus > 0 ? maxcpus : cpus;
+
+        if (mc->smp_props.prefer_sockets) {
+            /* prefer sockets over cores before 6.2 */
+            if (sockets == 0) {
+                cores = cores > 0 ? cores : 1;
+                threads = threads > 0 ? threads : 1;
+                sockets = maxcpus / (dies * cores * threads);
+            } else if (cores == 0) {
+                threads = threads > 0 ? threads : 1;
+                cores = maxcpus / (sockets * dies * threads);
+            }
+        } else {
+            /* prefer cores over sockets since 6.2 */
+            if (cores == 0) {
+                sockets = sockets > 0 ? sockets : 1;
+                threads = threads > 0 ? threads : 1;
+                cores = maxcpus / (sockets * dies * threads);
+            } else if (sockets == 0) {
+                threads = threads > 0 ? threads : 1;
+                sockets = maxcpus / (dies * cores * threads);
+            }
+        }
+
+        /* try to calculate omitted threads at last */
+        if (threads == 0) {
+            threads = maxcpus / (sockets * dies * cores);
+        }
+    }
+
+    maxcpus = maxcpus > 0 ? maxcpus : sockets * dies * cores * threads;
+    cpus = cpus > 0 ? cpus : maxcpus;
+
+    ms->smp.cpus = cpus;
+    ms->smp.sockets = sockets;
+    ms->smp.dies = dies;
+    ms->smp.cores = cores;
+    ms->smp.threads = threads;
+    ms->smp.max_cpus = maxcpus;
+
+    /* sanity-check of the computed topology */
+    if (sockets * dies * cores * threads != maxcpus) {
+        g_autofree char *topo_msg = cpu_hierarchy_to_string(ms);
+        error_setg(errp, "Invalid CPU topology: "
+                   "product of the hierarchy must match maxcpus: "
+                   "%s != maxcpus (%u)",
+                   topo_msg, maxcpus);
+        return;
+    }
+
+    if (maxcpus < cpus) {
+        g_autofree char *topo_msg = cpu_hierarchy_to_string(ms);
+        error_setg(errp, "Invalid CPU topology: "
+                   "maxcpus must be equal to or greater than smp: "
+                   "%s == maxcpus (%u) < smp_cpus (%u)",
+                   topo_msg, maxcpus, cpus);
+        return;
+    }
+
+    if (ms->smp.cpus < mc->min_cpus) {
+        error_setg(errp, "Invalid SMP CPUs %d. The min CPUs "
+                   "supported by machine '%s' is %d",
+                   ms->smp.cpus,
+                   mc->name, mc->min_cpus);
+        return;
+    }
+
+    if (ms->smp.max_cpus > mc->max_cpus) {
+        error_setg(errp, "Invalid SMP CPUs %d. The max CPUs "
+                   "supported by machine '%s' is %d",
+                   ms->smp.max_cpus,
+                   mc->name, mc->max_cpus);
+        return;
+    }
+}
diff --git a/hw/core/machine.c b/hw/core/machine.c
index b8d95eec32..e24e3e27db 100644
--- a/hw/core/machine.c
+++ b/hw/core/machine.c
@@ -548,35 +548,30 @@ void machine_class_allow_dynamic_sysbus_dev(MachineClass *mc, const char *type)
 
 bool device_is_dynamic_sysbus(MachineClass *mc, DeviceState *dev)
 {
-    bool allowed = false;
-    strList *wl;
     Object *obj = OBJECT(dev);
 
     if (!object_dynamic_cast(obj, TYPE_SYS_BUS_DEVICE)) {
         return false;
     }
 
+    return device_type_is_dynamic_sysbus(mc, object_get_typename(obj));
+}
+
+bool device_type_is_dynamic_sysbus(MachineClass *mc, const char *type)
+{
+    bool allowed = false;
+    strList *wl;
+    ObjectClass *klass = object_class_by_name(type);
+
     for (wl = mc->allowed_dynamic_sysbus_devices;
          !allowed && wl;
          wl = wl->next) {
-        allowed |= !!object_dynamic_cast(obj, wl->value);
+        allowed |= !!object_class_dynamic_cast(klass, wl->value);
     }
 
     return allowed;
 }
 
-static void validate_sysbus_device(SysBusDevice *sbdev, void *opaque)
-{
-    MachineState *machine = opaque;
-    MachineClass *mc = MACHINE_GET_CLASS(machine);
-
-    if (!device_is_dynamic_sysbus(mc, DEVICE(sbdev))) {
-        error_report("Option '-device %s' cannot be handled by this machine",
-                     object_class_get_name(object_get_class(OBJECT(sbdev))));
-        exit(1);
-    }
-}
-
 static char *machine_get_memdev(Object *obj, Error **errp)
 {
     MachineState *ms = MACHINE(obj);
@@ -592,17 +587,6 @@ static void machine_set_memdev(Object *obj, const char *value, Error **errp)
     ms->ram_memdev_id = g_strdup(value);
 }
 
-static void machine_init_notify(Notifier *notifier, void *data)
-{
-    MachineState *machine = MACHINE(qdev_get_machine());
-
-    /*
-     * Loop through all dynamically created sysbus devices and check if they are
-     * all allowed.  If a device is not allowed, error out.
-     */
-    foreach_dynamic_sysbus_device(validate_sysbus_device, machine);
-}
-
 HotpluggableCPUList *machine_query_hotpluggable_cpus(MachineState *machine)
 {
     int i;
@@ -749,165 +733,6 @@ void machine_set_cpu_numa_node(MachineState *machine,
     }
 }
 
-/*
- * Report information of a machine's supported CPU topology hierarchy.
- * Topology members will be ordered from the largest to the smallest
- * in the string.
- */
-static char *cpu_hierarchy_to_string(MachineState *ms)
-{
-    MachineClass *mc = MACHINE_GET_CLASS(ms);
-    GString *s = g_string_new(NULL);
-
-    g_string_append_printf(s, "sockets (%u)", ms->smp.sockets);
-
-    if (mc->smp_props.dies_supported) {
-        g_string_append_printf(s, " * dies (%u)", ms->smp.dies);
-    }
-
-    g_string_append_printf(s, " * cores (%u)", ms->smp.cores);
-    g_string_append_printf(s, " * threads (%u)", ms->smp.threads);
-
-    return g_string_free(s, false);
-}
-
-/*
- * smp_parse - Generic function used to parse the given SMP configuration
- *
- * Any missing parameter in "cpus/maxcpus/sockets/cores/threads" will be
- * automatically computed based on the provided ones.
- *
- * In the calculation of omitted sockets/cores/threads: we prefer sockets
- * over cores over threads before 6.2, while preferring cores over sockets
- * over threads since 6.2.
- *
- * In the calculation of cpus/maxcpus: When both maxcpus and cpus are omitted,
- * maxcpus will be computed from the given parameters and cpus will be set
- * equal to maxcpus. When only one of maxcpus and cpus is given then the
- * omitted one will be set to its given counterpart's value. Both maxcpus and
- * cpus may be specified, but maxcpus must be equal to or greater than cpus.
- *
- * For compatibility, apart from the parameters that will be computed, newly
- * introduced topology members which are likely to be target specific should
- * be directly set as 1 if they are omitted (e.g. dies for PC since 4.1).
- */
-static void smp_parse(MachineState *ms, SMPConfiguration *config, Error **errp)
-{
-    MachineClass *mc = MACHINE_GET_CLASS(ms);
-    unsigned cpus    = config->has_cpus ? config->cpus : 0;
-    unsigned sockets = config->has_sockets ? config->sockets : 0;
-    unsigned dies    = config->has_dies ? config->dies : 0;
-    unsigned cores   = config->has_cores ? config->cores : 0;
-    unsigned threads = config->has_threads ? config->threads : 0;
-    unsigned maxcpus = config->has_maxcpus ? config->maxcpus : 0;
-
-    /*
-     * Specified CPU topology parameters must be greater than zero,
-     * explicit configuration like "cpus=0" is not allowed.
-     */
-    if ((config->has_cpus && config->cpus == 0) ||
-        (config->has_sockets && config->sockets == 0) ||
-        (config->has_dies && config->dies == 0) ||
-        (config->has_cores && config->cores == 0) ||
-        (config->has_threads && config->threads == 0) ||
-        (config->has_maxcpus && config->maxcpus == 0)) {
-        warn_report("Deprecated CPU topology (considered invalid): "
-                    "CPU topology parameters must be greater than zero");
-    }
-
-    /*
-     * If not supported by the machine, a topology parameter must be
-     * omitted or specified equal to 1.
-     */
-    if (!mc->smp_props.dies_supported && dies > 1) {
-        error_setg(errp, "dies not supported by this machine's CPU topology");
-        return;
-    }
-
-    dies = dies > 0 ? dies : 1;
-
-    /* compute missing values based on the provided ones */
-    if (cpus == 0 && maxcpus == 0) {
-        sockets = sockets > 0 ? sockets : 1;
-        cores = cores > 0 ? cores : 1;
-        threads = threads > 0 ? threads : 1;
-    } else {
-        maxcpus = maxcpus > 0 ? maxcpus : cpus;
-
-        if (mc->smp_props.prefer_sockets) {
-            /* prefer sockets over cores before 6.2 */
-            if (sockets == 0) {
-                cores = cores > 0 ? cores : 1;
-                threads = threads > 0 ? threads : 1;
-                sockets = maxcpus / (dies * cores * threads);
-            } else if (cores == 0) {
-                threads = threads > 0 ? threads : 1;
-                cores = maxcpus / (sockets * dies * threads);
-            }
-        } else {
-            /* prefer cores over sockets since 6.2 */
-            if (cores == 0) {
-                sockets = sockets > 0 ? sockets : 1;
-                threads = threads > 0 ? threads : 1;
-                cores = maxcpus / (sockets * dies * threads);
-            } else if (sockets == 0) {
-                threads = threads > 0 ? threads : 1;
-                sockets = maxcpus / (dies * cores * threads);
-            }
-        }
-
-        /* try to calculate omitted threads at last */
-        if (threads == 0) {
-            threads = maxcpus / (sockets * dies * cores);
-        }
-    }
-
-    maxcpus = maxcpus > 0 ? maxcpus : sockets * dies * cores * threads;
-    cpus = cpus > 0 ? cpus : maxcpus;
-
-    ms->smp.cpus = cpus;
-    ms->smp.sockets = sockets;
-    ms->smp.dies = dies;
-    ms->smp.cores = cores;
-    ms->smp.threads = threads;
-    ms->smp.max_cpus = maxcpus;
-
-    /* sanity-check of the computed topology */
-    if (sockets * dies * cores * threads != maxcpus) {
-        g_autofree char *topo_msg = cpu_hierarchy_to_string(ms);
-        error_setg(errp, "Invalid CPU topology: "
-                   "product of the hierarchy must match maxcpus: "
-                   "%s != maxcpus (%u)",
-                   topo_msg, maxcpus);
-        return;
-    }
-
-    if (maxcpus < cpus) {
-        g_autofree char *topo_msg = cpu_hierarchy_to_string(ms);
-        error_setg(errp, "Invalid CPU topology: "
-                   "maxcpus must be equal to or greater than smp: "
-                   "%s == maxcpus (%u) < smp_cpus (%u)",
-                   topo_msg, maxcpus, cpus);
-        return;
-    }
-
-    if (ms->smp.cpus < mc->min_cpus) {
-        error_setg(errp, "Invalid SMP CPUs %d. The min CPUs "
-                   "supported by machine '%s' is %d",
-                   ms->smp.cpus,
-                   mc->name, mc->min_cpus);
-        return;
-    }
-
-    if (ms->smp.max_cpus > mc->max_cpus) {
-        error_setg(errp, "Invalid SMP CPUs %d. The max CPUs "
-                   "supported by machine '%s' is %d",
-                   ms->smp.max_cpus,
-                   mc->name, mc->max_cpus);
-        return;
-    }
-}
-
 static void machine_get_smp(Object *obj, Visitor *v, const char *name,
                             void *opaque, Error **errp)
 {
@@ -1101,10 +926,6 @@ static void machine_initfn(Object *obj)
                                         "Table (HMAT)");
     }
 
-    /* Register notifier when init is done for sysbus sanity checks */
-    ms->sysbus_notifier.notify = machine_init_notify;
-    qemu_add_machine_init_done_notifier(&ms->sysbus_notifier);
-
     /* default to mc->default_cpus */
     ms->smp.cpus = mc->default_cpus;
     ms->smp.max_cpus = mc->default_cpus;
diff --git a/hw/core/meson.build b/hw/core/meson.build
index 18f44fb7c2..0f884d6fd4 100644
--- a/hw/core/meson.build
+++ b/hw/core/meson.build
@@ -1,7 +1,6 @@
 # core qdev-related obj files, also used by *-user and unit tests
-hwcore_files = files(
+hwcore_ss.add(files(
   'bus.c',
-  'hotplug.c',
   'qdev-properties.c',
   'qdev.c',
   'reset.c',
@@ -11,22 +10,34 @@ hwcore_files = files(
   'irq.c',
   'clock.c',
   'qdev-clock.c',
-)
+))
+if have_system
+  hwcore_ss.add(files(
+    'hotplug.c',
+    'qdev-hotplug.c',
+  ))
+else
+  hwcore_ss.add(files(
+    'hotplug-stubs.c',
+  ))
+endif
 
 common_ss.add(files('cpu-common.c'))
-common_ss.add(when: 'CONFIG_FITLOADER', if_true: files('loader-fit.c'))
-common_ss.add(when: 'CONFIG_GENERIC_LOADER', if_true: files('generic-loader.c'))
-common_ss.add(when: ['CONFIG_GUEST_LOADER', fdt], if_true: files('guest-loader.c'))
-common_ss.add(when: 'CONFIG_OR_IRQ', if_true: files('or-irq.c'))
-common_ss.add(when: 'CONFIG_PLATFORM_BUS', if_true: files('platform-bus.c'))
-common_ss.add(when: 'CONFIG_PTIMER', if_true: files('ptimer.c'))
-common_ss.add(when: 'CONFIG_REGISTER', if_true: files('register.c'))
-common_ss.add(when: 'CONFIG_SPLIT_IRQ', if_true: files('split-irq.c'))
-common_ss.add(when: 'CONFIG_XILINX_AXI', if_true: files('stream.c'))
+common_ss.add(files('machine-smp.c'))
+softmmu_ss.add(when: 'CONFIG_FITLOADER', if_true: files('loader-fit.c'))
+softmmu_ss.add(when: 'CONFIG_GENERIC_LOADER', if_true: files('generic-loader.c'))
+softmmu_ss.add(when: ['CONFIG_GUEST_LOADER', fdt], if_true: files('guest-loader.c'))
+softmmu_ss.add(when: 'CONFIG_OR_IRQ', if_true: files('or-irq.c'))
+softmmu_ss.add(when: 'CONFIG_PLATFORM_BUS', if_true: files('platform-bus.c'))
+softmmu_ss.add(when: 'CONFIG_PTIMER', if_true: files('ptimer.c'))
+softmmu_ss.add(when: 'CONFIG_REGISTER', if_true: files('register.c'))
+softmmu_ss.add(when: 'CONFIG_SPLIT_IRQ', if_true: files('split-irq.c'))
+softmmu_ss.add(when: 'CONFIG_XILINX_AXI', if_true: files('stream.c'))
 
 softmmu_ss.add(files(
   'cpu-sysemu.c',
   'fw-path-provider.c',
+  'gpio.c',
   'loader.c',
   'machine-hmp-cmds.c',
   'machine.c',
diff --git a/hw/core/qdev-hotplug.c b/hw/core/qdev-hotplug.c
new file mode 100644
index 0000000000..d495d0e9c7
--- /dev/null
+++ b/hw/core/qdev-hotplug.c
@@ -0,0 +1,73 @@
+/*
+ * QDev Hotplug handlers
+ *
+ * Copyright (c) Red Hat
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+#include "hw/qdev-core.h"
+#include "hw/boards.h"
+
+HotplugHandler *qdev_get_machine_hotplug_handler(DeviceState *dev)
+{
+    MachineState *machine;
+    MachineClass *mc;
+    Object *m_obj = qdev_get_machine();
+
+    if (object_dynamic_cast(m_obj, TYPE_MACHINE)) {
+        machine = MACHINE(m_obj);
+        mc = MACHINE_GET_CLASS(machine);
+        if (mc->get_hotplug_handler) {
+            return mc->get_hotplug_handler(machine, dev);
+        }
+    }
+
+    return NULL;
+}
+
+bool qdev_hotplug_allowed(DeviceState *dev, Error **errp)
+{
+    MachineState *machine;
+    MachineClass *mc;
+    Object *m_obj = qdev_get_machine();
+
+    if (object_dynamic_cast(m_obj, TYPE_MACHINE)) {
+        machine = MACHINE(m_obj);
+        mc = MACHINE_GET_CLASS(machine);
+        if (mc->hotplug_allowed) {
+            return mc->hotplug_allowed(machine, dev, errp);
+        }
+    }
+
+    return true;
+}
+
+HotplugHandler *qdev_get_bus_hotplug_handler(DeviceState *dev)
+{
+    if (dev->parent_bus) {
+        return dev->parent_bus->hotplug_handler;
+    }
+    return NULL;
+}
+
+HotplugHandler *qdev_get_hotplug_handler(DeviceState *dev)
+{
+    HotplugHandler *hotplug_ctrl = qdev_get_machine_hotplug_handler(dev);
+
+    if (hotplug_ctrl == NULL && dev->parent_bus) {
+        hotplug_ctrl = qdev_get_bus_hotplug_handler(dev);
+    }
+    return hotplug_ctrl;
+}
+
+/* can be used as ->unplug() callback for the simple cases */
+void qdev_simple_device_unplug_cb(HotplugHandler *hotplug_dev,
+                                  DeviceState *dev, Error **errp)
+{
+    qdev_unrealize(dev);
+}
diff --git a/hw/core/qdev.c b/hw/core/qdev.c
index 7f06403752..84f3019440 100644
--- a/hw/core/qdev.c
+++ b/hw/core/qdev.c
@@ -33,7 +33,6 @@
 #include "qapi/visitor.h"
 #include "qemu/error-report.h"
 #include "qemu/option.h"
-#include "hw/hotplug.h"
 #include "hw/irq.h"
 #include "hw/qdev-properties.h"
 #include "hw/boards.h"
@@ -238,58 +237,6 @@ void qdev_set_legacy_instance_id(DeviceState *dev, int alias_id,
     dev->alias_required_for_version = required_for_version;
 }
 
-HotplugHandler *qdev_get_machine_hotplug_handler(DeviceState *dev)
-{
-    MachineState *machine;
-    MachineClass *mc;
-    Object *m_obj = qdev_get_machine();
-
-    if (object_dynamic_cast(m_obj, TYPE_MACHINE)) {
-        machine = MACHINE(m_obj);
-        mc = MACHINE_GET_CLASS(machine);
-        if (mc->get_hotplug_handler) {
-            return mc->get_hotplug_handler(machine, dev);
-        }
-    }
-
-    return NULL;
-}
-
-bool qdev_hotplug_allowed(DeviceState *dev, Error **errp)
-{
-    MachineState *machine;
-    MachineClass *mc;
-    Object *m_obj = qdev_get_machine();
-
-    if (object_dynamic_cast(m_obj, TYPE_MACHINE)) {
-        machine = MACHINE(m_obj);
-        mc = MACHINE_GET_CLASS(machine);
-        if (mc->hotplug_allowed) {
-            return mc->hotplug_allowed(machine, dev, errp);
-        }
-    }
-
-    return true;
-}
-
-HotplugHandler *qdev_get_bus_hotplug_handler(DeviceState *dev)
-{
-    if (dev->parent_bus) {
-        return dev->parent_bus->hotplug_handler;
-    }
-    return NULL;
-}
-
-HotplugHandler *qdev_get_hotplug_handler(DeviceState *dev)
-{
-    HotplugHandler *hotplug_ctrl = qdev_get_machine_hotplug_handler(dev);
-
-    if (hotplug_ctrl == NULL && dev->parent_bus) {
-        hotplug_ctrl = qdev_get_bus_hotplug_handler(dev);
-    }
-    return hotplug_ctrl;
-}
-
 static int qdev_prereset(DeviceState *dev, void *opaque)
 {
     trace_qdev_reset_tree(dev, object_get_typename(OBJECT(dev)));
@@ -371,13 +318,6 @@ static void device_reset_child_foreach(Object *obj, ResettableChildCallback cb,
     }
 }
 
-/* can be used as ->unplug() callback for the simple cases */
-void qdev_simple_device_unplug_cb(HotplugHandler *hotplug_dev,
-                                  DeviceState *dev, Error **errp)
-{
-    qdev_unrealize(dev);
-}
-
 bool qdev_realize(DeviceState *dev, BusState *bus, Error **errp)
 {
     assert(!dev->realized && !dev->parent_bus);
@@ -436,180 +376,6 @@ BusState *qdev_get_parent_bus(DeviceState *dev)
     return dev->parent_bus;
 }
 
-static NamedGPIOList *qdev_get_named_gpio_list(DeviceState *dev,
-                                               const char *name)
-{
-    NamedGPIOList *ngl;
-
-    QLIST_FOREACH(ngl, &dev->gpios, node) {
-        /* NULL is a valid and matchable name. */
-        if (g_strcmp0(name, ngl->name) == 0) {
-            return ngl;
-        }
-    }
-
-    ngl = g_malloc0(sizeof(*ngl));
-    ngl->name = g_strdup(name);
-    QLIST_INSERT_HEAD(&dev->gpios, ngl, node);
-    return ngl;
-}
-
-void qdev_init_gpio_in_named_with_opaque(DeviceState *dev,
-                                         qemu_irq_handler handler,
-                                         void *opaque,
-                                         const char *name, int n)
-{
-    int i;
-    NamedGPIOList *gpio_list = qdev_get_named_gpio_list(dev, name);
-
-    assert(gpio_list->num_out == 0 || !name);
-    gpio_list->in = qemu_extend_irqs(gpio_list->in, gpio_list->num_in, handler,
-                                     opaque, n);
-
-    if (!name) {
-        name = "unnamed-gpio-in";
-    }
-    for (i = gpio_list->num_in; i < gpio_list->num_in + n; i++) {
-        gchar *propname = g_strdup_printf("%s[%u]", name, i);
-
-        object_property_add_child(OBJECT(dev), propname,
-                                  OBJECT(gpio_list->in[i]));
-        g_free(propname);
-    }
-
-    gpio_list->num_in += n;
-}
-
-void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n)
-{
-    qdev_init_gpio_in_named(dev, handler, NULL, n);
-}
-
-void qdev_init_gpio_out_named(DeviceState *dev, qemu_irq *pins,
-                              const char *name, int n)
-{
-    int i;
-    NamedGPIOList *gpio_list = qdev_get_named_gpio_list(dev, name);
-
-    assert(gpio_list->num_in == 0 || !name);
-
-    if (!name) {
-        name = "unnamed-gpio-out";
-    }
-    memset(pins, 0, sizeof(*pins) * n);
-    for (i = 0; i < n; ++i) {
-        gchar *propname = g_strdup_printf("%s[%u]", name,
-                                          gpio_list->num_out + i);
-
-        object_property_add_link(OBJECT(dev), propname, TYPE_IRQ,
-                                 (Object **)&pins[i],
-                                 object_property_allow_set_link,
-                                 OBJ_PROP_LINK_STRONG);
-        g_free(propname);
-    }
-    gpio_list->num_out += n;
-}
-
-void qdev_init_gpio_out(DeviceState *dev, qemu_irq *pins, int n)
-{
-    qdev_init_gpio_out_named(dev, pins, NULL, n);
-}
-
-qemu_irq qdev_get_gpio_in_named(DeviceState *dev, const char *name, int n)
-{
-    NamedGPIOList *gpio_list = qdev_get_named_gpio_list(dev, name);
-
-    assert(n >= 0 && n < gpio_list->num_in);
-    return gpio_list->in[n];
-}
-
-qemu_irq qdev_get_gpio_in(DeviceState *dev, int n)
-{
-    return qdev_get_gpio_in_named(dev, NULL, n);
-}
-
-void qdev_connect_gpio_out_named(DeviceState *dev, const char *name, int n,
-                                 qemu_irq pin)
-{
-    char *propname = g_strdup_printf("%s[%d]",
-                                     name ? name : "unnamed-gpio-out", n);
-    if (pin && !OBJECT(pin)->parent) {
-        /* We need a name for object_property_set_link to work */
-        object_property_add_child(container_get(qdev_get_machine(),
-                                                "/unattached"),
-                                  "non-qdev-gpio[*]", OBJECT(pin));
-    }
-    object_property_set_link(OBJECT(dev), propname, OBJECT(pin), &error_abort);
-    g_free(propname);
-}
-
-qemu_irq qdev_get_gpio_out_connector(DeviceState *dev, const char *name, int n)
-{
-    g_autofree char *propname = g_strdup_printf("%s[%d]",
-                                     name ? name : "unnamed-gpio-out", n);
-
-    qemu_irq ret = (qemu_irq)object_property_get_link(OBJECT(dev), propname,
-                                                      NULL);
-
-    return ret;
-}
-
-/* disconnect a GPIO output, returning the disconnected input (if any) */
-
-static qemu_irq qdev_disconnect_gpio_out_named(DeviceState *dev,
-                                               const char *name, int n)
-{
-    char *propname = g_strdup_printf("%s[%d]",
-                                     name ? name : "unnamed-gpio-out", n);
-
-    qemu_irq ret = (qemu_irq)object_property_get_link(OBJECT(dev), propname,
-                                                      NULL);
-    if (ret) {
-        object_property_set_link(OBJECT(dev), propname, NULL, NULL);
-    }
-    g_free(propname);
-    return ret;
-}
-
-qemu_irq qdev_intercept_gpio_out(DeviceState *dev, qemu_irq icpt,
-                                 const char *name, int n)
-{
-    qemu_irq disconnected = qdev_disconnect_gpio_out_named(dev, name, n);
-    qdev_connect_gpio_out_named(dev, name, n, icpt);
-    return disconnected;
-}
-
-void qdev_connect_gpio_out(DeviceState * dev, int n, qemu_irq pin)
-{
-    qdev_connect_gpio_out_named(dev, NULL, n, pin);
-}
-
-void qdev_pass_gpios(DeviceState *dev, DeviceState *container,
-                     const char *name)
-{
-    int i;
-    NamedGPIOList *ngl = qdev_get_named_gpio_list(dev, name);
-
-    for (i = 0; i < ngl->num_in; i++) {
-        const char *nm = ngl->name ? ngl->name : "unnamed-gpio-in";
-        char *propname = g_strdup_printf("%s[%d]", nm, i);
-
-        object_property_add_alias(OBJECT(container), propname,
-                                  OBJECT(dev), propname);
-        g_free(propname);
-    }
-    for (i = 0; i < ngl->num_out; i++) {
-        const char *nm = ngl->name ? ngl->name : "unnamed-gpio-out";
-        char *propname = g_strdup_printf("%s[%d]", nm, i);
-
-        object_property_add_alias(OBJECT(container), propname,
-                                  OBJECT(dev), propname);
-        g_free(propname);
-    }
-    QLIST_REMOVE(ngl, node);
-    QLIST_INSERT_HEAD(&container->gpios, ngl, node);
-}
-
 BusState *qdev_get_child_bus(DeviceState *dev, const char *name)
 {
     BusState *bus;
diff --git a/hw/i386/xen/xen-hvm.c b/hw/i386/xen/xen-hvm.c
index e3d3d5cf89..482be95415 100644
--- a/hw/i386/xen/xen-hvm.c
+++ b/hw/i386/xen/xen-hvm.c
@@ -1613,8 +1613,8 @@ void xen_hvm_modified_memory(ram_addr_t start, ram_addr_t length)
 void qmp_xen_set_global_dirty_log(bool enable, Error **errp)
 {
     if (enable) {
-        memory_global_dirty_log_start();
+        memory_global_dirty_log_start(GLOBAL_DIRTY_MIGRATION);
     } else {
-        memory_global_dirty_log_stop();
+        memory_global_dirty_log_stop(GLOBAL_DIRTY_MIGRATION);
     }
 }
diff --git a/hw/intc/sh_intc.c b/hw/intc/sh_intc.c
index 72a55e32dd..c9b0b0c1ec 100644
--- a/hw/intc/sh_intc.c
+++ b/hw/intc/sh_intc.c
@@ -9,40 +9,37 @@
  */
 
 #include "qemu/osdep.h"
+#include "qemu/log.h"
 #include "cpu.h"
 #include "hw/sh4/sh_intc.h"
 #include "hw/irq.h"
 #include "hw/sh4/sh.h"
-
-//#define DEBUG_INTC
-//#define DEBUG_INTC_SOURCES
-
-#define INTC_A7(x) ((x) & 0x1fffffff)
+#include "trace.h"
 
 void sh_intc_toggle_source(struct intc_source *source,
-			   int enable_adj, int assert_adj)
+                           int enable_adj, int assert_adj)
 {
     int enable_changed = 0;
     int pending_changed = 0;
     int old_pending;
 
-    if ((source->enable_count == source->enable_max) && (enable_adj == -1))
+    if (source->enable_count == source->enable_max && enable_adj == -1) {
         enable_changed = -1;
-
+    }
     source->enable_count += enable_adj;
 
-    if (source->enable_count == source->enable_max)
+    if (source->enable_count == source->enable_max) {
         enable_changed = 1;
-
+    }
     source->asserted += assert_adj;
 
     old_pending = source->pending;
     source->pending = source->asserted &&
       (source->enable_count == source->enable_max);
 
-    if (old_pending != source->pending)
+    if (old_pending != source->pending) {
         pending_changed = 1;
-
+    }
     if (pending_changed) {
         if (source->pending) {
             source->parent->pending++;
@@ -54,35 +51,30 @@ void sh_intc_toggle_source(struct intc_source *source,
             if (source->parent->pending == 0) {
                 cpu_reset_interrupt(first_cpu, CPU_INTERRUPT_HARD);
             }
-	}
+        }
     }
 
-  if (enable_changed || assert_adj || pending_changed) {
-#ifdef DEBUG_INTC_SOURCES
-            printf("sh_intc: (%d/%d/%d/%d) interrupt source 0x%x %s%s%s\n",
-		   source->parent->pending,
-		   source->asserted,
-		   source->enable_count,
-		   source->enable_max,
-		   source->vect,
-		   source->asserted ? "asserted " :
-		   assert_adj ? "deasserted" : "",
-		   enable_changed == 1 ? "enabled " :
-		   enable_changed == -1 ? "disabled " : "",
-		   source->pending ? "pending" : "");
-#endif
-  }
+    if (enable_changed || assert_adj || pending_changed) {
+        trace_sh_intc_sources(source->parent->pending, source->asserted,
+                              source->enable_count, source->enable_max,
+                              source->vect, source->asserted ? "asserted " :
+                              assert_adj ? "deasserted" : "",
+                              enable_changed == 1 ? "enabled " :
+                              enable_changed == -1 ? "disabled " : "",
+                              source->pending ? "pending" : "");
+    }
 }
 
-static void sh_intc_set_irq (void *opaque, int n, int level)
+static void sh_intc_set_irq(void *opaque, int n, int level)
 {
-  struct intc_desc *desc = opaque;
-  struct intc_source *source = &(desc->sources[n]);
+    struct intc_desc *desc = opaque;
+    struct intc_source *source = &desc->sources[n];
 
-  if (level && !source->asserted)
-    sh_intc_toggle_source(source, 0, 1);
-  else if (!level && source->asserted)
-    sh_intc_toggle_source(source, 0, -1);
+    if (level && !source->asserted) {
+        sh_intc_toggle_source(source, 0, 1);
+    } else if (!level && source->asserted) {
+        sh_intc_toggle_source(source, 0, -1);
+    }
 }
 
 int sh_intc_get_pending_vector(struct intc_desc *desc, int imask)
@@ -97,147 +89,124 @@ int sh_intc_get_pending_vector(struct intc_desc *desc, int imask)
     }
 
     for (i = 0; i < desc->nr_sources; i++) {
-        struct intc_source *source = desc->sources + i;
+        struct intc_source *source = &desc->sources[i];
 
-	if (source->pending) {
-#ifdef DEBUG_INTC_SOURCES
-            printf("sh_intc: (%d) returning interrupt source 0x%x\n",
-		   desc->pending, source->vect);
-#endif
+        if (source->pending) {
+            trace_sh_intc_pending(desc->pending, source->vect);
             return source->vect;
-	}
+        }
     }
-
-    abort();
+    g_assert_not_reached();
 }
 
-#define INTC_MODE_NONE       0
-#define INTC_MODE_DUAL_SET   1
-#define INTC_MODE_DUAL_CLR   2
-#define INTC_MODE_ENABLE_REG 3
-#define INTC_MODE_MASK_REG   4
-#define INTC_MODE_IS_PRIO    8
-
-static unsigned int sh_intc_mode(unsigned long address,
-				 unsigned long set_reg, unsigned long clr_reg)
+typedef enum {
+    INTC_MODE_NONE,
+    INTC_MODE_DUAL_SET,
+    INTC_MODE_DUAL_CLR,
+    INTC_MODE_ENABLE_REG,
+    INTC_MODE_MASK_REG,
+} SHIntCMode;
+#define INTC_MODE_IS_PRIO 0x80
+
+static SHIntCMode sh_intc_mode(unsigned long address, unsigned long set_reg,
+                               unsigned long clr_reg)
 {
-    if ((address != INTC_A7(set_reg)) &&
-	(address != INTC_A7(clr_reg)))
+    if (address != A7ADDR(set_reg) && address != A7ADDR(clr_reg)) {
         return INTC_MODE_NONE;
-
+    }
     if (set_reg && clr_reg) {
-        if (address == INTC_A7(set_reg))
-            return INTC_MODE_DUAL_SET;
-	else
-            return INTC_MODE_DUAL_CLR;
+        return address == A7ADDR(set_reg) ?
+               INTC_MODE_DUAL_SET : INTC_MODE_DUAL_CLR;
     }
-
-    if (set_reg)
-        return INTC_MODE_ENABLE_REG;
-    else
-        return INTC_MODE_MASK_REG;
+    return set_reg ? INTC_MODE_ENABLE_REG : INTC_MODE_MASK_REG;
 }
 
 static void sh_intc_locate(struct intc_desc *desc,
-			   unsigned long address,
-			   unsigned long **datap,
-			   intc_enum **enums,
-			   unsigned int *first,
-			   unsigned int *width,
-			   unsigned int *modep)
+                           unsigned long address,
+                           unsigned long **datap,
+                           intc_enum **enums,
+                           unsigned int *first,
+                           unsigned int *width,
+                           unsigned int *modep)
 {
-    unsigned int i, mode;
+    SHIntCMode mode;
+    unsigned int i;
 
     /* this is slow but works for now */
 
     if (desc->mask_regs) {
         for (i = 0; i < desc->nr_mask_regs; i++) {
-	    struct intc_mask_reg *mr = desc->mask_regs + i;
-
-	    mode = sh_intc_mode(address, mr->set_reg, mr->clr_reg);
-	    if (mode == INTC_MODE_NONE)
-                continue;
-
-	    *modep = mode;
-	    *datap = &mr->value;
-	    *enums = mr->enum_ids;
-	    *first = mr->reg_width - 1;
-	    *width = 1;
-	    return;
-	}
+            struct intc_mask_reg *mr = &desc->mask_regs[i];
+
+            mode = sh_intc_mode(address, mr->set_reg, mr->clr_reg);
+            if (mode != INTC_MODE_NONE) {
+                *modep = mode;
+                *datap = &mr->value;
+                *enums = mr->enum_ids;
+                *first = mr->reg_width - 1;
+                *width = 1;
+                return;
+            }
+        }
     }
 
     if (desc->prio_regs) {
         for (i = 0; i < desc->nr_prio_regs; i++) {
-	    struct intc_prio_reg *pr = desc->prio_regs + i;
-
-	    mode = sh_intc_mode(address, pr->set_reg, pr->clr_reg);
-	    if (mode == INTC_MODE_NONE)
-                continue;
-
-	    *modep = mode | INTC_MODE_IS_PRIO;
-	    *datap = &pr->value;
-	    *enums = pr->enum_ids;
-	    *first = (pr->reg_width / pr->field_width) - 1;
-	    *width = pr->field_width;
-	    return;
-	}
+            struct intc_prio_reg *pr = &desc->prio_regs[i];
+
+            mode = sh_intc_mode(address, pr->set_reg, pr->clr_reg);
+            if (mode != INTC_MODE_NONE) {
+                *modep = mode | INTC_MODE_IS_PRIO;
+                *datap = &pr->value;
+                *enums = pr->enum_ids;
+                *first = pr->reg_width / pr->field_width - 1;
+                *width = pr->field_width;
+                return;
+            }
+        }
     }
-
-    abort();
+    g_assert_not_reached();
 }
 
 static void sh_intc_toggle_mask(struct intc_desc *desc, intc_enum id,
-				int enable, int is_group)
+                                int enable, int is_group)
 {
-    struct intc_source *source = desc->sources + id;
-
-    if (!id)
-	return;
+    struct intc_source *source = &desc->sources[id];
 
+    if (!id) {
+        return;
+    }
     if (!source->next_enum_id && (!source->enable_max || !source->vect)) {
-#ifdef DEBUG_INTC_SOURCES
-        printf("sh_intc: reserved interrupt source %d modified\n", id);
-#endif
-	return;
+        qemu_log_mask(LOG_UNIMP,
+                      "sh_intc: reserved interrupt source %d modified\n", id);
+        return;
     }
 
-    if (source->vect)
+    if (source->vect) {
         sh_intc_toggle_source(source, enable ? 1 : -1, 0);
-
-#ifdef DEBUG_INTC
-    else {
-        printf("setting interrupt group %d to %d\n", id, !!enable);
     }
-#endif
 
     if ((is_group || !source->vect) && source->next_enum_id) {
         sh_intc_toggle_mask(desc, source->next_enum_id, enable, 1);
     }
 
-#ifdef DEBUG_INTC
     if (!source->vect) {
-        printf("setting interrupt group %d to %d - done\n", id, !!enable);
+        trace_sh_intc_set(id, !!enable);
     }
-#endif
 }
 
-static uint64_t sh_intc_read(void *opaque, hwaddr offset,
-                             unsigned size)
+static uint64_t sh_intc_read(void *opaque, hwaddr offset, unsigned size)
 {
     struct intc_desc *desc = opaque;
-    intc_enum *enum_ids = NULL;
-    unsigned int first = 0;
-    unsigned int width = 0;
-    unsigned int mode = 0;
+    intc_enum *enum_ids;
+    unsigned int first;
+    unsigned int width;
+    unsigned int mode;
     unsigned long *valuep;
 
-#ifdef DEBUG_INTC
-    printf("sh_intc_read 0x%lx\n", (unsigned long) offset);
-#endif
-
-    sh_intc_locate(desc, (unsigned long)offset, &valuep, 
-		   &enum_ids, &first, &width, &mode);
+    sh_intc_locate(desc, (unsigned long)offset, &valuep,
+                   &enum_ids, &first, &width, &mode);
+    trace_sh_intc_read(size, (uint64_t)offset, *valuep);
     return *valuep;
 }
 
@@ -245,45 +214,40 @@ static void sh_intc_write(void *opaque, hwaddr offset,
                           uint64_t value, unsigned size)
 {
     struct intc_desc *desc = opaque;
-    intc_enum *enum_ids = NULL;
-    unsigned int first = 0;
-    unsigned int width = 0;
-    unsigned int mode = 0;
-    unsigned int k;
+    intc_enum *enum_ids;
+    unsigned int first;
+    unsigned int width;
+    unsigned int mode;
     unsigned long *valuep;
+    unsigned int k;
     unsigned long mask;
 
-#ifdef DEBUG_INTC
-    printf("sh_intc_write 0x%lx 0x%08x\n", (unsigned long) offset, value);
-#endif
-
-    sh_intc_locate(desc, (unsigned long)offset, &valuep, 
-		   &enum_ids, &first, &width, &mode);
-
+    trace_sh_intc_write(size, (uint64_t)offset, value);
+    sh_intc_locate(desc, (unsigned long)offset, &valuep,
+                   &enum_ids, &first, &width, &mode);
     switch (mode) {
-    case INTC_MODE_ENABLE_REG | INTC_MODE_IS_PRIO: break;
-    case INTC_MODE_DUAL_SET: value |= *valuep; break;
-    case INTC_MODE_DUAL_CLR: value = *valuep & ~value; break;
-    default: abort();
+    case INTC_MODE_ENABLE_REG | INTC_MODE_IS_PRIO:
+        break;
+    case INTC_MODE_DUAL_SET:
+        value |= *valuep;
+        break;
+    case INTC_MODE_DUAL_CLR:
+        value = *valuep & ~value;
+        break;
+    default:
+        g_assert_not_reached();
     }
 
     for (k = 0; k <= first; k++) {
-        mask = ((1 << width) - 1) << ((first - k) * width);
-
-	if ((*valuep & mask) == (value & mask))
-            continue;
-#if 0
-	printf("k = %d, first = %d, enum = %d, mask = 0x%08x\n", 
-	       k, first, enum_ids[k], (unsigned int)mask);
-#endif
-        sh_intc_toggle_mask(desc, enum_ids[k], value & mask, 0);
+        mask = (1 << width) - 1;
+        mask <<= (first - k) * width;
+
+        if ((*valuep & mask) != (value & mask)) {
+            sh_intc_toggle_mask(desc, enum_ids[k], value & mask, 0);
+        }
     }
 
     *valuep = value;
-
-#ifdef DEBUG_INTC
-    printf("sh_intc_write 0x%lx -> 0x%08x\n", (unsigned long) offset, value);
-#endif
 }
 
 static const MemoryRegionOps sh_intc_ops = {
@@ -292,155 +256,136 @@ static const MemoryRegionOps sh_intc_ops = {
     .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
-struct intc_source *sh_intc_source(struct intc_desc *desc, intc_enum id)
-{
-    if (id)
-        return desc->sources + id;
-
-    return NULL;
-}
-
-static unsigned int sh_intc_register(MemoryRegion *sysmem,
-                             struct intc_desc *desc,
-                             const unsigned long address,
-                             const char *type,
-                             const char *action,
-                             const unsigned int index)
-{
-    char name[60];
-    MemoryRegion *iomem, *iomem_p4, *iomem_a7;
-
-    if (!address) {
-        return 0;
-    }
-
-    iomem = &desc->iomem;
-    iomem_p4 = desc->iomem_aliases + index;
-    iomem_a7 = iomem_p4 + 1;
-
-#define SH_INTC_IOMEM_FORMAT "interrupt-controller-%s-%s-%s"
-    snprintf(name, sizeof(name), SH_INTC_IOMEM_FORMAT, type, action, "p4");
-    memory_region_init_alias(iomem_p4, NULL, name, iomem, INTC_A7(address), 4);
-    memory_region_add_subregion(sysmem, P4ADDR(address), iomem_p4);
-
-    snprintf(name, sizeof(name), SH_INTC_IOMEM_FORMAT, type, action, "a7");
-    memory_region_init_alias(iomem_a7, NULL, name, iomem, INTC_A7(address), 4);
-    memory_region_add_subregion(sysmem, A7ADDR(address), iomem_a7);
-#undef SH_INTC_IOMEM_FORMAT
-
-    /* used to increment aliases index */
-    return 2;
-}
-
 static void sh_intc_register_source(struct intc_desc *desc,
-				    intc_enum source,
-				    struct intc_group *groups,
-				    int nr_groups)
+                                    intc_enum source,
+                                    struct intc_group *groups,
+                                    int nr_groups)
 {
     unsigned int i, k;
-    struct intc_source *s;
+    intc_enum id;
 
     if (desc->mask_regs) {
         for (i = 0; i < desc->nr_mask_regs; i++) {
-	    struct intc_mask_reg *mr = desc->mask_regs + i;
-
-	    for (k = 0; k < ARRAY_SIZE(mr->enum_ids); k++) {
-                if (mr->enum_ids[k] != source)
-                    continue;
+            struct intc_mask_reg *mr = &desc->mask_regs[i];
 
-		s = sh_intc_source(desc, mr->enum_ids[k]);
-		if (s)
-                    s->enable_max++;
-	    }
-	}
+            for (k = 0; k < ARRAY_SIZE(mr->enum_ids); k++) {
+                id = mr->enum_ids[k];
+                if (id && id == source) {
+                    desc->sources[id].enable_max++;
+                }
+            }
+        }
     }
 
     if (desc->prio_regs) {
         for (i = 0; i < desc->nr_prio_regs; i++) {
-	    struct intc_prio_reg *pr = desc->prio_regs + i;
-
-	    for (k = 0; k < ARRAY_SIZE(pr->enum_ids); k++) {
-                if (pr->enum_ids[k] != source)
-                    continue;
+            struct intc_prio_reg *pr = &desc->prio_regs[i];
 
-		s = sh_intc_source(desc, pr->enum_ids[k]);
-		if (s)
-                    s->enable_max++;
-	    }
-	}
+            for (k = 0; k < ARRAY_SIZE(pr->enum_ids); k++) {
+                id = pr->enum_ids[k];
+                if (id && id == source) {
+                    desc->sources[id].enable_max++;
+                }
+            }
+        }
     }
 
     if (groups) {
         for (i = 0; i < nr_groups; i++) {
-	    struct intc_group *gr = groups + i;
+            struct intc_group *gr = &groups[i];
 
-	    for (k = 0; k < ARRAY_SIZE(gr->enum_ids); k++) {
-                if (gr->enum_ids[k] != source)
-                    continue;
-
-		s = sh_intc_source(desc, gr->enum_ids[k]);
-		if (s)
-                    s->enable_max++;
-	    }
-	}
+            for (k = 0; k < ARRAY_SIZE(gr->enum_ids); k++) {
+                id = gr->enum_ids[k];
+                if (id && id == source) {
+                    desc->sources[id].enable_max++;
+                }
+            }
+        }
     }
 
 }
 
 void sh_intc_register_sources(struct intc_desc *desc,
-			      struct intc_vect *vectors,
-			      int nr_vectors,
-			      struct intc_group *groups,
-			      int nr_groups)
+                              struct intc_vect *vectors,
+                              int nr_vectors,
+                              struct intc_group *groups,
+                              int nr_groups)
 {
     unsigned int i, k;
+    intc_enum id;
     struct intc_source *s;
 
     for (i = 0; i < nr_vectors; i++) {
-	struct intc_vect *vect = vectors + i;
+        struct intc_vect *vect = &vectors[i];
 
-	sh_intc_register_source(desc, vect->enum_id, groups, nr_groups);
-	s = sh_intc_source(desc, vect->enum_id);
-        if (s) {
+        sh_intc_register_source(desc, vect->enum_id, groups, nr_groups);
+        id = vect->enum_id;
+        if (id) {
+            s = &desc->sources[id];
             s->vect = vect->vect;
-
-#ifdef DEBUG_INTC_SOURCES
-            printf("sh_intc: registered source %d -> 0x%04x (%d/%d)\n",
-                   vect->enum_id, s->vect, s->enable_count, s->enable_max);
-#endif
+            trace_sh_intc_register("source", vect->enum_id, s->vect,
+                                   s->enable_count, s->enable_max);
         }
     }
 
     if (groups) {
         for (i = 0; i < nr_groups; i++) {
-	    struct intc_group *gr = groups + i;
+            struct intc_group *gr = &groups[i];
+
+            id = gr->enum_id;
+            s = &desc->sources[id];
+            s->next_enum_id = gr->enum_ids[0];
+
+            for (k = 1; k < ARRAY_SIZE(gr->enum_ids); k++) {
+                if (gr->enum_ids[k]) {
+                    id = gr->enum_ids[k - 1];
+                    s = &desc->sources[id];
+                    s->next_enum_id = gr->enum_ids[k];
+                }
+            }
+            trace_sh_intc_register("group", gr->enum_id, 0xffff,
+                                   s->enable_count, s->enable_max);
+        }
+    }
+}
+
+static unsigned int sh_intc_register(MemoryRegion *sysmem,
+                                     struct intc_desc *desc,
+                                     const unsigned long address,
+                                     const char *type,
+                                     const char *action,
+                                     const unsigned int index)
+{
+    char name[60];
+    MemoryRegion *iomem, *iomem_p4, *iomem_a7;
 
-	    s = sh_intc_source(desc, gr->enum_id);
-	    s->next_enum_id = gr->enum_ids[0];
+    if (!address) {
+        return 0;
+    }
 
-	    for (k = 1; k < ARRAY_SIZE(gr->enum_ids); k++) {
-                if (!gr->enum_ids[k])
-                    continue;
+    iomem = &desc->iomem;
+    iomem_p4 = &desc->iomem_aliases[index];
+    iomem_a7 = iomem_p4 + 1;
 
-		s = sh_intc_source(desc, gr->enum_ids[k - 1]);
-		s->next_enum_id = gr->enum_ids[k];
-	    }
+    snprintf(name, sizeof(name), "intc-%s-%s-%s", type, action, "p4");
+    memory_region_init_alias(iomem_p4, NULL, name, iomem, A7ADDR(address), 4);
+    memory_region_add_subregion(sysmem, P4ADDR(address), iomem_p4);
 
-#ifdef DEBUG_INTC_SOURCES
-	    printf("sh_intc: registered group %d (%d/%d)\n",
-		   gr->enum_id, s->enable_count, s->enable_max);
-#endif
-	}
-    }
+    snprintf(name, sizeof(name), "intc-%s-%s-%s", type, action, "a7");
+    memory_region_init_alias(iomem_a7, NULL, name, iomem, A7ADDR(address), 4);
+    memory_region_add_subregion(sysmem, A7ADDR(address), iomem_a7);
+
+    /* used to increment aliases index */
+    return 2;
 }
 
 int sh_intc_init(MemoryRegion *sysmem,
-         struct intc_desc *desc,
-		 int nr_sources,
-		 struct intc_mask_reg *mask_regs,
-		 int nr_mask_regs,
-		 struct intc_prio_reg *prio_regs,
-		 int nr_prio_regs)
+                 struct intc_desc *desc,
+                 int nr_sources,
+                 struct intc_mask_reg *mask_regs,
+                 int nr_mask_regs,
+                 struct intc_prio_reg *prio_regs,
+                 int nr_prio_regs)
 {
     unsigned int i, j;
 
@@ -450,65 +395,55 @@ int sh_intc_init(MemoryRegion *sysmem,
     desc->nr_mask_regs = nr_mask_regs;
     desc->prio_regs = prio_regs;
     desc->nr_prio_regs = nr_prio_regs;
-    /* Allocate 4 MemoryRegions per register (2 actions * 2 aliases).
-     **/
+    /* Allocate 4 MemoryRegions per register (2 actions * 2 aliases) */
     desc->iomem_aliases = g_new0(MemoryRegion,
                                  (nr_mask_regs + nr_prio_regs) * 4);
-
-    j = 0;
-    i = sizeof(struct intc_source) * nr_sources;
-    desc->sources = g_malloc0(i);
-
-    for (i = 0; i < desc->nr_sources; i++) {
-        struct intc_source *source = desc->sources + i;
-
-        source->parent = desc;
+    desc->sources = g_new0(struct intc_source, nr_sources);
+    for (i = 0; i < nr_sources; i++) {
+        desc->sources[i].parent = desc;
     }
-
     desc->irqs = qemu_allocate_irqs(sh_intc_set_irq, desc, nr_sources);
- 
-    memory_region_init_io(&desc->iomem, NULL, &sh_intc_ops, desc,
-                          "interrupt-controller", 0x100000000ULL);
-
-#define INT_REG_PARAMS(reg_struct, type, action, j) \
-        reg_struct->action##_reg, #type, #action, j
+    memory_region_init_io(&desc->iomem, NULL, &sh_intc_ops, desc, "intc",
+                          0x100000000ULL);
+    j = 0;
     if (desc->mask_regs) {
         for (i = 0; i < desc->nr_mask_regs; i++) {
-	    struct intc_mask_reg *mr = desc->mask_regs + i;
+            struct intc_mask_reg *mr = &desc->mask_regs[i];
 
-            j += sh_intc_register(sysmem, desc,
-                                  INT_REG_PARAMS(mr, mask, set, j));
-            j += sh_intc_register(sysmem, desc,
-                                  INT_REG_PARAMS(mr, mask, clr, j));
-	}
+            j += sh_intc_register(sysmem, desc, mr->set_reg, "mask", "set", j);
+            j += sh_intc_register(sysmem, desc, mr->clr_reg, "mask", "clr", j);
+        }
     }
 
     if (desc->prio_regs) {
         for (i = 0; i < desc->nr_prio_regs; i++) {
-	    struct intc_prio_reg *pr = desc->prio_regs + i;
+            struct intc_prio_reg *pr = &desc->prio_regs[i];
 
-            j += sh_intc_register(sysmem, desc,
-                                  INT_REG_PARAMS(pr, prio, set, j));
-            j += sh_intc_register(sysmem, desc,
-                                  INT_REG_PARAMS(pr, prio, clr, j));
-	}
+            j += sh_intc_register(sysmem, desc, pr->set_reg, "prio", "set", j);
+            j += sh_intc_register(sysmem, desc, pr->clr_reg, "prio", "clr", j);
+        }
     }
-#undef INT_REG_PARAMS
 
     return 0;
 }
 
-/* Assert level <n> IRL interrupt. 
-   0:deassert. 1:lowest priority,... 15:highest priority. */
+/*
+ * Assert level <n> IRL interrupt.
+ * 0:deassert. 1:lowest priority,... 15:highest priority
+ */
 void sh_intc_set_irl(void *opaque, int n, int level)
 {
     struct intc_source *s = opaque;
     int i, irl = level ^ 15;
-    for (i = 0; (s = sh_intc_source(s->parent, s->next_enum_id)); i++) {
-	if (i == irl)
-	    sh_intc_toggle_source(s, s->enable_count?0:1, s->asserted?0:1);
-	else
-	    if (s->asserted)
-	        sh_intc_toggle_source(s, 0, -1);
+    intc_enum id = s->next_enum_id;
+
+    for (i = 0; id; id = s->next_enum_id, i++) {
+        s = &s->parent->sources[id];
+        if (i == irl) {
+            sh_intc_toggle_source(s, s->enable_count ? 0 : 1,
+                                  s->asserted ? 0 : 1);
+        } else if (s->asserted) {
+            sh_intc_toggle_source(s, 0, -1);
+        }
     }
 }
diff --git a/hw/intc/trace-events b/hw/intc/trace-events
index 6a17d38998..9aba7e3a7a 100644
--- a/hw/intc/trace-events
+++ b/hw/intc/trace-events
@@ -238,3 +238,11 @@ goldfish_pic_write(void *dev, int idx, unsigned int addr, unsigned int size, uin
 goldfish_pic_reset(void *dev, int idx) "pic: %p goldfish-irq.%d"
 goldfish_pic_realize(void *dev, int idx) "pic: %p goldfish-irq.%d"
 goldfish_pic_instance_init(void *dev) "pic: %p goldfish-irq"
+
+# sh_intc.c
+sh_intc_sources(int p, int a, int c, int m, unsigned short v, const char *s1, const char *s2, const char *s3) "(%d/%d/%d/%d) interrupt source 0x%x %s%s%s"
+sh_intc_pending(int p, unsigned short v) "(%d) returning interrupt source 0x%x"
+sh_intc_register(const char *s, int id, unsigned short v, int c, int m) "%s %u -> 0x%04x (%d/%d)"
+sh_intc_read(unsigned size, uint64_t offset, unsigned long val) "size %u 0x%" PRIx64 " -> 0x%lx"
+sh_intc_write(unsigned size, uint64_t offset, unsigned long val) "size %u 0x%" PRIx64 " <- 0x%lx"
+sh_intc_set(int id, int enable) "setting interrupt group %d to %d"
diff --git a/hw/pci-host/sh_pci.c b/hw/pci-host/sh_pci.c
index 08c1562e22..719d6ca2a6 100644
--- a/hw/pci-host/sh_pci.c
+++ b/hw/pci-host/sh_pci.c
@@ -49,13 +49,12 @@ struct SHPCIState {
     uint32_t iobr;
 };
 
-static void sh_pci_reg_write (void *p, hwaddr addr, uint64_t val,
-                              unsigned size)
+static void sh_pci_reg_write(void *p, hwaddr addr, uint64_t val, unsigned size)
 {
     SHPCIState *pcic = p;
     PCIHostState *phb = PCI_HOST_BRIDGE(pcic);
 
-    switch(addr) {
+    switch (addr) {
     case 0 ... 0xfc:
         stl_le_p(pcic->dev->config + addr, val);
         break;
@@ -75,13 +74,12 @@ static void sh_pci_reg_write (void *p, hwaddr addr, uint64_t val,
     }
 }
 
-static uint64_t sh_pci_reg_read (void *p, hwaddr addr,
-                                 unsigned size)
+static uint64_t sh_pci_reg_read(void *p, hwaddr addr, unsigned size)
 {
     SHPCIState *pcic = p;
     PCIHostState *phb = PCI_HOST_BRIDGE(pcic);
 
-    switch(addr) {
+    switch (addr) {
     case 0 ... 0xfc:
         return ldl_le_p(pcic->dev->config + addr);
     case 0x1c0:
diff --git a/hw/sh4/r2d.c b/hw/sh4/r2d.c
index 006010f30a..72759413f3 100644
--- a/hw/sh4/r2d.c
+++ b/hw/sh4/r2d.c
@@ -26,6 +26,7 @@
 #include "qemu/osdep.h"
 #include "qemu/units.h"
 #include "qapi/error.h"
+#include "qemu/error-report.h"
 #include "cpu.h"
 #include "hw/sysbus.h"
 #include "hw/sh4/sh.h"
@@ -56,10 +57,10 @@
 #define LINUX_LOAD_OFFSET  0x0800000
 #define INITRD_LOAD_OFFSET 0x1800000
 
-#define PA_IRLMSK	0x00
-#define PA_POWOFF	0x30
-#define PA_VERREG	0x32
-#define PA_OUTPORT	0x36
+#define PA_IRLMSK 0x00
+#define PA_POWOFF 0x30
+#define PA_VERREG 0x32
+#define PA_OUTPORT 0x36
 
 typedef struct {
     uint16_t bcr;
@@ -96,38 +97,41 @@ enum r2d_fpga_irq {
 };
 
 static const struct { short irl; uint16_t msk; } irqtab[NR_IRQS] = {
-    [CF_IDE]	= {  1, 1<<9 },
-    [CF_CD]	= {  2, 1<<8 },
-    [PCI_INTA]	= {  9, 1<<14 },
-    [PCI_INTB]	= { 10, 1<<13 },
-    [PCI_INTC]	= {  3, 1<<12 },
-    [PCI_INTD]	= {  0, 1<<11 },
-    [SM501]	= {  4, 1<<10 },
-    [KEY]	= {  5, 1<<6 },
-    [RTC_A]	= {  6, 1<<5 },
-    [RTC_T]	= {  7, 1<<4 },
-    [SDCARD]	= {  8, 1<<7 },
-    [EXT]	= { 11, 1<<0 },
-    [TP]	= { 12, 1<<15 },
+    [CF_IDE] =   {  1, 1 << 9 },
+    [CF_CD] =    {  2, 1 << 8 },
+    [PCI_INTA] = {  9, 1 << 14 },
+    [PCI_INTB] = { 10, 1 << 13 },
+    [PCI_INTC] = {  3, 1 << 12 },
+    [PCI_INTD] = {  0, 1 << 11 },
+    [SM501] =    {  4, 1 << 10 },
+    [KEY] =      {  5, 1 << 6 },
+    [RTC_A] =    {  6, 1 << 5 },
+    [RTC_T] =    {  7, 1 << 4 },
+    [SDCARD] =   {  8, 1 << 7 },
+    [EXT] =      { 11, 1 << 0 },
+    [TP] =       { 12, 1 << 15 },
 };
 
 static void update_irl(r2d_fpga_t *fpga)
 {
     int i, irl = 15;
-    for (i = 0; i < NR_IRQS; i++)
-        if (fpga->irlmon & fpga->irlmsk & irqtab[i].msk)
-            if (irqtab[i].irl < irl)
-                irl = irqtab[i].irl;
+    for (i = 0; i < NR_IRQS; i++) {
+        if ((fpga->irlmon & fpga->irlmsk & irqtab[i].msk) &&
+            irqtab[i].irl < irl) {
+            irl = irqtab[i].irl;
+        }
+    }
     qemu_set_irq(fpga->irl, irl ^ 15);
 }
 
 static void r2d_fpga_irq_set(void *opaque, int n, int level)
 {
     r2d_fpga_t *fpga = opaque;
-    if (level)
+    if (level) {
         fpga->irlmon |= irqtab[n].msk;
-    else
+    } else {
         fpga->irlmon &= ~irqtab[n].msk;
+    }
     update_irl(fpga);
 }
 
@@ -306,7 +310,7 @@ static void r2d_init(MachineState *machine)
     /* NIC: rtl8139 on-board, and 2 slots. */
     for (i = 0; i < nb_nics; i++)
         pci_nic_init_nofail(&nd_table[i], pci_bus,
-                            "rtl8139", i==0 ? "2" : NULL);
+                            "rtl8139", i == 0 ? "2" : NULL);
 
     /* USB keyboard */
     usb_create_simple(usb_bus_find(-1), "usb-kbd");
@@ -321,8 +325,8 @@ static void r2d_init(MachineState *machine)
                                           SDRAM_BASE + LINUX_LOAD_OFFSET,
                                           INITRD_LOAD_OFFSET - LINUX_LOAD_OFFSET);
         if (kernel_size < 0) {
-          fprintf(stderr, "qemu: could not load kernel '%s'\n", kernel_filename);
-          exit(1);
+            error_report("qemu: could not load kernel '%s'", kernel_filename);
+            exit(1);
         }
 
         /* initialization which should be done by firmware */
@@ -330,7 +334,8 @@ static void r2d_init(MachineState *machine)
                           MEMTXATTRS_UNSPECIFIED, NULL); /* cs3 SDRAM */
         address_space_stw(&address_space_memory, SH7750_BCR2, 3 << (3 * 2),
                           MEMTXATTRS_UNSPECIFIED, NULL); /* cs3 32bit */
-        reset_info->vector = (SDRAM_BASE + LINUX_LOAD_OFFSET) | 0xa0000000; /* Start from P2 area */
+        /* Start from P2 area */
+        reset_info->vector = (SDRAM_BASE + LINUX_LOAD_OFFSET) | 0xa0000000;
     }
 
     if (initrd_filename) {
@@ -341,8 +346,8 @@ static void r2d_init(MachineState *machine)
                                           SDRAM_SIZE - INITRD_LOAD_OFFSET);
 
         if (initrd_size < 0) {
-          fprintf(stderr, "qemu: could not load initrd '%s'\n", initrd_filename);
-          exit(1);
+            error_report("qemu: could not load initrd '%s'", initrd_filename);
+            exit(1);
         }
 
         /* initialization which should be done by firmware */
@@ -352,8 +357,10 @@ static void r2d_init(MachineState *machine)
     }
 
     if (kernel_cmdline) {
-        /* I see no evidence that this .kernel_cmdline buffer requires
-           NUL-termination, so using strncpy should be ok. */
+        /*
+         * I see no evidence that this .kernel_cmdline buffer requires
+         * NUL-termination, so using strncpy should be ok.
+         */
         strncpy(boot_params.kernel_cmdline, kernel_cmdline,
                 sizeof(boot_params.kernel_cmdline));
     }
diff --git a/hw/sh4/sh7750.c b/hw/sh4/sh7750.c
index d53a436d8c..43dfb6497b 100644
--- a/hw/sh4/sh7750.c
+++ b/hw/sh4/sh7750.c
@@ -24,14 +24,19 @@
  */
 
 #include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "hw/sysbus.h"
 #include "hw/irq.h"
 #include "hw/sh4/sh.h"
 #include "sysemu/sysemu.h"
+#include "hw/qdev-properties.h"
+#include "hw/qdev-properties-system.h"
 #include "sh7750_regs.h"
 #include "sh7750_regnames.h"
 #include "hw/sh4/sh_intc.h"
 #include "hw/timer/tmu012.h"
 #include "exec/exec-all.h"
+#include "trace.h"
 
 #define NB_DEVICES 4
 
@@ -60,17 +65,17 @@ typedef struct SH7750State {
     uint16_t gpioic;
     uint32_t pctra;
     uint32_t pctrb;
-    uint16_t portdira;		/* Cached */
-    uint16_t portpullupa;	/* Cached */
-    uint16_t portdirb;		/* Cached */
-    uint16_t portpullupb;	/* Cached */
+    uint16_t portdira;        /* Cached */
+    uint16_t portpullupa;     /* Cached */
+    uint16_t portdirb;        /* Cached */
+    uint16_t portpullupb;     /* Cached */
     uint16_t pdtra;
     uint16_t pdtrb;
-    uint16_t periph_pdtra;	/* Imposed by the peripherals */
-    uint16_t periph_portdira;	/* Direction seen from the peripherals */
-    uint16_t periph_pdtrb;	/* Imposed by the peripherals */
-    uint16_t periph_portdirb;	/* Direction seen from the peripherals */
-    sh7750_io_device *devices[NB_DEVICES];	/* External peripherals */
+    uint16_t periph_pdtra;    /* Imposed by the peripherals */
+    uint16_t periph_portdira; /* Direction seen from the peripherals */
+    uint16_t periph_pdtrb;    /* Imposed by the peripherals */
+    uint16_t periph_portdirb; /* Direction seen from the peripherals */
+    sh7750_io_device *devices[NB_DEVICES]; /* External peripherals */
 
     /* Cache */
     uint32_t ccr;
@@ -78,143 +83,145 @@ typedef struct SH7750State {
     struct intc_desc intc;
 } SH7750State;
 
-static inline int has_bcr3_and_bcr4(SH7750State * s)
+static inline int has_bcr3_and_bcr4(SH7750State *s)
 {
     return s->cpu->env.features & SH_FEATURE_BCR3_AND_BCR4;
 }
-/**********************************************************************
- I/O ports
-**********************************************************************/
 
-int sh7750_register_io_device(SH7750State * s, sh7750_io_device * device)
+/*
+ * I/O ports
+ */
+
+int sh7750_register_io_device(SH7750State *s, sh7750_io_device *device)
 {
     int i;
 
     for (i = 0; i < NB_DEVICES; i++) {
-	if (s->devices[i] == NULL) {
-	    s->devices[i] = device;
-	    return 0;
-	}
+        if (s->devices[i] == NULL) {
+            s->devices[i] = device;
+            return 0;
+        }
     }
     return -1;
 }
 
 static uint16_t portdir(uint32_t v)
 {
-#define EVENPORTMASK(n) ((v & (1<<((n)<<1))) >> (n))
+#define EVENPORTMASK(n) ((v & (1 << ((n) << 1))) >> (n))
     return
-	EVENPORTMASK(15) | EVENPORTMASK(14) | EVENPORTMASK(13) |
-	EVENPORTMASK(12) | EVENPORTMASK(11) | EVENPORTMASK(10) |
-	EVENPORTMASK(9) | EVENPORTMASK(8) | EVENPORTMASK(7) |
-	EVENPORTMASK(6) | EVENPORTMASK(5) | EVENPORTMASK(4) |
-	EVENPORTMASK(3) | EVENPORTMASK(2) | EVENPORTMASK(1) |
-	EVENPORTMASK(0);
+        EVENPORTMASK(15) | EVENPORTMASK(14) | EVENPORTMASK(13) |
+        EVENPORTMASK(12) | EVENPORTMASK(11) | EVENPORTMASK(10) |
+        EVENPORTMASK(9) | EVENPORTMASK(8) | EVENPORTMASK(7) |
+        EVENPORTMASK(6) | EVENPORTMASK(5) | EVENPORTMASK(4) |
+        EVENPORTMASK(3) | EVENPORTMASK(2) | EVENPORTMASK(1) |
+        EVENPORTMASK(0);
 }
 
 static uint16_t portpullup(uint32_t v)
 {
-#define ODDPORTMASK(n) ((v & (1<<(((n)<<1)+1))) >> (n))
+#define ODDPORTMASK(n) ((v & (1 << (((n) << 1) + 1))) >> (n))
     return
-	ODDPORTMASK(15) | ODDPORTMASK(14) | ODDPORTMASK(13) |
-	ODDPORTMASK(12) | ODDPORTMASK(11) | ODDPORTMASK(10) |
-	ODDPORTMASK(9) | ODDPORTMASK(8) | ODDPORTMASK(7) | ODDPORTMASK(6) |
-	ODDPORTMASK(5) | ODDPORTMASK(4) | ODDPORTMASK(3) | ODDPORTMASK(2) |
-	ODDPORTMASK(1) | ODDPORTMASK(0);
+        ODDPORTMASK(15) | ODDPORTMASK(14) | ODDPORTMASK(13) |
+        ODDPORTMASK(12) | ODDPORTMASK(11) | ODDPORTMASK(10) |
+        ODDPORTMASK(9) | ODDPORTMASK(8) | ODDPORTMASK(7) | ODDPORTMASK(6) |
+        ODDPORTMASK(5) | ODDPORTMASK(4) | ODDPORTMASK(3) | ODDPORTMASK(2) |
+        ODDPORTMASK(1) | ODDPORTMASK(0);
 }
 
-static uint16_t porta_lines(SH7750State * s)
+static uint16_t porta_lines(SH7750State *s)
 {
-    return (s->portdira & s->pdtra) |	/* CPU */
-	(s->periph_portdira & s->periph_pdtra) |	/* Peripherals */
-	(~(s->portdira | s->periph_portdira) & s->portpullupa);	/* Pullups */
+    return (s->portdira & s->pdtra) | /* CPU */
+        (s->periph_portdira & s->periph_pdtra) | /* Peripherals */
+        (~(s->portdira | s->periph_portdira) & s->portpullupa); /* Pullups */
 }
 
-static uint16_t portb_lines(SH7750State * s)
+static uint16_t portb_lines(SH7750State *s)
 {
-    return (s->portdirb & s->pdtrb) |	/* CPU */
-	(s->periph_portdirb & s->periph_pdtrb) |	/* Peripherals */
-	(~(s->portdirb | s->periph_portdirb) & s->portpullupb);	/* Pullups */
+    return (s->portdirb & s->pdtrb) | /* CPU */
+        (s->periph_portdirb & s->periph_pdtrb) | /* Peripherals */
+        (~(s->portdirb | s->periph_portdirb) & s->portpullupb); /* Pullups */
 }
 
-static void gen_port_interrupts(SH7750State * s)
+static void gen_port_interrupts(SH7750State *s)
 {
     /* XXXXX interrupts not generated */
 }
 
-static void porta_changed(SH7750State * s, uint16_t prev)
+static void porta_changed(SH7750State *s, uint16_t prev)
 {
     uint16_t currenta, changes;
     int i, r = 0;
 
-#if 0
-    fprintf(stderr, "porta changed from 0x%04x to 0x%04x\n",
-	    prev, porta_lines(s));
-    fprintf(stderr, "pdtra=0x%04x, pctra=0x%08x\n", s->pdtra, s->pctra);
-#endif
     currenta = porta_lines(s);
-    if (currenta == prev)
-	return;
+    if (currenta == prev) {
+        return;
+    }
+    trace_sh7750_porta(prev, currenta, s->pdtra, s->pctra);
     changes = currenta ^ prev;
 
     for (i = 0; i < NB_DEVICES; i++) {
-	if (s->devices[i] && (s->devices[i]->portamask_trigger & changes)) {
-	    r |= s->devices[i]->port_change_cb(currenta, portb_lines(s),
-					       &s->periph_pdtra,
-					       &s->periph_portdira,
-					       &s->periph_pdtrb,
-					       &s->periph_portdirb);
-	}
+        if (s->devices[i] && (s->devices[i]->portamask_trigger & changes)) {
+            r |= s->devices[i]->port_change_cb(currenta, portb_lines(s),
+                                               &s->periph_pdtra,
+                                               &s->periph_portdira,
+                                               &s->periph_pdtrb,
+                                               &s->periph_portdirb);
+        }
     }
 
-    if (r)
-	gen_port_interrupts(s);
+    if (r) {
+        gen_port_interrupts(s);
+    }
 }
 
-static void portb_changed(SH7750State * s, uint16_t prev)
+static void portb_changed(SH7750State *s, uint16_t prev)
 {
     uint16_t currentb, changes;
     int i, r = 0;
 
     currentb = portb_lines(s);
-    if (currentb == prev)
-	return;
+    if (currentb == prev) {
+        return;
+    }
+    trace_sh7750_portb(prev, currentb, s->pdtrb, s->pctrb);
     changes = currentb ^ prev;
 
     for (i = 0; i < NB_DEVICES; i++) {
-	if (s->devices[i] && (s->devices[i]->portbmask_trigger & changes)) {
-	    r |= s->devices[i]->port_change_cb(portb_lines(s), currentb,
-					       &s->periph_pdtra,
-					       &s->periph_portdira,
-					       &s->periph_pdtrb,
-					       &s->periph_portdirb);
-	}
+        if (s->devices[i] && (s->devices[i]->portbmask_trigger & changes)) {
+            r |= s->devices[i]->port_change_cb(portb_lines(s), currentb,
+                                               &s->periph_pdtra,
+                                               &s->periph_portdira,
+                                               &s->periph_pdtrb,
+                                               &s->periph_portdirb);
+        }
     }
 
-    if (r)
-	gen_port_interrupts(s);
+    if (r) {
+        gen_port_interrupts(s);
+    }
 }
 
-/**********************************************************************
- Memory
-**********************************************************************/
+/*
+ * Memory
+ */
 
 static void error_access(const char *kind, hwaddr addr)
 {
     fprintf(stderr, "%s to %s (0x" TARGET_FMT_plx ") not supported\n",
-	    kind, regname(addr), addr);
+            kind, regname(addr), addr);
 }
 
 static void ignore_access(const char *kind, hwaddr addr)
 {
     fprintf(stderr, "%s to %s (0x" TARGET_FMT_plx ") ignored\n",
-	    kind, regname(addr), addr);
+            kind, regname(addr), addr);
 }
 
 static uint32_t sh7750_mem_readb(void *opaque, hwaddr addr)
 {
     switch (addr) {
     default:
-	error_access("byte read", addr);
+        error_access("byte read", addr);
         abort();
     }
 }
@@ -225,30 +232,31 @@ static uint32_t sh7750_mem_readw(void *opaque, hwaddr addr)
 
     switch (addr) {
     case SH7750_BCR2_A7:
-	return s->bcr2;
+        return s->bcr2;
     case SH7750_BCR3_A7:
-	if(!has_bcr3_and_bcr4(s))
-	    error_access("word read", addr);
-	return s->bcr3;
+        if (!has_bcr3_and_bcr4(s)) {
+            error_access("word read", addr);
+        }
+        return s->bcr3;
     case SH7750_FRQCR_A7:
-	return 0;
+        return 0;
     case SH7750_PCR_A7:
-	return s->pcr;
+        return s->pcr;
     case SH7750_RFCR_A7:
-	fprintf(stderr,
-		"Read access to refresh count register, incrementing\n");
-	return s->rfcr++;
+        fprintf(stderr,
+                "Read access to refresh count register, incrementing\n");
+        return s->rfcr++;
     case SH7750_PDTRA_A7:
-	return porta_lines(s);
+        return porta_lines(s);
     case SH7750_PDTRB_A7:
-	return portb_lines(s);
+        return portb_lines(s);
     case SH7750_RTCOR_A7:
     case SH7750_RTCNT_A7:
     case SH7750_RTCSR_A7:
-	ignore_access("word read", addr);
-	return 0;
+        ignore_access("word read", addr);
+        return 0;
     default:
-	error_access("word read", addr);
+        error_access("word read", addr);
         abort();
     }
 }
@@ -260,11 +268,12 @@ static uint32_t sh7750_mem_readl(void *opaque, hwaddr addr)
 
     switch (addr) {
     case SH7750_BCR1_A7:
-	return s->bcr1;
+        return s->bcr1;
     case SH7750_BCR4_A7:
-	if(!has_bcr3_and_bcr4(s))
-	    error_access("long read", addr);
-	return s->bcr4;
+        if (!has_bcr3_and_bcr4(s)) {
+            error_access("long read", addr);
+        }
+        return s->bcr4;
     case SH7750_WCR1_A7:
     case SH7750_WCR2_A7:
     case SH7750_WCR3_A7:
@@ -288,31 +297,31 @@ static uint32_t sh7750_mem_readl(void *opaque, hwaddr addr)
     case SH7750_INTEVT_A7:
         return s->cpu->env.intevt;
     case SH7750_CCR_A7:
-	return s->ccr;
-    case 0x1f000030:		/* Processor version */
+        return s->ccr;
+    case 0x1f000030: /* Processor version */
         scc = SUPERH_CPU_GET_CLASS(s->cpu);
         return scc->pvr;
-    case 0x1f000040:		/* Cache version */
+    case 0x1f000040: /* Cache version */
         scc = SUPERH_CPU_GET_CLASS(s->cpu);
         return scc->cvr;
-    case 0x1f000044:		/* Processor revision */
+    case 0x1f000044: /* Processor revision */
         scc = SUPERH_CPU_GET_CLASS(s->cpu);
         return scc->prr;
     default:
-	error_access("long read", addr);
+        error_access("long read", addr);
         abort();
     }
 }
 
 #define is_in_sdrmx(a, x) (a >= SH7750_SDMR ## x ## _A7 \
-			&& a <= (SH7750_SDMR ## x ## _A7 + SH7750_SDMR ## x ## _REGNB))
+                        && a <= (SH7750_SDMR ## x ## _A7 + SH7750_SDMR ## x ## _REGNB))
 static void sh7750_mem_writeb(void *opaque, hwaddr addr,
-			      uint32_t mem_value)
+                              uint32_t mem_value)
 {
 
     if (is_in_sdrmx(addr, 2) || is_in_sdrmx(addr, 3)) {
-	ignore_access("byte write", addr);
-	return;
+        ignore_access("byte write", addr);
+        return;
     }
 
     error_access("byte write", addr);
@@ -320,94 +329,96 @@ static void sh7750_mem_writeb(void *opaque, hwaddr addr,
 }
 
 static void sh7750_mem_writew(void *opaque, hwaddr addr,
-			      uint32_t mem_value)
+                              uint32_t mem_value)
 {
     SH7750State *s = opaque;
     uint16_t temp;
 
     switch (addr) {
-	/* SDRAM controller */
+        /* SDRAM controller */
     case SH7750_BCR2_A7:
         s->bcr2 = mem_value;
         return;
     case SH7750_BCR3_A7:
-	if(!has_bcr3_and_bcr4(s))
-	    error_access("word write", addr);
-	s->bcr3 = mem_value;
-	return;
+        if (!has_bcr3_and_bcr4(s)) {
+            error_access("word write", addr);
+        }
+        s->bcr3 = mem_value;
+        return;
     case SH7750_PCR_A7:
-	s->pcr = mem_value;
-	return;
+        s->pcr = mem_value;
+        return;
     case SH7750_RTCNT_A7:
     case SH7750_RTCOR_A7:
     case SH7750_RTCSR_A7:
-	ignore_access("word write", addr);
-	return;
-	/* IO ports */
+        ignore_access("word write", addr);
+        return;
+        /* IO ports */
     case SH7750_PDTRA_A7:
-	temp = porta_lines(s);
-	s->pdtra = mem_value;
-	porta_changed(s, temp);
-	return;
+        temp = porta_lines(s);
+        s->pdtra = mem_value;
+        porta_changed(s, temp);
+        return;
     case SH7750_PDTRB_A7:
-	temp = portb_lines(s);
-	s->pdtrb = mem_value;
-	portb_changed(s, temp);
-	return;
+        temp = portb_lines(s);
+        s->pdtrb = mem_value;
+        portb_changed(s, temp);
+        return;
     case SH7750_RFCR_A7:
-	fprintf(stderr, "Write access to refresh count register\n");
-	s->rfcr = mem_value;
-	return;
+        fprintf(stderr, "Write access to refresh count register\n");
+        s->rfcr = mem_value;
+        return;
     case SH7750_GPIOIC_A7:
-	s->gpioic = mem_value;
-	if (mem_value != 0) {
-	    fprintf(stderr, "I/O interrupts not implemented\n");
+        s->gpioic = mem_value;
+        if (mem_value != 0) {
+            fprintf(stderr, "I/O interrupts not implemented\n");
             abort();
-	}
-	return;
+        }
+        return;
     default:
-	error_access("word write", addr);
+        error_access("word write", addr);
         abort();
     }
 }
 
 static void sh7750_mem_writel(void *opaque, hwaddr addr,
-			      uint32_t mem_value)
+                              uint32_t mem_value)
 {
     SH7750State *s = opaque;
     uint16_t temp;
 
     switch (addr) {
-	/* SDRAM controller */
+        /* SDRAM controller */
     case SH7750_BCR1_A7:
         s->bcr1 = mem_value;
         return;
     case SH7750_BCR4_A7:
-	if(!has_bcr3_and_bcr4(s))
-	    error_access("long write", addr);
-	s->bcr4 = mem_value;
-	return;
+        if (!has_bcr3_and_bcr4(s)) {
+            error_access("long write", addr);
+        }
+        s->bcr4 = mem_value;
+        return;
     case SH7750_WCR1_A7:
     case SH7750_WCR2_A7:
     case SH7750_WCR3_A7:
     case SH7750_MCR_A7:
-	ignore_access("long write", addr);
-	return;
-	/* IO ports */
+        ignore_access("long write", addr);
+        return;
+        /* IO ports */
     case SH7750_PCTRA_A7:
-	temp = porta_lines(s);
-	s->pctra = mem_value;
-	s->portdira = portdir(mem_value);
-	s->portpullupa = portpullup(mem_value);
-	porta_changed(s, temp);
-	return;
+        temp = porta_lines(s);
+        s->pctra = mem_value;
+        s->portdira = portdir(mem_value);
+        s->portpullupa = portpullup(mem_value);
+        porta_changed(s, temp);
+        return;
     case SH7750_PCTRB_A7:
-	temp = portb_lines(s);
-	s->pctrb = mem_value;
-	s->portdirb = portdir(mem_value);
-	s->portpullupb = portpullup(mem_value);
-	portb_changed(s, temp);
-	return;
+        temp = portb_lines(s);
+        s->pctrb = mem_value;
+        s->portdirb = portdir(mem_value);
+        s->portpullupb = portpullup(mem_value);
+        portb_changed(s, temp);
+        return;
     case SH7750_MMUCR_A7:
         if (mem_value & MMUCR_TI) {
             cpu_sh4_invalidate_tlb(&s->cpu->env);
@@ -443,10 +454,10 @@ static void sh7750_mem_writel(void *opaque, hwaddr addr,
         s->cpu->env.intevt = mem_value & 0x000007ff;
         return;
     case SH7750_CCR_A7:
-	s->ccr = mem_value;
-	return;
+        s->ccr = mem_value;
+        return;
     default:
-	error_access("long write", addr);
+        error_access("long write", addr);
         abort();
     }
 }
@@ -491,161 +502,161 @@ static const MemoryRegionOps sh7750_mem_ops = {
     .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
-/* sh775x interrupt controller tables for sh_intc.c
+/*
+ * sh775x interrupt controller tables for sh_intc.c
  * stolen from linux/arch/sh/kernel/cpu/sh4/setup-sh7750.c
  */
 
 enum {
-	UNUSED = 0,
-
-	/* interrupt sources */
-	IRL_0, IRL_1, IRL_2, IRL_3, IRL_4, IRL_5, IRL_6, IRL_7,
-	IRL_8, IRL_9, IRL_A, IRL_B, IRL_C, IRL_D, IRL_E,
-	IRL0, IRL1, IRL2, IRL3,
-	HUDI, GPIOI,
-	DMAC_DMTE0, DMAC_DMTE1, DMAC_DMTE2, DMAC_DMTE3,
-	DMAC_DMTE4, DMAC_DMTE5, DMAC_DMTE6, DMAC_DMTE7,
-	DMAC_DMAE,
-	PCIC0_PCISERR, PCIC1_PCIERR, PCIC1_PCIPWDWN, PCIC1_PCIPWON,
-	PCIC1_PCIDMA0, PCIC1_PCIDMA1, PCIC1_PCIDMA2, PCIC1_PCIDMA3,
-	TMU3, TMU4, TMU0, TMU1, TMU2_TUNI, TMU2_TICPI,
-	RTC_ATI, RTC_PRI, RTC_CUI,
-	SCI1_ERI, SCI1_RXI, SCI1_TXI, SCI1_TEI,
-	SCIF_ERI, SCIF_RXI, SCIF_BRI, SCIF_TXI,
-	WDT,
-	REF_RCMI, REF_ROVI,
-
-	/* interrupt groups */
-	DMAC, PCIC1, TMU2, RTC, SCI1, SCIF, REF,
-	/* irl bundle */
-	IRL,
-
-	NR_SOURCES,
+    UNUSED = 0,
+
+    /* interrupt sources */
+    IRL_0, IRL_1, IRL_2, IRL_3, IRL_4, IRL_5, IRL_6, IRL_7,
+    IRL_8, IRL_9, IRL_A, IRL_B, IRL_C, IRL_D, IRL_E,
+    IRL0, IRL1, IRL2, IRL3,
+    HUDI, GPIOI,
+    DMAC_DMTE0, DMAC_DMTE1, DMAC_DMTE2, DMAC_DMTE3,
+    DMAC_DMTE4, DMAC_DMTE5, DMAC_DMTE6, DMAC_DMTE7,
+    DMAC_DMAE,
+    PCIC0_PCISERR, PCIC1_PCIERR, PCIC1_PCIPWDWN, PCIC1_PCIPWON,
+    PCIC1_PCIDMA0, PCIC1_PCIDMA1, PCIC1_PCIDMA2, PCIC1_PCIDMA3,
+    TMU3, TMU4, TMU0, TMU1, TMU2_TUNI, TMU2_TICPI,
+    RTC_ATI, RTC_PRI, RTC_CUI,
+    SCI1_ERI, SCI1_RXI, SCI1_TXI, SCI1_TEI,
+    SCIF_ERI, SCIF_RXI, SCIF_BRI, SCIF_TXI,
+    WDT,
+    REF_RCMI, REF_ROVI,
+
+    /* interrupt groups */
+    DMAC, PCIC1, TMU2, RTC, SCI1, SCIF, REF,
+    /* irl bundle */
+    IRL,
+
+    NR_SOURCES,
 };
 
 static struct intc_vect vectors[] = {
-	INTC_VECT(HUDI, 0x600), INTC_VECT(GPIOI, 0x620),
-	INTC_VECT(TMU0, 0x400), INTC_VECT(TMU1, 0x420),
-	INTC_VECT(TMU2_TUNI, 0x440), INTC_VECT(TMU2_TICPI, 0x460),
-	INTC_VECT(RTC_ATI, 0x480), INTC_VECT(RTC_PRI, 0x4a0),
-	INTC_VECT(RTC_CUI, 0x4c0),
-	INTC_VECT(SCI1_ERI, 0x4e0), INTC_VECT(SCI1_RXI, 0x500),
-	INTC_VECT(SCI1_TXI, 0x520), INTC_VECT(SCI1_TEI, 0x540),
-	INTC_VECT(SCIF_ERI, 0x700), INTC_VECT(SCIF_RXI, 0x720),
-	INTC_VECT(SCIF_BRI, 0x740), INTC_VECT(SCIF_TXI, 0x760),
-	INTC_VECT(WDT, 0x560),
-	INTC_VECT(REF_RCMI, 0x580), INTC_VECT(REF_ROVI, 0x5a0),
+    INTC_VECT(HUDI, 0x600), INTC_VECT(GPIOI, 0x620),
+    INTC_VECT(TMU0, 0x400), INTC_VECT(TMU1, 0x420),
+    INTC_VECT(TMU2_TUNI, 0x440), INTC_VECT(TMU2_TICPI, 0x460),
+    INTC_VECT(RTC_ATI, 0x480), INTC_VECT(RTC_PRI, 0x4a0),
+    INTC_VECT(RTC_CUI, 0x4c0),
+    INTC_VECT(SCI1_ERI, 0x4e0), INTC_VECT(SCI1_RXI, 0x500),
+    INTC_VECT(SCI1_TXI, 0x520), INTC_VECT(SCI1_TEI, 0x540),
+    INTC_VECT(SCIF_ERI, 0x700), INTC_VECT(SCIF_RXI, 0x720),
+    INTC_VECT(SCIF_BRI, 0x740), INTC_VECT(SCIF_TXI, 0x760),
+    INTC_VECT(WDT, 0x560),
+    INTC_VECT(REF_RCMI, 0x580), INTC_VECT(REF_ROVI, 0x5a0),
 };
 
 static struct intc_group groups[] = {
-	INTC_GROUP(TMU2, TMU2_TUNI, TMU2_TICPI),
-	INTC_GROUP(RTC, RTC_ATI, RTC_PRI, RTC_CUI),
-	INTC_GROUP(SCI1, SCI1_ERI, SCI1_RXI, SCI1_TXI, SCI1_TEI),
-	INTC_GROUP(SCIF, SCIF_ERI, SCIF_RXI, SCIF_BRI, SCIF_TXI),
-	INTC_GROUP(REF, REF_RCMI, REF_ROVI),
+    INTC_GROUP(TMU2, TMU2_TUNI, TMU2_TICPI),
+    INTC_GROUP(RTC, RTC_ATI, RTC_PRI, RTC_CUI),
+    INTC_GROUP(SCI1, SCI1_ERI, SCI1_RXI, SCI1_TXI, SCI1_TEI),
+    INTC_GROUP(SCIF, SCIF_ERI, SCIF_RXI, SCIF_BRI, SCIF_TXI),
+    INTC_GROUP(REF, REF_RCMI, REF_ROVI),
 };
 
 static struct intc_prio_reg prio_registers[] = {
-	{ 0xffd00004, 0, 16, 4, /* IPRA */ { TMU0, TMU1, TMU2, RTC } },
-	{ 0xffd00008, 0, 16, 4, /* IPRB */ { WDT, REF, SCI1, 0 } },
-	{ 0xffd0000c, 0, 16, 4, /* IPRC */ { GPIOI, DMAC, SCIF, HUDI } },
-	{ 0xffd00010, 0, 16, 4, /* IPRD */ { IRL0, IRL1, IRL2, IRL3 } },
-	{ 0xfe080000, 0, 32, 4, /* INTPRI00 */ { 0, 0, 0, 0,
-						 TMU4, TMU3,
-						 PCIC1, PCIC0_PCISERR } },
+    { 0xffd00004, 0, 16, 4, /* IPRA */ { TMU0, TMU1, TMU2, RTC } },
+    { 0xffd00008, 0, 16, 4, /* IPRB */ { WDT, REF, SCI1, 0 } },
+    { 0xffd0000c, 0, 16, 4, /* IPRC */ { GPIOI, DMAC, SCIF, HUDI } },
+    { 0xffd00010, 0, 16, 4, /* IPRD */ { IRL0, IRL1, IRL2, IRL3 } },
+    { 0xfe080000, 0, 32, 4, /* INTPRI00 */ { 0, 0, 0, 0, TMU4, TMU3,
+                                             PCIC1, PCIC0_PCISERR } },
 };
 
 /* SH7750, SH7750S, SH7751 and SH7091 all have 4-channel DMA controllers */
 
 static struct intc_vect vectors_dma4[] = {
-	INTC_VECT(DMAC_DMTE0, 0x640), INTC_VECT(DMAC_DMTE1, 0x660),
-	INTC_VECT(DMAC_DMTE2, 0x680), INTC_VECT(DMAC_DMTE3, 0x6a0),
-	INTC_VECT(DMAC_DMAE, 0x6c0),
+    INTC_VECT(DMAC_DMTE0, 0x640), INTC_VECT(DMAC_DMTE1, 0x660),
+    INTC_VECT(DMAC_DMTE2, 0x680), INTC_VECT(DMAC_DMTE3, 0x6a0),
+    INTC_VECT(DMAC_DMAE, 0x6c0),
 };
 
 static struct intc_group groups_dma4[] = {
-	INTC_GROUP(DMAC, DMAC_DMTE0, DMAC_DMTE1, DMAC_DMTE2,
-		   DMAC_DMTE3, DMAC_DMAE),
+    INTC_GROUP(DMAC, DMAC_DMTE0, DMAC_DMTE1, DMAC_DMTE2,
+               DMAC_DMTE3, DMAC_DMAE),
 };
 
 /* SH7750R and SH7751R both have 8-channel DMA controllers */
 
 static struct intc_vect vectors_dma8[] = {
-	INTC_VECT(DMAC_DMTE0, 0x640), INTC_VECT(DMAC_DMTE1, 0x660),
-	INTC_VECT(DMAC_DMTE2, 0x680), INTC_VECT(DMAC_DMTE3, 0x6a0),
-	INTC_VECT(DMAC_DMTE4, 0x780), INTC_VECT(DMAC_DMTE5, 0x7a0),
-	INTC_VECT(DMAC_DMTE6, 0x7c0), INTC_VECT(DMAC_DMTE7, 0x7e0),
-	INTC_VECT(DMAC_DMAE, 0x6c0),
+    INTC_VECT(DMAC_DMTE0, 0x640), INTC_VECT(DMAC_DMTE1, 0x660),
+    INTC_VECT(DMAC_DMTE2, 0x680), INTC_VECT(DMAC_DMTE3, 0x6a0),
+    INTC_VECT(DMAC_DMTE4, 0x780), INTC_VECT(DMAC_DMTE5, 0x7a0),
+    INTC_VECT(DMAC_DMTE6, 0x7c0), INTC_VECT(DMAC_DMTE7, 0x7e0),
+    INTC_VECT(DMAC_DMAE, 0x6c0),
 };
 
 static struct intc_group groups_dma8[] = {
-	INTC_GROUP(DMAC, DMAC_DMTE0, DMAC_DMTE1, DMAC_DMTE2,
-		   DMAC_DMTE3, DMAC_DMTE4, DMAC_DMTE5,
-		   DMAC_DMTE6, DMAC_DMTE7, DMAC_DMAE),
+    INTC_GROUP(DMAC, DMAC_DMTE0, DMAC_DMTE1, DMAC_DMTE2,
+               DMAC_DMTE3, DMAC_DMTE4, DMAC_DMTE5,
+               DMAC_DMTE6, DMAC_DMTE7, DMAC_DMAE),
 };
 
 /* SH7750R, SH7751 and SH7751R all have two extra timer channels */
 
 static struct intc_vect vectors_tmu34[] = {
-	INTC_VECT(TMU3, 0xb00), INTC_VECT(TMU4, 0xb80),
+    INTC_VECT(TMU3, 0xb00), INTC_VECT(TMU4, 0xb80),
 };
 
 static struct intc_mask_reg mask_registers[] = {
-	{ 0xfe080040, 0xfe080060, 32, /* INTMSK00 / INTMSKCLR00 */
-	  { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-	    0, 0, 0, 0, 0, 0, TMU4, TMU3,
-	    PCIC1_PCIERR, PCIC1_PCIPWDWN, PCIC1_PCIPWON,
-	    PCIC1_PCIDMA0, PCIC1_PCIDMA1, PCIC1_PCIDMA2,
-	    PCIC1_PCIDMA3, PCIC0_PCISERR } },
+    { 0xfe080040, 0xfe080060, 32, /* INTMSK00 / INTMSKCLR00 */
+      { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 0, 0, 0, 0, TMU4, TMU3,
+        PCIC1_PCIERR, PCIC1_PCIPWDWN, PCIC1_PCIPWON,
+        PCIC1_PCIDMA0, PCIC1_PCIDMA1, PCIC1_PCIDMA2,
+        PCIC1_PCIDMA3, PCIC0_PCISERR } },
 };
 
 /* SH7750S, SH7750R, SH7751 and SH7751R all have IRLM priority registers */
 
 static struct intc_vect vectors_irlm[] = {
-	INTC_VECT(IRL0, 0x240), INTC_VECT(IRL1, 0x2a0),
-	INTC_VECT(IRL2, 0x300), INTC_VECT(IRL3, 0x360),
+    INTC_VECT(IRL0, 0x240), INTC_VECT(IRL1, 0x2a0),
+    INTC_VECT(IRL2, 0x300), INTC_VECT(IRL3, 0x360),
 };
 
 /* SH7751 and SH7751R both have PCI */
 
 static struct intc_vect vectors_pci[] = {
-	INTC_VECT(PCIC0_PCISERR, 0xa00), INTC_VECT(PCIC1_PCIERR, 0xae0),
-	INTC_VECT(PCIC1_PCIPWDWN, 0xac0), INTC_VECT(PCIC1_PCIPWON, 0xaa0),
-	INTC_VECT(PCIC1_PCIDMA0, 0xa80), INTC_VECT(PCIC1_PCIDMA1, 0xa60),
-	INTC_VECT(PCIC1_PCIDMA2, 0xa40), INTC_VECT(PCIC1_PCIDMA3, 0xa20),
+    INTC_VECT(PCIC0_PCISERR, 0xa00), INTC_VECT(PCIC1_PCIERR, 0xae0),
+    INTC_VECT(PCIC1_PCIPWDWN, 0xac0), INTC_VECT(PCIC1_PCIPWON, 0xaa0),
+    INTC_VECT(PCIC1_PCIDMA0, 0xa80), INTC_VECT(PCIC1_PCIDMA1, 0xa60),
+    INTC_VECT(PCIC1_PCIDMA2, 0xa40), INTC_VECT(PCIC1_PCIDMA3, 0xa20),
 };
 
 static struct intc_group groups_pci[] = {
-	INTC_GROUP(PCIC1, PCIC1_PCIERR, PCIC1_PCIPWDWN, PCIC1_PCIPWON,
-		   PCIC1_PCIDMA0, PCIC1_PCIDMA1, PCIC1_PCIDMA2, PCIC1_PCIDMA3),
+    INTC_GROUP(PCIC1, PCIC1_PCIERR, PCIC1_PCIPWDWN, PCIC1_PCIPWON,
+               PCIC1_PCIDMA0, PCIC1_PCIDMA1, PCIC1_PCIDMA2, PCIC1_PCIDMA3),
 };
 
 static struct intc_vect vectors_irl[] = {
-	INTC_VECT(IRL_0, 0x200),
-	INTC_VECT(IRL_1, 0x220),
-	INTC_VECT(IRL_2, 0x240),
-	INTC_VECT(IRL_3, 0x260),
-	INTC_VECT(IRL_4, 0x280),
-	INTC_VECT(IRL_5, 0x2a0),
-	INTC_VECT(IRL_6, 0x2c0),
-	INTC_VECT(IRL_7, 0x2e0),
-	INTC_VECT(IRL_8, 0x300),
-	INTC_VECT(IRL_9, 0x320),
-	INTC_VECT(IRL_A, 0x340),
-	INTC_VECT(IRL_B, 0x360),
-	INTC_VECT(IRL_C, 0x380),
-	INTC_VECT(IRL_D, 0x3a0),
-	INTC_VECT(IRL_E, 0x3c0),
+    INTC_VECT(IRL_0, 0x200),
+    INTC_VECT(IRL_1, 0x220),
+    INTC_VECT(IRL_2, 0x240),
+    INTC_VECT(IRL_3, 0x260),
+    INTC_VECT(IRL_4, 0x280),
+    INTC_VECT(IRL_5, 0x2a0),
+    INTC_VECT(IRL_6, 0x2c0),
+    INTC_VECT(IRL_7, 0x2e0),
+    INTC_VECT(IRL_8, 0x300),
+    INTC_VECT(IRL_9, 0x320),
+    INTC_VECT(IRL_A, 0x340),
+    INTC_VECT(IRL_B, 0x360),
+    INTC_VECT(IRL_C, 0x380),
+    INTC_VECT(IRL_D, 0x3a0),
+    INTC_VECT(IRL_E, 0x3c0),
 };
 
 static struct intc_group groups_irl[] = {
-	INTC_GROUP(IRL, IRL_0, IRL_1, IRL_2, IRL_3, IRL_4, IRL_5, IRL_6,
-		IRL_7, IRL_8, IRL_9, IRL_A, IRL_B, IRL_C, IRL_D, IRL_E),
+    INTC_GROUP(IRL, IRL_0, IRL_1, IRL_2, IRL_3, IRL_4, IRL_5, IRL_6,
+        IRL_7, IRL_8, IRL_9, IRL_A, IRL_B, IRL_C, IRL_D, IRL_E),
 };
 
-/**********************************************************************
- Memory mapped cache and TLB
-**********************************************************************/
+/*
+ * Memory mapped cache and TLB
+ */
 
 #define MM_REGION_MASK   0x07000000
 #define MM_ICACHE_ADDR   (0)
@@ -679,7 +690,7 @@ static uint64_t sh7750_mmct_read(void *opaque, hwaddr addr,
     case MM_ICACHE_ADDR:
     case MM_ICACHE_DATA:
         /* do nothing */
-	break;
+        break;
     case MM_ITLB_ADDR:
         ret = cpu_sh4_read_mmaped_itlb_addr(&s->cpu->env, addr);
         break;
@@ -689,7 +700,7 @@ static uint64_t sh7750_mmct_read(void *opaque, hwaddr addr,
     case MM_OCACHE_ADDR:
     case MM_OCACHE_DATA:
         /* do nothing */
-	break;
+        break;
     case MM_UTLB_ADDR:
         ret = cpu_sh4_read_mmaped_utlb_addr(&s->cpu->env, addr);
         break;
@@ -722,27 +733,27 @@ static void sh7750_mmct_write(void *opaque, hwaddr addr,
     case MM_ICACHE_ADDR:
     case MM_ICACHE_DATA:
         /* do nothing */
-	break;
+        break;
     case MM_ITLB_ADDR:
         cpu_sh4_write_mmaped_itlb_addr(&s->cpu->env, addr, mem_value);
         break;
     case MM_ITLB_DATA:
         cpu_sh4_write_mmaped_itlb_data(&s->cpu->env, addr, mem_value);
         abort();
-	break;
+        break;
     case MM_OCACHE_ADDR:
     case MM_OCACHE_DATA:
         /* do nothing */
-	break;
+        break;
     case MM_UTLB_ADDR:
         cpu_sh4_write_mmaped_utlb_addr(&s->cpu->env, addr, mem_value);
-	break;
+        break;
     case MM_UTLB_DATA:
         cpu_sh4_write_mmaped_utlb_data(&s->cpu->env, addr, mem_value);
-	break;
+        break;
     default:
         abort();
-	break;
+        break;
     }
 }
 
@@ -755,10 +766,13 @@ static const MemoryRegionOps sh7750_mmct_ops = {
 SH7750State *sh7750_init(SuperHCPU *cpu, MemoryRegion *sysmem)
 {
     SH7750State *s;
+    DeviceState *dev;
+    SysBusDevice *sb;
+    MemoryRegion *mr, *alias;
 
     s = g_malloc0(sizeof(SH7750State));
     s->cpu = cpu;
-    s->periph_freq = 60000000;	/* 60MHz */
+    s->periph_freq = 60000000; /* 60MHz */
     memory_region_init_io(&s->iomem, NULL, &sh7750_mem_ops, s,
                           "memory", 0x1fc01000);
 
@@ -791,81 +805,100 @@ SH7750State *sh7750_init(SuperHCPU *cpu, MemoryRegion *sysmem)
     memory_region_add_subregion(sysmem, 0xf0000000, &s->mmct_iomem);
 
     sh_intc_init(sysmem, &s->intc, NR_SOURCES,
-		 _INTC_ARRAY(mask_registers),
-		 _INTC_ARRAY(prio_registers));
+                 _INTC_ARRAY(mask_registers),
+                 _INTC_ARRAY(prio_registers));
 
     sh_intc_register_sources(&s->intc,
-			     _INTC_ARRAY(vectors),
-			     _INTC_ARRAY(groups));
+                             _INTC_ARRAY(vectors),
+                             _INTC_ARRAY(groups));
 
     cpu->env.intc_handle = &s->intc;
 
-    sh_serial_init(sysmem, 0x1fe00000,
-                   0, s->periph_freq, serial_hd(0),
-                   s->intc.irqs[SCI1_ERI],
-                   s->intc.irqs[SCI1_RXI],
-                   s->intc.irqs[SCI1_TXI],
-                   s->intc.irqs[SCI1_TEI],
-                   NULL);
-    sh_serial_init(sysmem, 0x1fe80000,
-                   SH_SERIAL_FEAT_SCIF,
-                   s->periph_freq, serial_hd(1),
-                   s->intc.irqs[SCIF_ERI],
-                   s->intc.irqs[SCIF_RXI],
-                   s->intc.irqs[SCIF_TXI],
-                   NULL,
-                   s->intc.irqs[SCIF_BRI]);
+    /* SCI */
+    dev = qdev_new(TYPE_SH_SERIAL);
+    dev->id = g_strdup("sci");
+    qdev_prop_set_chr(dev, "chardev", serial_hd(0));
+    sb = SYS_BUS_DEVICE(dev);
+    sysbus_realize_and_unref(sb, &error_fatal);
+    sysbus_mmio_map(sb, 0, 0xffe00000);
+    alias = g_malloc(sizeof(*alias));
+    mr = sysbus_mmio_get_region(sb, 0);
+    memory_region_init_alias(alias, OBJECT(dev), "sci-a7", mr,
+                             0, memory_region_size(mr));
+    memory_region_add_subregion(sysmem, A7ADDR(0xffe00000), alias);
+    qdev_connect_gpio_out_named(dev, "eri", 0, s->intc.irqs[SCI1_ERI]);
+    qdev_connect_gpio_out_named(dev, "rxi", 0, s->intc.irqs[SCI1_RXI]);
+    qdev_connect_gpio_out_named(dev, "txi", 0, s->intc.irqs[SCI1_TXI]);
+    qdev_connect_gpio_out_named(dev, "tei", 0, s->intc.irqs[SCI1_TEI]);
+
+    /* SCIF */
+    dev = qdev_new(TYPE_SH_SERIAL);
+    dev->id = g_strdup("scif");
+    qdev_prop_set_chr(dev, "chardev", serial_hd(1));
+    qdev_prop_set_uint8(dev, "features", SH_SERIAL_FEAT_SCIF);
+    sb = SYS_BUS_DEVICE(dev);
+    sysbus_realize_and_unref(sb, &error_fatal);
+    sysbus_mmio_map(sb, 0, 0xffe80000);
+    alias = g_malloc(sizeof(*alias));
+    mr = sysbus_mmio_get_region(sb, 0);
+    memory_region_init_alias(alias, OBJECT(dev), "scif-a7", mr,
+                             0, memory_region_size(mr));
+    memory_region_add_subregion(sysmem, A7ADDR(0xffe80000), alias);
+    qdev_connect_gpio_out_named(dev, "eri", 0, s->intc.irqs[SCIF_ERI]);
+    qdev_connect_gpio_out_named(dev, "rxi", 0, s->intc.irqs[SCIF_RXI]);
+    qdev_connect_gpio_out_named(dev, "txi", 0, s->intc.irqs[SCIF_TXI]);
+    qdev_connect_gpio_out_named(dev, "bri", 0, s->intc.irqs[SCIF_BRI]);
 
     tmu012_init(sysmem, 0x1fd80000,
-		TMU012_FEAT_TOCR | TMU012_FEAT_3CHAN | TMU012_FEAT_EXTCLK,
-		s->periph_freq,
-		s->intc.irqs[TMU0],
-		s->intc.irqs[TMU1],
-		s->intc.irqs[TMU2_TUNI],
-		s->intc.irqs[TMU2_TICPI]);
+                TMU012_FEAT_TOCR | TMU012_FEAT_3CHAN | TMU012_FEAT_EXTCLK,
+                s->periph_freq,
+                s->intc.irqs[TMU0],
+                s->intc.irqs[TMU1],
+                s->intc.irqs[TMU2_TUNI],
+                s->intc.irqs[TMU2_TICPI]);
 
     if (cpu->env.id & (SH_CPU_SH7750 | SH_CPU_SH7750S | SH_CPU_SH7751)) {
         sh_intc_register_sources(&s->intc,
-				 _INTC_ARRAY(vectors_dma4),
-				 _INTC_ARRAY(groups_dma4));
+                                 _INTC_ARRAY(vectors_dma4),
+                                 _INTC_ARRAY(groups_dma4));
     }
 
     if (cpu->env.id & (SH_CPU_SH7750R | SH_CPU_SH7751R)) {
         sh_intc_register_sources(&s->intc,
-				 _INTC_ARRAY(vectors_dma8),
-				 _INTC_ARRAY(groups_dma8));
+                                 _INTC_ARRAY(vectors_dma8),
+                                 _INTC_ARRAY(groups_dma8));
     }
 
     if (cpu->env.id & (SH_CPU_SH7750R | SH_CPU_SH7751 | SH_CPU_SH7751R)) {
         sh_intc_register_sources(&s->intc,
-				 _INTC_ARRAY(vectors_tmu34),
-				 NULL, 0);
+                                 _INTC_ARRAY(vectors_tmu34),
+                                 NULL, 0);
         tmu012_init(sysmem, 0x1e100000, 0, s->periph_freq,
-		    s->intc.irqs[TMU3],
-		    s->intc.irqs[TMU4],
-		    NULL, NULL);
+                    s->intc.irqs[TMU3],
+                    s->intc.irqs[TMU4],
+                    NULL, NULL);
     }
 
     if (cpu->env.id & (SH_CPU_SH7751_ALL)) {
         sh_intc_register_sources(&s->intc,
-				 _INTC_ARRAY(vectors_pci),
-				 _INTC_ARRAY(groups_pci));
+                                 _INTC_ARRAY(vectors_pci),
+                                 _INTC_ARRAY(groups_pci));
     }
 
     if (cpu->env.id & (SH_CPU_SH7750S | SH_CPU_SH7750R | SH_CPU_SH7751_ALL)) {
         sh_intc_register_sources(&s->intc,
-				 _INTC_ARRAY(vectors_irlm),
-				 NULL, 0);
+                                 _INTC_ARRAY(vectors_irlm),
+                                 NULL, 0);
     }
 
     sh_intc_register_sources(&s->intc,
-				_INTC_ARRAY(vectors_irl),
-				_INTC_ARRAY(groups_irl));
+                                _INTC_ARRAY(vectors_irl),
+                                _INTC_ARRAY(groups_irl));
     return s;
 }
 
 qemu_irq sh7750_irl(SH7750State *s)
 {
-    sh_intc_toggle_source(sh_intc_source(&s->intc, IRL), 1, 0); /* enable */
-    return qemu_allocate_irq(sh_intc_set_irl, sh_intc_source(&s->intc, IRL), 0);
+    sh_intc_toggle_source(&s->intc.sources[IRL], 1, 0); /* enable */
+    return qemu_allocate_irq(sh_intc_set_irl, &s->intc.sources[IRL], 0);
 }
diff --git a/hw/sh4/sh7750_regnames.c b/hw/sh4/sh7750_regnames.c
index 0630fe3cf4..e531d46a8e 100644
--- a/hw/sh4/sh7750_regnames.c
+++ b/hw/sh4/sh7750_regnames.c
@@ -12,85 +12,87 @@ typedef struct {
 
 static regname_t regnames[] = {
     REGNAME(SH7750_PTEH_A7)
-	REGNAME(SH7750_PTEL_A7)
-	REGNAME(SH7750_PTEA_A7)
-	REGNAME(SH7750_TTB_A7)
-	REGNAME(SH7750_TEA_A7)
-	REGNAME(SH7750_MMUCR_A7)
-	REGNAME(SH7750_CCR_A7)
-	REGNAME(SH7750_QACR0_A7)
-	REGNAME(SH7750_QACR1_A7)
-	REGNAME(SH7750_TRA_A7)
-	REGNAME(SH7750_EXPEVT_A7)
-	REGNAME(SH7750_INTEVT_A7)
-	REGNAME(SH7750_STBCR_A7)
-	REGNAME(SH7750_STBCR2_A7)
-	REGNAME(SH7750_FRQCR_A7)
-	REGNAME(SH7750_WTCNT_A7)
-	REGNAME(SH7750_WTCSR_A7)
-	REGNAME(SH7750_R64CNT_A7)
-	REGNAME(SH7750_RSECCNT_A7)
-	REGNAME(SH7750_RMINCNT_A7)
-	REGNAME(SH7750_RHRCNT_A7)
-	REGNAME(SH7750_RWKCNT_A7)
-	REGNAME(SH7750_RDAYCNT_A7)
-	REGNAME(SH7750_RMONCNT_A7)
-	REGNAME(SH7750_RYRCNT_A7)
-	REGNAME(SH7750_RSECAR_A7)
-	REGNAME(SH7750_RMINAR_A7)
-	REGNAME(SH7750_RHRAR_A7)
-	REGNAME(SH7750_RWKAR_A7)
-	REGNAME(SH7750_RDAYAR_A7)
-	REGNAME(SH7750_RMONAR_A7)
-	REGNAME(SH7750_RCR1_A7)
-	REGNAME(SH7750_RCR2_A7)
-	REGNAME(SH7750_BCR1_A7)
-	REGNAME(SH7750_BCR2_A7)
-	REGNAME(SH7750_WCR1_A7)
-	REGNAME(SH7750_WCR2_A7)
-	REGNAME(SH7750_WCR3_A7)
-	REGNAME(SH7750_MCR_A7)
-	REGNAME(SH7750_PCR_A7)
-	REGNAME(SH7750_RTCSR_A7)
-	REGNAME(SH7750_RTCNT_A7)
-	REGNAME(SH7750_RTCOR_A7)
-	REGNAME(SH7750_RFCR_A7)
-	REGNAME(SH7750_SAR0_A7)
-	REGNAME(SH7750_SAR1_A7)
-	REGNAME(SH7750_SAR2_A7)
-	REGNAME(SH7750_SAR3_A7)
-	REGNAME(SH7750_DAR0_A7)
-	REGNAME(SH7750_DAR1_A7)
-	REGNAME(SH7750_DAR2_A7)
-	REGNAME(SH7750_DAR3_A7)
-	REGNAME(SH7750_DMATCR0_A7)
-	REGNAME(SH7750_DMATCR1_A7)
-	REGNAME(SH7750_DMATCR2_A7)
-	REGNAME(SH7750_DMATCR3_A7)
-	REGNAME(SH7750_CHCR0_A7)
-	REGNAME(SH7750_CHCR1_A7)
-	REGNAME(SH7750_CHCR2_A7)
-	REGNAME(SH7750_CHCR3_A7)
-	REGNAME(SH7750_DMAOR_A7)
-	REGNAME(SH7750_PCTRA_A7)
-	REGNAME(SH7750_PDTRA_A7)
-	REGNAME(SH7750_PCTRB_A7)
-	REGNAME(SH7750_PDTRB_A7)
-	REGNAME(SH7750_GPIOIC_A7)
-	REGNAME(SH7750_ICR_A7)
-	REGNAME(SH7750_BCR3_A7)
-	REGNAME(SH7750_BCR4_A7)
-	REGNAME(SH7750_SDMR2_A7)
-	REGNAME(SH7750_SDMR3_A7) {(uint32_t) - 1, NULL}
+    REGNAME(SH7750_PTEL_A7)
+    REGNAME(SH7750_PTEA_A7)
+    REGNAME(SH7750_TTB_A7)
+    REGNAME(SH7750_TEA_A7)
+    REGNAME(SH7750_MMUCR_A7)
+    REGNAME(SH7750_CCR_A7)
+    REGNAME(SH7750_QACR0_A7)
+    REGNAME(SH7750_QACR1_A7)
+    REGNAME(SH7750_TRA_A7)
+    REGNAME(SH7750_EXPEVT_A7)
+    REGNAME(SH7750_INTEVT_A7)
+    REGNAME(SH7750_STBCR_A7)
+    REGNAME(SH7750_STBCR2_A7)
+    REGNAME(SH7750_FRQCR_A7)
+    REGNAME(SH7750_WTCNT_A7)
+    REGNAME(SH7750_WTCSR_A7)
+    REGNAME(SH7750_R64CNT_A7)
+    REGNAME(SH7750_RSECCNT_A7)
+    REGNAME(SH7750_RMINCNT_A7)
+    REGNAME(SH7750_RHRCNT_A7)
+    REGNAME(SH7750_RWKCNT_A7)
+    REGNAME(SH7750_RDAYCNT_A7)
+    REGNAME(SH7750_RMONCNT_A7)
+    REGNAME(SH7750_RYRCNT_A7)
+    REGNAME(SH7750_RSECAR_A7)
+    REGNAME(SH7750_RMINAR_A7)
+    REGNAME(SH7750_RHRAR_A7)
+    REGNAME(SH7750_RWKAR_A7)
+    REGNAME(SH7750_RDAYAR_A7)
+    REGNAME(SH7750_RMONAR_A7)
+    REGNAME(SH7750_RCR1_A7)
+    REGNAME(SH7750_RCR2_A7)
+    REGNAME(SH7750_BCR1_A7)
+    REGNAME(SH7750_BCR2_A7)
+    REGNAME(SH7750_WCR1_A7)
+    REGNAME(SH7750_WCR2_A7)
+    REGNAME(SH7750_WCR3_A7)
+    REGNAME(SH7750_MCR_A7)
+    REGNAME(SH7750_PCR_A7)
+    REGNAME(SH7750_RTCSR_A7)
+    REGNAME(SH7750_RTCNT_A7)
+    REGNAME(SH7750_RTCOR_A7)
+    REGNAME(SH7750_RFCR_A7)
+    REGNAME(SH7750_SAR0_A7)
+    REGNAME(SH7750_SAR1_A7)
+    REGNAME(SH7750_SAR2_A7)
+    REGNAME(SH7750_SAR3_A7)
+    REGNAME(SH7750_DAR0_A7)
+    REGNAME(SH7750_DAR1_A7)
+    REGNAME(SH7750_DAR2_A7)
+    REGNAME(SH7750_DAR3_A7)
+    REGNAME(SH7750_DMATCR0_A7)
+    REGNAME(SH7750_DMATCR1_A7)
+    REGNAME(SH7750_DMATCR2_A7)
+    REGNAME(SH7750_DMATCR3_A7)
+    REGNAME(SH7750_CHCR0_A7)
+    REGNAME(SH7750_CHCR1_A7)
+    REGNAME(SH7750_CHCR2_A7)
+    REGNAME(SH7750_CHCR3_A7)
+    REGNAME(SH7750_DMAOR_A7)
+    REGNAME(SH7750_PCTRA_A7)
+    REGNAME(SH7750_PDTRA_A7)
+    REGNAME(SH7750_PCTRB_A7)
+    REGNAME(SH7750_PDTRB_A7)
+    REGNAME(SH7750_GPIOIC_A7)
+    REGNAME(SH7750_ICR_A7)
+    REGNAME(SH7750_BCR3_A7)
+    REGNAME(SH7750_BCR4_A7)
+    REGNAME(SH7750_SDMR2_A7)
+    REGNAME(SH7750_SDMR3_A7)
+    { (uint32_t)-1, NULL }
 };
 
 const char *regname(uint32_t addr)
 {
     unsigned int i;
 
-    for (i = 0; regnames[i].regaddr != (uint32_t) - 1; i++) {
-	if (regnames[i].regaddr == addr)
-	    return regnames[i].regname;
+    for (i = 0; regnames[i].regaddr != (uint32_t)-1; i++) {
+        if (regnames[i].regaddr == addr) {
+            return regnames[i].regname;
+        }
     }
 
     return "<unknown reg>";
diff --git a/hw/sh4/sh7750_regs.h b/hw/sh4/sh7750_regs.h
index ab073dadc7..beb571d5e9 100644
--- a/hw/sh4/sh7750_regs.h
+++ b/hw/sh4/sh7750_regs.h
@@ -43,9 +43,8 @@
  * All register has 2 addresses: in 0xff000000 - 0xffffffff (P4 address)  and
  * in 0x1f000000 - 0x1fffffff (area 7 address)
  */
-#define SH7750_P4_BASE       0xff000000	/* Accessible only in
-					   privileged mode */
-#define SH7750_A7_BASE       0x1f000000	/* Accessible only using TLB */
+#define SH7750_P4_BASE       0xff000000 /* Accessible only in privileged mode */
+#define SH7750_A7_BASE       0x1f000000 /* Accessible only using TLB */
 
 #define SH7750_P4_REG32(ofs) (SH7750_P4_BASE + (ofs))
 #define SH7750_A7_REG32(ofs) (SH7750_A7_BASE + (ofs))
@@ -55,84 +54,84 @@
  */
 
 /* Page Table Entry High register - PTEH */
-#define SH7750_PTEH_REGOFS    0x000000	/* offset */
+#define SH7750_PTEH_REGOFS    0x000000  /* offset */
 #define SH7750_PTEH           SH7750_P4_REG32(SH7750_PTEH_REGOFS)
 #define SH7750_PTEH_A7        SH7750_A7_REG32(SH7750_PTEH_REGOFS)
-#define SH7750_PTEH_VPN       0xfffffd00	/* Virtual page number */
+#define SH7750_PTEH_VPN       0xfffffd00 /* Virtual page number */
 #define SH7750_PTEH_VPN_S     10
-#define SH7750_PTEH_ASID      0x000000ff	/* Address space identifier */
+#define SH7750_PTEH_ASID      0x000000ff /* Address space identifier */
 #define SH7750_PTEH_ASID_S    0
 
 /* Page Table Entry Low register - PTEL */
-#define SH7750_PTEL_REGOFS    0x000004	/* offset */
+#define SH7750_PTEL_REGOFS    0x000004  /* offset */
 #define SH7750_PTEL           SH7750_P4_REG32(SH7750_PTEL_REGOFS)
 #define SH7750_PTEL_A7        SH7750_A7_REG32(SH7750_PTEL_REGOFS)
-#define SH7750_PTEL_PPN       0x1ffffc00	/* Physical page number */
+#define SH7750_PTEL_PPN       0x1ffffc00 /* Physical page number */
 #define SH7750_PTEL_PPN_S     10
-#define SH7750_PTEL_V         0x00000100	/* Validity (0-entry is invalid) */
-#define SH7750_PTEL_SZ1       0x00000080	/* Page size bit 1 */
-#define SH7750_PTEL_SZ0       0x00000010	/* Page size bit 0 */
-#define SH7750_PTEL_SZ_1KB    0x00000000	/*   1-kbyte page */
-#define SH7750_PTEL_SZ_4KB    0x00000010	/*   4-kbyte page */
-#define SH7750_PTEL_SZ_64KB   0x00000080	/*   64-kbyte page */
-#define SH7750_PTEL_SZ_1MB    0x00000090	/*   1-Mbyte page */
-#define SH7750_PTEL_PR        0x00000060	/* Protection Key Data */
-#define SH7750_PTEL_PR_ROPO   0x00000000	/*   read-only in priv mode */
-#define SH7750_PTEL_PR_RWPO   0x00000020	/*   read-write in priv mode */
-#define SH7750_PTEL_PR_ROPU   0x00000040	/*   read-only in priv or user mode */
-#define SH7750_PTEL_PR_RWPU   0x00000060	/*   read-write in priv or user mode */
-#define SH7750_PTEL_C         0x00000008	/* Cacheability
-						   (0 - page not cacheable) */
-#define SH7750_PTEL_D         0x00000004	/* Dirty bit (1 - write has been
-						   performed to a page) */
-#define SH7750_PTEL_SH        0x00000002	/* Share Status bit (1 - page are
-						   shared by processes) */
-#define SH7750_PTEL_WT        0x00000001	/* Write-through bit, specifies the
-						   cache write mode:
-						   0 - Copy-back mode
-						   1 - Write-through mode */
+#define SH7750_PTEL_V         0x00000100 /* Validity (0-entry is invalid) */
+#define SH7750_PTEL_SZ1       0x00000080 /* Page size bit 1 */
+#define SH7750_PTEL_SZ0       0x00000010 /* Page size bit 0 */
+#define SH7750_PTEL_SZ_1KB    0x00000000 /*   1-kbyte page */
+#define SH7750_PTEL_SZ_4KB    0x00000010 /*   4-kbyte page */
+#define SH7750_PTEL_SZ_64KB   0x00000080 /*   64-kbyte page */
+#define SH7750_PTEL_SZ_1MB    0x00000090 /*   1-Mbyte page */
+#define SH7750_PTEL_PR        0x00000060 /* Protection Key Data */
+#define SH7750_PTEL_PR_ROPO   0x00000000 /*   read-only in priv mode */
+#define SH7750_PTEL_PR_RWPO   0x00000020 /*   read-write in priv mode */
+#define SH7750_PTEL_PR_ROPU   0x00000040 /*   read-only in priv or user mode */
+#define SH7750_PTEL_PR_RWPU   0x00000060 /*   read-write in priv or user mode */
+#define SH7750_PTEL_C         0x00000008 /* Cacheability */
+                                         /*   (0 - page not cacheable) */
+#define SH7750_PTEL_D         0x00000004 /* Dirty bit (1 - write has been */
+                                         /*   performed to a page) */
+#define SH7750_PTEL_SH        0x00000002 /* Share Status bit (1 - page are */
+                                         /*   shared by processes) */
+#define SH7750_PTEL_WT        0x00000001 /* Write-through bit, specifies the */
+                                         /*   cache write mode: */
+                                         /*     0 - Copy-back mode */
+                                         /*     1 - Write-through mode */
 
 /* Page Table Entry Assistance register - PTEA */
-#define SH7750_PTEA_REGOFS    0x000034	/* offset */
+#define SH7750_PTEA_REGOFS    0x000034 /* offset */
 #define SH7750_PTEA           SH7750_P4_REG32(SH7750_PTEA_REGOFS)
 #define SH7750_PTEA_A7        SH7750_A7_REG32(SH7750_PTEA_REGOFS)
-#define SH7750_PTEA_TC        0x00000008	/* Timing Control bit
-						   0 - use area 5 wait states
-						   1 - use area 6 wait states */
-#define SH7750_PTEA_SA        0x00000007	/* Space Attribute bits: */
-#define SH7750_PTEA_SA_UNDEF  0x00000000	/*    0 - undefined */
-#define SH7750_PTEA_SA_IOVAR  0x00000001	/*    1 - variable-size I/O space */
-#define SH7750_PTEA_SA_IO8    0x00000002	/*    2 - 8-bit I/O space */
-#define SH7750_PTEA_SA_IO16   0x00000003	/*    3 - 16-bit I/O space */
-#define SH7750_PTEA_SA_CMEM8  0x00000004	/*    4 - 8-bit common memory space */
-#define SH7750_PTEA_SA_CMEM16 0x00000005	/*    5 - 16-bit common memory space */
-#define SH7750_PTEA_SA_AMEM8  0x00000006	/*    6 - 8-bit attr memory space */
-#define SH7750_PTEA_SA_AMEM16 0x00000007	/*    7 - 16-bit attr memory space */
+#define SH7750_PTEA_TC        0x00000008 /* Timing Control bit */
+                                         /*   0 - use area 5 wait states */
+                                         /*   1 - use area 6 wait states */
+#define SH7750_PTEA_SA        0x00000007 /* Space Attribute bits: */
+#define SH7750_PTEA_SA_UNDEF  0x00000000 /*   0 - undefined */
+#define SH7750_PTEA_SA_IOVAR  0x00000001 /*   1 - variable-size I/O space */
+#define SH7750_PTEA_SA_IO8    0x00000002 /*   2 - 8-bit I/O space */
+#define SH7750_PTEA_SA_IO16   0x00000003 /*   3 - 16-bit I/O space */
+#define SH7750_PTEA_SA_CMEM8  0x00000004 /*   4 - 8-bit common memory space */
+#define SH7750_PTEA_SA_CMEM16 0x00000005 /*   5 - 16-bit common memory space */
+#define SH7750_PTEA_SA_AMEM8  0x00000006 /*   6 - 8-bit attr memory space */
+#define SH7750_PTEA_SA_AMEM16 0x00000007 /*   7 - 16-bit attr memory space */
 
 
 /* Translation table base register */
-#define SH7750_TTB_REGOFS     0x000008	/* offset */
+#define SH7750_TTB_REGOFS     0x000008 /* offset */
 #define SH7750_TTB            SH7750_P4_REG32(SH7750_TTB_REGOFS)
 #define SH7750_TTB_A7         SH7750_A7_REG32(SH7750_TTB_REGOFS)
 
 /* TLB exeption address register - TEA */
-#define SH7750_TEA_REGOFS     0x00000c	/* offset */
+#define SH7750_TEA_REGOFS     0x00000c /* offset */
 #define SH7750_TEA            SH7750_P4_REG32(SH7750_TEA_REGOFS)
 #define SH7750_TEA_A7         SH7750_A7_REG32(SH7750_TEA_REGOFS)
 
 /* MMU control register - MMUCR */
-#define SH7750_MMUCR_REGOFS   0x000010	/* offset */
+#define SH7750_MMUCR_REGOFS   0x000010 /* offset */
 #define SH7750_MMUCR          SH7750_P4_REG32(SH7750_MMUCR_REGOFS)
 #define SH7750_MMUCR_A7       SH7750_A7_REG32(SH7750_MMUCR_REGOFS)
-#define SH7750_MMUCR_AT       0x00000001	/* Address translation bit */
-#define SH7750_MMUCR_TI       0x00000004	/* TLB invalidate */
-#define SH7750_MMUCR_SV       0x00000100	/* Single Virtual Mode bit */
-#define SH7750_MMUCR_SQMD     0x00000200	/* Store Queue Mode bit */
-#define SH7750_MMUCR_URC      0x0000FC00	/* UTLB Replace Counter */
+#define SH7750_MMUCR_AT       0x00000001 /* Address translation bit */
+#define SH7750_MMUCR_TI       0x00000004 /* TLB invalidate */
+#define SH7750_MMUCR_SV       0x00000100 /* Single Virtual Mode bit */
+#define SH7750_MMUCR_SQMD     0x00000200 /* Store Queue Mode bit */
+#define SH7750_MMUCR_URC      0x0000FC00 /* UTLB Replace Counter */
 #define SH7750_MMUCR_URC_S    10
-#define SH7750_MMUCR_URB      0x00FC0000	/* UTLB Replace Boundary */
+#define SH7750_MMUCR_URB      0x00FC0000 /* UTLB Replace Boundary */
 #define SH7750_MMUCR_URB_S    18
-#define SH7750_MMUCR_LRUI     0xFC000000	/* Least Recently Used ITLB */
+#define SH7750_MMUCR_LRUI     0xFC000000 /* Least Recently Used ITLB */
 #define SH7750_MMUCR_LRUI_S   26
 
 
@@ -145,30 +144,30 @@
  */
 
 /* Cache Control Register - CCR */
-#define SH7750_CCR_REGOFS     0x00001c	/* offset */
+#define SH7750_CCR_REGOFS     0x00001c /* offset */
 #define SH7750_CCR            SH7750_P4_REG32(SH7750_CCR_REGOFS)
 #define SH7750_CCR_A7         SH7750_A7_REG32(SH7750_CCR_REGOFS)
 
-#define SH7750_CCR_IIX      0x00008000	/* IC index enable bit */
-#define SH7750_CCR_ICI      0x00000800	/* IC invalidation bit:
-					   set it to clear IC */
-#define SH7750_CCR_ICE      0x00000100	/* IC enable bit */
-#define SH7750_CCR_OIX      0x00000080	/* OC index enable bit */
-#define SH7750_CCR_ORA      0x00000020	/* OC RAM enable bit
-					   if you set OCE = 0,
-					   you should set ORA = 0 */
-#define SH7750_CCR_OCI      0x00000008	/* OC invalidation bit */
-#define SH7750_CCR_CB       0x00000004	/* Copy-back bit for P1 area */
-#define SH7750_CCR_WT       0x00000002	/* Write-through bit for P0,U0,P3 area */
-#define SH7750_CCR_OCE      0x00000001	/* OC enable bit */
+#define SH7750_CCR_IIX      0x00008000 /* IC index enable bit */
+#define SH7750_CCR_ICI      0x00000800 /* IC invalidation bit: */
+                                       /*  set it to clear IC */
+#define SH7750_CCR_ICE      0x00000100 /* IC enable bit */
+#define SH7750_CCR_OIX      0x00000080 /* OC index enable bit */
+#define SH7750_CCR_ORA      0x00000020 /* OC RAM enable bit */
+                                       /*  if you set OCE = 0, */
+                                       /*  you should set ORA = 0 */
+#define SH7750_CCR_OCI      0x00000008 /* OC invalidation bit */
+#define SH7750_CCR_CB       0x00000004 /* Copy-back bit for P1 area */
+#define SH7750_CCR_WT       0x00000002 /* Write-through bit for P0,U0,P3 area */
+#define SH7750_CCR_OCE      0x00000001 /* OC enable bit */
 
 /* Queue address control register 0 - QACR0 */
-#define SH7750_QACR0_REGOFS   0x000038	/* offset */
+#define SH7750_QACR0_REGOFS   0x000038  /* offset */
 #define SH7750_QACR0          SH7750_P4_REG32(SH7750_QACR0_REGOFS)
 #define SH7750_QACR0_A7       SH7750_A7_REG32(SH7750_QACR0_REGOFS)
 
 /* Queue address control register 1 - QACR1 */
-#define SH7750_QACR1_REGOFS   0x00003c	/* offset */
+#define SH7750_QACR1_REGOFS   0x00003c /* offset */
 #define SH7750_QACR1          SH7750_P4_REG32(SH7750_QACR1_REGOFS)
 #define SH7750_QACR1_A7       SH7750_A7_REG32(SH7750_QACR1_REGOFS)
 
@@ -178,11 +177,11 @@
  */
 
 /* Immediate data for TRAPA instruction - TRA */
-#define SH7750_TRA_REGOFS     0x000020	/* offset */
+#define SH7750_TRA_REGOFS     0x000020 /* offset */
 #define SH7750_TRA            SH7750_P4_REG32(SH7750_TRA_REGOFS)
 #define SH7750_TRA_A7         SH7750_A7_REG32(SH7750_TRA_REGOFS)
 
-#define SH7750_TRA_IMM      0x000003fd	/* Immediate data operand */
+#define SH7750_TRA_IMM      0x000003fd /* Immediate data operand */
 #define SH7750_TRA_IMM_S    2
 
 /* Exeption event register - EXPEVT */
@@ -190,14 +189,14 @@
 #define SH7750_EXPEVT         SH7750_P4_REG32(SH7750_EXPEVT_REGOFS)
 #define SH7750_EXPEVT_A7      SH7750_A7_REG32(SH7750_EXPEVT_REGOFS)
 
-#define SH7750_EXPEVT_EX      0x00000fff	/* Exeption code */
+#define SH7750_EXPEVT_EX      0x00000fff /* Exeption code */
 #define SH7750_EXPEVT_EX_S    0
 
 /* Interrupt event register */
 #define SH7750_INTEVT_REGOFS  0x000028
 #define SH7750_INTEVT         SH7750_P4_REG32(SH7750_INTEVT_REGOFS)
 #define SH7750_INTEVT_A7      SH7750_A7_REG32(SH7750_INTEVT_REGOFS)
-#define SH7750_INTEVT_EX    0x00000fff	/* Exeption code */
+#define SH7750_INTEVT_EX    0x00000fff /* Exeption code */
 #define SH7750_INTEVT_EX_S  0
 
 /*
@@ -206,683 +205,684 @@
 #define SH7750_EVT_TO_NUM(evt)  ((evt) >> 5)
 
 /* Reset exception category */
-#define SH7750_EVT_POWER_ON_RST        0x000	/* Power-on reset */
-#define SH7750_EVT_MANUAL_RST          0x020	/* Manual reset */
-#define SH7750_EVT_TLB_MULT_HIT        0x140	/* TLB multiple-hit exception */
+#define SH7750_EVT_POWER_ON_RST        0x000 /* Power-on reset */
+#define SH7750_EVT_MANUAL_RST          0x020 /* Manual reset */
+#define SH7750_EVT_TLB_MULT_HIT        0x140 /* TLB multiple-hit exception */
 
 /* General exception category */
-#define SH7750_EVT_USER_BREAK          0x1E0	/* User break */
-#define SH7750_EVT_IADDR_ERR           0x0E0	/* Instruction address error */
-#define SH7750_EVT_TLB_READ_MISS       0x040	/* ITLB miss exception /
-						   DTLB miss exception (read) */
-#define SH7750_EVT_TLB_READ_PROTV      0x0A0	/* ITLB protection violation /
-						   DTLB protection violation (read) */
-#define SH7750_EVT_ILLEGAL_INSTR       0x180	/* General Illegal Instruction
-						   exception */
-#define SH7750_EVT_SLOT_ILLEGAL_INSTR  0x1A0	/* Slot Illegal Instruction
-						   exception */
-#define SH7750_EVT_FPU_DISABLE         0x800	/* General FPU disable exception */
-#define SH7750_EVT_SLOT_FPU_DISABLE    0x820	/* Slot FPU disable exception */
-#define SH7750_EVT_DATA_READ_ERR       0x0E0	/* Data address error (read) */
-#define SH7750_EVT_DATA_WRITE_ERR      0x100	/* Data address error (write) */
-#define SH7750_EVT_DTLB_WRITE_MISS     0x060	/* DTLB miss exception (write) */
-#define SH7750_EVT_DTLB_WRITE_PROTV    0x0C0	/* DTLB protection violation
-						   exception (write) */
-#define SH7750_EVT_FPU_EXCEPTION       0x120	/* FPU exception */
-#define SH7750_EVT_INITIAL_PGWRITE     0x080	/* Initial Page Write exception */
-#define SH7750_EVT_TRAPA               0x160	/* Unconditional trap (TRAPA) */
+#define SH7750_EVT_USER_BREAK          0x1E0 /* User break */
+#define SH7750_EVT_IADDR_ERR           0x0E0 /* Instruction address error */
+#define SH7750_EVT_TLB_READ_MISS       0x040 /* ITLB miss exception / */
+                                             /*    DTLB miss exception (read) */
+#define SH7750_EVT_TLB_READ_PROTV      0x0A0 /* ITLB protection violation, */
+                                             /* DTLB protection violation */
+                                             /*    (read) */
+#define SH7750_EVT_ILLEGAL_INSTR       0x180 /* General Illegal Instruction */
+                                             /*    exception */
+#define SH7750_EVT_SLOT_ILLEGAL_INSTR  0x1A0 /* Slot Illegal Instruction */
+                                             /*    exception */
+#define SH7750_EVT_FPU_DISABLE         0x800 /* General FPU disable exception */
+#define SH7750_EVT_SLOT_FPU_DISABLE    0x820 /* Slot FPU disable exception */
+#define SH7750_EVT_DATA_READ_ERR       0x0E0 /* Data address error (read) */
+#define SH7750_EVT_DATA_WRITE_ERR      0x100 /* Data address error (write) */
+#define SH7750_EVT_DTLB_WRITE_MISS     0x060 /* DTLB miss exception (write) */
+#define SH7750_EVT_DTLB_WRITE_PROTV    0x0C0 /* DTLB protection violation */
+                                             /*    exception (write) */
+#define SH7750_EVT_FPU_EXCEPTION       0x120 /* FPU exception */
+#define SH7750_EVT_INITIAL_PGWRITE     0x080 /* Initial Page Write exception */
+#define SH7750_EVT_TRAPA               0x160 /* Unconditional trap (TRAPA) */
 
 /* Interrupt exception category */
-#define SH7750_EVT_NMI                 0x1C0	/* Non-maskable interrupt */
-#define SH7750_EVT_IRQ0                0x200	/* External Interrupt 0 */
-#define SH7750_EVT_IRQ1                0x220	/* External Interrupt 1 */
-#define SH7750_EVT_IRQ2                0x240	/* External Interrupt 2 */
-#define SH7750_EVT_IRQ3                0x260	/* External Interrupt 3 */
-#define SH7750_EVT_IRQ4                0x280	/* External Interrupt 4 */
-#define SH7750_EVT_IRQ5                0x2A0	/* External Interrupt 5 */
-#define SH7750_EVT_IRQ6                0x2C0	/* External Interrupt 6 */
-#define SH7750_EVT_IRQ7                0x2E0	/* External Interrupt 7 */
-#define SH7750_EVT_IRQ8                0x300	/* External Interrupt 8 */
-#define SH7750_EVT_IRQ9                0x320	/* External Interrupt 9 */
-#define SH7750_EVT_IRQA                0x340	/* External Interrupt A */
-#define SH7750_EVT_IRQB                0x360	/* External Interrupt B */
-#define SH7750_EVT_IRQC                0x380	/* External Interrupt C */
-#define SH7750_EVT_IRQD                0x3A0	/* External Interrupt D */
-#define SH7750_EVT_IRQE                0x3C0	/* External Interrupt E */
+#define SH7750_EVT_NMI                 0x1C0 /* Non-maskable interrupt */
+#define SH7750_EVT_IRQ0                0x200 /* External Interrupt 0 */
+#define SH7750_EVT_IRQ1                0x220 /* External Interrupt 1 */
+#define SH7750_EVT_IRQ2                0x240 /* External Interrupt 2 */
+#define SH7750_EVT_IRQ3                0x260 /* External Interrupt 3 */
+#define SH7750_EVT_IRQ4                0x280 /* External Interrupt 4 */
+#define SH7750_EVT_IRQ5                0x2A0 /* External Interrupt 5 */
+#define SH7750_EVT_IRQ6                0x2C0 /* External Interrupt 6 */
+#define SH7750_EVT_IRQ7                0x2E0 /* External Interrupt 7 */
+#define SH7750_EVT_IRQ8                0x300 /* External Interrupt 8 */
+#define SH7750_EVT_IRQ9                0x320 /* External Interrupt 9 */
+#define SH7750_EVT_IRQA                0x340 /* External Interrupt A */
+#define SH7750_EVT_IRQB                0x360 /* External Interrupt B */
+#define SH7750_EVT_IRQC                0x380 /* External Interrupt C */
+#define SH7750_EVT_IRQD                0x3A0 /* External Interrupt D */
+#define SH7750_EVT_IRQE                0x3C0 /* External Interrupt E */
 
 /* Peripheral Module Interrupts - Timer Unit (TMU) */
-#define SH7750_EVT_TUNI0               0x400	/* TMU Underflow Interrupt 0 */
-#define SH7750_EVT_TUNI1               0x420	/* TMU Underflow Interrupt 1 */
-#define SH7750_EVT_TUNI2               0x440	/* TMU Underflow Interrupt 2 */
-#define SH7750_EVT_TICPI2              0x460	/* TMU Input Capture Interrupt 2 */
+#define SH7750_EVT_TUNI0               0x400 /* TMU Underflow Interrupt 0 */
+#define SH7750_EVT_TUNI1               0x420 /* TMU Underflow Interrupt 1 */
+#define SH7750_EVT_TUNI2               0x440 /* TMU Underflow Interrupt 2 */
+#define SH7750_EVT_TICPI2              0x460 /* TMU Input Capture Interrupt 2 */
 
 /* Peripheral Module Interrupts - Real-Time Clock (RTC) */
-#define SH7750_EVT_RTC_ATI             0x480	/* Alarm Interrupt Request */
-#define SH7750_EVT_RTC_PRI             0x4A0	/* Periodic Interrupt Request */
-#define SH7750_EVT_RTC_CUI             0x4C0	/* Carry Interrupt Request */
+#define SH7750_EVT_RTC_ATI             0x480 /* Alarm Interrupt Request */
+#define SH7750_EVT_RTC_PRI             0x4A0 /* Periodic Interrupt Request */
+#define SH7750_EVT_RTC_CUI             0x4C0 /* Carry Interrupt Request */
 
 /* Peripheral Module Interrupts - Serial Communication Interface (SCI) */
-#define SH7750_EVT_SCI_ERI             0x4E0	/* Receive Error */
-#define SH7750_EVT_SCI_RXI             0x500	/* Receive Data Register Full */
-#define SH7750_EVT_SCI_TXI             0x520	/* Transmit Data Register Empty */
-#define SH7750_EVT_SCI_TEI             0x540	/* Transmit End */
+#define SH7750_EVT_SCI_ERI             0x4E0 /* Receive Error */
+#define SH7750_EVT_SCI_RXI             0x500 /* Receive Data Register Full */
+#define SH7750_EVT_SCI_TXI             0x520 /* Transmit Data Register Empty */
+#define SH7750_EVT_SCI_TEI             0x540 /* Transmit End */
 
 /* Peripheral Module Interrupts - Watchdog Timer (WDT) */
-#define SH7750_EVT_WDT_ITI             0x560	/* Interval Timer Interrupt
-						   (used when WDT operates in
-						   interval timer mode) */
+#define SH7750_EVT_WDT_ITI             0x560 /* Interval Timer Interrupt */
+                                             /*    (used when WDT operates in */
+                                             /*    interval timer mode) */
 
 /* Peripheral Module Interrupts - Memory Refresh Unit (REF) */
-#define SH7750_EVT_REF_RCMI            0x580	/* Compare-match Interrupt */
-#define SH7750_EVT_REF_ROVI            0x5A0	/* Refresh Counter Overflow
-						   interrupt */
+#define SH7750_EVT_REF_RCMI            0x580 /* Compare-match Interrupt */
+#define SH7750_EVT_REF_ROVI            0x5A0 /* Refresh Counter Overflow */
+                                             /*    interrupt */
 
 /* Peripheral Module Interrupts - Hitachi User Debug Interface (H-UDI) */
-#define SH7750_EVT_HUDI                0x600	/* UDI interrupt */
+#define SH7750_EVT_HUDI                0x600 /* UDI interrupt */
 
 /* Peripheral Module Interrupts - General-Purpose I/O (GPIO) */
-#define SH7750_EVT_GPIO                0x620	/* GPIO Interrupt */
+#define SH7750_EVT_GPIO                0x620 /* GPIO Interrupt */
 
 /* Peripheral Module Interrupts - DMA Controller (DMAC) */
-#define SH7750_EVT_DMAC_DMTE0          0x640	/* DMAC 0 Transfer End Interrupt */
-#define SH7750_EVT_DMAC_DMTE1          0x660	/* DMAC 1 Transfer End Interrupt */
-#define SH7750_EVT_DMAC_DMTE2          0x680	/* DMAC 2 Transfer End Interrupt */
-#define SH7750_EVT_DMAC_DMTE3          0x6A0	/* DMAC 3 Transfer End Interrupt */
-#define SH7750_EVT_DMAC_DMAE           0x6C0	/* DMAC Address Error Interrupt */
-
-/* Peripheral Module Interrupts - Serial Communication Interface with FIFO */
-/*                                                                  (SCIF) */
-#define SH7750_EVT_SCIF_ERI            0x700	/* Receive Error */
-#define SH7750_EVT_SCIF_RXI            0x720	/* Receive FIFO Data Full or
-						   Receive Data ready interrupt */
-#define SH7750_EVT_SCIF_BRI            0x740	/* Break or overrun error */
-#define SH7750_EVT_SCIF_TXI            0x760	/* Transmit FIFO Data Empty */
+#define SH7750_EVT_DMAC_DMTE0          0x640 /* DMAC 0 Transfer End Interrupt */
+#define SH7750_EVT_DMAC_DMTE1          0x660 /* DMAC 1 Transfer End Interrupt */
+#define SH7750_EVT_DMAC_DMTE2          0x680 /* DMAC 2 Transfer End Interrupt */
+#define SH7750_EVT_DMAC_DMTE3          0x6A0 /* DMAC 3 Transfer End Interrupt */
+#define SH7750_EVT_DMAC_DMAE           0x6C0 /* DMAC Address Error Interrupt */
+
+/* Peripheral Module Interrupts Serial Communication Interface w/ FIFO (SCIF) */
+#define SH7750_EVT_SCIF_ERI            0x700 /* Receive Error */
+#define SH7750_EVT_SCIF_RXI            0x720 /* Receive FIFO Data Full or */
+                                             /* Receive Data ready interrupt */
+#define SH7750_EVT_SCIF_BRI            0x740 /* Break or overrun error */
+#define SH7750_EVT_SCIF_TXI            0x760 /* Transmit FIFO Data Empty */
 
 /*
  * Power Management
  */
-#define SH7750_STBCR_REGOFS   0xC00004	/* offset */
+#define SH7750_STBCR_REGOFS   0xC00004 /* offset */
 #define SH7750_STBCR          SH7750_P4_REG32(SH7750_STBCR_REGOFS)
 #define SH7750_STBCR_A7       SH7750_A7_REG32(SH7750_STBCR_REGOFS)
 
-#define SH7750_STBCR_STBY     0x80	/* Specifies a transition to standby mode:
-					   0 - Transition to SLEEP mode on SLEEP
-					   1 - Transition to STANDBY mode on SLEEP */
-#define SH7750_STBCR_PHZ      0x40	/* State of peripheral module pins in
-					   standby mode:
-					   0 - normal state
-					   1 - high-impendance state */
+#define SH7750_STBCR_STBY     0x80 /* Specifies a transition to standby mode: */
+                                   /*   0 Transition to SLEEP mode on SLEEP */
+                                   /*   1 Transition to STANDBY mode on SLEEP */
+#define SH7750_STBCR_PHZ      0x40 /* State of peripheral module pins in */
+                                   /* standby mode: */
+                                   /*   0 normal state */
+                                   /*   1 high-impendance state */
 
-#define SH7750_STBCR_PPU      0x20	/* Peripheral module pins pull-up controls */
-#define SH7750_STBCR_MSTP4    0x10	/* Stopping the clock supply to DMAC */
+#define SH7750_STBCR_PPU      0x20 /* Peripheral module pins pull-up controls */
+#define SH7750_STBCR_MSTP4    0x10 /* Stopping the clock supply to DMAC */
 #define SH7750_STBCR_DMAC_STP SH7750_STBCR_MSTP4
-#define SH7750_STBCR_MSTP3    0x08	/* Stopping the clock supply to SCIF */
+#define SH7750_STBCR_MSTP3    0x08 /* Stopping the clock supply to SCIF */
 #define SH7750_STBCR_SCIF_STP SH7750_STBCR_MSTP3
-#define SH7750_STBCR_MSTP2    0x04	/* Stopping the clock supply to TMU */
+#define SH7750_STBCR_MSTP2    0x04 /* Stopping the clock supply to TMU */
 #define SH7750_STBCR_TMU_STP  SH7750_STBCR_MSTP2
-#define SH7750_STBCR_MSTP1    0x02	/* Stopping the clock supply to RTC */
+#define SH7750_STBCR_MSTP1    0x02 /* Stopping the clock supply to RTC */
 #define SH7750_STBCR_RTC_STP  SH7750_STBCR_MSTP1
-#define SH7750_STBCR_MSPT0    0x01	/* Stopping the clock supply to SCI */
+#define SH7750_STBCR_MSPT0    0x01 /* Stopping the clock supply to SCI */
 #define SH7750_STBCR_SCI_STP  SH7750_STBCR_MSTP0
 
 #define SH7750_STBCR_STBY     0x80
 
 
-#define SH7750_STBCR2_REGOFS  0xC00010	/* offset */
+#define SH7750_STBCR2_REGOFS  0xC00010 /* offset */
 #define SH7750_STBCR2         SH7750_P4_REG32(SH7750_STBCR2_REGOFS)
 #define SH7750_STBCR2_A7      SH7750_A7_REG32(SH7750_STBCR2_REGOFS)
 
-#define SH7750_STBCR2_DSLP    0x80	/* Specifies transition to deep sleep mode:
-					   0 - transition to sleep or standby mode
-					   as it is specified in STBY bit
-					   1 - transition to deep sleep mode on
-					   execution of SLEEP instruction */
-#define SH7750_STBCR2_MSTP6   0x02	/* Stopping the clock supply to Store Queue
-					   in the cache controller */
+#define SH7750_STBCR2_DSLP    0x80 /* Specifies transition to deep sleep mode */
+                                   /*   0 transition to sleep or standby mode */
+                                   /*     as it is specified in STBY bit */
+                                   /*   1 transition to deep sleep mode on */
+                                   /*     execution of SLEEP instruction */
+#define SH7750_STBCR2_MSTP6   0x02 /* Stopping the clock supply to the */
+                                   /*   Store Queue in the cache controller */
 #define SH7750_STBCR2_SQ_STP  SH7750_STBCR2_MSTP6
-#define SH7750_STBCR2_MSTP5   0x01	/* Stopping the clock supply to the User
-					   Break Controller (UBC) */
+#define SH7750_STBCR2_MSTP5   0x01 /* Stopping the clock supply to the  */
+                                   /*   User Break Controller (UBC) */
 #define SH7750_STBCR2_UBC_STP SH7750_STBCR2_MSTP5
 
 /*
  * Clock Pulse Generator (CPG)
  */
-#define SH7750_FRQCR_REGOFS   0xC00000	/* offset */
+#define SH7750_FRQCR_REGOFS   0xC00000 /* offset */
 #define SH7750_FRQCR          SH7750_P4_REG32(SH7750_FRQCR_REGOFS)
 #define SH7750_FRQCR_A7       SH7750_A7_REG32(SH7750_FRQCR_REGOFS)
 
-#define SH7750_FRQCR_CKOEN    0x0800	/* Clock Output Enable
-					   0 - CKIO pin goes to HiZ/pullup
-					   1 - Clock is output from CKIO */
-#define SH7750_FRQCR_PLL1EN   0x0400	/* PLL circuit 1 enable */
-#define SH7750_FRQCR_PLL2EN   0x0200	/* PLL circuit 2 enable */
-
-#define SH7750_FRQCR_IFC      0x01C0	/* CPU clock frequency division ratio: */
-#define SH7750_FRQCR_IFCDIV1  0x0000	/*    0 - * 1 */
-#define SH7750_FRQCR_IFCDIV2  0x0040	/*    1 - * 1/2 */
-#define SH7750_FRQCR_IFCDIV3  0x0080	/*    2 - * 1/3 */
-#define SH7750_FRQCR_IFCDIV4  0x00C0	/*    3 - * 1/4 */
-#define SH7750_FRQCR_IFCDIV6  0x0100	/*    4 - * 1/6 */
-#define SH7750_FRQCR_IFCDIV8  0x0140	/*    5 - * 1/8 */
-
-#define SH7750_FRQCR_BFC      0x0038	/* Bus clock frequency division ratio: */
-#define SH7750_FRQCR_BFCDIV1  0x0000	/*    0 - * 1 */
-#define SH7750_FRQCR_BFCDIV2  0x0008	/*    1 - * 1/2 */
-#define SH7750_FRQCR_BFCDIV3  0x0010	/*    2 - * 1/3 */
-#define SH7750_FRQCR_BFCDIV4  0x0018	/*    3 - * 1/4 */
-#define SH7750_FRQCR_BFCDIV6  0x0020	/*    4 - * 1/6 */
-#define SH7750_FRQCR_BFCDIV8  0x0028	/*    5 - * 1/8 */
-
-#define SH7750_FRQCR_PFC      0x0007	/* Peripheral module clock frequency
-					   division ratio: */
-#define SH7750_FRQCR_PFCDIV2  0x0000	/*    0 - * 1/2 */
-#define SH7750_FRQCR_PFCDIV3  0x0001	/*    1 - * 1/3 */
-#define SH7750_FRQCR_PFCDIV4  0x0002	/*    2 - * 1/4 */
-#define SH7750_FRQCR_PFCDIV6  0x0003	/*    3 - * 1/6 */
-#define SH7750_FRQCR_PFCDIV8  0x0004	/*    4 - * 1/8 */
+#define SH7750_FRQCR_CKOEN    0x0800 /* Clock Output Enable */
+                                     /*    0 - CKIO pin goes to HiZ/pullup */
+                                     /*    1 - Clock is output from CKIO */
+#define SH7750_FRQCR_PLL1EN   0x0400 /* PLL circuit 1 enable */
+#define SH7750_FRQCR_PLL2EN   0x0200 /* PLL circuit 2 enable */
+
+#define SH7750_FRQCR_IFC      0x01C0 /* CPU clock frequency division ratio: */
+#define SH7750_FRQCR_IFCDIV1  0x0000 /*    0 - * 1 */
+#define SH7750_FRQCR_IFCDIV2  0x0040 /*    1 - * 1/2 */
+#define SH7750_FRQCR_IFCDIV3  0x0080 /*    2 - * 1/3 */
+#define SH7750_FRQCR_IFCDIV4  0x00C0 /*    3 - * 1/4 */
+#define SH7750_FRQCR_IFCDIV6  0x0100 /*    4 - * 1/6 */
+#define SH7750_FRQCR_IFCDIV8  0x0140 /*    5 - * 1/8 */
+
+#define SH7750_FRQCR_BFC      0x0038 /* Bus clock frequency division ratio: */
+#define SH7750_FRQCR_BFCDIV1  0x0000 /*    0 - * 1 */
+#define SH7750_FRQCR_BFCDIV2  0x0008 /*    1 - * 1/2 */
+#define SH7750_FRQCR_BFCDIV3  0x0010 /*    2 - * 1/3 */
+#define SH7750_FRQCR_BFCDIV4  0x0018 /*    3 - * 1/4 */
+#define SH7750_FRQCR_BFCDIV6  0x0020 /*    4 - * 1/6 */
+#define SH7750_FRQCR_BFCDIV8  0x0028 /*    5 - * 1/8 */
+
+#define SH7750_FRQCR_PFC      0x0007 /* Peripheral module clock frequency */
+                                     /*    division ratio: */
+#define SH7750_FRQCR_PFCDIV2  0x0000 /*    0 - * 1/2 */
+#define SH7750_FRQCR_PFCDIV3  0x0001 /*    1 - * 1/3 */
+#define SH7750_FRQCR_PFCDIV4  0x0002 /*    2 - * 1/4 */
+#define SH7750_FRQCR_PFCDIV6  0x0003 /*    3 - * 1/6 */
+#define SH7750_FRQCR_PFCDIV8  0x0004 /*    4 - * 1/8 */
 
 /*
  * Watchdog Timer (WDT)
  */
 
 /* Watchdog Timer Counter register - WTCNT */
-#define SH7750_WTCNT_REGOFS   0xC00008	/* offset */
+#define SH7750_WTCNT_REGOFS   0xC00008 /* offset */
 #define SH7750_WTCNT          SH7750_P4_REG32(SH7750_WTCNT_REGOFS)
 #define SH7750_WTCNT_A7       SH7750_A7_REG32(SH7750_WTCNT_REGOFS)
-#define SH7750_WTCNT_KEY      0x5A00	/* When WTCNT byte register written,
-					   you have to set the upper byte to
-					   0x5A */
+#define SH7750_WTCNT_KEY      0x5A00 /* When WTCNT byte register written, you */
+                                     /* have to set the upper byte to 0x5A */
 
 /* Watchdog Timer Control/Status register - WTCSR */
-#define SH7750_WTCSR_REGOFS   0xC0000C	/* offset */
+#define SH7750_WTCSR_REGOFS   0xC0000C /* offset */
 #define SH7750_WTCSR          SH7750_P4_REG32(SH7750_WTCSR_REGOFS)
 #define SH7750_WTCSR_A7       SH7750_A7_REG32(SH7750_WTCSR_REGOFS)
-#define SH7750_WTCSR_KEY      0xA500	/* When WTCSR byte register written,
-					   you have to set the upper byte to
-					   0xA5 */
-#define SH7750_WTCSR_TME      0x80	/* Timer enable (1-upcount start) */
-#define SH7750_WTCSR_MODE     0x40	/* Timer Mode Select: */
-#define SH7750_WTCSR_MODE_WT  0x40	/*    Watchdog Timer Mode */
-#define SH7750_WTCSR_MODE_IT  0x00	/*    Interval Timer Mode */
-#define SH7750_WTCSR_RSTS     0x20	/* Reset Select: */
-#define SH7750_WTCSR_RST_MAN  0x20	/*    Manual Reset */
-#define SH7750_WTCSR_RST_PWR  0x00	/*    Power-on Reset */
-#define SH7750_WTCSR_WOVF     0x10	/* Watchdog Timer Overflow Flag */
-#define SH7750_WTCSR_IOVF     0x08	/* Interval Timer Overflow Flag */
-#define SH7750_WTCSR_CKS      0x07	/* Clock Select: */
-#define SH7750_WTCSR_CKS_DIV32   0x00	/*   1/32 of frequency divider 2 input */
-#define SH7750_WTCSR_CKS_DIV64   0x01	/*   1/64 */
-#define SH7750_WTCSR_CKS_DIV128  0x02	/*   1/128 */
-#define SH7750_WTCSR_CKS_DIV256  0x03	/*   1/256 */
-#define SH7750_WTCSR_CKS_DIV512  0x04	/*   1/512 */
-#define SH7750_WTCSR_CKS_DIV1024 0x05	/*   1/1024 */
-#define SH7750_WTCSR_CKS_DIV2048 0x06	/*   1/2048 */
-#define SH7750_WTCSR_CKS_DIV4096 0x07	/*   1/4096 */
+#define SH7750_WTCSR_KEY      0xA500 /* When WTCSR byte register written, you */
+                                     /* have to set the upper byte to 0xA5 */
+#define SH7750_WTCSR_TME      0x80 /* Timer enable (1-upcount start) */
+#define SH7750_WTCSR_MODE     0x40 /* Timer Mode Select: */
+#define SH7750_WTCSR_MODE_WT  0x40 /*    Watchdog Timer Mode */
+#define SH7750_WTCSR_MODE_IT  0x00 /*    Interval Timer Mode */
+#define SH7750_WTCSR_RSTS     0x20 /* Reset Select: */
+#define SH7750_WTCSR_RST_MAN  0x20 /*    Manual Reset */
+#define SH7750_WTCSR_RST_PWR  0x00 /*    Power-on Reset */
+#define SH7750_WTCSR_WOVF     0x10 /* Watchdog Timer Overflow Flag */
+#define SH7750_WTCSR_IOVF     0x08 /* Interval Timer Overflow Flag */
+#define SH7750_WTCSR_CKS      0x07 /* Clock Select: */
+#define SH7750_WTCSR_CKS_DIV32   0x00 /*   1/32 of frequency divider 2 input */
+#define SH7750_WTCSR_CKS_DIV64   0x01 /*   1/64 */
+#define SH7750_WTCSR_CKS_DIV128  0x02 /*   1/128 */
+#define SH7750_WTCSR_CKS_DIV256  0x03 /*   1/256 */
+#define SH7750_WTCSR_CKS_DIV512  0x04 /*   1/512 */
+#define SH7750_WTCSR_CKS_DIV1024 0x05 /*   1/1024 */
+#define SH7750_WTCSR_CKS_DIV2048 0x06 /*   1/2048 */
+#define SH7750_WTCSR_CKS_DIV4096 0x07 /*   1/4096 */
 
 /*
  * Real-Time Clock (RTC)
  */
 /* 64-Hz Counter Register (byte, read-only) - R64CNT */
-#define SH7750_R64CNT_REGOFS  0xC80000	/* offset */
+#define SH7750_R64CNT_REGOFS  0xC80000 /* offset */
 #define SH7750_R64CNT         SH7750_P4_REG32(SH7750_R64CNT_REGOFS)
 #define SH7750_R64CNT_A7      SH7750_A7_REG32(SH7750_R64CNT_REGOFS)
 
 /* Second Counter Register (byte, BCD-coded) - RSECCNT */
-#define SH7750_RSECCNT_REGOFS 0xC80004	/* offset */
+#define SH7750_RSECCNT_REGOFS 0xC80004 /* offset */
 #define SH7750_RSECCNT        SH7750_P4_REG32(SH7750_RSECCNT_REGOFS)
 #define SH7750_RSECCNT_A7     SH7750_A7_REG32(SH7750_RSECCNT_REGOFS)
 
 /* Minute Counter Register (byte, BCD-coded) - RMINCNT */
-#define SH7750_RMINCNT_REGOFS 0xC80008	/* offset */
+#define SH7750_RMINCNT_REGOFS 0xC80008 /* offset */
 #define SH7750_RMINCNT        SH7750_P4_REG32(SH7750_RMINCNT_REGOFS)
 #define SH7750_RMINCNT_A7     SH7750_A7_REG32(SH7750_RMINCNT_REGOFS)
 
 /* Hour Counter Register (byte, BCD-coded) - RHRCNT */
-#define SH7750_RHRCNT_REGOFS  0xC8000C	/* offset */
+#define SH7750_RHRCNT_REGOFS  0xC8000C /* offset */
 #define SH7750_RHRCNT         SH7750_P4_REG32(SH7750_RHRCNT_REGOFS)
 #define SH7750_RHRCNT_A7      SH7750_A7_REG32(SH7750_RHRCNT_REGOFS)
 
 /* Day-of-Week Counter Register (byte) - RWKCNT */
-#define SH7750_RWKCNT_REGOFS  0xC80010	/* offset */
+#define SH7750_RWKCNT_REGOFS  0xC80010 /* offset */
 #define SH7750_RWKCNT         SH7750_P4_REG32(SH7750_RWKCNT_REGOFS)
 #define SH7750_RWKCNT_A7      SH7750_A7_REG32(SH7750_RWKCNT_REGOFS)
 
-#define SH7750_RWKCNT_SUN     0	/* Sunday */
-#define SH7750_RWKCNT_MON     1	/* Monday */
-#define SH7750_RWKCNT_TUE     2	/* Tuesday */
-#define SH7750_RWKCNT_WED     3	/* Wednesday */
-#define SH7750_RWKCNT_THU     4	/* Thursday */
-#define SH7750_RWKCNT_FRI     5	/* Friday */
-#define SH7750_RWKCNT_SAT     6	/* Saturday */
+#define SH7750_RWKCNT_SUN     0 /* Sunday */
+#define SH7750_RWKCNT_MON     1 /* Monday */
+#define SH7750_RWKCNT_TUE     2 /* Tuesday */
+#define SH7750_RWKCNT_WED     3 /* Wednesday */
+#define SH7750_RWKCNT_THU     4 /* Thursday */
+#define SH7750_RWKCNT_FRI     5 /* Friday */
+#define SH7750_RWKCNT_SAT     6 /* Saturday */
 
 /* Day Counter Register (byte, BCD-coded) - RDAYCNT */
-#define SH7750_RDAYCNT_REGOFS 0xC80014	/* offset */
+#define SH7750_RDAYCNT_REGOFS 0xC80014 /* offset */
 #define SH7750_RDAYCNT        SH7750_P4_REG32(SH7750_RDAYCNT_REGOFS)
 #define SH7750_RDAYCNT_A7     SH7750_A7_REG32(SH7750_RDAYCNT_REGOFS)
 
 /* Month Counter Register (byte, BCD-coded) - RMONCNT */
-#define SH7750_RMONCNT_REGOFS 0xC80018	/* offset */
+#define SH7750_RMONCNT_REGOFS 0xC80018 /* offset */
 #define SH7750_RMONCNT        SH7750_P4_REG32(SH7750_RMONCNT_REGOFS)
 #define SH7750_RMONCNT_A7     SH7750_A7_REG32(SH7750_RMONCNT_REGOFS)
 
 /* Year Counter Register (half, BCD-coded) - RYRCNT */
-#define SH7750_RYRCNT_REGOFS  0xC8001C	/* offset */
+#define SH7750_RYRCNT_REGOFS  0xC8001C /* offset */
 #define SH7750_RYRCNT         SH7750_P4_REG32(SH7750_RYRCNT_REGOFS)
 #define SH7750_RYRCNT_A7      SH7750_A7_REG32(SH7750_RYRCNT_REGOFS)
 
 /* Second Alarm Register (byte, BCD-coded) - RSECAR */
-#define SH7750_RSECAR_REGOFS  0xC80020	/* offset */
+#define SH7750_RSECAR_REGOFS  0xC80020 /* offset */
 #define SH7750_RSECAR         SH7750_P4_REG32(SH7750_RSECAR_REGOFS)
 #define SH7750_RSECAR_A7      SH7750_A7_REG32(SH7750_RSECAR_REGOFS)
-#define SH7750_RSECAR_ENB     0x80	/* Second Alarm Enable */
+#define SH7750_RSECAR_ENB     0x80 /* Second Alarm Enable */
 
 /* Minute Alarm Register (byte, BCD-coded) - RMINAR */
-#define SH7750_RMINAR_REGOFS  0xC80024	/* offset */
+#define SH7750_RMINAR_REGOFS  0xC80024 /* offset */
 #define SH7750_RMINAR         SH7750_P4_REG32(SH7750_RMINAR_REGOFS)
 #define SH7750_RMINAR_A7      SH7750_A7_REG32(SH7750_RMINAR_REGOFS)
-#define SH7750_RMINAR_ENB     0x80	/* Minute Alarm Enable */
+#define SH7750_RMINAR_ENB     0x80 /* Minute Alarm Enable */
 
 /* Hour Alarm Register (byte, BCD-coded) - RHRAR */
-#define SH7750_RHRAR_REGOFS   0xC80028	/* offset */
+#define SH7750_RHRAR_REGOFS   0xC80028 /* offset */
 #define SH7750_RHRAR          SH7750_P4_REG32(SH7750_RHRAR_REGOFS)
 #define SH7750_RHRAR_A7       SH7750_A7_REG32(SH7750_RHRAR_REGOFS)
-#define SH7750_RHRAR_ENB      0x80	/* Hour Alarm Enable */
+#define SH7750_RHRAR_ENB      0x80 /* Hour Alarm Enable */
 
 /* Day-of-Week Alarm Register (byte) - RWKAR */
-#define SH7750_RWKAR_REGOFS   0xC8002C	/* offset */
+#define SH7750_RWKAR_REGOFS   0xC8002C /* offset */
 #define SH7750_RWKAR          SH7750_P4_REG32(SH7750_RWKAR_REGOFS)
 #define SH7750_RWKAR_A7       SH7750_A7_REG32(SH7750_RWKAR_REGOFS)
-#define SH7750_RWKAR_ENB      0x80	/* Day-of-week Alarm Enable */
+#define SH7750_RWKAR_ENB      0x80 /* Day-of-week Alarm Enable */
 
-#define SH7750_RWKAR_SUN      0	/* Sunday */
-#define SH7750_RWKAR_MON      1	/* Monday */
-#define SH7750_RWKAR_TUE      2	/* Tuesday */
-#define SH7750_RWKAR_WED      3	/* Wednesday */
-#define SH7750_RWKAR_THU      4	/* Thursday */
-#define SH7750_RWKAR_FRI      5	/* Friday */
-#define SH7750_RWKAR_SAT      6	/* Saturday */
+#define SH7750_RWKAR_SUN      0 /* Sunday */
+#define SH7750_RWKAR_MON      1 /* Monday */
+#define SH7750_RWKAR_TUE      2 /* Tuesday */
+#define SH7750_RWKAR_WED      3 /* Wednesday */
+#define SH7750_RWKAR_THU      4 /* Thursday */
+#define SH7750_RWKAR_FRI      5 /* Friday */
+#define SH7750_RWKAR_SAT      6 /* Saturday */
 
 /* Day Alarm Register (byte, BCD-coded) - RDAYAR */
-#define SH7750_RDAYAR_REGOFS  0xC80030	/* offset */
+#define SH7750_RDAYAR_REGOFS  0xC80030 /* offset */
 #define SH7750_RDAYAR         SH7750_P4_REG32(SH7750_RDAYAR_REGOFS)
 #define SH7750_RDAYAR_A7      SH7750_A7_REG32(SH7750_RDAYAR_REGOFS)
-#define SH7750_RDAYAR_ENB     0x80	/* Day Alarm Enable */
+#define SH7750_RDAYAR_ENB     0x80 /* Day Alarm Enable */
 
 /* Month Counter Register (byte, BCD-coded) - RMONAR */
-#define SH7750_RMONAR_REGOFS  0xC80034	/* offset */
+#define SH7750_RMONAR_REGOFS  0xC80034 /* offset */
 #define SH7750_RMONAR         SH7750_P4_REG32(SH7750_RMONAR_REGOFS)
 #define SH7750_RMONAR_A7      SH7750_A7_REG32(SH7750_RMONAR_REGOFS)
-#define SH7750_RMONAR_ENB     0x80	/* Month Alarm Enable */
+#define SH7750_RMONAR_ENB     0x80 /* Month Alarm Enable */
 
 /* RTC Control Register 1 (byte) - RCR1 */
-#define SH7750_RCR1_REGOFS    0xC80038	/* offset */
+#define SH7750_RCR1_REGOFS    0xC80038 /* offset */
 #define SH7750_RCR1           SH7750_P4_REG32(SH7750_RCR1_REGOFS)
 #define SH7750_RCR1_A7        SH7750_A7_REG32(SH7750_RCR1_REGOFS)
-#define SH7750_RCR1_CF        0x80	/* Carry Flag */
-#define SH7750_RCR1_CIE       0x10	/* Carry Interrupt Enable */
-#define SH7750_RCR1_AIE       0x08	/* Alarm Interrupt Enable */
-#define SH7750_RCR1_AF        0x01	/* Alarm Flag */
+#define SH7750_RCR1_CF        0x80 /* Carry Flag */
+#define SH7750_RCR1_CIE       0x10 /* Carry Interrupt Enable */
+#define SH7750_RCR1_AIE       0x08 /* Alarm Interrupt Enable */
+#define SH7750_RCR1_AF        0x01 /* Alarm Flag */
 
 /* RTC Control Register 2 (byte) - RCR2 */
-#define SH7750_RCR2_REGOFS    0xC8003C	/* offset */
+#define SH7750_RCR2_REGOFS    0xC8003C /* offset */
 #define SH7750_RCR2           SH7750_P4_REG32(SH7750_RCR2_REGOFS)
 #define SH7750_RCR2_A7        SH7750_A7_REG32(SH7750_RCR2_REGOFS)
-#define SH7750_RCR2_PEF        0x80	/* Periodic Interrupt Flag */
-#define SH7750_RCR2_PES        0x70	/* Periodic Interrupt Enable: */
-#define SH7750_RCR2_PES_DIS    0x00	/*   Periodic Interrupt Disabled */
-#define SH7750_RCR2_PES_DIV256 0x10	/*   Generated at 1/256 sec interval */
-#define SH7750_RCR2_PES_DIV64  0x20	/*   Generated at 1/64 sec interval */
-#define SH7750_RCR2_PES_DIV16  0x30	/*   Generated at 1/16 sec interval */
-#define SH7750_RCR2_PES_DIV4   0x40	/*   Generated at 1/4 sec interval */
-#define SH7750_RCR2_PES_DIV2   0x50	/*   Generated at 1/2 sec interval */
-#define SH7750_RCR2_PES_x1     0x60	/*   Generated at 1 sec interval */
-#define SH7750_RCR2_PES_x2     0x70	/*   Generated at 2 sec interval */
-#define SH7750_RCR2_RTCEN      0x08	/* RTC Crystal Oscillator is Operated */
-#define SH7750_RCR2_ADJ        0x04	/* 30-Second Adjastment */
-#define SH7750_RCR2_RESET      0x02	/* Frequency divider circuits are reset */
-#define SH7750_RCR2_START      0x01	/* 0 - sec, min, hr, day-of-week, month,
-					   year counters are stopped
-					   1 - sec, min, hr, day-of-week, month,
-					   year counters operate normally */
+#define SH7750_RCR2_PEF        0x80 /* Periodic Interrupt Flag */
+#define SH7750_RCR2_PES        0x70 /* Periodic Interrupt Enable: */
+#define SH7750_RCR2_PES_DIS    0x00 /*   Periodic Interrupt Disabled */
+#define SH7750_RCR2_PES_DIV256 0x10 /*   Generated at 1/256 sec interval */
+#define SH7750_RCR2_PES_DIV64  0x20 /*   Generated at 1/64 sec interval */
+#define SH7750_RCR2_PES_DIV16  0x30 /*   Generated at 1/16 sec interval */
+#define SH7750_RCR2_PES_DIV4   0x40 /*   Generated at 1/4 sec interval */
+#define SH7750_RCR2_PES_DIV2   0x50 /*   Generated at 1/2 sec interval */
+#define SH7750_RCR2_PES_x1     0x60 /*   Generated at 1 sec interval */
+#define SH7750_RCR2_PES_x2     0x70 /*   Generated at 2 sec interval */
+#define SH7750_RCR2_RTCEN      0x08 /* RTC Crystal Oscillator is Operated */
+#define SH7750_RCR2_ADJ        0x04 /* 30-Second Adjastment */
+#define SH7750_RCR2_RESET      0x02 /* Frequency divider circuits are reset */
+#define SH7750_RCR2_START      0x01 /* 0 - sec, min, hr, day-of-week, month, */
+                                    /*     year counters are stopped */
+                                    /* 1 - sec, min, hr, day-of-week, month, */
+                                    /*     year counters operate normally */
 /*
  * Bus State Controller - BSC
  */
 /* Bus Control Register 1 - BCR1 */
-#define SH7750_BCR1_REGOFS    0x800000	/* offset */
+#define SH7750_BCR1_REGOFS    0x800000 /* offset */
 #define SH7750_BCR1           SH7750_P4_REG32(SH7750_BCR1_REGOFS)
 #define SH7750_BCR1_A7        SH7750_A7_REG32(SH7750_BCR1_REGOFS)
-#define SH7750_BCR1_ENDIAN    0x80000000	/* Endianness (1 - little endian) */
-#define SH7750_BCR1_MASTER    0x40000000	/* Master/Slave mode (1-master) */
-#define SH7750_BCR1_A0MPX     0x20000000	/* Area 0 Memory Type (0-SRAM,1-MPX) */
-#define SH7750_BCR1_IPUP      0x02000000	/* Input Pin Pull-up Control:
-						   0 - pull-up resistor is on for
-						   control input pins
-						   1 - pull-up resistor is off */
-#define SH7750_BCR1_OPUP      0x01000000	/* Output Pin Pull-up Control:
-						   0 - pull-up resistor is on for
-						   control output pins
-						   1 - pull-up resistor is off */
-#define SH7750_BCR1_A1MBC     0x00200000	/* Area 1 SRAM Byte Control Mode:
-						   0 - Area 1 SRAM is set to
-						   normal mode
-						   1 - Area 1 SRAM is set to byte
-						   control mode */
-#define SH7750_BCR1_A4MBC     0x00100000	/* Area 4 SRAM Byte Control Mode:
-						   0 - Area 4 SRAM is set to
-						   normal mode
-						   1 - Area 4 SRAM is set to byte
-						   control mode */
-#define SH7750_BCR1_BREQEN    0x00080000	/* BREQ Enable:
-						   0 - External requests are  not
-						   accepted
-						   1 - External requests are
-						   accepted */
-#define SH7750_BCR1_PSHR      0x00040000	/* Partial Sharing Bit:
-						   0 - Master Mode
-						   1 - Partial-sharing Mode */
-#define SH7750_BCR1_MEMMPX    0x00020000	/* Area 1 to 6 MPX Interface:
-						   0 - SRAM/burst ROM interface
-						   1 - MPX interface */
-#define SH7750_BCR1_HIZMEM    0x00008000	/* High Impendance Control. Specifies
-						   the state of A[25:0], BS\, CSn\,
-						   RD/WR\, CE2A\, CE2B\ in standby
-						   mode and when bus is released:
-						   0 - signals go to High-Z mode
-						   1 - signals driven */
-#define SH7750_BCR1_HIZCNT    0x00004000	/* High Impendance Control. Specifies
-						   the state of the RAS\, RAS2\, WEn\,
-						   CASn\, DQMn, RD\, CASS\, FRAME\,
-						   RD2\ signals in standby mode and
-						   when bus is released:
-						   0 - signals go to High-Z mode
-						   1 - signals driven */
-#define SH7750_BCR1_A0BST     0x00003800	/* Area 0 Burst ROM Control */
-#define SH7750_BCR1_A0BST_SRAM    0x0000	/*   Area 0 accessed as SRAM i/f */
-#define SH7750_BCR1_A0BST_ROM4    0x0800	/*   Area 0 accessed as burst ROM
-						   interface, 4 cosequtive access */
-#define SH7750_BCR1_A0BST_ROM8    0x1000	/*   Area 0 accessed as burst ROM
-						   interface, 8 cosequtive access */
-#define SH7750_BCR1_A0BST_ROM16   0x1800	/*   Area 0 accessed as burst ROM
-						   interface, 16 cosequtive access */
-#define SH7750_BCR1_A0BST_ROM32   0x2000	/*   Area 0 accessed as burst ROM
-						   interface, 32 cosequtive access */
-
-#define SH7750_BCR1_A5BST     0x00000700	/* Area 5 Burst ROM Control */
-#define SH7750_BCR1_A5BST_SRAM    0x0000	/*   Area 5 accessed as SRAM i/f */
-#define SH7750_BCR1_A5BST_ROM4    0x0100	/*   Area 5 accessed as burst ROM
-						   interface, 4 cosequtive access */
-#define SH7750_BCR1_A5BST_ROM8    0x0200	/*   Area 5 accessed as burst ROM
-						   interface, 8 cosequtive access */
-#define SH7750_BCR1_A5BST_ROM16   0x0300	/*   Area 5 accessed as burst ROM
-						   interface, 16 cosequtive access */
-#define SH7750_BCR1_A5BST_ROM32   0x0400	/*   Area 5 accessed as burst ROM
-						   interface, 32 cosequtive access */
-
-#define SH7750_BCR1_A6BST     0x000000E0	/* Area 6 Burst ROM Control */
-#define SH7750_BCR1_A6BST_SRAM    0x0000	/*   Area 6 accessed as SRAM i/f */
-#define SH7750_BCR1_A6BST_ROM4    0x0020	/*   Area 6 accessed as burst ROM
-						   interface, 4 cosequtive access */
-#define SH7750_BCR1_A6BST_ROM8    0x0040	/*   Area 6 accessed as burst ROM
-						   interface, 8 cosequtive access */
-#define SH7750_BCR1_A6BST_ROM16   0x0060	/*   Area 6 accessed as burst ROM
-						   interface, 16 cosequtive access */
-#define SH7750_BCR1_A6BST_ROM32   0x0080	/*   Area 6 accessed as burst ROM
-						   interface, 32 cosequtive access */
-
-#define SH7750_BCR1_DRAMTP        0x001C	/* Area 2 and 3 Memory Type */
-#define SH7750_BCR1_DRAMTP_2SRAM_3SRAM   0x0000	/* Area 2 and 3 are SRAM or MPX
-						   interface. */
-#define SH7750_BCR1_DRAMTP_2SRAM_3SDRAM  0x0008	/* Area 2 - SRAM/MPX, Area 3 -
-						   synchronous DRAM */
-#define SH7750_BCR1_DRAMTP_2SDRAM_3SDRAM 0x000C	/* Area 2 and 3 are synchronous
-						   DRAM interface */
-#define SH7750_BCR1_DRAMTP_2SRAM_3DRAM   0x0010	/* Area 2 - SRAM/MPX, Area 3 -
-						   DRAM interface */
-#define SH7750_BCR1_DRAMTP_2DRAM_3DRAM   0x0014	/* Area 2 and 3 are DRAM
-						   interface */
-
-#define SH7750_BCR1_A56PCM    0x00000001	/* Area 5 and 6 Bus Type:
-						   0 - SRAM interface
-						   1 - PCMCIA interface */
+#define SH7750_BCR1_ENDIAN    0x80000000 /* Endianness (1 - little endian) */
+#define SH7750_BCR1_MASTER    0x40000000 /* Master/Slave mode (1-master) */
+#define SH7750_BCR1_A0MPX     0x20000000 /* Area 0 Memory Type (0-SRAM,1-MPX) */
+#define SH7750_BCR1_IPUP      0x02000000 /* Input Pin Pull-up Control: */
+                                         /*   0 - pull-up resistor is on for */
+                                         /*       control input pins */
+                                         /*   1 - pull-up resistor is off */
+#define SH7750_BCR1_OPUP      0x01000000 /* Output Pin Pull-up Control: */
+                                         /*   0 - pull-up resistor is on for */
+                                         /*       control output pins */
+                                         /*   1 - pull-up resistor is off */
+#define SH7750_BCR1_A1MBC     0x00200000 /* Area 1 SRAM Byte Control Mode: */
+                                         /*   0 - Area 1 SRAM is set to */
+                                         /*       normal mode */
+                                         /*   1 - Area 1 SRAM is set to byte */
+                                         /*       control mode */
+#define SH7750_BCR1_A4MBC     0x00100000 /* Area 4 SRAM Byte Control Mode: */
+                                         /*   0 - Area 4 SRAM is set to */
+                                         /*       normal mode */
+                                         /*   1 - Area 4 SRAM is set to byte */
+                                         /*       control mode */
+#define SH7750_BCR1_BREQEN    0x00080000 /* BREQ Enable: */
+                                         /*   0 - External requests are  not */
+                                         /*       accepted */
+                                         /*   1 - External requests are */
+                                         /*       accepted */
+#define SH7750_BCR1_PSHR      0x00040000 /* Partial Sharing Bit: */
+                                         /*   0 - Master Mode */
+                                         /*   1 - Partial-sharing Mode */
+#define SH7750_BCR1_MEMMPX    0x00020000 /* Area 1 to 6 MPX Interface: */
+                                         /*   0 - SRAM/burst ROM interface */
+                                         /*   1 - MPX interface */
+#define SH7750_BCR1_HIZMEM    0x00008000 /* High Impendance Control. */
+                                         /*   Specifies the state of A[25:0], */
+                                         /*   BS\, CSn\, RD/WR\, CE2A\, CE2B\ */
+                                         /*   in standby mode and when bus is */
+                                         /*   released: */
+                                         /*   0 - signals go to High-Z mode */
+                                         /*   1 - signals driven */
+#define SH7750_BCR1_HIZCNT    0x00004000 /* High Impendance Control. */
+                                         /*   Specifies the state of the */
+                                         /*   RAS\, RAS2\, WEn\, CASn\, DQMn, */
+                                         /*   RD\, CASS\, FRAME\, RD2\ */
+                                         /*   signals in standby mode and */
+                                         /* when bus is released: */
+                                         /*   0 - signals go to High-Z mode */
+                                         /*   1 - signals driven */
+#define SH7750_BCR1_A0BST     0x00003800 /* Area 0 Burst ROM Control */
+#define SH7750_BCR1_A0BST_SRAM    0x0000 /*   Area 0 accessed as SRAM i/f */
+#define SH7750_BCR1_A0BST_ROM4    0x0800 /*   Area 0 accessed as burst ROM */
+                                         /*   interface, 4 cosequtive access */
+#define SH7750_BCR1_A0BST_ROM8    0x1000 /*   Area 0 accessed as burst ROM */
+                                         /*   interface, 8 cosequtive access */
+#define SH7750_BCR1_A0BST_ROM16   0x1800 /*   Area 0 accessed as burst ROM */
+                                         /*   interface, 16 cosequtive access */
+#define SH7750_BCR1_A0BST_ROM32   0x2000 /*   Area 0 accessed as burst ROM */
+                                         /*   interface, 32 cosequtive access */
+
+#define SH7750_BCR1_A5BST     0x00000700 /* Area 5 Burst ROM Control */
+#define SH7750_BCR1_A5BST_SRAM    0x0000 /*   Area 5 accessed as SRAM i/f */
+#define SH7750_BCR1_A5BST_ROM4    0x0100 /*   Area 5 accessed as burst ROM */
+                                         /*   interface, 4 cosequtive access */
+#define SH7750_BCR1_A5BST_ROM8    0x0200 /*   Area 5 accessed as burst ROM */
+                                         /*   interface, 8 cosequtive access */
+#define SH7750_BCR1_A5BST_ROM16   0x0300 /*   Area 5 accessed as burst ROM */
+                                         /*   interface, 16 cosequtive access */
+#define SH7750_BCR1_A5BST_ROM32   0x0400 /*   Area 5 accessed as burst ROM */
+                                         /*   interface, 32 cosequtive access */
+
+#define SH7750_BCR1_A6BST     0x000000E0 /* Area 6 Burst ROM Control */
+#define SH7750_BCR1_A6BST_SRAM    0x0000 /*   Area 6 accessed as SRAM i/f */
+#define SH7750_BCR1_A6BST_ROM4    0x0020 /*   Area 6 accessed as burst ROM */
+                                         /*   interface, 4 cosequtive access */
+#define SH7750_BCR1_A6BST_ROM8    0x0040 /*   Area 6 accessed as burst ROM */
+                                         /*   interface, 8 cosequtive access */
+#define SH7750_BCR1_A6BST_ROM16   0x0060 /*   Area 6 accessed as burst ROM */
+                                         /*   interface, 16 cosequtive access */
+#define SH7750_BCR1_A6BST_ROM32   0x0080 /*   Area 6 accessed as burst ROM */
+                                         /*   interface, 32 cosequtive access */
+
+#define SH7750_BCR1_DRAMTP        0x001C /* Area 2 and 3 Memory Type */
+#define SH7750_BCR1_DRAMTP_2SRAM_3SRAM   0x0000 /* Area 2 and 3 are SRAM or */
+                                                /* MPX interface. */
+#define SH7750_BCR1_DRAMTP_2SRAM_3SDRAM  0x0008 /* Area 2 - SRAM/MPX, Area 3 */
+                                                /* synchronous DRAM */
+#define SH7750_BCR1_DRAMTP_2SDRAM_3SDRAM 0x000C /* Area 2 and 3 are */
+                                                /* synchronous DRAM interface */
+#define SH7750_BCR1_DRAMTP_2SRAM_3DRAM   0x0010 /* Area 2 - SRAM/MPX, Area 3 */
+                                                /* DRAM interface */
+#define SH7750_BCR1_DRAMTP_2DRAM_3DRAM   0x0014 /* Area 2 and 3 are DRAM */
+                                                /* interface */
+
+#define SH7750_BCR1_A56PCM    0x00000001 /* Area 5 and 6 Bus Type: */
+                                         /*   0 - SRAM interface */
+                                         /*   1 - PCMCIA interface */
 
 /* Bus Control Register 2 (half) - BCR2 */
-#define SH7750_BCR2_REGOFS    0x800004	/* offset */
+#define SH7750_BCR2_REGOFS    0x800004 /* offset */
 #define SH7750_BCR2           SH7750_P4_REG32(SH7750_BCR2_REGOFS)
 #define SH7750_BCR2_A7        SH7750_A7_REG32(SH7750_BCR2_REGOFS)
 
-#define SH7750_BCR2_A0SZ      0xC000	/* Area 0 Bus Width */
+#define SH7750_BCR2_A0SZ      0xC000 /* Area 0 Bus Width */
 #define SH7750_BCR2_A0SZ_S    14
-#define SH7750_BCR2_A6SZ      0x3000	/* Area 6 Bus Width */
+#define SH7750_BCR2_A6SZ      0x3000 /* Area 6 Bus Width */
 #define SH7750_BCR2_A6SZ_S    12
-#define SH7750_BCR2_A5SZ      0x0C00	/* Area 5 Bus Width */
+#define SH7750_BCR2_A5SZ      0x0C00 /* Area 5 Bus Width */
 #define SH7750_BCR2_A5SZ_S    10
-#define SH7750_BCR2_A4SZ      0x0300	/* Area 4 Bus Width */
+#define SH7750_BCR2_A4SZ      0x0300 /* Area 4 Bus Width */
 #define SH7750_BCR2_A4SZ_S    8
-#define SH7750_BCR2_A3SZ      0x00C0	/* Area 3 Bus Width */
+#define SH7750_BCR2_A3SZ      0x00C0 /* Area 3 Bus Width */
 #define SH7750_BCR2_A3SZ_S    6
-#define SH7750_BCR2_A2SZ      0x0030	/* Area 2 Bus Width */
+#define SH7750_BCR2_A2SZ      0x0030 /* Area 2 Bus Width */
 #define SH7750_BCR2_A2SZ_S    4
-#define SH7750_BCR2_A1SZ      0x000C	/* Area 1 Bus Width */
+#define SH7750_BCR2_A1SZ      0x000C /* Area 1 Bus Width */
 #define SH7750_BCR2_A1SZ_S    2
-#define SH7750_BCR2_SZ_64     0	/* 64 bits */
-#define SH7750_BCR2_SZ_8      1	/* 8 bits */
-#define SH7750_BCR2_SZ_16     2	/* 16 bits */
-#define SH7750_BCR2_SZ_32     3	/* 32 bits */
-#define SH7750_BCR2_PORTEN    0x0001	/* Port Function Enable :
-					   0 - D51-D32 are not used as a port
-					   1 - D51-D32 are used as a port */
+#define SH7750_BCR2_SZ_64     0 /* 64 bits */
+#define SH7750_BCR2_SZ_8      1 /* 8 bits */
+#define SH7750_BCR2_SZ_16     2 /* 16 bits */
+#define SH7750_BCR2_SZ_32     3 /* 32 bits */
+#define SH7750_BCR2_PORTEN    0x0001 /* Port Function Enable */
+                                     /* 0 - D51-D32 are not used as a port */
+                                     /* 1 - D51-D32 are used as a port */
 
 /* Wait Control Register 1 - WCR1 */
-#define SH7750_WCR1_REGOFS    0x800008	/* offset */
+#define SH7750_WCR1_REGOFS    0x800008 /* offset */
 #define SH7750_WCR1           SH7750_P4_REG32(SH7750_WCR1_REGOFS)
 #define SH7750_WCR1_A7        SH7750_A7_REG32(SH7750_WCR1_REGOFS)
-#define SH7750_WCR1_DMAIW     0x70000000	/* DACK Device Inter-Cycle Idle
-						   specification */
+#define SH7750_WCR1_DMAIW     0x70000000 /* DACK Device Inter-Cycle Idle */
+                                         /*   specification */
 #define SH7750_WCR1_DMAIW_S   28
-#define SH7750_WCR1_A6IW      0x07000000	/* Area 6 Inter-Cycle Idle spec. */
+#define SH7750_WCR1_A6IW      0x07000000 /* Area 6 Inter-Cycle Idle spec. */
 #define SH7750_WCR1_A6IW_S    24
-#define SH7750_WCR1_A5IW      0x00700000	/* Area 5 Inter-Cycle Idle spec. */
+#define SH7750_WCR1_A5IW      0x00700000 /* Area 5 Inter-Cycle Idle spec. */
 #define SH7750_WCR1_A5IW_S    20
-#define SH7750_WCR1_A4IW      0x00070000	/* Area 4 Inter-Cycle Idle spec. */
+#define SH7750_WCR1_A4IW      0x00070000 /* Area 4 Inter-Cycle Idle spec. */
 #define SH7750_WCR1_A4IW_S    16
-#define SH7750_WCR1_A3IW      0x00007000	/* Area 3 Inter-Cycle Idle spec. */
+#define SH7750_WCR1_A3IW      0x00007000 /* Area 3 Inter-Cycle Idle spec. */
 #define SH7750_WCR1_A3IW_S    12
-#define SH7750_WCR1_A2IW      0x00000700	/* Area 2 Inter-Cycle Idle spec. */
+#define SH7750_WCR1_A2IW      0x00000700 /* Area 2 Inter-Cycle Idle spec. */
 #define SH7750_WCR1_A2IW_S    8
-#define SH7750_WCR1_A1IW      0x00000070	/* Area 1 Inter-Cycle Idle spec. */
+#define SH7750_WCR1_A1IW      0x00000070 /* Area 1 Inter-Cycle Idle spec. */
 #define SH7750_WCR1_A1IW_S    4
-#define SH7750_WCR1_A0IW      0x00000007	/* Area 0 Inter-Cycle Idle spec. */
+#define SH7750_WCR1_A0IW      0x00000007 /* Area 0 Inter-Cycle Idle spec. */
 #define SH7750_WCR1_A0IW_S    0
 
 /* Wait Control Register 2 - WCR2 */
-#define SH7750_WCR2_REGOFS    0x80000C	/* offset */
+#define SH7750_WCR2_REGOFS    0x80000C /* offset */
 #define SH7750_WCR2           SH7750_P4_REG32(SH7750_WCR2_REGOFS)
 #define SH7750_WCR2_A7        SH7750_A7_REG32(SH7750_WCR2_REGOFS)
 
-#define SH7750_WCR2_A6W       0xE0000000	/* Area 6 Wait Control */
+#define SH7750_WCR2_A6W       0xE0000000 /* Area 6 Wait Control */
 #define SH7750_WCR2_A6W_S     29
-#define SH7750_WCR2_A6B       0x1C000000	/* Area 6 Burst Pitch */
+#define SH7750_WCR2_A6B       0x1C000000 /* Area 6 Burst Pitch */
 #define SH7750_WCR2_A6B_S     26
-#define SH7750_WCR2_A5W       0x03800000	/* Area 5 Wait Control */
+#define SH7750_WCR2_A5W       0x03800000 /* Area 5 Wait Control */
 #define SH7750_WCR2_A5W_S     23
-#define SH7750_WCR2_A5B       0x00700000	/* Area 5 Burst Pitch */
+#define SH7750_WCR2_A5B       0x00700000 /* Area 5 Burst Pitch */
 #define SH7750_WCR2_A5B_S     20
-#define SH7750_WCR2_A4W       0x000E0000	/* Area 4 Wait Control */
+#define SH7750_WCR2_A4W       0x000E0000 /* Area 4 Wait Control */
 #define SH7750_WCR2_A4W_S     17
-#define SH7750_WCR2_A3W       0x0000E000	/* Area 3 Wait Control */
+#define SH7750_WCR2_A3W       0x0000E000 /* Area 3 Wait Control */
 #define SH7750_WCR2_A3W_S     13
-#define SH7750_WCR2_A2W       0x00000E00	/* Area 2 Wait Control */
+#define SH7750_WCR2_A2W       0x00000E00 /* Area 2 Wait Control */
 #define SH7750_WCR2_A2W_S     9
-#define SH7750_WCR2_A1W       0x000001C0	/* Area 1 Wait Control */
+#define SH7750_WCR2_A1W       0x000001C0 /* Area 1 Wait Control */
 #define SH7750_WCR2_A1W_S     6
-#define SH7750_WCR2_A0W       0x00000038	/* Area 0 Wait Control */
+#define SH7750_WCR2_A0W       0x00000038 /* Area 0 Wait Control */
 #define SH7750_WCR2_A0W_S     3
-#define SH7750_WCR2_A0B       0x00000007	/* Area 0 Burst Pitch */
+#define SH7750_WCR2_A0B       0x00000007 /* Area 0 Burst Pitch */
 #define SH7750_WCR2_A0B_S     0
 
-#define SH7750_WCR2_WS0       0	/* 0 wait states inserted */
-#define SH7750_WCR2_WS1       1	/* 1 wait states inserted */
-#define SH7750_WCR2_WS2       2	/* 2 wait states inserted */
-#define SH7750_WCR2_WS3       3	/* 3 wait states inserted */
-#define SH7750_WCR2_WS6       4	/* 6 wait states inserted */
-#define SH7750_WCR2_WS9       5	/* 9 wait states inserted */
-#define SH7750_WCR2_WS12      6	/* 12 wait states inserted */
-#define SH7750_WCR2_WS15      7	/* 15 wait states inserted */
-
-#define SH7750_WCR2_BPWS0     0	/* 0 wait states inserted from 2nd access */
-#define SH7750_WCR2_BPWS1     1	/* 1 wait states inserted from 2nd access */
-#define SH7750_WCR2_BPWS2     2	/* 2 wait states inserted from 2nd access */
-#define SH7750_WCR2_BPWS3     3	/* 3 wait states inserted from 2nd access */
-#define SH7750_WCR2_BPWS4     4	/* 4 wait states inserted from 2nd access */
-#define SH7750_WCR2_BPWS5     5	/* 5 wait states inserted from 2nd access */
-#define SH7750_WCR2_BPWS6     6	/* 6 wait states inserted from 2nd access */
-#define SH7750_WCR2_BPWS7     7	/* 7 wait states inserted from 2nd access */
+#define SH7750_WCR2_WS0       0 /* 0 wait states inserted */
+#define SH7750_WCR2_WS1       1 /* 1 wait states inserted */
+#define SH7750_WCR2_WS2       2 /* 2 wait states inserted */
+#define SH7750_WCR2_WS3       3 /* 3 wait states inserted */
+#define SH7750_WCR2_WS6       4 /* 6 wait states inserted */
+#define SH7750_WCR2_WS9       5 /* 9 wait states inserted */
+#define SH7750_WCR2_WS12      6 /* 12 wait states inserted */
+#define SH7750_WCR2_WS15      7 /* 15 wait states inserted */
+
+#define SH7750_WCR2_BPWS0     0 /* 0 wait states inserted from 2nd access */
+#define SH7750_WCR2_BPWS1     1 /* 1 wait states inserted from 2nd access */
+#define SH7750_WCR2_BPWS2     2 /* 2 wait states inserted from 2nd access */
+#define SH7750_WCR2_BPWS3     3 /* 3 wait states inserted from 2nd access */
+#define SH7750_WCR2_BPWS4     4 /* 4 wait states inserted from 2nd access */
+#define SH7750_WCR2_BPWS5     5 /* 5 wait states inserted from 2nd access */
+#define SH7750_WCR2_BPWS6     6 /* 6 wait states inserted from 2nd access */
+#define SH7750_WCR2_BPWS7     7 /* 7 wait states inserted from 2nd access */
 
 /* DRAM CAS\ Assertion Delay (area 3,2) */
-#define SH7750_WCR2_DRAM_CAS_ASW1   0	/* 1 cycle */
-#define SH7750_WCR2_DRAM_CAS_ASW2   1	/* 2 cycles */
-#define SH7750_WCR2_DRAM_CAS_ASW3   2	/* 3 cycles */
-#define SH7750_WCR2_DRAM_CAS_ASW4   3	/* 4 cycles */
-#define SH7750_WCR2_DRAM_CAS_ASW7   4	/* 7 cycles */
-#define SH7750_WCR2_DRAM_CAS_ASW10  5	/* 10 cycles */
-#define SH7750_WCR2_DRAM_CAS_ASW13  6	/* 13 cycles */
-#define SH7750_WCR2_DRAM_CAS_ASW16  7	/* 16 cycles */
+#define SH7750_WCR2_DRAM_CAS_ASW1   0 /* 1 cycle */
+#define SH7750_WCR2_DRAM_CAS_ASW2   1 /* 2 cycles */
+#define SH7750_WCR2_DRAM_CAS_ASW3   2 /* 3 cycles */
+#define SH7750_WCR2_DRAM_CAS_ASW4   3 /* 4 cycles */
+#define SH7750_WCR2_DRAM_CAS_ASW7   4 /* 7 cycles */
+#define SH7750_WCR2_DRAM_CAS_ASW10  5 /* 10 cycles */
+#define SH7750_WCR2_DRAM_CAS_ASW13  6 /* 13 cycles */
+#define SH7750_WCR2_DRAM_CAS_ASW16  7 /* 16 cycles */
 
 /* SDRAM CAS\ Latency Cycles */
-#define SH7750_WCR2_SDRAM_CAS_LAT1  1	/* 1 cycle */
-#define SH7750_WCR2_SDRAM_CAS_LAT2  2	/* 2 cycles */
-#define SH7750_WCR2_SDRAM_CAS_LAT3  3	/* 3 cycles */
-#define SH7750_WCR2_SDRAM_CAS_LAT4  4	/* 4 cycles */
-#define SH7750_WCR2_SDRAM_CAS_LAT5  5	/* 5 cycles */
+#define SH7750_WCR2_SDRAM_CAS_LAT1  1 /* 1 cycle */
+#define SH7750_WCR2_SDRAM_CAS_LAT2  2 /* 2 cycles */
+#define SH7750_WCR2_SDRAM_CAS_LAT3  3 /* 3 cycles */
+#define SH7750_WCR2_SDRAM_CAS_LAT4  4 /* 4 cycles */
+#define SH7750_WCR2_SDRAM_CAS_LAT5  5 /* 5 cycles */
 
 /* Wait Control Register 3 - WCR3 */
-#define SH7750_WCR3_REGOFS    0x800010	/* offset */
+#define SH7750_WCR3_REGOFS    0x800010 /* offset */
 #define SH7750_WCR3           SH7750_P4_REG32(SH7750_WCR3_REGOFS)
 #define SH7750_WCR3_A7        SH7750_A7_REG32(SH7750_WCR3_REGOFS)
 
-#define SH7750_WCR3_A6S       0x04000000	/* Area 6 Write Strobe Setup time */
-#define SH7750_WCR3_A6H       0x03000000	/* Area 6 Data Hold Time */
+#define SH7750_WCR3_A6S       0x04000000 /* Area 6 Write Strobe Setup time */
+#define SH7750_WCR3_A6H       0x03000000 /* Area 6 Data Hold Time */
 #define SH7750_WCR3_A6H_S     24
-#define SH7750_WCR3_A5S       0x00400000	/* Area 5 Write Strobe Setup time */
-#define SH7750_WCR3_A5H       0x00300000	/* Area 5 Data Hold Time */
+#define SH7750_WCR3_A5S       0x00400000 /* Area 5 Write Strobe Setup time */
+#define SH7750_WCR3_A5H       0x00300000 /* Area 5 Data Hold Time */
 #define SH7750_WCR3_A5H_S     20
-#define SH7750_WCR3_A4S       0x00040000	/* Area 4 Write Strobe Setup time */
-#define SH7750_WCR3_A4H       0x00030000	/* Area 4 Data Hold Time */
+#define SH7750_WCR3_A4S       0x00040000 /* Area 4 Write Strobe Setup time */
+#define SH7750_WCR3_A4H       0x00030000 /* Area 4 Data Hold Time */
 #define SH7750_WCR3_A4H_S     16
-#define SH7750_WCR3_A3S       0x00004000	/* Area 3 Write Strobe Setup time */
-#define SH7750_WCR3_A3H       0x00003000	/* Area 3 Data Hold Time */
+#define SH7750_WCR3_A3S       0x00004000 /* Area 3 Write Strobe Setup time */
+#define SH7750_WCR3_A3H       0x00003000 /* Area 3 Data Hold Time */
 #define SH7750_WCR3_A3H_S     12
-#define SH7750_WCR3_A2S       0x00000400	/* Area 2 Write Strobe Setup time */
-#define SH7750_WCR3_A2H       0x00000300	/* Area 2 Data Hold Time */
+#define SH7750_WCR3_A2S       0x00000400 /* Area 2 Write Strobe Setup time */
+#define SH7750_WCR3_A2H       0x00000300 /* Area 2 Data Hold Time */
 #define SH7750_WCR3_A2H_S     8
-#define SH7750_WCR3_A1S       0x00000040	/* Area 1 Write Strobe Setup time */
-#define SH7750_WCR3_A1H       0x00000030	/* Area 1 Data Hold Time */
+#define SH7750_WCR3_A1S       0x00000040 /* Area 1 Write Strobe Setup time */
+#define SH7750_WCR3_A1H       0x00000030 /* Area 1 Data Hold Time */
 #define SH7750_WCR3_A1H_S     4
-#define SH7750_WCR3_A0S       0x00000004	/* Area 0 Write Strobe Setup time */
-#define SH7750_WCR3_A0H       0x00000003	/* Area 0 Data Hold Time */
+#define SH7750_WCR3_A0S       0x00000004 /* Area 0 Write Strobe Setup time */
+#define SH7750_WCR3_A0H       0x00000003 /* Area 0 Data Hold Time */
 #define SH7750_WCR3_A0H_S     0
 
-#define SH7750_WCR3_DHWS_0    0	/* 0 wait states data hold time */
-#define SH7750_WCR3_DHWS_1    1	/* 1 wait states data hold time */
-#define SH7750_WCR3_DHWS_2    2	/* 2 wait states data hold time */
-#define SH7750_WCR3_DHWS_3    3	/* 3 wait states data hold time */
+#define SH7750_WCR3_DHWS_0    0 /* 0 wait states data hold time */
+#define SH7750_WCR3_DHWS_1    1 /* 1 wait states data hold time */
+#define SH7750_WCR3_DHWS_2    2 /* 2 wait states data hold time */
+#define SH7750_WCR3_DHWS_3    3 /* 3 wait states data hold time */
 
-#define SH7750_MCR_REGOFS     0x800014	/* offset */
+#define SH7750_MCR_REGOFS     0x800014 /* offset */
 #define SH7750_MCR            SH7750_P4_REG32(SH7750_MCR_REGOFS)
 #define SH7750_MCR_A7         SH7750_A7_REG32(SH7750_MCR_REGOFS)
 
-#define SH7750_MCR_RASD       0x80000000	/* RAS Down mode */
-#define SH7750_MCR_MRSET      0x40000000	/* SDRAM Mode Register Set */
-#define SH7750_MCR_PALL       0x00000000	/* SDRAM Precharge All cmd. Mode */
-#define SH7750_MCR_TRC        0x38000000	/* RAS Precharge Time at End of
-						   Refresh: */
-#define SH7750_MCR_TRC_0      0x00000000	/*    0 */
-#define SH7750_MCR_TRC_3      0x08000000	/*    3 */
-#define SH7750_MCR_TRC_6      0x10000000	/*    6 */
-#define SH7750_MCR_TRC_9      0x18000000	/*    9 */
-#define SH7750_MCR_TRC_12     0x20000000	/*    12 */
-#define SH7750_MCR_TRC_15     0x28000000	/*    15 */
-#define SH7750_MCR_TRC_18     0x30000000	/*    18 */
-#define SH7750_MCR_TRC_21     0x38000000	/*    21 */
-
-#define SH7750_MCR_TCAS       0x00800000	/* CAS Negation Period */
-#define SH7750_MCR_TCAS_1     0x00000000	/*    1 */
-#define SH7750_MCR_TCAS_2     0x00800000	/*    2 */
-
-#define SH7750_MCR_TPC        0x00380000	/* DRAM: RAS Precharge Period
-						   SDRAM: minimum number of cycles
-						   until the next bank active cmd
-						   is output after precharging */
+#define SH7750_MCR_RASD       0x80000000 /* RAS Down mode */
+#define SH7750_MCR_MRSET      0x40000000 /* SDRAM Mode Register Set */
+#define SH7750_MCR_PALL       0x00000000 /* SDRAM Precharge All cmd. Mode */
+#define SH7750_MCR_TRC        0x38000000 /* RAS Precharge Time at End of */
+                                         /* Refresh: */
+#define SH7750_MCR_TRC_0      0x00000000 /*    0 */
+#define SH7750_MCR_TRC_3      0x08000000 /*    3 */
+#define SH7750_MCR_TRC_6      0x10000000 /*    6 */
+#define SH7750_MCR_TRC_9      0x18000000 /*    9 */
+#define SH7750_MCR_TRC_12     0x20000000 /*    12 */
+#define SH7750_MCR_TRC_15     0x28000000 /*    15 */
+#define SH7750_MCR_TRC_18     0x30000000 /*    18 */
+#define SH7750_MCR_TRC_21     0x38000000 /*    21 */
+
+#define SH7750_MCR_TCAS       0x00800000 /* CAS Negation Period */
+#define SH7750_MCR_TCAS_1     0x00000000 /*    1 */
+#define SH7750_MCR_TCAS_2     0x00800000 /*    2 */
+
+#define SH7750_MCR_TPC        0x00380000 /* DRAM: RAS Precharge Period */
+                                         /* SDRAM: minimum number of cycles */
+                                         /* until the next bank active cmd */
+                                         /* is output after precharging */
 #define SH7750_MCR_TPC_S      19
-#define SH7750_MCR_TPC_SDRAM_1 0x00000000	/* 1 cycle */
-#define SH7750_MCR_TPC_SDRAM_2 0x00080000	/* 2 cycles */
-#define SH7750_MCR_TPC_SDRAM_3 0x00100000	/* 3 cycles */
-#define SH7750_MCR_TPC_SDRAM_4 0x00180000	/* 4 cycles */
-#define SH7750_MCR_TPC_SDRAM_5 0x00200000	/* 5 cycles */
-#define SH7750_MCR_TPC_SDRAM_6 0x00280000	/* 6 cycles */
-#define SH7750_MCR_TPC_SDRAM_7 0x00300000	/* 7 cycles */
-#define SH7750_MCR_TPC_SDRAM_8 0x00380000	/* 8 cycles */
-
-#define SH7750_MCR_RCD        0x00030000	/* DRAM: RAS-CAS Assertion Delay time
-						   SDRAM: bank active-read/write cmd
-						   delay time */
-#define SH7750_MCR_RCD_DRAM_2  0x00000000	/* DRAM delay 2 clocks */
-#define SH7750_MCR_RCD_DRAM_3  0x00010000	/* DRAM delay 3 clocks */
-#define SH7750_MCR_RCD_DRAM_4  0x00020000	/* DRAM delay 4 clocks */
-#define SH7750_MCR_RCD_DRAM_5  0x00030000	/* DRAM delay 5 clocks */
-#define SH7750_MCR_RCD_SDRAM_2 0x00010000	/* DRAM delay 2 clocks */
-#define SH7750_MCR_RCD_SDRAM_3 0x00020000	/* DRAM delay 3 clocks */
-#define SH7750_MCR_RCD_SDRAM_4 0x00030000	/* DRAM delay 4 clocks */
-
-#define SH7750_MCR_TRWL       0x0000E000	/* SDRAM Write Precharge Delay */
-#define SH7750_MCR_TRWL_1     0x00000000	/*    1 */
-#define SH7750_MCR_TRWL_2     0x00002000	/*    2 */
-#define SH7750_MCR_TRWL_3     0x00004000	/*    3 */
-#define SH7750_MCR_TRWL_4     0x00006000	/*    4 */
-#define SH7750_MCR_TRWL_5     0x00008000	/*    5 */
-
-#define SH7750_MCR_TRAS       0x00001C00	/* DRAM: CAS-Before-RAS Refresh RAS
-						   asserting period
-						   SDRAM: Command interval after
-						   synchronous DRAM refresh */
-#define SH7750_MCR_TRAS_DRAM_2         0x00000000	/* 2 */
-#define SH7750_MCR_TRAS_DRAM_3         0x00000400	/* 3 */
-#define SH7750_MCR_TRAS_DRAM_4         0x00000800	/* 4 */
-#define SH7750_MCR_TRAS_DRAM_5         0x00000C00	/* 5 */
-#define SH7750_MCR_TRAS_DRAM_6         0x00001000	/* 6 */
-#define SH7750_MCR_TRAS_DRAM_7         0x00001400	/* 7 */
-#define SH7750_MCR_TRAS_DRAM_8         0x00001800	/* 8 */
-#define SH7750_MCR_TRAS_DRAM_9         0x00001C00	/* 9 */
-
-#define SH7750_MCR_TRAS_SDRAM_TRC_4    0x00000000	/* 4 + TRC */
-#define SH7750_MCR_TRAS_SDRAM_TRC_5    0x00000400	/* 5 + TRC */
-#define SH7750_MCR_TRAS_SDRAM_TRC_6    0x00000800	/* 6 + TRC */
-#define SH7750_MCR_TRAS_SDRAM_TRC_7    0x00000C00	/* 7 + TRC */
-#define SH7750_MCR_TRAS_SDRAM_TRC_8    0x00001000	/* 8 + TRC */
-#define SH7750_MCR_TRAS_SDRAM_TRC_9    0x00001400	/* 9 + TRC */
-#define SH7750_MCR_TRAS_SDRAM_TRC_10   0x00001800	/* 10 + TRC */
-#define SH7750_MCR_TRAS_SDRAM_TRC_11   0x00001C00	/* 11 + TRC */
-
-#define SH7750_MCR_BE         0x00000200	/* Burst Enable */
-#define SH7750_MCR_SZ         0x00000180	/* Memory Data Size */
-#define SH7750_MCR_SZ_64      0x00000000	/*    64 bits */
-#define SH7750_MCR_SZ_16      0x00000100	/*    16 bits */
-#define SH7750_MCR_SZ_32      0x00000180	/*    32 bits */
-
-#define SH7750_MCR_AMX        0x00000078	/* Address Multiplexing */
+#define SH7750_MCR_TPC_SDRAM_1 0x00000000 /* 1 cycle */
+#define SH7750_MCR_TPC_SDRAM_2 0x00080000 /* 2 cycles */
+#define SH7750_MCR_TPC_SDRAM_3 0x00100000 /* 3 cycles */
+#define SH7750_MCR_TPC_SDRAM_4 0x00180000 /* 4 cycles */
+#define SH7750_MCR_TPC_SDRAM_5 0x00200000 /* 5 cycles */
+#define SH7750_MCR_TPC_SDRAM_6 0x00280000 /* 6 cycles */
+#define SH7750_MCR_TPC_SDRAM_7 0x00300000 /* 7 cycles */
+#define SH7750_MCR_TPC_SDRAM_8 0x00380000 /* 8 cycles */
+
+#define SH7750_MCR_RCD         0x00030000 /* DRAM: RAS-CAS Assertion Delay */
+                                          /*   time */
+                                          /* SDRAM: bank active-read/write */
+                                          /*   command delay time */
+#define SH7750_MCR_RCD_DRAM_2  0x00000000 /* DRAM delay 2 clocks */
+#define SH7750_MCR_RCD_DRAM_3  0x00010000 /* DRAM delay 3 clocks */
+#define SH7750_MCR_RCD_DRAM_4  0x00020000 /* DRAM delay 4 clocks */
+#define SH7750_MCR_RCD_DRAM_5  0x00030000 /* DRAM delay 5 clocks */
+#define SH7750_MCR_RCD_SDRAM_2 0x00010000 /* DRAM delay 2 clocks */
+#define SH7750_MCR_RCD_SDRAM_3 0x00020000 /* DRAM delay 3 clocks */
+#define SH7750_MCR_RCD_SDRAM_4 0x00030000 /* DRAM delay 4 clocks */
+
+#define SH7750_MCR_TRWL       0x0000E000 /* SDRAM Write Precharge Delay */
+#define SH7750_MCR_TRWL_1     0x00000000 /* 1 */
+#define SH7750_MCR_TRWL_2     0x00002000 /* 2 */
+#define SH7750_MCR_TRWL_3     0x00004000 /* 3 */
+#define SH7750_MCR_TRWL_4     0x00006000 /* 4 */
+#define SH7750_MCR_TRWL_5     0x00008000 /* 5 */
+
+#define SH7750_MCR_TRAS       0x00001C00 /* DRAM: CAS-Before-RAS Refresh RAS */
+                                         /* asserting period */
+                                         /* SDRAM: Command interval after */
+                                         /* synchronous DRAM refresh */
+#define SH7750_MCR_TRAS_DRAM_2         0x00000000 /* 2 */
+#define SH7750_MCR_TRAS_DRAM_3         0x00000400 /* 3 */
+#define SH7750_MCR_TRAS_DRAM_4         0x00000800 /* 4 */
+#define SH7750_MCR_TRAS_DRAM_5         0x00000C00 /* 5 */
+#define SH7750_MCR_TRAS_DRAM_6         0x00001000 /* 6 */
+#define SH7750_MCR_TRAS_DRAM_7         0x00001400 /* 7 */
+#define SH7750_MCR_TRAS_DRAM_8         0x00001800 /* 8 */
+#define SH7750_MCR_TRAS_DRAM_9         0x00001C00 /* 9 */
+
+#define SH7750_MCR_TRAS_SDRAM_TRC_4    0x00000000 /* 4 + TRC */
+#define SH7750_MCR_TRAS_SDRAM_TRC_5    0x00000400 /* 5 + TRC */
+#define SH7750_MCR_TRAS_SDRAM_TRC_6    0x00000800 /* 6 + TRC */
+#define SH7750_MCR_TRAS_SDRAM_TRC_7    0x00000C00 /* 7 + TRC */
+#define SH7750_MCR_TRAS_SDRAM_TRC_8    0x00001000 /* 8 + TRC */
+#define SH7750_MCR_TRAS_SDRAM_TRC_9    0x00001400 /* 9 + TRC */
+#define SH7750_MCR_TRAS_SDRAM_TRC_10   0x00001800 /* 10 + TRC */
+#define SH7750_MCR_TRAS_SDRAM_TRC_11   0x00001C00 /* 11 + TRC */
+
+#define SH7750_MCR_BE         0x00000200 /* Burst Enable */
+#define SH7750_MCR_SZ         0x00000180 /* Memory Data Size */
+#define SH7750_MCR_SZ_64      0x00000000 /* 64 bits */
+#define SH7750_MCR_SZ_16      0x00000100 /* 16 bits */
+#define SH7750_MCR_SZ_32      0x00000180 /* 32 bits */
+
+#define SH7750_MCR_AMX        0x00000078 /* Address Multiplexing */
 #define SH7750_MCR_AMX_S      3
-#define SH7750_MCR_AMX_DRAM_8BIT_COL    0x00000000	/* 8-bit column addr */
-#define SH7750_MCR_AMX_DRAM_9BIT_COL    0x00000008	/* 9-bit column addr */
-#define SH7750_MCR_AMX_DRAM_10BIT_COL   0x00000010	/* 10-bit column addr */
-#define SH7750_MCR_AMX_DRAM_11BIT_COL   0x00000018	/* 11-bit column addr */
-#define SH7750_MCR_AMX_DRAM_12BIT_COL   0x00000020	/* 12-bit column addr */
+#define SH7750_MCR_AMX_DRAM_8BIT_COL    0x00000000 /* 8-bit column addr */
+#define SH7750_MCR_AMX_DRAM_9BIT_COL    0x00000008 /* 9-bit column addr */
+#define SH7750_MCR_AMX_DRAM_10BIT_COL   0x00000010 /* 10-bit column addr */
+#define SH7750_MCR_AMX_DRAM_11BIT_COL   0x00000018 /* 11-bit column addr */
+#define SH7750_MCR_AMX_DRAM_12BIT_COL   0x00000020 /* 12-bit column addr */
 /* See SH7750 Hardware Manual for SDRAM address multiplexor selection */
 
-#define SH7750_MCR_RFSH       0x00000004	/* Refresh Control */
-#define SH7750_MCR_RMODE      0x00000002	/* Refresh Mode: */
-#define SH7750_MCR_RMODE_NORMAL 0x00000000	/* Normal Refresh Mode */
-#define SH7750_MCR_RMODE_SELF   0x00000002	/* Self-Refresh Mode */
-#define SH7750_MCR_RMODE_EDO    0x00000001	/* EDO Mode */
+#define SH7750_MCR_RFSH       0x00000004 /* Refresh Control */
+#define SH7750_MCR_RMODE      0x00000002 /* Refresh Mode: */
+#define SH7750_MCR_RMODE_NORMAL 0x00000000 /* Normal Refresh Mode */
+#define SH7750_MCR_RMODE_SELF   0x00000002 /* Self-Refresh Mode */
+#define SH7750_MCR_RMODE_EDO    0x00000001 /* EDO Mode */
 
 /* SDRAM Mode Set address */
 #define SH7750_SDRAM_MODE_A2_BASE  0xFF900000
@@ -894,119 +894,119 @@
 
 
 /* PCMCIA Control Register (half) - PCR */
-#define SH7750_PCR_REGOFS     0x800018	/* offset */
+#define SH7750_PCR_REGOFS     0x800018 /* offset */
 #define SH7750_PCR            SH7750_P4_REG32(SH7750_PCR_REGOFS)
 #define SH7750_PCR_A7         SH7750_A7_REG32(SH7750_PCR_REGOFS)
 
-#define SH7750_PCR_A5PCW      0xC000	/* Area 5 PCMCIA Wait - Number of wait
-					   states to be added to the number of
-					   waits specified by WCR2 in a low-speed
-					   PCMCIA wait cycle */
-#define SH7750_PCR_A5PCW_0    0x0000	/*    0 waits inserted */
-#define SH7750_PCR_A5PCW_15   0x4000	/*    15 waits inserted */
-#define SH7750_PCR_A5PCW_30   0x8000	/*    30 waits inserted */
-#define SH7750_PCR_A5PCW_50   0xC000	/*    50 waits inserted */
-
-#define SH7750_PCR_A6PCW      0x3000	/* Area 6 PCMCIA Wait - Number of wait
-					   states to be added to the number of
-					   waits specified by WCR2 in a low-speed
-					   PCMCIA wait cycle */
-#define SH7750_PCR_A6PCW_0    0x0000	/*    0 waits inserted */
-#define SH7750_PCR_A6PCW_15   0x1000	/*    15 waits inserted */
-#define SH7750_PCR_A6PCW_30   0x2000	/*    30 waits inserted */
-#define SH7750_PCR_A6PCW_50   0x3000	/*    50 waits inserted */
-
-#define SH7750_PCR_A5TED      0x0E00	/* Area 5 Address-OE\/WE\ Assertion Delay,
-					   delay time from address output to
-					   OE\/WE\ assertion on the connected
-					   PCMCIA interface */
+#define SH7750_PCR_A5PCW      0xC000 /* Area 5 PCMCIA Wait - Number of wait */
+                                     /* states to be added to the number of */
+                                     /* waits specified by WCR2 in a */
+                                     /* low-speed PCMCIA wait cycle */
+#define SH7750_PCR_A5PCW_0    0x0000 /*    0 waits inserted */
+#define SH7750_PCR_A5PCW_15   0x4000 /*    15 waits inserted */
+#define SH7750_PCR_A5PCW_30   0x8000 /*    30 waits inserted */
+#define SH7750_PCR_A5PCW_50   0xC000 /*    50 waits inserted */
+
+#define SH7750_PCR_A6PCW      0x3000 /* Area 6 PCMCIA Wait - Number of wait */
+                                     /* states to be added to the number of */
+                                     /* waits specified by WCR2 in a */
+                                     /* low-speed PCMCIA wait cycle */
+#define SH7750_PCR_A6PCW_0    0x0000 /*    0 waits inserted */
+#define SH7750_PCR_A6PCW_15   0x1000 /*    15 waits inserted */
+#define SH7750_PCR_A6PCW_30   0x2000 /*    30 waits inserted */
+#define SH7750_PCR_A6PCW_50   0x3000 /*    50 waits inserted */
+
+#define SH7750_PCR_A5TED      0x0E00 /* Area 5 Addr-OE\/WE\ Assertion Delay */
+                                     /* delay time from address output to */
+                                     /* OE\/WE\ assertion on the connected */
+                                     /* PCMCIA interface */
 #define SH7750_PCR_A5TED_S    9
-#define SH7750_PCR_A6TED      0x01C0	/* Area 6 Address-OE\/WE\ Assertion Delay */
+#define SH7750_PCR_A6TED      0x01C0 /* Area 6 Addr-OE\/WE\ Assertion Delay */
 #define SH7750_PCR_A6TED_S    6
 
-#define SH7750_PCR_TED_0WS    0	/* 0 Waits inserted */
-#define SH7750_PCR_TED_1WS    1	/* 1 Waits inserted */
-#define SH7750_PCR_TED_2WS    2	/* 2 Waits inserted */
-#define SH7750_PCR_TED_3WS    3	/* 3 Waits inserted */
-#define SH7750_PCR_TED_6WS    4	/* 6 Waits inserted */
-#define SH7750_PCR_TED_9WS    5	/* 9 Waits inserted */
-#define SH7750_PCR_TED_12WS   6	/* 12 Waits inserted */
-#define SH7750_PCR_TED_15WS   7	/* 15 Waits inserted */
-
-#define SH7750_PCR_A5TEH      0x0038	/* Area 5 OE\/WE\ Negation Address delay,
-					   address hold delay time from OE\/WE\
-					   negation in a write on the connected
-					   PCMCIA interface */
+#define SH7750_PCR_TED_0WS    0 /* 0 Waits inserted */
+#define SH7750_PCR_TED_1WS    1 /* 1 Waits inserted */
+#define SH7750_PCR_TED_2WS    2 /* 2 Waits inserted */
+#define SH7750_PCR_TED_3WS    3 /* 3 Waits inserted */
+#define SH7750_PCR_TED_6WS    4 /* 6 Waits inserted */
+#define SH7750_PCR_TED_9WS    5 /* 9 Waits inserted */
+#define SH7750_PCR_TED_12WS   6 /* 12 Waits inserted */
+#define SH7750_PCR_TED_15WS   7 /* 15 Waits inserted */
+
+#define SH7750_PCR_A5TEH      0x0038 /* Area 5 OE\/WE\ Negation Addr delay, */
+                                     /* address hold delay time from OE\/WE\ */
+                                     /* negation in a write on the connected */
+                                     /* PCMCIA interface */
 #define SH7750_PCR_A5TEH_S    3
 
-#define SH7750_PCR_A6TEH      0x0007	/* Area 6 OE\/WE\ Negation Address delay */
+#define SH7750_PCR_A6TEH      0x0007 /* Area 6 OE\/WE\ Negation Address delay */
 #define SH7750_PCR_A6TEH_S    0
 
-#define SH7750_PCR_TEH_0WS    0	/* 0 Waits inserted */
-#define SH7750_PCR_TEH_1WS    1	/* 1 Waits inserted */
-#define SH7750_PCR_TEH_2WS    2	/* 2 Waits inserted */
-#define SH7750_PCR_TEH_3WS    3	/* 3 Waits inserted */
-#define SH7750_PCR_TEH_6WS    4	/* 6 Waits inserted */
-#define SH7750_PCR_TEH_9WS    5	/* 9 Waits inserted */
-#define SH7750_PCR_TEH_12WS   6	/* 12 Waits inserted */
-#define SH7750_PCR_TEH_15WS   7	/* 15 Waits inserted */
+#define SH7750_PCR_TEH_0WS    0 /* 0 Waits inserted */
+#define SH7750_PCR_TEH_1WS    1 /* 1 Waits inserted */
+#define SH7750_PCR_TEH_2WS    2 /* 2 Waits inserted */
+#define SH7750_PCR_TEH_3WS    3 /* 3 Waits inserted */
+#define SH7750_PCR_TEH_6WS    4 /* 6 Waits inserted */
+#define SH7750_PCR_TEH_9WS    5 /* 9 Waits inserted */
+#define SH7750_PCR_TEH_12WS   6 /* 12 Waits inserted */
+#define SH7750_PCR_TEH_15WS   7 /* 15 Waits inserted */
 
 /* Refresh Timer Control/Status Register (half) - RTSCR */
-#define SH7750_RTCSR_REGOFS   0x80001C	/* offset */
+#define SH7750_RTCSR_REGOFS   0x80001C /* offset */
 #define SH7750_RTCSR          SH7750_P4_REG32(SH7750_RTCSR_REGOFS)
 #define SH7750_RTCSR_A7       SH7750_A7_REG32(SH7750_RTCSR_REGOFS)
 
-#define SH7750_RTCSR_KEY      0xA500	/* RTCSR write key */
-#define SH7750_RTCSR_CMF      0x0080	/* Compare-Match Flag (indicates a
-					   match between the refresh timer
-					   counter and refresh time constant) */
-#define SH7750_RTCSR_CMIE     0x0040	/* Compare-Match Interrupt Enable */
-#define SH7750_RTCSR_CKS      0x0038	/* Refresh Counter Clock Selects */
-#define SH7750_RTCSR_CKS_DIS          0x0000	/* Clock Input Disabled */
-#define SH7750_RTCSR_CKS_CKIO_DIV4    0x0008	/* Bus Clock / 4 */
-#define SH7750_RTCSR_CKS_CKIO_DIV16   0x0010	/* Bus Clock / 16 */
-#define SH7750_RTCSR_CKS_CKIO_DIV64   0x0018	/* Bus Clock / 64 */
-#define SH7750_RTCSR_CKS_CKIO_DIV256  0x0020	/* Bus Clock / 256 */
-#define SH7750_RTCSR_CKS_CKIO_DIV1024 0x0028	/* Bus Clock / 1024 */
-#define SH7750_RTCSR_CKS_CKIO_DIV2048 0x0030	/* Bus Clock / 2048 */
-#define SH7750_RTCSR_CKS_CKIO_DIV4096 0x0038	/* Bus Clock / 4096 */
-
-#define SH7750_RTCSR_OVF      0x0004	/* Refresh Count Overflow Flag */
-#define SH7750_RTCSR_OVIE     0x0002	/* Refresh Count Overflow Interrupt
-					   Enable */
-#define SH7750_RTCSR_LMTS     0x0001	/* Refresh Count Overflow Limit Select */
-#define SH7750_RTCSR_LMTS_1024 0x0000	/* Count Limit is 1024 */
-#define SH7750_RTCSR_LMTS_512  0x0001	/* Count Limit is 512 */
+#define SH7750_RTCSR_KEY      0xA500 /* RTCSR write key */
+#define SH7750_RTCSR_CMF      0x0080 /* Compare-Match Flag (indicates a */
+                                     /* match between the refresh timer */
+                                     /* counter and refresh time constant) */
+#define SH7750_RTCSR_CMIE     0x0040 /* Compare-Match Interrupt Enable */
+#define SH7750_RTCSR_CKS      0x0038 /* Refresh Counter Clock Selects */
+#define SH7750_RTCSR_CKS_DIS          0x0000 /* Clock Input Disabled */
+#define SH7750_RTCSR_CKS_CKIO_DIV4    0x0008 /* Bus Clock / 4 */
+#define SH7750_RTCSR_CKS_CKIO_DIV16   0x0010 /* Bus Clock / 16 */
+#define SH7750_RTCSR_CKS_CKIO_DIV64   0x0018 /* Bus Clock / 64 */
+#define SH7750_RTCSR_CKS_CKIO_DIV256  0x0020 /* Bus Clock / 256 */
+#define SH7750_RTCSR_CKS_CKIO_DIV1024 0x0028 /* Bus Clock / 1024 */
+#define SH7750_RTCSR_CKS_CKIO_DIV2048 0x0030 /* Bus Clock / 2048 */
+#define SH7750_RTCSR_CKS_CKIO_DIV4096 0x0038 /* Bus Clock / 4096 */
+
+#define SH7750_RTCSR_OVF      0x0004 /* Refresh Count Overflow Flag */
+#define SH7750_RTCSR_OVIE     0x0002 /* Refresh Count Overflow Interrupt */
+                                     /*   Enable */
+#define SH7750_RTCSR_LMTS     0x0001 /* Refresh Count Overflow Limit Select */
+#define SH7750_RTCSR_LMTS_1024 0x0000 /* Count Limit is 1024 */
+#define SH7750_RTCSR_LMTS_512  0x0001 /* Count Limit is 512 */
 
 /* Refresh Timer Counter (half) - RTCNT */
-#define SH7750_RTCNT_REGOFS   0x800020	/* offset */
+#define SH7750_RTCNT_REGOFS   0x800020 /* offset */
 #define SH7750_RTCNT          SH7750_P4_REG32(SH7750_RTCNT_REGOFS)
 #define SH7750_RTCNT_A7       SH7750_A7_REG32(SH7750_RTCNT_REGOFS)
 
-#define SH7750_RTCNT_KEY      0xA500	/* RTCNT write key */
+#define SH7750_RTCNT_KEY      0xA500 /* RTCNT write key */
 
 /* Refresh Time Constant Register (half) - RTCOR */
-#define SH7750_RTCOR_REGOFS   0x800024	/* offset */
+#define SH7750_RTCOR_REGOFS   0x800024 /* offset */
 #define SH7750_RTCOR          SH7750_P4_REG32(SH7750_RTCOR_REGOFS)
 #define SH7750_RTCOR_A7       SH7750_A7_REG32(SH7750_RTCOR_REGOFS)
 
-#define SH7750_RTCOR_KEY      0xA500	/* RTCOR write key */
+#define SH7750_RTCOR_KEY      0xA500 /* RTCOR write key */
 
 /* Refresh Count Register (half) - RFCR */
-#define SH7750_RFCR_REGOFS    0x800028	/* offset */
+#define SH7750_RFCR_REGOFS    0x800028 /* offset */
 #define SH7750_RFCR           SH7750_P4_REG32(SH7750_RFCR_REGOFS)
 #define SH7750_RFCR_A7        SH7750_A7_REG32(SH7750_RFCR_REGOFS)
 
-#define SH7750_RFCR_KEY       0xA400	/* RFCR write key */
+#define SH7750_RFCR_KEY       0xA400 /* RFCR write key */
 
 /* Synchronous DRAM mode registers - SDMR */
-#define SH7750_SDMR2_REGOFS   0x900000	/* base offset */
-#define SH7750_SDMR2_REGNB    0x0FFC	/* nb of register */
+#define SH7750_SDMR2_REGOFS   0x900000 /* base offset */
+#define SH7750_SDMR2_REGNB    0x0FFC /* nb of register */
 #define SH7750_SDMR2          SH7750_P4_REG32(SH7750_SDMR2_REGOFS)
 #define SH7750_SDMR2_A7       SH7750_A7_REG32(SH7750_SDMR2_REGOFS)
 
-#define SH7750_SDMR3_REGOFS   0x940000	/* offset */
-#define SH7750_SDMR3_REGNB    0x0FFC	/* nb of register */
+#define SH7750_SDMR3_REGOFS   0x940000 /* offset */
+#define SH7750_SDMR3_REGNB    0x0FFC /* nb of register */
 #define SH7750_SDMR3          SH7750_P4_REG32(SH7750_SDMR3_REGOFS)
 #define SH7750_SDMR3_A7       SH7750_A7_REG32(SH7750_SDMR3_REGOFS)
 
@@ -1015,7 +1015,7 @@
  */
 
 /* DMA Source Address Register - SAR0, SAR1, SAR2, SAR3 */
-#define SH7750_SAR_REGOFS(n)  (0xA00000 + ((n)*16))	/* offset */
+#define SH7750_SAR_REGOFS(n)  (0xA00000 + ((n) * 16)) /* offset */
 #define SH7750_SAR(n)         SH7750_P4_REG32(SH7750_SAR_REGOFS(n))
 #define SH7750_SAR_A7(n)      SH7750_A7_REG32(SH7750_SAR_REGOFS(n))
 #define SH7750_SAR0           SH7750_SAR(0)
@@ -1028,7 +1028,7 @@
 #define SH7750_SAR3_A7        SH7750_SAR_A7(3)
 
 /* DMA Destination Address Register - DAR0, DAR1, DAR2, DAR3 */
-#define SH7750_DAR_REGOFS(n)  (0xA00004 + ((n)*16))	/* offset */
+#define SH7750_DAR_REGOFS(n)  (0xA00004 + ((n) * 16)) /* offset */
 #define SH7750_DAR(n)         SH7750_P4_REG32(SH7750_DAR_REGOFS(n))
 #define SH7750_DAR_A7(n)      SH7750_A7_REG32(SH7750_DAR_REGOFS(n))
 #define SH7750_DAR0           SH7750_DAR(0)
@@ -1041,7 +1041,7 @@
 #define SH7750_DAR3_A7        SH7750_DAR_A7(3)
 
 /* DMA Transfer Count Register - DMATCR0, DMATCR1, DMATCR2, DMATCR3 */
-#define SH7750_DMATCR_REGOFS(n)  (0xA00008 + ((n)*16))	/* offset */
+#define SH7750_DMATCR_REGOFS(n)  (0xA00008 + ((n) * 16)) /* offset */
 #define SH7750_DMATCR(n)      SH7750_P4_REG32(SH7750_DMATCR_REGOFS(n))
 #define SH7750_DMATCR_A7(n)   SH7750_A7_REG32(SH7750_DMATCR_REGOFS(n))
 #define SH7750_DMATCR0_P4     SH7750_DMATCR(0)
@@ -1054,7 +1054,7 @@
 #define SH7750_DMATCR3_A7     SH7750_DMATCR_A7(3)
 
 /* DMA Channel Control Register - CHCR0, CHCR1, CHCR2, CHCR3 */
-#define SH7750_CHCR_REGOFS(n)  (0xA0000C + ((n)*16))	/* offset */
+#define SH7750_CHCR_REGOFS(n)  (0xA0000C + ((n) * 16)) /* offset */
 #define SH7750_CHCR(n)        SH7750_P4_REG32(SH7750_CHCR_REGOFS(n))
 #define SH7750_CHCR_A7(n)     SH7750_A7_REG32(SH7750_CHCR_REGOFS(n))
 #define SH7750_CHCR0          SH7750_CHCR(0)
@@ -1066,227 +1066,227 @@
 #define SH7750_CHCR2_A7       SH7750_CHCR_A7(2)
 #define SH7750_CHCR3_A7       SH7750_CHCR_A7(3)
 
-#define SH7750_CHCR_SSA       0xE0000000	/* Source Address Space Attribute */
-#define SH7750_CHCR_SSA_PCMCIA  0x00000000	/* Reserved in PCMCIA access */
-#define SH7750_CHCR_SSA_DYNBSZ  0x20000000	/* Dynamic Bus Sizing I/O space */
-#define SH7750_CHCR_SSA_IO8     0x40000000	/* 8-bit I/O space */
-#define SH7750_CHCR_SSA_IO16    0x60000000	/* 16-bit I/O space */
-#define SH7750_CHCR_SSA_CMEM8   0x80000000	/* 8-bit common memory space */
-#define SH7750_CHCR_SSA_CMEM16  0xA0000000	/* 16-bit common memory space */
-#define SH7750_CHCR_SSA_AMEM8   0xC0000000	/* 8-bit attribute memory space */
-#define SH7750_CHCR_SSA_AMEM16  0xE0000000	/* 16-bit attribute memory space */
-
-#define SH7750_CHCR_STC       0x10000000	/* Source Address Wait Control Select,
-						   specifies CS5 or CS6 space wait
-						   control for PCMCIA access */
-
-#define SH7750_CHCR_DSA       0x0E000000	/* Source Address Space Attribute */
-#define SH7750_CHCR_DSA_PCMCIA  0x00000000	/* Reserved in PCMCIA access */
-#define SH7750_CHCR_DSA_DYNBSZ  0x02000000	/* Dynamic Bus Sizing I/O space */
-#define SH7750_CHCR_DSA_IO8     0x04000000	/* 8-bit I/O space */
-#define SH7750_CHCR_DSA_IO16    0x06000000	/* 16-bit I/O space */
-#define SH7750_CHCR_DSA_CMEM8   0x08000000	/* 8-bit common memory space */
-#define SH7750_CHCR_DSA_CMEM16  0x0A000000	/* 16-bit common memory space */
-#define SH7750_CHCR_DSA_AMEM8   0x0C000000	/* 8-bit attribute memory space */
-#define SH7750_CHCR_DSA_AMEM16  0x0E000000	/* 16-bit attribute memory space */
-
-#define SH7750_CHCR_DTC       0x01000000	/* Destination Address Wait Control
-						   Select, specifies CS5 or CS6
-						   space wait control for PCMCIA
-						   access */
-
-#define SH7750_CHCR_DS        0x00080000	/* DREQ\ Select : */
-#define SH7750_CHCR_DS_LOWLVL 0x00000000	/*     Low Level Detection */
-#define SH7750_CHCR_DS_FALL   0x00080000	/*     Falling Edge Detection */
-
-#define SH7750_CHCR_RL        0x00040000	/* Request Check Level: */
-#define SH7750_CHCR_RL_ACTH   0x00000000	/*     DRAK is an active high out */
-#define SH7750_CHCR_RL_ACTL   0x00040000	/*     DRAK is an active low out */
-
-#define SH7750_CHCR_AM        0x00020000	/* Acknowledge Mode: */
-#define SH7750_CHCR_AM_RD     0x00000000	/*     DACK is output in read cycle */
-#define SH7750_CHCR_AM_WR     0x00020000	/*     DACK is output in write cycle */
-
-#define SH7750_CHCR_AL        0x00010000	/* Acknowledge Level: */
-#define SH7750_CHCR_AL_ACTH   0x00000000	/*     DACK is an active high out */
-#define SH7750_CHCR_AL_ACTL   0x00010000	/*     DACK is an active low out */
-
-#define SH7750_CHCR_DM        0x0000C000	/* Destination Address Mode: */
-#define SH7750_CHCR_DM_FIX    0x00000000	/*     Destination Addr Fixed */
-#define SH7750_CHCR_DM_INC    0x00004000	/*     Destination Addr Incremented */
-#define SH7750_CHCR_DM_DEC    0x00008000	/*     Destination Addr Decremented */
-
-#define SH7750_CHCR_SM        0x00003000	/* Source Address Mode: */
-#define SH7750_CHCR_SM_FIX    0x00000000	/*     Source Addr Fixed */
-#define SH7750_CHCR_SM_INC    0x00001000	/*     Source Addr Incremented */
-#define SH7750_CHCR_SM_DEC    0x00002000	/*     Source Addr Decremented */
-
-#define SH7750_CHCR_RS        0x00000F00	/* Request Source Select: */
-#define SH7750_CHCR_RS_ER_DA_EA_TO_EA   0x000	/* External Request, Dual Address
-						   Mode (External Addr Space->
-						   External Addr Space) */
-#define SH7750_CHCR_RS_ER_SA_EA_TO_ED   0x200	/* External Request, Single
-						   Address Mode (External Addr
-						   Space -> External Device) */
-#define SH7750_CHCR_RS_ER_SA_ED_TO_EA   0x300	/* External Request, Single
-						   Address Mode, (External
-						   Device -> External Addr
-						   Space) */
-#define SH7750_CHCR_RS_AR_EA_TO_EA      0x400	/* Auto-Request (External Addr
-						   Space -> External Addr Space) */
-
-#define SH7750_CHCR_RS_AR_EA_TO_OCP     0x500	/* Auto-Request (External Addr
-						   Space -> On-chip Peripheral
-						   Module) */
-#define SH7750_CHCR_RS_AR_OCP_TO_EA     0x600	/* Auto-Request (On-chip
-						   Peripheral Module ->
-						   External Addr Space */
-#define SH7750_CHCR_RS_SCITX_EA_TO_SC   0x800	/* SCI Transmit-Data-Empty intr
-						   transfer request (external
-						   address space -> SCTDR1) */
-#define SH7750_CHCR_RS_SCIRX_SC_TO_EA   0x900	/* SCI Receive-Data-Full intr
-						   transfer request (SCRDR1 ->
-						   External Addr Space) */
-#define SH7750_CHCR_RS_SCIFTX_EA_TO_SC  0xA00	/* SCIF Transmit-Data-Empty intr
-						   transfer request (external
-						   address space -> SCFTDR1) */
-#define SH7750_CHCR_RS_SCIFRX_SC_TO_EA  0xB00	/* SCIF Receive-Data-Full intr
-						   transfer request (SCFRDR2 ->
-						   External Addr Space) */
-#define SH7750_CHCR_RS_TMU2_EA_TO_EA    0xC00	/* TMU Channel 2 (input capture
-						   interrupt), (external address
-						   space -> external address
-						   space) */
-#define SH7750_CHCR_RS_TMU2_EA_TO_OCP   0xD00	/* TMU Channel 2 (input capture
-						   interrupt), (external address
-						   space -> on-chip peripheral
-						   module) */
-#define SH7750_CHCR_RS_TMU2_OCP_TO_EA   0xE00	/* TMU Channel 2 (input capture
-						   interrupt), (on-chip
-						   peripheral module -> external
-						   address space) */
-
-#define SH7750_CHCR_TM        0x00000080	/* Transmit mode: */
-#define SH7750_CHCR_TM_CSTEAL 0x00000000	/*     Cycle Steal Mode */
-#define SH7750_CHCR_TM_BURST  0x00000080	/*     Burst Mode */
-
-#define SH7750_CHCR_TS        0x00000070	/* Transmit Size: */
-#define SH7750_CHCR_TS_QUAD   0x00000000	/*     Quadword Size (64 bits) */
-#define SH7750_CHCR_TS_BYTE   0x00000010	/*     Byte Size (8 bit) */
-#define SH7750_CHCR_TS_WORD   0x00000020	/*     Word Size (16 bit) */
-#define SH7750_CHCR_TS_LONG   0x00000030	/*     Longword Size (32 bit) */
-#define SH7750_CHCR_TS_BLOCK  0x00000040	/*     32-byte block transfer */
-
-#define SH7750_CHCR_IE        0x00000004	/* Interrupt Enable */
-#define SH7750_CHCR_TE        0x00000002	/* Transfer End */
-#define SH7750_CHCR_DE        0x00000001	/* DMAC Enable */
+#define SH7750_CHCR_SSA       0xE0000000 /* Source Address Space Attribute */
+#define SH7750_CHCR_SSA_PCMCIA  0x00000000 /* Reserved in PCMCIA access */
+#define SH7750_CHCR_SSA_DYNBSZ  0x20000000 /* Dynamic Bus Sizing I/O space */
+#define SH7750_CHCR_SSA_IO8     0x40000000 /* 8-bit I/O space */
+#define SH7750_CHCR_SSA_IO16    0x60000000 /* 16-bit I/O space */
+#define SH7750_CHCR_SSA_CMEM8   0x80000000 /* 8-bit common memory space */
+#define SH7750_CHCR_SSA_CMEM16  0xA0000000 /* 16-bit common memory space */
+#define SH7750_CHCR_SSA_AMEM8   0xC0000000 /* 8-bit attribute memory space */
+#define SH7750_CHCR_SSA_AMEM16  0xE0000000 /* 16-bit attribute memory space */
+
+#define SH7750_CHCR_STC       0x10000000 /* Source Addr Wait Control Select */
+                                         /*   specifies CS5 or CS6 space wait */
+                                         /*   control for PCMCIA access */
+
+#define SH7750_CHCR_DSA       0x0E000000 /* Source Address Space Attribute */
+#define SH7750_CHCR_DSA_PCMCIA  0x00000000 /* Reserved in PCMCIA access */
+#define SH7750_CHCR_DSA_DYNBSZ  0x02000000 /* Dynamic Bus Sizing I/O space */
+#define SH7750_CHCR_DSA_IO8     0x04000000 /* 8-bit I/O space */
+#define SH7750_CHCR_DSA_IO16    0x06000000 /* 16-bit I/O space */
+#define SH7750_CHCR_DSA_CMEM8   0x08000000 /* 8-bit common memory space */
+#define SH7750_CHCR_DSA_CMEM16  0x0A000000 /* 16-bit common memory space */
+#define SH7750_CHCR_DSA_AMEM8   0x0C000000 /* 8-bit attribute memory space */
+#define SH7750_CHCR_DSA_AMEM16  0x0E000000 /* 16-bit attribute memory space */
+
+#define SH7750_CHCR_DTC       0x01000000 /* Destination Address Wait Control */
+                                         /*   Select, specifies CS5 or CS6 */
+                                         /*   space wait control for PCMCIA */
+                                         /*   access */
+
+#define SH7750_CHCR_DS        0x00080000 /* DREQ\ Select : */
+#define SH7750_CHCR_DS_LOWLVL 0x00000000 /*   Low Level Detection */
+#define SH7750_CHCR_DS_FALL   0x00080000 /*   Falling Edge Detection */
+
+#define SH7750_CHCR_RL        0x00040000 /* Request Check Level: */
+#define SH7750_CHCR_RL_ACTH   0x00000000 /*   DRAK is an active high out */
+#define SH7750_CHCR_RL_ACTL   0x00040000 /*   DRAK is an active low out */
+
+#define SH7750_CHCR_AM        0x00020000 /* Acknowledge Mode: */
+#define SH7750_CHCR_AM_RD     0x00000000 /*   DACK is output in read cycle */
+#define SH7750_CHCR_AM_WR     0x00020000 /*   DACK is output in write cycle */
+
+#define SH7750_CHCR_AL        0x00010000 /* Acknowledge Level: */
+#define SH7750_CHCR_AL_ACTH   0x00000000 /*   DACK is an active high out */
+#define SH7750_CHCR_AL_ACTL   0x00010000 /*   DACK is an active low out */
+
+#define SH7750_CHCR_DM        0x0000C000 /* Destination Address Mode: */
+#define SH7750_CHCR_DM_FIX    0x00000000 /*   Destination Addr Fixed */
+#define SH7750_CHCR_DM_INC    0x00004000 /*   Destination Addr Incremented */
+#define SH7750_CHCR_DM_DEC    0x00008000 /*   Destination Addr Decremented */
+
+#define SH7750_CHCR_SM        0x00003000 /* Source Address Mode: */
+#define SH7750_CHCR_SM_FIX    0x00000000 /*   Source Addr Fixed */
+#define SH7750_CHCR_SM_INC    0x00001000 /*   Source Addr Incremented */
+#define SH7750_CHCR_SM_DEC    0x00002000 /*   Source Addr Decremented */
+
+#define SH7750_CHCR_RS        0x00000F00 /* Request Source Select: */
+#define SH7750_CHCR_RS_ER_DA_EA_TO_EA   0x000 /* External Request, Dual Addr */
+                                              /*   Mode, External Addr Space */
+                                              /*   -> External Addr Space) */
+#define SH7750_CHCR_RS_ER_SA_EA_TO_ED   0x200 /* External Request, Single */
+                                              /*   Address Mode (Ext. Addr */
+                                              /*   Space -> External Device) */
+#define SH7750_CHCR_RS_ER_SA_ED_TO_EA   0x300 /* External Request, Single */
+                                              /*   Address Mode, (External */
+                                              /*   Device -> External Addr */
+                                              /*   Space) */
+#define SH7750_CHCR_RS_AR_EA_TO_EA      0x400 /* Auto-Request (External Addr */
+                                              /*   Space -> Ext. Addr Space) */
+
+#define SH7750_CHCR_RS_AR_EA_TO_OCP     0x500 /* Auto-Request (External Addr */
+                                              /*   Space -> On-chip */
+                                              /*   Peripheral Module) */
+#define SH7750_CHCR_RS_AR_OCP_TO_EA     0x600 /* Auto-Request (On-chip */
+                                              /*   Peripheral Module -> */
+                                              /*   External Addr Space */
+#define SH7750_CHCR_RS_SCITX_EA_TO_SC   0x800 /* SCI Transmit-Data-Empty intr */
+                                              /*   transfer request (external */
+                                              /*   address space -> SCTDR1) */
+#define SH7750_CHCR_RS_SCIRX_SC_TO_EA   0x900 /* SCI Receive-Data-Full intr */
+                                              /*   transfer request (SCRDR1 */
+                                              /*   -> External Addr Space) */
+#define SH7750_CHCR_RS_SCIFTX_EA_TO_SC  0xA00 /* SCIF TX-Data-Empty intr */
+                                              /*   transfer request (external */
+                                              /*   address space -> SCFTDR1) */
+#define SH7750_CHCR_RS_SCIFRX_SC_TO_EA  0xB00 /* SCIF Receive-Data-Full intr */
+                                              /*   transfer request (SCFRDR2 */
+                                              /*   -> External Addr Space) */
+#define SH7750_CHCR_RS_TMU2_EA_TO_EA    0xC00 /* TMU Channel 2 (input capture */
+                                              /*   interrupt), (external */
+                                              /*   address space -> external */
+                                              /*   address space) */
+#define SH7750_CHCR_RS_TMU2_EA_TO_OCP   0xD00 /* TMU Channel 2 (input capture */
+                                              /*   interrupt), (external */
+                                              /*   address space -> on-chip */
+                                              /*   peripheral module) */
+#define SH7750_CHCR_RS_TMU2_OCP_TO_EA   0xE00 /* TMU Channel 2 (input capture */
+                                              /*   interrupt), (on-chip */
+                                              /*   peripheral module -> */
+                                              /*   external address space) */
+
+#define SH7750_CHCR_TM        0x00000080 /* Transmit mode: */
+#define SH7750_CHCR_TM_CSTEAL 0x00000000 /*     Cycle Steal Mode */
+#define SH7750_CHCR_TM_BURST  0x00000080 /*     Burst Mode */
+
+#define SH7750_CHCR_TS        0x00000070 /* Transmit Size: */
+#define SH7750_CHCR_TS_QUAD   0x00000000 /*     Quadword Size (64 bits) */
+#define SH7750_CHCR_TS_BYTE   0x00000010 /*     Byte Size (8 bit) */
+#define SH7750_CHCR_TS_WORD   0x00000020 /*     Word Size (16 bit) */
+#define SH7750_CHCR_TS_LONG   0x00000030 /*     Longword Size (32 bit) */
+#define SH7750_CHCR_TS_BLOCK  0x00000040 /*     32-byte block transfer */
+
+#define SH7750_CHCR_IE        0x00000004 /* Interrupt Enable */
+#define SH7750_CHCR_TE        0x00000002 /* Transfer End */
+#define SH7750_CHCR_DE        0x00000001 /* DMAC Enable */
 
 /* DMA Operation Register - DMAOR */
-#define SH7750_DMAOR_REGOFS   0xA00040	/* offset */
+#define SH7750_DMAOR_REGOFS   0xA00040 /* offset */
 #define SH7750_DMAOR          SH7750_P4_REG32(SH7750_DMAOR_REGOFS)
 #define SH7750_DMAOR_A7       SH7750_A7_REG32(SH7750_DMAOR_REGOFS)
 
-#define SH7750_DMAOR_DDT      0x00008000	/* On-Demand Data Transfer Mode */
+#define SH7750_DMAOR_DDT      0x00008000 /* On-Demand Data Transfer Mode */
 
-#define SH7750_DMAOR_PR       0x00000300	/* Priority Mode: */
-#define SH7750_DMAOR_PR_0123  0x00000000	/*     CH0 > CH1 > CH2 > CH3 */
-#define SH7750_DMAOR_PR_0231  0x00000100	/*     CH0 > CH2 > CH3 > CH1 */
-#define SH7750_DMAOR_PR_2013  0x00000200	/*     CH2 > CH0 > CH1 > CH3 */
-#define SH7750_DMAOR_PR_RR    0x00000300	/*     Round-robin mode */
+#define SH7750_DMAOR_PR       0x00000300 /* Priority Mode: */
+#define SH7750_DMAOR_PR_0123  0x00000000 /*     CH0 > CH1 > CH2 > CH3 */
+#define SH7750_DMAOR_PR_0231  0x00000100 /*     CH0 > CH2 > CH3 > CH1 */
+#define SH7750_DMAOR_PR_2013  0x00000200 /*     CH2 > CH0 > CH1 > CH3 */
+#define SH7750_DMAOR_PR_RR    0x00000300 /*     Round-robin mode */
 
-#define SH7750_DMAOR_COD      0x00000010	/* Check Overrun for DREQ\ */
-#define SH7750_DMAOR_AE       0x00000004	/* Address Error flag */
-#define SH7750_DMAOR_NMIF     0x00000002	/* NMI Flag */
-#define SH7750_DMAOR_DME      0x00000001	/* DMAC Master Enable */
+#define SH7750_DMAOR_COD      0x00000010 /* Check Overrun for DREQ\ */
+#define SH7750_DMAOR_AE       0x00000004 /* Address Error flag */
+#define SH7750_DMAOR_NMIF     0x00000002 /* NMI Flag */
+#define SH7750_DMAOR_DME      0x00000001 /* DMAC Master Enable */
 
 /*
  * I/O Ports
  */
 /* Port Control Register A - PCTRA */
-#define SH7750_PCTRA_REGOFS   0x80002C	/* offset */
+#define SH7750_PCTRA_REGOFS   0x80002C /* offset */
 #define SH7750_PCTRA          SH7750_P4_REG32(SH7750_PCTRA_REGOFS)
 #define SH7750_PCTRA_A7       SH7750_A7_REG32(SH7750_PCTRA_REGOFS)
 
-#define SH7750_PCTRA_PBPUP(n) 0	/* Bit n is pulled up */
-#define SH7750_PCTRA_PBNPUP(n) (1 << ((n)*2+1))	/* Bit n is not pulled up */
-#define SH7750_PCTRA_PBINP(n) 0	/* Bit n is an input */
-#define SH7750_PCTRA_PBOUT(n) (1 << ((n)*2))	/* Bit n is an output */
+#define SH7750_PCTRA_PBPUP(n) 0 /* Bit n is pulled up */
+#define SH7750_PCTRA_PBNPUP(n) (1 << ((n) * 2 + 1)) /* Bit n is not pulled up */
+#define SH7750_PCTRA_PBINP(n) 0 /* Bit n is an input */
+#define SH7750_PCTRA_PBOUT(n) (1 << ((n) * 2)) /* Bit n is an output */
 
 /* Port Data Register A - PDTRA(half) */
-#define SH7750_PDTRA_REGOFS   0x800030	/* offset */
+#define SH7750_PDTRA_REGOFS   0x800030 /* offset */
 #define SH7750_PDTRA          SH7750_P4_REG32(SH7750_PDTRA_REGOFS)
 #define SH7750_PDTRA_A7       SH7750_A7_REG32(SH7750_PDTRA_REGOFS)
 
 #define SH7750_PDTRA_BIT(n) (1 << (n))
 
 /* Port Control Register B - PCTRB */
-#define SH7750_PCTRB_REGOFS   0x800040	/* offset */
+#define SH7750_PCTRB_REGOFS   0x800040 /* offset */
 #define SH7750_PCTRB          SH7750_P4_REG32(SH7750_PCTRB_REGOFS)
 #define SH7750_PCTRB_A7       SH7750_A7_REG32(SH7750_PCTRB_REGOFS)
 
-#define SH7750_PCTRB_PBPUP(n) 0	/* Bit n is pulled up */
-#define SH7750_PCTRB_PBNPUP(n) (1 << ((n-16)*2+1))	/* Bit n is not pulled up */
-#define SH7750_PCTRB_PBINP(n) 0	/* Bit n is an input */
-#define SH7750_PCTRB_PBOUT(n) (1 << ((n-16)*2))	/* Bit n is an output */
+#define SH7750_PCTRB_PBPUP(n) 0 /* Bit n is pulled up */
+#define SH7750_PCTRB_PBNPUP(n) (1 << ((n - 16) * 2 + 1)) /* Bit n is not pulled up */
+#define SH7750_PCTRB_PBINP(n) 0 /* Bit n is an input */
+#define SH7750_PCTRB_PBOUT(n) (1 << ((n - 16) * 2)) /* Bit n is an output */
 
 /* Port Data Register B - PDTRB(half) */
-#define SH7750_PDTRB_REGOFS   0x800044	/* offset */
+#define SH7750_PDTRB_REGOFS   0x800044 /* offset */
 #define SH7750_PDTRB          SH7750_P4_REG32(SH7750_PDTRB_REGOFS)
 #define SH7750_PDTRB_A7       SH7750_A7_REG32(SH7750_PDTRB_REGOFS)
 
-#define SH7750_PDTRB_BIT(n) (1 << ((n)-16))
+#define SH7750_PDTRB_BIT(n) (1 << ((n) - 16))
 
 /* GPIO Interrupt Control Register - GPIOIC(half) */
-#define SH7750_GPIOIC_REGOFS  0x800048	/* offset */
+#define SH7750_GPIOIC_REGOFS  0x800048 /* offset */
 #define SH7750_GPIOIC         SH7750_P4_REG32(SH7750_GPIOIC_REGOFS)
 #define SH7750_GPIOIC_A7      SH7750_A7_REG32(SH7750_GPIOIC_REGOFS)
 
-#define SH7750_GPIOIC_PTIREN(n) (1 << (n))	/* Port n is used as a GPIO int */
+#define SH7750_GPIOIC_PTIREN(n) (1 << (n)) /* Port n is used as a GPIO int */
 
 /*
  * Interrupt Controller - INTC
  */
 /* Interrupt Control Register - ICR (half) */
-#define SH7750_ICR_REGOFS     0xD00000	/* offset */
+#define SH7750_ICR_REGOFS     0xD00000 /* offset */
 #define SH7750_ICR            SH7750_P4_REG32(SH7750_ICR_REGOFS)
 #define SH7750_ICR_A7         SH7750_A7_REG32(SH7750_ICR_REGOFS)
 
-#define SH7750_ICR_NMIL       0x8000	/* NMI Input Level */
-#define SH7750_ICR_MAI        0x4000	/* NMI Interrupt Mask */
+#define SH7750_ICR_NMIL       0x8000 /* NMI Input Level */
+#define SH7750_ICR_MAI        0x4000 /* NMI Interrupt Mask */
 
-#define SH7750_ICR_NMIB       0x0200	/* NMI Block Mode: */
-#define SH7750_ICR_NMIB_BLK   0x0000	/*   NMI requests held pending while
-					   SR.BL bit is set to 1 */
-#define SH7750_ICR_NMIB_NBLK  0x0200	/*   NMI requests detected when SR.BL bit
-					   set to 1 */
+#define SH7750_ICR_NMIB       0x0200 /* NMI Block Mode: */
+#define SH7750_ICR_NMIB_BLK   0x0000 /*   NMI requests held pending while */
+                                     /*     SR.BL bit is set to 1 */
+#define SH7750_ICR_NMIB_NBLK  0x0200 /*   NMI requests detected when SR.BL */
+                                     /*     bit set to 1 */
 
-#define SH7750_ICR_NMIE       0x0100	/* NMI Edge Select: */
-#define SH7750_ICR_NMIE_FALL  0x0000	/*   Interrupt request detected on falling
-					   edge of NMI input */
-#define SH7750_ICR_NMIE_RISE  0x0100	/*   Interrupt request detected on rising
-					   edge of NMI input */
+#define SH7750_ICR_NMIE       0x0100 /* NMI Edge Select: */
+#define SH7750_ICR_NMIE_FALL  0x0000 /*   Interrupt request detected on */
+                                     /*     falling edge of NMI input */
+#define SH7750_ICR_NMIE_RISE  0x0100 /*   Interrupt request detected on */
+                                     /*     rising edge of NMI input */
 
-#define SH7750_ICR_IRLM       0x0080	/* IRL Pin Mode: */
-#define SH7750_ICR_IRLM_ENC   0x0000	/*   IRL\ pins used as a level-encoded
-					   interrupt requests */
-#define SH7750_ICR_IRLM_RAW   0x0080	/*   IRL\ pins used as a four independent
-					   interrupt requests */
+#define SH7750_ICR_IRLM       0x0080 /* IRL Pin Mode: */
+#define SH7750_ICR_IRLM_ENC   0x0000 /*   IRL\ pins used as a level-encoded */
+                                     /*     interrupt requests */
+#define SH7750_ICR_IRLM_RAW   0x0080 /*   IRL\ pins used as a four */
+                                     /*     independent interrupt requests */
 
 /*
  * User Break Controller registers
  */
-#define SH7750_BARA           0x200000	/* Break address regiser A */
-#define SH7750_BAMRA          0x200004	/* Break address mask regiser A */
-#define SH7750_BBRA           0x200008	/* Break bus cycle regiser A */
-#define SH7750_BARB           0x20000c	/* Break address regiser B */
-#define SH7750_BAMRB          0x200010	/* Break address mask regiser B */
-#define SH7750_BBRB           0x200014	/* Break bus cycle regiser B */
-#define SH7750_BASRB          0x000018	/* Break ASID regiser B */
-#define SH7750_BDRB           0x200018	/* Break data regiser B */
-#define SH7750_BDMRB          0x20001c	/* Break data mask regiser B */
-#define SH7750_BRCR           0x200020	/* Break control register */
-
-#define SH7750_BRCR_UDBE        0x0001	/* User break debug enable bit */
+#define SH7750_BARA           0x200000 /* Break address regiser A */
+#define SH7750_BAMRA          0x200004 /* Break address mask regiser A */
+#define SH7750_BBRA           0x200008 /* Break bus cycle regiser A */
+#define SH7750_BARB           0x20000c /* Break address regiser B */
+#define SH7750_BAMRB          0x200010 /* Break address mask regiser B */
+#define SH7750_BBRB           0x200014 /* Break bus cycle regiser B */
+#define SH7750_BASRB          0x000018 /* Break ASID regiser B */
+#define SH7750_BDRB           0x200018 /* Break data regiser B */
+#define SH7750_BDMRB          0x20001c /* Break data mask regiser B */
+#define SH7750_BRCR           0x200020 /* Break control register */
+
+#define SH7750_BRCR_UDBE        0x0001 /* User break debug enable bit */
 
 /*
  * Missing in RTEMS, added for QEMU
diff --git a/hw/sh4/shix.c b/hw/sh4/shix.c
index b0579aa0f1..aa812512f0 100644
--- a/hw/sh4/shix.c
+++ b/hw/sh4/shix.c
@@ -22,11 +22,11 @@
  * THE SOFTWARE.
  */
 /*
-   Shix 2.0 board by Alexis Polti, described at
-   https://web.archive.org/web/20070917001736/perso.enst.fr/~polti/realisations/shix20
-
-   More information in target/sh4/README.sh4
-*/
+ * Shix 2.0 board by Alexis Polti, described at
+ * https://web.archive.org/web/20070917001736/perso.enst.fr/~polti/realisations/shix20
+ *
+ * More information in target/sh4/README.sh4
+ */
 #include "qemu/osdep.h"
 #include "qapi/error.h"
 #include "cpu.h"
@@ -48,7 +48,7 @@ static void shix_init(MachineState *machine)
     MemoryRegion *rom = g_new(MemoryRegion, 1);
     MemoryRegion *sdram = g_new(MemoryRegion, 2);
     const char *bios_name = machine->firmware ?: BIOS_FILENAME;
-    
+
     cpu = SUPERH_CPU(cpu_create(machine->cpu_type));
 
     /* Allocate memory space */
diff --git a/hw/sh4/trace-events b/hw/sh4/trace-events
new file mode 100644
index 0000000000..4b61cd56c8
--- /dev/null
+++ b/hw/sh4/trace-events
@@ -0,0 +1,3 @@
+# sh7750.c
+sh7750_porta(uint16_t prev, uint16_t cur, uint16_t pdtr, uint16_t pctr) "porta changed from 0x%04x to 0x%04x\npdtra=0x%04x, pctra=0x%08x"
+sh7750_portb(uint16_t prev, uint16_t cur, uint16_t pdtr, uint16_t pctr) "portb changed from 0x%04x to 0x%04x\npdtrb=0x%04x, pctrb=0x%08x"
diff --git a/hw/sh4/trace.h b/hw/sh4/trace.h
new file mode 100644
index 0000000000..e2c13323b7
--- /dev/null
+++ b/hw/sh4/trace.h
@@ -0,0 +1 @@
+#include "trace/trace-hw_sh4.h"
diff --git a/hw/timer/sh_timer.c b/hw/timer/sh_timer.c
index 58af1a1edb..c72c327bfa 100644
--- a/hw/timer/sh_timer.c
+++ b/hw/timer/sh_timer.c
@@ -10,13 +10,12 @@
 
 #include "qemu/osdep.h"
 #include "exec/memory.h"
-#include "hw/hw.h"
+#include "qemu/log.h"
 #include "hw/irq.h"
 #include "hw/sh4/sh.h"
 #include "hw/timer/tmu012.h"
 #include "hw/ptimer.h"
-
-//#define DEBUG_TIMER
+#include "trace.h"
 
 #define TIMER_TCR_TPSC          (7 << 0)
 #define TIMER_TCR_CKEG          (3 << 3)
@@ -46,24 +45,24 @@ typedef struct {
     int feat;
     int enabled;
     qemu_irq irq;
-} sh_timer_state;
+} SHTimerState;
 
 /* Check all active timers, and schedule the next timer interrupt. */
 
-static void sh_timer_update(sh_timer_state *s)
+static void sh_timer_update(SHTimerState *s)
 {
     int new_level = s->int_level && (s->tcr & TIMER_TCR_UNIE);
 
-    if (new_level != s->old_level)
-      qemu_set_irq (s->irq, new_level);
-
+    if (new_level != s->old_level) {
+        qemu_set_irq(s->irq, new_level);
+    }
     s->old_level = s->int_level;
     s->int_level = new_level;
 }
 
 static uint32_t sh_timer_read(void *opaque, hwaddr offset)
 {
-    sh_timer_state *s = (sh_timer_state *)opaque;
+    SHTimerState *s = opaque;
 
     switch (offset >> 2) {
     case OFFSET_TCOR:
@@ -73,19 +72,18 @@ static uint32_t sh_timer_read(void *opaque, hwaddr offset)
     case OFFSET_TCR:
         return s->tcr | (s->int_level ? TIMER_TCR_UNF : 0);
     case OFFSET_TCPR:
-        if (s->feat & TIMER_FEAT_CAPT)
+        if (s->feat & TIMER_FEAT_CAPT) {
             return s->tcpr;
-        /* fall through */
-    default:
-        hw_error("sh_timer_read: Bad offset %x\n", (int)offset);
-        return 0;
+        }
     }
+    qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIx "\n",
+                  __func__, offset);
+    return 0;
 }
 
-static void sh_timer_write(void *opaque, hwaddr offset,
-                            uint32_t value)
+static void sh_timer_write(void *opaque, hwaddr offset, uint32_t value)
 {
-    sh_timer_state *s = (sh_timer_state *)opaque;
+    SHTimerState *s = opaque;
     int freq;
 
     switch (offset >> 2) {
@@ -104,19 +102,30 @@ static void sh_timer_write(void *opaque, hwaddr offset,
     case OFFSET_TCR:
         ptimer_transaction_begin(s->timer);
         if (s->enabled) {
-            /* Pause the timer if it is running.  This may cause some
-               inaccuracy dure to rounding, but avoids a whole lot of other
-               messyness.  */
+            /*
+             * Pause the timer if it is running. This may cause some inaccuracy
+             * due to rounding, but avoids a whole lot of other messiness
+             */
             ptimer_stop(s->timer);
         }
         freq = s->freq;
         /* ??? Need to recalculate expiry time after changing divisor.  */
         switch (value & TIMER_TCR_TPSC) {
-        case 0: freq >>= 2; break;
-        case 1: freq >>= 4; break;
-        case 2: freq >>= 6; break;
-        case 3: freq >>= 8; break;
-        case 4: freq >>= 10; break;
+        case 0:
+            freq >>= 2;
+            break;
+        case 1:
+            freq >>= 4;
+            break;
+        case 2:
+            freq >>= 6;
+            break;
+        case 3:
+            freq >>= 8;
+            break;
+        case 4:
+            freq >>= 10;
+            break;
         case 6:
         case 7:
             if (s->feat & TIMER_FEAT_EXTCLK) {
@@ -124,7 +133,8 @@ static void sh_timer_write(void *opaque, hwaddr offset,
             }
             /* fallthrough */
         default:
-            hw_error("sh_timer_write: Reserved TPSC value\n");
+            qemu_log_mask(LOG_GUEST_ERROR,
+                          "%s: Reserved TPSC value\n", __func__);
         }
         switch ((value & TIMER_TCR_CKEG) >> 3) {
         case 0:
@@ -137,7 +147,8 @@ static void sh_timer_write(void *opaque, hwaddr offset,
             }
             /* fallthrough */
         default:
-            hw_error("sh_timer_write: Reserved CKEG value\n");
+            qemu_log_mask(LOG_GUEST_ERROR,
+                          "%s: Reserved CKEG value\n", __func__);
         }
         switch ((value & TIMER_TCR_ICPE) >> 6) {
         case 0:
@@ -149,7 +160,8 @@ static void sh_timer_write(void *opaque, hwaddr offset,
             }
             /* fallthrough */
         default:
-            hw_error("sh_timer_write: Reserved ICPE value\n");
+            qemu_log_mask(LOG_GUEST_ERROR,
+                          "%s: Reserved ICPE value\n", __func__);
         }
         if ((value & TIMER_TCR_UNF) == 0) {
             s->int_level = 0;
@@ -158,13 +170,15 @@ static void sh_timer_write(void *opaque, hwaddr offset,
         value &= ~TIMER_TCR_UNF;
 
         if ((value & TIMER_TCR_ICPF) && (!(s->feat & TIMER_FEAT_CAPT))) {
-            hw_error("sh_timer_write: Reserved ICPF value\n");
+            qemu_log_mask(LOG_GUEST_ERROR,
+                          "%s: Reserved ICPF value\n", __func__);
         }
 
         value &= ~TIMER_TCR_ICPF; /* capture not supported */
 
         if (value & TIMER_TCR_RESERVED) {
-            hw_error("sh_timer_write: Reserved TCR bits set\n");
+            qemu_log_mask(LOG_GUEST_ERROR,
+                          "%s: Reserved TCR bits set\n", __func__);
         }
         s->tcr = value;
         ptimer_set_limit(s->timer, s->tcor, 0);
@@ -182,19 +196,17 @@ static void sh_timer_write(void *opaque, hwaddr offset,
         }
         /* fallthrough */
     default:
-        hw_error("sh_timer_write: Bad offset %x\n", (int)offset);
+        qemu_log_mask(LOG_GUEST_ERROR,
+                      "%s: Bad offset 0x%" HWADDR_PRIx "\n", __func__, offset);
     }
     sh_timer_update(s);
 }
 
 static void sh_timer_start_stop(void *opaque, int enable)
 {
-    sh_timer_state *s = (sh_timer_state *)opaque;
-
-#ifdef DEBUG_TIMER
-    printf("sh_timer_start_stop %d (%d)\n", enable, s->enabled);
-#endif
+    SHTimerState *s = opaque;
 
+    trace_sh_timer_start_stop(enable, s->enabled);
     ptimer_transaction_begin(s->timer);
     if (s->enabled && !enable) {
         ptimer_stop(s->timer);
@@ -204,24 +216,20 @@ static void sh_timer_start_stop(void *opaque, int enable)
     }
     ptimer_transaction_commit(s->timer);
     s->enabled = !!enable;
-
-#ifdef DEBUG_TIMER
-    printf("sh_timer_start_stop done %d\n", s->enabled);
-#endif
 }
 
 static void sh_timer_tick(void *opaque)
 {
-    sh_timer_state *s = (sh_timer_state *)opaque;
+    SHTimerState *s = opaque;
     s->int_level = s->enabled;
     sh_timer_update(s);
 }
 
 static void *sh_timer_init(uint32_t freq, int feat, qemu_irq irq)
 {
-    sh_timer_state *s;
+    SHTimerState *s;
 
-    s = (sh_timer_state *)g_malloc0(sizeof(sh_timer_state));
+    s = g_malloc0(sizeof(*s));
     s->freq = freq;
     s->feat = feat;
     s->tcor = 0xffffffff;
@@ -252,50 +260,49 @@ typedef struct {
     int feat;
 } tmu012_state;
 
-static uint64_t tmu012_read(void *opaque, hwaddr offset,
-                            unsigned size)
+static uint64_t tmu012_read(void *opaque, hwaddr offset, unsigned size)
 {
-    tmu012_state *s = (tmu012_state *)opaque;
-
-#ifdef DEBUG_TIMER
-    printf("tmu012_read 0x%lx\n", (unsigned long) offset);
-#endif
+    tmu012_state *s = opaque;
 
+    trace_sh_timer_read(offset);
     if (offset >= 0x20) {
         if (!(s->feat & TMU012_FEAT_3CHAN)) {
-            hw_error("tmu012_write: Bad channel offset %x\n", (int)offset);
+            qemu_log_mask(LOG_GUEST_ERROR,
+                          "%s: Bad channel offset 0x%" HWADDR_PRIx "\n",
+                          __func__, offset);
         }
         return sh_timer_read(s->timer[2], offset - 0x20);
     }
 
-    if (offset >= 0x14)
+    if (offset >= 0x14) {
         return sh_timer_read(s->timer[1], offset - 0x14);
-
-    if (offset >= 0x08)
+    }
+    if (offset >= 0x08) {
         return sh_timer_read(s->timer[0], offset - 0x08);
-
-    if (offset == 4)
+    }
+    if (offset == 4) {
         return s->tstr;
-
-    if ((s->feat & TMU012_FEAT_TOCR) && offset == 0)
+    }
+    if ((s->feat & TMU012_FEAT_TOCR) && offset == 0) {
         return s->tocr;
+    }
 
-    hw_error("tmu012_write: Bad offset %x\n", (int)offset);
+    qemu_log_mask(LOG_GUEST_ERROR,
+                  "%s: Bad offset 0x%" HWADDR_PRIx "\n", __func__, offset);
     return 0;
 }
 
 static void tmu012_write(void *opaque, hwaddr offset,
                         uint64_t value, unsigned size)
 {
-    tmu012_state *s = (tmu012_state *)opaque;
-
-#ifdef DEBUG_TIMER
-    printf("tmu012_write 0x%lx 0x%08x\n", (unsigned long) offset, value);
-#endif
+    tmu012_state *s = opaque;
 
+    trace_sh_timer_write(offset, value);
     if (offset >= 0x20) {
         if (!(s->feat & TMU012_FEAT_3CHAN)) {
-            hw_error("tmu012_write: Bad channel offset %x\n", (int)offset);
+            qemu_log_mask(LOG_GUEST_ERROR,
+                          "%s: Bad channel offset 0x%" HWADDR_PRIx "\n",
+                          __func__, offset);
         }
         sh_timer_write(s->timer[2], offset - 0x20, value);
         return;
@@ -318,7 +325,7 @@ static void tmu012_write(void *opaque, hwaddr offset,
             sh_timer_start_stop(s->timer[2], value & (1 << 2));
         } else {
             if (value & (1 << 2)) {
-                hw_error("tmu012_write: Bad channel\n");
+                qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad channel\n", __func__);
             }
         }
 
@@ -337,15 +344,14 @@ static const MemoryRegionOps tmu012_ops = {
     .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
-void tmu012_init(MemoryRegion *sysmem, hwaddr base,
-                 int feat, uint32_t freq,
+void tmu012_init(MemoryRegion *sysmem, hwaddr base, int feat, uint32_t freq,
                  qemu_irq ch0_irq, qemu_irq ch1_irq,
                  qemu_irq ch2_irq0, qemu_irq ch2_irq1)
 {
     tmu012_state *s;
     int timer_feat = (feat & TMU012_FEAT_EXTCLK) ? TIMER_FEAT_EXTCLK : 0;
 
-    s = (tmu012_state *)g_malloc0(sizeof(tmu012_state));
+    s = g_malloc0(sizeof(*s));
     s->feat = feat;
     s->timer[0] = sh_timer_init(freq, timer_feat, ch0_irq);
     s->timer[1] = sh_timer_init(freq, timer_feat, ch1_irq);
@@ -354,15 +360,14 @@ void tmu012_init(MemoryRegion *sysmem, hwaddr base,
                                     ch2_irq0); /* ch2_irq1 not supported */
     }
 
-    memory_region_init_io(&s->iomem, NULL, &tmu012_ops, s,
-                          "timer", 0x100000000ULL);
+    memory_region_init_io(&s->iomem, NULL, &tmu012_ops, s, "timer", 0x30);
 
     memory_region_init_alias(&s->iomem_p4, NULL, "timer-p4",
-                             &s->iomem, 0, 0x1000);
+                             &s->iomem, 0, memory_region_size(&s->iomem));
     memory_region_add_subregion(sysmem, P4ADDR(base), &s->iomem_p4);
 
     memory_region_init_alias(&s->iomem_a7, NULL, "timer-a7",
-                             &s->iomem, 0, 0x1000);
+                             &s->iomem, 0, memory_region_size(&s->iomem));
     memory_region_add_subregion(sysmem, A7ADDR(base), &s->iomem_a7);
     /* ??? Save/restore.  */
 }
diff --git a/hw/timer/trace-events b/hw/timer/trace-events
index d0edcd2a80..3eccef8385 100644
--- a/hw/timer/trace-events
+++ b/hw/timer/trace-events
@@ -94,3 +94,8 @@ sifive_pwm_set_alarm(uint64_t alarm, uint64_t now) "Setting alarm to: 0x%" PRIx6
 sifive_pwm_interrupt(int num) "Interrupt %d"
 sifive_pwm_read(uint64_t offset) "Read at address: 0x%" PRIx64
 sifive_pwm_write(uint64_t data, uint64_t offset) "Write 0x%" PRIx64 " at address: 0x%" PRIx64
+
+# sh_timer.c
+sh_timer_start_stop(int enable, int current) "%d (%d)"
+sh_timer_read(uint64_t offset) "tmu012_read 0x%" PRIx64
+sh_timer_write(uint64_t offset, uint64_t value) "tmu012_write 0x%" PRIx64 " 0x%08" PRIx64
diff --git a/hw/vfio/common.c b/hw/vfio/common.c
index a784b219e6..dd387b0d39 100644
--- a/hw/vfio/common.c
+++ b/hw/vfio/common.c
@@ -893,6 +893,13 @@ static void vfio_listener_region_add(MemoryListener *listener,
     llend = int128_and(llend, int128_exts64(qemu_real_host_page_mask));
 
     if (int128_ge(int128_make64(iova), llend)) {
+        if (memory_region_is_ram_device(section->mr)) {
+            trace_vfio_listener_region_add_no_dma_map(
+                memory_region_name(section->mr),
+                section->offset_within_address_space,
+                int128_getlo(section->size),
+                qemu_real_host_page_size);
+        }
         return;
     }
     end = int128_get64(int128_sub(llend, int128_one()));
diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c
index 5cdf1d4298..7b45353ce2 100644
--- a/hw/vfio/pci.c
+++ b/hw/vfio/pci.c
@@ -2453,7 +2453,12 @@ static int vfio_pci_load_config(VFIODevice *vbasedev, QEMUFile *f)
 {
     VFIOPCIDevice *vdev = container_of(vbasedev, VFIOPCIDevice, vbasedev);
     PCIDevice *pdev = &vdev->pdev;
-    int ret;
+    pcibus_t old_addr[PCI_NUM_REGIONS - 1];
+    int bar, ret;
+
+    for (bar = 0; bar < PCI_ROM_SLOT; bar++) {
+        old_addr[bar] = pdev->io_regions[bar].addr;
+    }
 
     ret = vmstate_load_state(f, &vmstate_vfio_pci_config, vdev, 1);
     if (ret) {
@@ -2463,6 +2468,18 @@ static int vfio_pci_load_config(VFIODevice *vbasedev, QEMUFile *f)
     vfio_pci_write_config(pdev, PCI_COMMAND,
                           pci_get_word(pdev->config + PCI_COMMAND), 2);
 
+    for (bar = 0; bar < PCI_ROM_SLOT; bar++) {
+        /*
+         * The address may not be changed in some scenarios
+         * (e.g. the VF driver isn't loaded in VM).
+         */
+        if (old_addr[bar] != pdev->io_regions[bar].addr &&
+            vdev->bars[bar].region.size > 0 &&
+            vdev->bars[bar].region.size < qemu_real_host_page_size) {
+            vfio_sub_page_bar_update_mapping(pdev, bar);
+        }
+    }
+
     if (msi_enabled(pdev)) {
         vfio_msi_enable(vdev);
     } else if (msix_enabled(pdev)) {
diff --git a/hw/virtio/virtio-mem.c b/hw/virtio/virtio-mem.c
index df91e454b2..d5a578142b 100644
--- a/hw/virtio/virtio-mem.c
+++ b/hw/virtio/virtio-mem.c
@@ -228,6 +228,38 @@ static int virtio_mem_for_each_plugged_section(const VirtIOMEM *vmem,
     return ret;
 }
 
+static int virtio_mem_for_each_unplugged_section(const VirtIOMEM *vmem,
+                                                 MemoryRegionSection *s,
+                                                 void *arg,
+                                                 virtio_mem_section_cb cb)
+{
+    unsigned long first_bit, last_bit;
+    uint64_t offset, size;
+    int ret = 0;
+
+    first_bit = s->offset_within_region / vmem->bitmap_size;
+    first_bit = find_next_zero_bit(vmem->bitmap, vmem->bitmap_size, first_bit);
+    while (first_bit < vmem->bitmap_size) {
+        MemoryRegionSection tmp = *s;
+
+        offset = first_bit * vmem->block_size;
+        last_bit = find_next_bit(vmem->bitmap, vmem->bitmap_size,
+                                 first_bit + 1) - 1;
+        size = (last_bit - first_bit + 1) * vmem->block_size;
+
+        if (!virito_mem_intersect_memory_section(&tmp, offset, size)) {
+            break;
+        }
+        ret = cb(&tmp, arg);
+        if (ret) {
+            break;
+        }
+        first_bit = find_next_zero_bit(vmem->bitmap, vmem->bitmap_size,
+                                       last_bit + 2);
+    }
+    return ret;
+}
+
 static int virtio_mem_notify_populate_cb(MemoryRegionSection *s, void *arg)
 {
     RamDiscardListener *rdl = arg;
@@ -744,7 +776,6 @@ static void virtio_mem_device_realize(DeviceState *dev, Error **errp)
     host_memory_backend_set_mapped(vmem->memdev, true);
     vmstate_register_ram(&vmem->memdev->mr, DEVICE(vmem));
     qemu_register_reset(virtio_mem_system_reset, vmem);
-    precopy_add_notifier(&vmem->precopy_notifier);
 
     /*
      * Set ourselves as RamDiscardManager before the plug handler maps the
@@ -764,7 +795,6 @@ static void virtio_mem_device_unrealize(DeviceState *dev)
      * found via an address space anymore. Unset ourselves.
      */
     memory_region_set_ram_discard_manager(&vmem->memdev->mr, NULL);
-    precopy_remove_notifier(&vmem->precopy_notifier);
     qemu_unregister_reset(virtio_mem_system_reset, vmem);
     vmstate_unregister_ram(&vmem->memdev->mr, DEVICE(vmem));
     host_memory_backend_set_mapped(vmem->memdev, false);
@@ -1057,43 +1087,11 @@ static void virtio_mem_set_block_size(Object *obj, Visitor *v, const char *name,
     vmem->block_size = value;
 }
 
-static int virtio_mem_precopy_exclude_range_cb(const VirtIOMEM *vmem, void *arg,
-                                               uint64_t offset, uint64_t size)
-{
-    void * const host = qemu_ram_get_host_addr(vmem->memdev->mr.ram_block);
-
-    qemu_guest_free_page_hint(host + offset, size);
-    return 0;
-}
-
-static void virtio_mem_precopy_exclude_unplugged(VirtIOMEM *vmem)
-{
-    virtio_mem_for_each_unplugged_range(vmem, NULL,
-                                        virtio_mem_precopy_exclude_range_cb);
-}
-
-static int virtio_mem_precopy_notify(NotifierWithReturn *n, void *data)
-{
-    VirtIOMEM *vmem = container_of(n, VirtIOMEM, precopy_notifier);
-    PrecopyNotifyData *pnd = data;
-
-    switch (pnd->reason) {
-    case PRECOPY_NOTIFY_AFTER_BITMAP_SYNC:
-        virtio_mem_precopy_exclude_unplugged(vmem);
-        break;
-    default:
-        break;
-    }
-
-    return 0;
-}
-
 static void virtio_mem_instance_init(Object *obj)
 {
     VirtIOMEM *vmem = VIRTIO_MEM(obj);
 
     notifier_list_init(&vmem->size_change_notifiers);
-    vmem->precopy_notifier.notify = virtio_mem_precopy_notify;
     QLIST_INIT(&vmem->rdl_list);
 
     object_property_add(obj, VIRTIO_MEM_SIZE_PROP, "size", virtio_mem_get_size,
@@ -1170,6 +1168,31 @@ static int virtio_mem_rdm_replay_populated(const RamDiscardManager *rdm,
                                             virtio_mem_rdm_replay_populated_cb);
 }
 
+static int virtio_mem_rdm_replay_discarded_cb(MemoryRegionSection *s,
+                                              void *arg)
+{
+    struct VirtIOMEMReplayData *data = arg;
+
+    ((ReplayRamDiscard)data->fn)(s, data->opaque);
+    return 0;
+}
+
+static void virtio_mem_rdm_replay_discarded(const RamDiscardManager *rdm,
+                                            MemoryRegionSection *s,
+                                            ReplayRamDiscard replay_fn,
+                                            void *opaque)
+{
+    const VirtIOMEM *vmem = VIRTIO_MEM(rdm);
+    struct VirtIOMEMReplayData data = {
+        .fn = replay_fn,
+        .opaque = opaque,
+    };
+
+    g_assert(s->mr == &vmem->memdev->mr);
+    virtio_mem_for_each_unplugged_section(vmem, s, &data,
+                                          virtio_mem_rdm_replay_discarded_cb);
+}
+
 static void virtio_mem_rdm_register_listener(RamDiscardManager *rdm,
                                              RamDiscardListener *rdl,
                                              MemoryRegionSection *s)
@@ -1234,6 +1257,7 @@ static void virtio_mem_class_init(ObjectClass *klass, void *data)
     rdmc->get_min_granularity = virtio_mem_rdm_get_min_granularity;
     rdmc->is_populated = virtio_mem_rdm_is_populated;
     rdmc->replay_populated = virtio_mem_rdm_replay_populated;
+    rdmc->replay_discarded = virtio_mem_rdm_replay_discarded;
     rdmc->register_listener = virtio_mem_rdm_register_listener;
     rdmc->unregister_listener = virtio_mem_rdm_unregister_listener;
 }
diff --git a/include/exec/memory.h b/include/exec/memory.h
index a185b6dcb8..20f1b27377 100644
--- a/include/exec/memory.h
+++ b/include/exec/memory.h
@@ -61,7 +61,17 @@ static inline void fuzz_dma_read_cb(size_t addr,
 }
 #endif
 
-extern bool global_dirty_log;
+/* Possible bits for global_dirty_log_{start|stop} */
+
+/* Dirty tracking enabled because migration is running */
+#define GLOBAL_DIRTY_MIGRATION  (1U << 0)
+
+/* Dirty tracking enabled because measuring dirty rate */
+#define GLOBAL_DIRTY_DIRTY_RATE (1U << 1)
+
+#define GLOBAL_DIRTY_MASK  (0x3)
+
+extern unsigned int global_dirty_tracking;
 
 typedef struct MemoryRegionOps MemoryRegionOps;
 
@@ -540,6 +550,7 @@ static inline void ram_discard_listener_init(RamDiscardListener *rdl,
 }
 
 typedef int (*ReplayRamPopulate)(MemoryRegionSection *section, void *opaque);
+typedef void (*ReplayRamDiscard)(MemoryRegionSection *section, void *opaque);
 
 /*
  * RamDiscardManagerClass:
@@ -629,6 +640,21 @@ struct RamDiscardManagerClass {
                             ReplayRamPopulate replay_fn, void *opaque);
 
     /**
+     * @replay_discarded:
+     *
+     * Call the #ReplayRamDiscard callback for all discarded parts within the
+     * #MemoryRegionSection via the #RamDiscardManager.
+     *
+     * @rdm: the #RamDiscardManager
+     * @section: the #MemoryRegionSection
+     * @replay_fn: the #ReplayRamDiscard callback
+     * @opaque: pointer to forward to the callback
+     */
+    void (*replay_discarded)(const RamDiscardManager *rdm,
+                             MemoryRegionSection *section,
+                             ReplayRamDiscard replay_fn, void *opaque);
+
+    /**
      * @register_listener:
      *
      * Register a #RamDiscardListener for the given #MemoryRegionSection and
@@ -672,6 +698,11 @@ int ram_discard_manager_replay_populated(const RamDiscardManager *rdm,
                                          ReplayRamPopulate replay_fn,
                                          void *opaque);
 
+void ram_discard_manager_replay_discarded(const RamDiscardManager *rdm,
+                                          MemoryRegionSection *section,
+                                          ReplayRamDiscard replay_fn,
+                                          void *opaque);
+
 void ram_discard_manager_register_listener(RamDiscardManager *rdm,
                                            RamDiscardListener *rdl,
                                            MemoryRegionSection *section);
@@ -2388,13 +2419,17 @@ void memory_listener_unregister(MemoryListener *listener);
 
 /**
  * memory_global_dirty_log_start: begin dirty logging for all regions
+ *
+ * @flags: purpose of starting dirty log, migration or dirty rate
  */
-void memory_global_dirty_log_start(void);
+void memory_global_dirty_log_start(unsigned int flags);
 
 /**
  * memory_global_dirty_log_stop: end dirty logging for all regions
+ *
+ * @flags: purpose of stopping dirty log, migration or dirty rate
  */
-void memory_global_dirty_log_stop(void);
+void memory_global_dirty_log_stop(unsigned int flags);
 
 void mtree_info(bool flatview, bool dispatch_tree, bool owner, bool disabled);
 
diff --git a/include/exec/ram_addr.h b/include/exec/ram_addr.h
index 551876bed0..64fb936c7c 100644
--- a/include/exec/ram_addr.h
+++ b/include/exec/ram_addr.h
@@ -26,6 +26,8 @@
 #include "exec/ramlist.h"
 #include "exec/ramblock.h"
 
+extern uint64_t total_dirty_pages;
+
 /**
  * clear_bmap_size: calculate clear bitmap size
  *
@@ -369,10 +371,14 @@ static inline void cpu_physical_memory_set_dirty_lebitmap(unsigned long *bitmap,
 
                     qatomic_or(&blocks[DIRTY_MEMORY_VGA][idx][offset], temp);
 
-                    if (global_dirty_log) {
+                    if (global_dirty_tracking) {
                         qatomic_or(
                                 &blocks[DIRTY_MEMORY_MIGRATION][idx][offset],
                                 temp);
+                        if (unlikely(
+                            global_dirty_tracking & GLOBAL_DIRTY_DIRTY_RATE)) {
+                            total_dirty_pages += ctpopl(temp);
+                        }
                     }
 
                     if (tcg_enabled()) {
@@ -392,7 +398,7 @@ static inline void cpu_physical_memory_set_dirty_lebitmap(unsigned long *bitmap,
     } else {
         uint8_t clients = tcg_enabled() ? DIRTY_CLIENTS_ALL : DIRTY_CLIENTS_NOCODE;
 
-        if (!global_dirty_log) {
+        if (!global_dirty_tracking) {
             clients &= ~(1 << DIRTY_MEMORY_MIGRATION);
         }
 
@@ -403,6 +409,9 @@ static inline void cpu_physical_memory_set_dirty_lebitmap(unsigned long *bitmap,
         for (i = 0; i < len; i++) {
             if (bitmap[i] != 0) {
                 c = leul_to_cpu(bitmap[i]);
+                if (unlikely(global_dirty_tracking & GLOBAL_DIRTY_DIRTY_RATE)) {
+                    total_dirty_pages += ctpopl(c);
+                }
                 do {
                     j = ctzl(c);
                     c &= ~(1ul << j);
diff --git a/include/hw/boards.h b/include/hw/boards.h
index 5adbcbb99b..9c1c190104 100644
--- a/include/hw/boards.h
+++ b/include/hw/boards.h
@@ -34,6 +34,7 @@ HotpluggableCPUList *machine_query_hotpluggable_cpus(MachineState *machine);
 void machine_set_cpu_numa_node(MachineState *machine,
                                const CpuInstanceProperties *props,
                                Error **errp);
+void smp_parse(MachineState *ms, SMPConfiguration *config, Error **errp);
 
 /**
  * machine_class_allow_dynamic_sysbus_dev: Add type to list of valid devices
@@ -52,6 +53,21 @@ void machine_set_cpu_numa_node(MachineState *machine,
 void machine_class_allow_dynamic_sysbus_dev(MachineClass *mc, const char *type);
 
 /**
+ * device_type_is_dynamic_sysbus: Check if type is an allowed sysbus device
+ * type for the machine class.
+ * @mc: Machine class
+ * @type: type to check (should be a subtype of TYPE_SYS_BUS_DEVICE)
+ *
+ * Returns: true if @type is a type in the machine's list of
+ * dynamically pluggable sysbus devices; otherwise false.
+ *
+ * Check if the QOM type @type is in the list of allowed sysbus device
+ * types (see machine_class_allowed_dynamic_sysbus_dev()).
+ * Note that if @type has a parent type in the list, it is allowed too.
+ */
+bool device_type_is_dynamic_sysbus(MachineClass *mc, const char *type);
+
+/**
  * device_is_dynamic_sysbus: test whether device is a dynamic sysbus device
  * @mc: Machine class
  * @dev: device to check
@@ -301,7 +317,6 @@ typedef struct CpuTopology {
 struct MachineState {
     /*< private >*/
     Object parent_obj;
-    Notifier sysbus_notifier;
 
     /*< public >*/
 
diff --git a/include/hw/core/cpu.h b/include/hw/core/cpu.h
index 1a10497af3..e948e81f1a 100644
--- a/include/hw/core/cpu.h
+++ b/include/hw/core/cpu.h
@@ -381,6 +381,7 @@ struct CPUState {
     struct kvm_run *kvm_run;
     struct kvm_dirty_gfn *kvm_dirty_gfns;
     uint32_t kvm_fetch_index;
+    uint64_t dirty_pages;
 
     /* Used for events with 'vcpu' and *without* the 'disabled' properties */
     DECLARE_BITMAP(trace_dstate_delayed, CPU_TRACE_DSTATE_MAX_EVENTS);
diff --git a/include/hw/sh4/sh.h b/include/hw/sh4/sh.h
index becb596979..ec716cdd45 100644
--- a/include/hw/sh4/sh.h
+++ b/include/hw/sh4/sh.h
@@ -44,25 +44,18 @@ typedef struct {
     uint16_t portbmask_trigger;
     /* Return 0 if no action was taken */
     int (*port_change_cb) (uint16_t porta, uint16_t portb,
-			   uint16_t * periph_pdtra,
-			   uint16_t * periph_portdira,
-			   uint16_t * periph_pdtrb,
-			   uint16_t * periph_portdirb);
+                           uint16_t *periph_pdtra,
+                           uint16_t *periph_portdira,
+                           uint16_t *periph_pdtrb,
+                           uint16_t *periph_portdirb);
 } sh7750_io_device;
 
 int sh7750_register_io_device(struct SH7750State *s,
-			      sh7750_io_device * device);
+                              sh7750_io_device *device);
 
 /* sh_serial.c */
+#define TYPE_SH_SERIAL "sh-serial"
 #define SH_SERIAL_FEAT_SCIF (1 << 0)
-void sh_serial_init(MemoryRegion *sysmem,
-                    hwaddr base, int feat,
-                    uint32_t freq, Chardev *chr,
-		     qemu_irq eri_source,
-		     qemu_irq rxi_source,
-		     qemu_irq txi_source,
-		     qemu_irq tei_source,
-		     qemu_irq bri_source);
 
 /* sh7750.c */
 qemu_irq sh7750_irl(struct SH7750State *s);
diff --git a/include/hw/sh4/sh_intc.h b/include/hw/sh4/sh_intc.h
index 65f3425057..f62d5c5e13 100644
--- a/include/hw/sh4/sh_intc.h
+++ b/include/hw/sh4/sh_intc.h
@@ -58,7 +58,7 @@ struct intc_desc {
 };
 
 int sh_intc_get_pending_vector(struct intc_desc *desc, int imask);
-struct intc_source *sh_intc_source(struct intc_desc *desc, intc_enum id);
+
 void sh_intc_toggle_source(struct intc_source *source,
                            int enable_adj, int assert_adj);
 
diff --git a/include/hw/virtio/virtio-mem.h b/include/hw/virtio/virtio-mem.h
index 9a6e348fa2..a5dd6a493b 100644
--- a/include/hw/virtio/virtio-mem.h
+++ b/include/hw/virtio/virtio-mem.h
@@ -65,9 +65,6 @@ struct VirtIOMEM {
     /* notifiers to notify when "size" changes */
     NotifierList size_change_notifiers;
 
-    /* don't migrate unplugged memory */
-    NotifierWithReturn precopy_notifier;
-
     /* listeners to notify on plug/unplug activity. */
     QLIST_HEAD(, RamDiscardListener) rdl_list;
 };
diff --git a/include/migration/blocker.h b/include/migration/blocker.h
index acd27018e9..9cebe2ba06 100644
--- a/include/migration/blocker.h
+++ b/include/migration/blocker.h
@@ -26,6 +26,22 @@
 int migrate_add_blocker(Error *reason, Error **errp);
 
 /**
+ * @migrate_add_blocker_internal - prevent migration from proceeding without
+ *                                 only-migrate implications
+ *
+ * @reason - an error to be returned whenever migration is attempted
+ *
+ * @errp - [out] The reason (if any) we cannot block migration right now.
+ *
+ * @returns - 0 on success, -EBUSY on failure, with errp set.
+ *
+ * Some of the migration blockers can be temporary (e.g., for a few seconds),
+ * so it shouldn't need to conflict with "-only-migratable".  For those cases,
+ * we can call this function rather than @migrate_add_blocker().
+ */
+int migrate_add_blocker_internal(Error *reason, Error **errp);
+
+/**
  * @migrate_del_blocker - remove a blocking error from migration
  *
  * @reason - the error blocking migration
diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h
index a1ab1ee12d..7b22aeb6ae 100644
--- a/include/sysemu/kvm.h
+++ b/include/sysemu/kvm.h
@@ -547,4 +547,5 @@ bool kvm_cpu_check_are_resettable(void);
 
 bool kvm_arch_cpu_check_are_resettable(void);
 
+bool kvm_dirty_ring_enabled(void);
 #endif
diff --git a/meson.build b/meson.build
index 90e3e85f20..bc918fbe58 100644
--- a/meson.build
+++ b/meson.build
@@ -2363,6 +2363,7 @@ bsd_user_ss = ss.source_set()
 chardev_ss = ss.source_set()
 common_ss = ss.source_set()
 crypto_ss = ss.source_set()
+hwcore_ss = ss.source_set()
 io_ss = ss.source_set()
 linux_user_ss = ss.source_set()
 qmp_ss = ss.source_set()
@@ -2457,6 +2458,7 @@ if have_system
     'hw/s390x',
     'hw/scsi',
     'hw/sd',
+    'hw/sh4',
     'hw/sparc',
     'hw/sparc64',
     'hw/ssi',
@@ -2803,7 +2805,8 @@ libchardev = static_library('chardev', chardev_ss.sources() + genh,
 
 chardev = declare_dependency(link_whole: libchardev)
 
-libhwcore = static_library('hwcore', sources: hwcore_files + genh,
+hwcore_ss = hwcore_ss.apply(config_host, strict: false)
+libhwcore = static_library('hwcore', sources: hwcore_ss.sources() + genh,
                            name_suffix: 'fa',
                            build_by_default: false)
 hwcore = declare_dependency(link_whole: libhwcore)
diff --git a/migration/dirtyrate.c b/migration/dirtyrate.c
index 320c56ba2c..d65e744af9 100644
--- a/migration/dirtyrate.c
+++ b/migration/dirtyrate.c
@@ -15,7 +15,9 @@
 #include "qapi/error.h"
 #include "cpu.h"
 #include "exec/ramblock.h"
+#include "exec/ram_addr.h"
 #include "qemu/rcu_queue.h"
+#include "qemu/main-loop.h"
 #include "qapi/qapi-commands-migration.h"
 #include "ram.h"
 #include "trace.h"
@@ -23,9 +25,26 @@
 #include "monitor/hmp.h"
 #include "monitor/monitor.h"
 #include "qapi/qmp/qdict.h"
+#include "sysemu/kvm.h"
+#include "sysemu/runstate.h"
+#include "exec/memory.h"
+
+/*
+ * total_dirty_pages is procted by BQL and is used
+ * to stat dirty pages during the period of two
+ * memory_global_dirty_log_sync
+ */
+uint64_t total_dirty_pages;
+
+typedef struct DirtyPageRecord {
+    uint64_t start_pages;
+    uint64_t end_pages;
+} DirtyPageRecord;
 
 static int CalculatingState = DIRTY_RATE_STATUS_UNSTARTED;
 static struct DirtyRateStat DirtyStat;
+static DirtyRateMeasureMode dirtyrate_mode =
+                DIRTY_RATE_MEASURE_MODE_PAGE_SAMPLING;
 
 static int64_t set_sample_page_period(int64_t msec, int64_t initial_time)
 {
@@ -70,51 +89,94 @@ static int dirtyrate_set_state(int *state, int old_state, int new_state)
 
 static struct DirtyRateInfo *query_dirty_rate_info(void)
 {
+    int i;
     int64_t dirty_rate = DirtyStat.dirty_rate;
     struct DirtyRateInfo *info = g_malloc0(sizeof(DirtyRateInfo));
-
-    if (qatomic_read(&CalculatingState) == DIRTY_RATE_STATUS_MEASURED) {
-        info->has_dirty_rate = true;
-        info->dirty_rate = dirty_rate;
-    }
+    DirtyRateVcpuList *head = NULL, **tail = &head;
 
     info->status = CalculatingState;
     info->start_time = DirtyStat.start_time;
     info->calc_time = DirtyStat.calc_time;
     info->sample_pages = DirtyStat.sample_pages;
+    info->mode = dirtyrate_mode;
+
+    if (qatomic_read(&CalculatingState) == DIRTY_RATE_STATUS_MEASURED) {
+        info->has_dirty_rate = true;
+        info->dirty_rate = dirty_rate;
+
+        if (dirtyrate_mode == DIRTY_RATE_MEASURE_MODE_DIRTY_RING) {
+            /*
+             * set sample_pages with 0 to indicate page sampling
+             * isn't enabled
+             **/
+            info->sample_pages = 0;
+            info->has_vcpu_dirty_rate = true;
+            for (i = 0; i < DirtyStat.dirty_ring.nvcpu; i++) {
+                DirtyRateVcpu *rate = g_malloc0(sizeof(DirtyRateVcpu));
+                rate->id = DirtyStat.dirty_ring.rates[i].id;
+                rate->dirty_rate = DirtyStat.dirty_ring.rates[i].dirty_rate;
+                QAPI_LIST_APPEND(tail, rate);
+            }
+            info->vcpu_dirty_rate = head;
+        }
+
+        if (dirtyrate_mode == DIRTY_RATE_MEASURE_MODE_DIRTY_BITMAP) {
+            info->sample_pages = 0;
+        }
+    }
 
     trace_query_dirty_rate_info(DirtyRateStatus_str(CalculatingState));
 
     return info;
 }
 
-static void init_dirtyrate_stat(int64_t start_time, int64_t calc_time,
-                                uint64_t sample_pages)
+static void init_dirtyrate_stat(int64_t start_time,
+                                struct DirtyRateConfig config)
 {
-    DirtyStat.total_dirty_samples = 0;
-    DirtyStat.total_sample_count = 0;
-    DirtyStat.total_block_mem_MB = 0;
     DirtyStat.dirty_rate = -1;
     DirtyStat.start_time = start_time;
-    DirtyStat.calc_time = calc_time;
-    DirtyStat.sample_pages = sample_pages;
+    DirtyStat.calc_time = config.sample_period_seconds;
+    DirtyStat.sample_pages = config.sample_pages_per_gigabytes;
+
+    switch (config.mode) {
+    case DIRTY_RATE_MEASURE_MODE_PAGE_SAMPLING:
+        DirtyStat.page_sampling.total_dirty_samples = 0;
+        DirtyStat.page_sampling.total_sample_count = 0;
+        DirtyStat.page_sampling.total_block_mem_MB = 0;
+        break;
+    case DIRTY_RATE_MEASURE_MODE_DIRTY_RING:
+        DirtyStat.dirty_ring.nvcpu = -1;
+        DirtyStat.dirty_ring.rates = NULL;
+        break;
+    default:
+        break;
+    }
+}
+
+static void cleanup_dirtyrate_stat(struct DirtyRateConfig config)
+{
+    /* last calc-dirty-rate qmp use dirty ring mode */
+    if (dirtyrate_mode == DIRTY_RATE_MEASURE_MODE_DIRTY_RING) {
+        free(DirtyStat.dirty_ring.rates);
+        DirtyStat.dirty_ring.rates = NULL;
+    }
 }
 
 static void update_dirtyrate_stat(struct RamblockDirtyInfo *info)
 {
-    DirtyStat.total_dirty_samples += info->sample_dirty_count;
-    DirtyStat.total_sample_count += info->sample_pages_count;
+    DirtyStat.page_sampling.total_dirty_samples += info->sample_dirty_count;
+    DirtyStat.page_sampling.total_sample_count += info->sample_pages_count;
     /* size of total pages in MB */
-    DirtyStat.total_block_mem_MB += (info->ramblock_pages *
-                                     TARGET_PAGE_SIZE) >> 20;
+    DirtyStat.page_sampling.total_block_mem_MB += (info->ramblock_pages *
+                                                   TARGET_PAGE_SIZE) >> 20;
 }
 
 static void update_dirtyrate(uint64_t msec)
 {
     uint64_t dirtyrate;
-    uint64_t total_dirty_samples = DirtyStat.total_dirty_samples;
-    uint64_t total_sample_count = DirtyStat.total_sample_count;
-    uint64_t total_block_mem_MB = DirtyStat.total_block_mem_MB;
+    uint64_t total_dirty_samples = DirtyStat.page_sampling.total_dirty_samples;
+    uint64_t total_sample_count = DirtyStat.page_sampling.total_sample_count;
+    uint64_t total_block_mem_MB = DirtyStat.page_sampling.total_block_mem_MB;
 
     dirtyrate = total_dirty_samples * total_block_mem_MB *
                 1000 / (total_sample_count * msec);
@@ -327,21 +389,183 @@ static bool compare_page_hash_info(struct RamblockDirtyInfo *info,
         update_dirtyrate_stat(block_dinfo);
     }
 
-    if (DirtyStat.total_sample_count == 0) {
+    if (DirtyStat.page_sampling.total_sample_count == 0) {
         return false;
     }
 
     return true;
 }
 
-static void calculate_dirtyrate(struct DirtyRateConfig config)
+static inline void record_dirtypages(DirtyPageRecord *dirty_pages,
+                                     CPUState *cpu, bool start)
+{
+    if (start) {
+        dirty_pages[cpu->cpu_index].start_pages = cpu->dirty_pages;
+    } else {
+        dirty_pages[cpu->cpu_index].end_pages = cpu->dirty_pages;
+    }
+}
+
+static void dirtyrate_global_dirty_log_start(void)
+{
+    qemu_mutex_lock_iothread();
+    memory_global_dirty_log_start(GLOBAL_DIRTY_DIRTY_RATE);
+    qemu_mutex_unlock_iothread();
+}
+
+static void dirtyrate_global_dirty_log_stop(void)
+{
+    qemu_mutex_lock_iothread();
+    memory_global_dirty_log_sync();
+    memory_global_dirty_log_stop(GLOBAL_DIRTY_DIRTY_RATE);
+    qemu_mutex_unlock_iothread();
+}
+
+static int64_t do_calculate_dirtyrate_vcpu(DirtyPageRecord dirty_pages)
+{
+    uint64_t memory_size_MB;
+    int64_t time_s;
+    uint64_t increased_dirty_pages =
+        dirty_pages.end_pages - dirty_pages.start_pages;
+
+    memory_size_MB = (increased_dirty_pages * TARGET_PAGE_SIZE) >> 20;
+    time_s = DirtyStat.calc_time;
+
+    return memory_size_MB / time_s;
+}
+
+static inline void record_dirtypages_bitmap(DirtyPageRecord *dirty_pages,
+                                            bool start)
+{
+    if (start) {
+        dirty_pages->start_pages = total_dirty_pages;
+    } else {
+        dirty_pages->end_pages = total_dirty_pages;
+    }
+}
+
+static void do_calculate_dirtyrate_bitmap(DirtyPageRecord dirty_pages)
+{
+    DirtyStat.dirty_rate = do_calculate_dirtyrate_vcpu(dirty_pages);
+}
+
+static inline void dirtyrate_manual_reset_protect(void)
+{
+    RAMBlock *block = NULL;
+
+    WITH_RCU_READ_LOCK_GUARD() {
+        RAMBLOCK_FOREACH_MIGRATABLE(block) {
+            memory_region_clear_dirty_bitmap(block->mr, 0,
+                                             block->used_length);
+        }
+    }
+}
+
+static void calculate_dirtyrate_dirty_bitmap(struct DirtyRateConfig config)
+{
+    int64_t msec = 0;
+    int64_t start_time;
+    DirtyPageRecord dirty_pages;
+
+    qemu_mutex_lock_iothread();
+    memory_global_dirty_log_start(GLOBAL_DIRTY_DIRTY_RATE);
+
+    /*
+     * 1'round of log sync may return all 1 bits with
+     * KVM_DIRTY_LOG_INITIALLY_SET enable
+     * skip it unconditionally and start dirty tracking
+     * from 2'round of log sync
+     */
+    memory_global_dirty_log_sync();
+
+    /*
+     * reset page protect manually and unconditionally.
+     * this make sure kvm dirty log be cleared if
+     * KVM_DIRTY_LOG_MANUAL_PROTECT_ENABLE cap is enabled.
+     */
+    dirtyrate_manual_reset_protect();
+    qemu_mutex_unlock_iothread();
+
+    record_dirtypages_bitmap(&dirty_pages, true);
+
+    start_time = qemu_clock_get_ms(QEMU_CLOCK_REALTIME);
+    DirtyStat.start_time = start_time / 1000;
+
+    msec = config.sample_period_seconds * 1000;
+    msec = set_sample_page_period(msec, start_time);
+    DirtyStat.calc_time = msec / 1000;
+
+    /*
+     * dirtyrate_global_dirty_log_stop do two things.
+     * 1. fetch dirty bitmap from kvm
+     * 2. stop dirty tracking
+     */
+    dirtyrate_global_dirty_log_stop();
+
+    record_dirtypages_bitmap(&dirty_pages, false);
+
+    do_calculate_dirtyrate_bitmap(dirty_pages);
+}
+
+static void calculate_dirtyrate_dirty_ring(struct DirtyRateConfig config)
+{
+    CPUState *cpu;
+    int64_t msec = 0;
+    int64_t start_time;
+    uint64_t dirtyrate = 0;
+    uint64_t dirtyrate_sum = 0;
+    DirtyPageRecord *dirty_pages;
+    int nvcpu = 0;
+    int i = 0;
+
+    CPU_FOREACH(cpu) {
+        nvcpu++;
+    }
+
+    dirty_pages = malloc(sizeof(*dirty_pages) * nvcpu);
+
+    DirtyStat.dirty_ring.nvcpu = nvcpu;
+    DirtyStat.dirty_ring.rates = malloc(sizeof(DirtyRateVcpu) * nvcpu);
+
+    dirtyrate_global_dirty_log_start();
+
+    CPU_FOREACH(cpu) {
+        record_dirtypages(dirty_pages, cpu, true);
+    }
+
+    start_time = qemu_clock_get_ms(QEMU_CLOCK_REALTIME);
+    DirtyStat.start_time = start_time / 1000;
+
+    msec = config.sample_period_seconds * 1000;
+    msec = set_sample_page_period(msec, start_time);
+    DirtyStat.calc_time = msec / 1000;
+
+    dirtyrate_global_dirty_log_stop();
+
+    CPU_FOREACH(cpu) {
+        record_dirtypages(dirty_pages, cpu, false);
+    }
+
+    for (i = 0; i < DirtyStat.dirty_ring.nvcpu; i++) {
+        dirtyrate = do_calculate_dirtyrate_vcpu(dirty_pages[i]);
+        trace_dirtyrate_do_calculate_vcpu(i, dirtyrate);
+
+        DirtyStat.dirty_ring.rates[i].id = i;
+        DirtyStat.dirty_ring.rates[i].dirty_rate = dirtyrate;
+        dirtyrate_sum += dirtyrate;
+    }
+
+    DirtyStat.dirty_rate = dirtyrate_sum;
+    free(dirty_pages);
+}
+
+static void calculate_dirtyrate_sample_vm(struct DirtyRateConfig config)
 {
     struct RamblockDirtyInfo *block_dinfo = NULL;
     int block_count = 0;
     int64_t msec = 0;
     int64_t initial_time;
 
-    rcu_register_thread();
     rcu_read_lock();
     initial_time = qemu_clock_get_ms(QEMU_CLOCK_REALTIME);
     if (!record_ramblock_hash_info(&block_dinfo, config, &block_count)) {
@@ -364,16 +588,26 @@ static void calculate_dirtyrate(struct DirtyRateConfig config)
 out:
     rcu_read_unlock();
     free_ramblock_dirty_info(block_dinfo, block_count);
-    rcu_unregister_thread();
+}
+
+static void calculate_dirtyrate(struct DirtyRateConfig config)
+{
+    if (config.mode == DIRTY_RATE_MEASURE_MODE_DIRTY_BITMAP) {
+        calculate_dirtyrate_dirty_bitmap(config);
+    } else if (config.mode == DIRTY_RATE_MEASURE_MODE_DIRTY_RING) {
+        calculate_dirtyrate_dirty_ring(config);
+    } else {
+        calculate_dirtyrate_sample_vm(config);
+    }
+
+    trace_dirtyrate_calculate(DirtyStat.dirty_rate);
 }
 
 void *get_dirtyrate_thread(void *arg)
 {
     struct DirtyRateConfig config = *(struct DirtyRateConfig *)arg;
     int ret;
-    int64_t start_time;
-    int64_t calc_time;
-    uint64_t sample_pages;
+    rcu_register_thread();
 
     ret = dirtyrate_set_state(&CalculatingState, DIRTY_RATE_STATUS_UNSTARTED,
                               DIRTY_RATE_STATUS_MEASURING);
@@ -382,11 +616,6 @@ void *get_dirtyrate_thread(void *arg)
         return NULL;
     }
 
-    start_time = qemu_clock_get_ms(QEMU_CLOCK_REALTIME) / 1000;
-    calc_time = config.sample_period_seconds;
-    sample_pages = config.sample_pages_per_gigabytes;
-    init_dirtyrate_stat(start_time, calc_time, sample_pages);
-
     calculate_dirtyrate(config);
 
     ret = dirtyrate_set_state(&CalculatingState, DIRTY_RATE_STATUS_MEASURING,
@@ -394,15 +623,22 @@ void *get_dirtyrate_thread(void *arg)
     if (ret == -1) {
         error_report("change dirtyrate state failed.");
     }
+
+    rcu_unregister_thread();
     return NULL;
 }
 
-void qmp_calc_dirty_rate(int64_t calc_time, bool has_sample_pages,
-                         int64_t sample_pages, Error **errp)
+void qmp_calc_dirty_rate(int64_t calc_time,
+                         bool has_sample_pages,
+                         int64_t sample_pages,
+                         bool has_mode,
+                         DirtyRateMeasureMode mode,
+                         Error **errp)
 {
     static struct DirtyRateConfig config;
     QemuThread thread;
     int ret;
+    int64_t start_time;
 
     /*
      * If the dirty rate is already being measured, don't attempt to start.
@@ -419,6 +655,15 @@ void qmp_calc_dirty_rate(int64_t calc_time, bool has_sample_pages,
         return;
     }
 
+    if (!has_mode) {
+        mode =  DIRTY_RATE_MEASURE_MODE_PAGE_SAMPLING;
+    }
+
+    if (has_sample_pages && mode == DIRTY_RATE_MEASURE_MODE_DIRTY_RING) {
+        error_setg(errp, "either sample-pages or dirty-ring can be specified.");
+        return;
+    }
+
     if (has_sample_pages) {
         if (!is_sample_pages_valid(sample_pages)) {
             error_setg(errp, "sample-pages is out of range[%d, %d].",
@@ -431,6 +676,19 @@ void qmp_calc_dirty_rate(int64_t calc_time, bool has_sample_pages,
     }
 
     /*
+     * dirty ring mode only works when kvm dirty ring is enabled.
+     * on the contrary, dirty bitmap mode is not.
+     */
+    if (((mode == DIRTY_RATE_MEASURE_MODE_DIRTY_RING) &&
+        !kvm_dirty_ring_enabled()) ||
+        ((mode == DIRTY_RATE_MEASURE_MODE_DIRTY_BITMAP) &&
+         kvm_dirty_ring_enabled())) {
+        error_setg(errp, "mode %s is not enabled, use other method instead.",
+                         DirtyRateMeasureMode_str(mode));
+         return;
+    }
+
+    /*
      * Init calculation state as unstarted.
      */
     ret = dirtyrate_set_state(&CalculatingState, CalculatingState,
@@ -442,6 +700,19 @@ void qmp_calc_dirty_rate(int64_t calc_time, bool has_sample_pages,
 
     config.sample_period_seconds = calc_time;
     config.sample_pages_per_gigabytes = sample_pages;
+    config.mode = mode;
+
+    cleanup_dirtyrate_stat(config);
+
+    /*
+     * update dirty rate mode so that we can figure out what mode has
+     * been used in last calculation
+     **/
+    dirtyrate_mode = mode;
+
+    start_time = qemu_clock_get_ms(QEMU_CLOCK_REALTIME) / 1000;
+    init_dirtyrate_stat(start_time, config);
+
     qemu_thread_create(&thread, "get_dirtyrate", get_dirtyrate_thread,
                        (void *)&config, QEMU_THREAD_DETACHED);
 }
@@ -463,12 +734,24 @@ void hmp_info_dirty_rate(Monitor *mon, const QDict *qdict)
                    info->sample_pages);
     monitor_printf(mon, "Period: %"PRIi64" (sec)\n",
                    info->calc_time);
+    monitor_printf(mon, "Mode: %s\n",
+                   DirtyRateMeasureMode_str(info->mode));
     monitor_printf(mon, "Dirty rate: ");
     if (info->has_dirty_rate) {
         monitor_printf(mon, "%"PRIi64" (MB/s)\n", info->dirty_rate);
+        if (info->has_vcpu_dirty_rate) {
+            DirtyRateVcpuList *rate, *head = info->vcpu_dirty_rate;
+            for (rate = head; rate != NULL; rate = rate->next) {
+                monitor_printf(mon, "vcpu[%"PRIi64"], Dirty rate: %"PRIi64
+                               " (MB/s)\n", rate->value->id,
+                               rate->value->dirty_rate);
+            }
+        }
     } else {
         monitor_printf(mon, "(not ready)\n");
     }
+
+    qapi_free_DirtyRateVcpuList(info->vcpu_dirty_rate);
     g_free(info);
 }
 
@@ -477,6 +760,9 @@ void hmp_calc_dirty_rate(Monitor *mon, const QDict *qdict)
     int64_t sec = qdict_get_try_int(qdict, "second", 0);
     int64_t sample_pages = qdict_get_try_int(qdict, "sample_pages_per_GB", -1);
     bool has_sample_pages = (sample_pages != -1);
+    bool dirty_ring = qdict_get_try_bool(qdict, "dirty_ring", false);
+    bool dirty_bitmap = qdict_get_try_bool(qdict, "dirty_bitmap", false);
+    DirtyRateMeasureMode mode = DIRTY_RATE_MEASURE_MODE_PAGE_SAMPLING;
     Error *err = NULL;
 
     if (!sec) {
@@ -484,7 +770,20 @@ void hmp_calc_dirty_rate(Monitor *mon, const QDict *qdict)
         return;
     }
 
-    qmp_calc_dirty_rate(sec, has_sample_pages, sample_pages, &err);
+    if (dirty_ring && dirty_bitmap) {
+        monitor_printf(mon, "Either dirty ring or dirty bitmap "
+                       "can be specified!\n");
+        return;
+    }
+
+    if (dirty_bitmap) {
+        mode = DIRTY_RATE_MEASURE_MODE_DIRTY_BITMAP;
+    } else if (dirty_ring) {
+        mode = DIRTY_RATE_MEASURE_MODE_DIRTY_RING;
+    }
+
+    qmp_calc_dirty_rate(sec, has_sample_pages, sample_pages, true,
+                        mode, &err);
     if (err) {
         hmp_handle_error(mon, err);
         return;
diff --git a/migration/dirtyrate.h b/migration/dirtyrate.h
index e1fd29089e..69d4c5b865 100644
--- a/migration/dirtyrate.h
+++ b/migration/dirtyrate.h
@@ -43,6 +43,7 @@
 struct DirtyRateConfig {
     uint64_t sample_pages_per_gigabytes; /* sample pages per GB */
     int64_t sample_period_seconds; /* time duration between two sampling */
+    DirtyRateMeasureMode mode; /* mode of dirtyrate measurement */
 };
 
 /*
@@ -58,17 +59,29 @@ struct RamblockDirtyInfo {
     uint32_t *hash_result; /* array of hash result for sampled pages */
 };
 
+typedef struct SampleVMStat {
+    uint64_t total_dirty_samples; /* total dirty sampled page */
+    uint64_t total_sample_count; /* total sampled pages */
+    uint64_t total_block_mem_MB; /* size of total sampled pages in MB */
+} SampleVMStat;
+
+typedef struct VcpuStat {
+    int nvcpu; /* number of vcpu */
+    DirtyRateVcpu *rates; /* array of dirty rate for each vcpu */
+} VcpuStat;
+
 /*
  * Store calculation statistics for each measure.
  */
 struct DirtyRateStat {
-    uint64_t total_dirty_samples; /* total dirty sampled page */
-    uint64_t total_sample_count; /* total sampled pages */
-    uint64_t total_block_mem_MB; /* size of total sampled pages in MB */
     int64_t dirty_rate; /* dirty rate in MB/s */
     int64_t start_time; /* calculation start time in units of second */
     int64_t calc_time; /* time duration of two sampling in units of second */
     uint64_t sample_pages; /* sample pages per GB */
+    union {
+        SampleVMStat page_sampling;
+        VcpuStat dirty_ring;
+    };
 };
 
 void *get_dirtyrate_thread(void *arg);
diff --git a/migration/migration.c b/migration/migration.c
index 9172686b89..53b9a8af96 100644
--- a/migration/migration.c
+++ b/migration/migration.c
@@ -391,7 +391,7 @@ int migrate_send_rp_message_req_pages(MigrationIncomingState *mis,
 int migrate_send_rp_req_pages(MigrationIncomingState *mis,
                               RAMBlock *rb, ram_addr_t start, uint64_t haddr)
 {
-    void *aligned = (void *)(uintptr_t)(haddr & (-qemu_ram_pagesize(rb)));
+    void *aligned = (void *)(uintptr_t)ROUND_DOWN(haddr, qemu_ram_pagesize(rb));
     bool received = false;
 
     WITH_QEMU_LOCK_GUARD(&mis->page_request_mutex) {
@@ -2049,6 +2049,20 @@ void migrate_init(MigrationState *s)
     s->threshold_size = 0;
 }
 
+int migrate_add_blocker_internal(Error *reason, Error **errp)
+{
+    /* Snapshots are similar to migrations, so check RUN_STATE_SAVE_VM too. */
+    if (runstate_check(RUN_STATE_SAVE_VM) || !migration_is_idle()) {
+        error_propagate_prepend(errp, error_copy(reason),
+                                "disallowing migration blocker "
+                                "(migration/snapshot in progress) for: ");
+        return -EBUSY;
+    }
+
+    migration_blockers = g_slist_prepend(migration_blockers, reason);
+    return 0;
+}
+
 int migrate_add_blocker(Error *reason, Error **errp)
 {
     if (only_migratable) {
@@ -2058,15 +2072,7 @@ int migrate_add_blocker(Error *reason, Error **errp)
         return -EACCES;
     }
 
-    if (migration_is_idle()) {
-        migration_blockers = g_slist_prepend(migration_blockers, reason);
-        return 0;
-    }
-
-    error_propagate_prepend(errp, error_copy(reason),
-                            "disallowing migration blocker "
-                            "(migration in progress) for: ");
-    return -EBUSY;
+    return migrate_add_blocker_internal(reason, errp);
 }
 
 void migrate_del_blocker(Error *reason)
@@ -2631,8 +2637,8 @@ static void migrate_handle_rp_req_pages(MigrationState *ms, const char* rbname,
      * Since we currently insist on matching page sizes, just sanity check
      * we're being asked for whole host pages.
      */
-    if (start & (our_host_ps - 1) ||
-       (len & (our_host_ps - 1))) {
+    if (!QEMU_IS_ALIGNED(start, our_host_ps) ||
+        !QEMU_IS_ALIGNED(len, our_host_ps)) {
         error_report("%s: Misaligned page request, start: " RAM_ADDR_FMT
                      " len: %zd", __func__, start, len);
         mark_source_rp_bad(ms);
diff --git a/migration/postcopy-ram.c b/migration/postcopy-ram.c
index 2e9697bdd2..e721f69d0f 100644
--- a/migration/postcopy-ram.c
+++ b/migration/postcopy-ram.c
@@ -402,7 +402,7 @@ bool postcopy_ram_supported_by_host(MigrationIncomingState *mis)
                      strerror(errno));
         goto out;
     }
-    g_assert(((size_t)testarea & (pagesize - 1)) == 0);
+    g_assert(QEMU_PTR_IS_ALIGNED(testarea, pagesize));
 
     reg_struct.range.start = (uintptr_t)testarea;
     reg_struct.range.len = pagesize;
@@ -660,7 +660,7 @@ int postcopy_wake_shared(struct PostCopyFD *pcfd,
     struct uffdio_range range;
     int ret;
     trace_postcopy_wake_shared(client_addr, qemu_ram_get_idstr(rb));
-    range.start = client_addr & ~(pagesize - 1);
+    range.start = ROUND_DOWN(client_addr, pagesize);
     range.len = pagesize;
     ret = ioctl(pcfd->fd, UFFDIO_WAKE, &range);
     if (ret) {
@@ -671,6 +671,29 @@ int postcopy_wake_shared(struct PostCopyFD *pcfd,
     return ret;
 }
 
+static int postcopy_request_page(MigrationIncomingState *mis, RAMBlock *rb,
+                                 ram_addr_t start, uint64_t haddr)
+{
+    void *aligned = (void *)(uintptr_t)ROUND_DOWN(haddr, qemu_ram_pagesize(rb));
+
+    /*
+     * Discarded pages (via RamDiscardManager) are never migrated. On unlikely
+     * access, place a zeropage, which will also set the relevant bits in the
+     * recv_bitmap accordingly, so we won't try placing a zeropage twice.
+     *
+     * Checking a single bit is sufficient to handle pagesize > TPS as either
+     * all relevant bits are set or not.
+     */
+    assert(QEMU_IS_ALIGNED(start, qemu_ram_pagesize(rb)));
+    if (ramblock_page_is_discarded(rb, start)) {
+        bool received = ramblock_recv_bitmap_test_byte_offset(rb, start);
+
+        return received ? 0 : postcopy_place_page_zero(mis, aligned, rb);
+    }
+
+    return migrate_send_rp_req_pages(mis, rb, start, haddr);
+}
+
 /*
  * Callback from shared fault handlers to ask for a page,
  * the page must be specified by a RAMBlock and an offset in that rb
@@ -679,8 +702,7 @@ int postcopy_wake_shared(struct PostCopyFD *pcfd,
 int postcopy_request_shared_page(struct PostCopyFD *pcfd, RAMBlock *rb,
                                  uint64_t client_addr, uint64_t rb_offset)
 {
-    size_t pagesize = qemu_ram_pagesize(rb);
-    uint64_t aligned_rbo = rb_offset & ~(pagesize - 1);
+    uint64_t aligned_rbo = ROUND_DOWN(rb_offset, qemu_ram_pagesize(rb));
     MigrationIncomingState *mis = migration_incoming_get_current();
 
     trace_postcopy_request_shared_page(pcfd->idstr, qemu_ram_get_idstr(rb),
@@ -690,7 +712,7 @@ int postcopy_request_shared_page(struct PostCopyFD *pcfd, RAMBlock *rb,
                                         qemu_ram_get_idstr(rb), rb_offset);
         return postcopy_wake_shared(pcfd, client_addr, rb);
     }
-    migrate_send_rp_req_pages(mis, rb, aligned_rbo, client_addr);
+    postcopy_request_page(mis, rb, aligned_rbo, client_addr);
     return 0;
 }
 
@@ -970,7 +992,7 @@ static void *postcopy_ram_fault_thread(void *opaque)
                 break;
             }
 
-            rb_offset &= ~(qemu_ram_pagesize(rb) - 1);
+            rb_offset = ROUND_DOWN(rb_offset, qemu_ram_pagesize(rb));
             trace_postcopy_ram_fault_thread_request(msg.arg.pagefault.address,
                                                 qemu_ram_get_idstr(rb),
                                                 rb_offset,
@@ -984,8 +1006,8 @@ retry:
              * Send the request to the source - we want to request one
              * of our host page sizes (which is >= TPS)
              */
-            ret = migrate_send_rp_req_pages(mis, rb, rb_offset,
-                                            msg.arg.pagefault.address);
+            ret = postcopy_request_page(mis, rb, rb_offset,
+                                        msg.arg.pagefault.address);
             if (ret) {
                 /* May be network failure, try to wait for recovery */
                 if (ret == -EIO && postcopy_pause_fault_thread(mis)) {
@@ -993,7 +1015,7 @@ retry:
                     goto retry;
                 } else {
                     /* This is a unavoidable fault */
-                    error_report("%s: migrate_send_rp_req_pages() get %d",
+                    error_report("%s: postcopy_request_page() get %d",
                                  __func__, ret);
                     break;
                 }
diff --git a/migration/ram.c b/migration/ram.c
index bb908822d5..680a5158aa 100644
--- a/migration/ram.c
+++ b/migration/ram.c
@@ -811,7 +811,7 @@ static void migration_clear_memory_region_dirty_bitmap(RAMBlock *rb,
     assert(shift >= 6);
 
     size = 1ULL << (TARGET_PAGE_BITS + shift);
-    start = (((ram_addr_t)page) << TARGET_PAGE_BITS) & (-size);
+    start = QEMU_ALIGN_DOWN((ram_addr_t)page << TARGET_PAGE_BITS, size);
     trace_migration_bitmap_clear_dirty(rb->idstr, start, size, page);
     memory_region_clear_dirty_bitmap(rb->mr, start, size);
 }
@@ -858,6 +858,81 @@ static inline bool migration_bitmap_clear_dirty(RAMState *rs,
     return ret;
 }
 
+static void dirty_bitmap_clear_section(MemoryRegionSection *section,
+                                       void *opaque)
+{
+    const hwaddr offset = section->offset_within_region;
+    const hwaddr size = int128_get64(section->size);
+    const unsigned long start = offset >> TARGET_PAGE_BITS;
+    const unsigned long npages = size >> TARGET_PAGE_BITS;
+    RAMBlock *rb = section->mr->ram_block;
+    uint64_t *cleared_bits = opaque;
+
+    /*
+     * We don't grab ram_state->bitmap_mutex because we expect to run
+     * only when starting migration or during postcopy recovery where
+     * we don't have concurrent access.
+     */
+    if (!migration_in_postcopy() && !migrate_background_snapshot()) {
+        migration_clear_memory_region_dirty_bitmap_range(rb, start, npages);
+    }
+    *cleared_bits += bitmap_count_one_with_offset(rb->bmap, start, npages);
+    bitmap_clear(rb->bmap, start, npages);
+}
+
+/*
+ * Exclude all dirty pages from migration that fall into a discarded range as
+ * managed by a RamDiscardManager responsible for the mapped memory region of
+ * the RAMBlock. Clear the corresponding bits in the dirty bitmaps.
+ *
+ * Discarded pages ("logically unplugged") have undefined content and must
+ * not get migrated, because even reading these pages for migration might
+ * result in undesired behavior.
+ *
+ * Returns the number of cleared bits in the RAMBlock dirty bitmap.
+ *
+ * Note: The result is only stable while migrating (precopy/postcopy).
+ */
+static uint64_t ramblock_dirty_bitmap_clear_discarded_pages(RAMBlock *rb)
+{
+    uint64_t cleared_bits = 0;
+
+    if (rb->mr && rb->bmap && memory_region_has_ram_discard_manager(rb->mr)) {
+        RamDiscardManager *rdm = memory_region_get_ram_discard_manager(rb->mr);
+        MemoryRegionSection section = {
+            .mr = rb->mr,
+            .offset_within_region = 0,
+            .size = int128_make64(qemu_ram_get_used_length(rb)),
+        };
+
+        ram_discard_manager_replay_discarded(rdm, &section,
+                                             dirty_bitmap_clear_section,
+                                             &cleared_bits);
+    }
+    return cleared_bits;
+}
+
+/*
+ * Check if a host-page aligned page falls into a discarded range as managed by
+ * a RamDiscardManager responsible for the mapped memory region of the RAMBlock.
+ *
+ * Note: The result is only stable while migrating (precopy/postcopy).
+ */
+bool ramblock_page_is_discarded(RAMBlock *rb, ram_addr_t start)
+{
+    if (rb->mr && memory_region_has_ram_discard_manager(rb->mr)) {
+        RamDiscardManager *rdm = memory_region_get_ram_discard_manager(rb->mr);
+        MemoryRegionSection section = {
+            .mr = rb->mr,
+            .offset_within_region = start,
+            .size = int128_make64(qemu_ram_pagesize(rb)),
+        };
+
+        return !ram_discard_manager_is_populated(rdm, &section);
+    }
+    return false;
+}
+
 /* Called with RCU critical section */
 static void ramblock_sync_dirty_bitmap(RAMState *rs, RAMBlock *rb)
 {
@@ -1564,25 +1639,68 @@ out:
     return ret;
 }
 
+static inline void populate_read_range(RAMBlock *block, ram_addr_t offset,
+                                       ram_addr_t size)
+{
+    /*
+     * We read one byte of each page; this will preallocate page tables if
+     * required and populate the shared zeropage on MAP_PRIVATE anonymous memory
+     * where no page was populated yet. This might require adaption when
+     * supporting other mappings, like shmem.
+     */
+    for (; offset < size; offset += block->page_size) {
+        char tmp = *((char *)block->host + offset);
+
+        /* Don't optimize the read out */
+        asm volatile("" : "+r" (tmp));
+    }
+}
+
+static inline int populate_read_section(MemoryRegionSection *section,
+                                        void *opaque)
+{
+    const hwaddr size = int128_get64(section->size);
+    hwaddr offset = section->offset_within_region;
+    RAMBlock *block = section->mr->ram_block;
+
+    populate_read_range(block, offset, size);
+    return 0;
+}
+
 /*
- * ram_block_populate_pages: populate memory in the RAM block by reading
- *   an integer from the beginning of each page.
+ * ram_block_populate_read: preallocate page tables and populate pages in the
+ *   RAM block by reading a byte of each page.
  *
  * Since it's solely used for userfault_fd WP feature, here we just
  *   hardcode page size to qemu_real_host_page_size.
  *
  * @block: RAM block to populate
  */
-static void ram_block_populate_pages(RAMBlock *block)
+static void ram_block_populate_read(RAMBlock *rb)
 {
-    char *ptr = (char *) block->host;
-
-    for (ram_addr_t offset = 0; offset < block->used_length;
-            offset += qemu_real_host_page_size) {
-        char tmp = *(ptr + offset);
-
-        /* Don't optimize the read out */
-        asm volatile("" : "+r" (tmp));
+    /*
+     * Skip populating all pages that fall into a discarded range as managed by
+     * a RamDiscardManager responsible for the mapped memory region of the
+     * RAMBlock. Such discarded ("logically unplugged") parts of a RAMBlock
+     * must not get populated automatically. We don't have to track
+     * modifications via userfaultfd WP reliably, because these pages will
+     * not be part of the migration stream either way -- see
+     * ramblock_dirty_bitmap_exclude_discarded_pages().
+     *
+     * Note: The result is only stable while migrating (precopy/postcopy).
+     */
+    if (rb->mr && memory_region_has_ram_discard_manager(rb->mr)) {
+        RamDiscardManager *rdm = memory_region_get_ram_discard_manager(rb->mr);
+        MemoryRegionSection section = {
+            .mr = rb->mr,
+            .offset_within_region = 0,
+            .size = rb->mr->size,
+        };
+
+        ram_discard_manager_replay_populated(rdm, &section,
+                                             populate_read_section, NULL);
+    } else {
+        populate_read_range(rb, 0, rb->used_length);
     }
 }
 
@@ -1609,7 +1727,7 @@ void ram_write_tracking_prepare(void)
          * UFFDIO_WRITEPROTECT_MODE_WP mode setting would silently skip
          * pages with pte_none() entries in page table.
          */
-        ram_block_populate_pages(block);
+        ram_block_populate_read(block);
     }
 }
 
@@ -2216,7 +2334,14 @@ static void ram_save_cleanup(void *opaque)
         /* caller have hold iothread lock or is in a bh, so there is
          * no writing race against the migration bitmap
          */
-        memory_global_dirty_log_stop();
+        if (global_dirty_tracking & GLOBAL_DIRTY_MIGRATION) {
+            /*
+             * do not stop dirty log without starting it, since
+             * memory_global_dirty_log_stop will assert that
+             * memory_global_dirty_log_start/stop used in pairs
+             */
+            memory_global_dirty_log_stop(GLOBAL_DIRTY_MIGRATION);
+        }
     }
 
     RAMBLOCK_FOREACH_NOT_IGNORED(block) {
@@ -2668,6 +2793,19 @@ static void ram_list_init_bitmaps(void)
     }
 }
 
+static void migration_bitmap_clear_discarded_pages(RAMState *rs)
+{
+    unsigned long pages;
+    RAMBlock *rb;
+
+    RCU_READ_LOCK_GUARD();
+
+    RAMBLOCK_FOREACH_NOT_IGNORED(rb) {
+            pages = ramblock_dirty_bitmap_clear_discarded_pages(rb);
+            rs->migration_dirty_pages -= pages;
+    }
+}
+
 static void ram_init_bitmaps(RAMState *rs)
 {
     /* For memory_global_dirty_log_start below.  */
@@ -2678,12 +2816,18 @@ static void ram_init_bitmaps(RAMState *rs)
         ram_list_init_bitmaps();
         /* We don't use dirty log with background snapshots */
         if (!migrate_background_snapshot()) {
-            memory_global_dirty_log_start();
+            memory_global_dirty_log_start(GLOBAL_DIRTY_MIGRATION);
             migration_bitmap_sync_precopy(rs);
         }
     }
     qemu_mutex_unlock_ramlist();
     qemu_mutex_unlock_iothread();
+
+    /*
+     * After an eventual first bitmap sync, fixup the initial bitmap
+     * containing all 1s to exclude any discarded pages from migration.
+     */
+    migration_bitmap_clear_discarded_pages(rs);
 }
 
 static int ram_init_all(RAMState **rsp)
@@ -3434,7 +3578,7 @@ void colo_incoming_start_dirty_log(void)
             /* Discard this dirty bitmap record */
             bitmap_zero(block->bmap, block->max_length >> TARGET_PAGE_BITS);
         }
-        memory_global_dirty_log_start();
+        memory_global_dirty_log_start(GLOBAL_DIRTY_MIGRATION);
     }
     ram_state->migration_dirty_pages = 0;
     qemu_mutex_unlock_ramlist();
@@ -3446,7 +3590,7 @@ void colo_release_ram_cache(void)
 {
     RAMBlock *block;
 
-    memory_global_dirty_log_stop();
+    memory_global_dirty_log_stop(GLOBAL_DIRTY_MIGRATION);
     RAMBLOCK_FOREACH_NOT_IGNORED(block) {
         g_free(block->bmap);
         block->bmap = NULL;
@@ -4112,6 +4256,10 @@ int ram_dirty_bitmap_reload(MigrationState *s, RAMBlock *block)
      */
     bitmap_complement(block->bmap, block->bmap, nbits);
 
+    /* Clear dirty bits of discarded ranges that we don't want to migrate. */
+    ramblock_dirty_bitmap_clear_discarded_pages(block);
+
+    /* We'll recalculate migration_dirty_pages in ram_state_resume_prepare(). */
     trace_ram_dirty_bitmap_reload_complete(block->idstr);
 
     /*
diff --git a/migration/ram.h b/migration/ram.h
index 4833e9fd5b..dda1988f3d 100644
--- a/migration/ram.h
+++ b/migration/ram.h
@@ -72,6 +72,7 @@ void ramblock_recv_bitmap_set_range(RAMBlock *rb, void *host_addr, size_t nr);
 int64_t ramblock_recv_bitmap_send(QEMUFile *file,
                                   const char *block_name);
 int ram_dirty_bitmap_reload(MigrationState *s, RAMBlock *rb);
+bool ramblock_page_is_discarded(RAMBlock *rb, ram_addr_t start);
 
 /* ram cache */
 int colo_init_ram_cache(void);
diff --git a/migration/rdma.c b/migration/rdma.c
index 2a3c7889b9..f5d3bbe7e9 100644
--- a/migration/rdma.c
+++ b/migration/rdma.c
@@ -358,9 +358,11 @@ typedef struct RDMAContext {
     struct ibv_context          *verbs;
     struct rdma_event_channel   *channel;
     struct ibv_qp *qp;                      /* queue pair */
-    struct ibv_comp_channel *comp_channel;  /* completion channel */
+    struct ibv_comp_channel *recv_comp_channel;  /* recv completion channel */
+    struct ibv_comp_channel *send_comp_channel;  /* send completion channel */
     struct ibv_pd *pd;                      /* protection domain */
-    struct ibv_cq *cq;                      /* completion queue */
+    struct ibv_cq *recv_cq;                 /* recvieve completion queue */
+    struct ibv_cq *send_cq;                 /* send completion queue */
 
     /*
      * If a previous write failed (perhaps because of a failed
@@ -1059,21 +1061,34 @@ static int qemu_rdma_alloc_pd_cq(RDMAContext *rdma)
         return -1;
     }
 
-    /* create completion channel */
-    rdma->comp_channel = ibv_create_comp_channel(rdma->verbs);
-    if (!rdma->comp_channel) {
-        error_report("failed to allocate completion channel");
+    /* create receive completion channel */
+    rdma->recv_comp_channel = ibv_create_comp_channel(rdma->verbs);
+    if (!rdma->recv_comp_channel) {
+        error_report("failed to allocate receive completion channel");
         goto err_alloc_pd_cq;
     }
 
     /*
-     * Completion queue can be filled by both read and write work requests,
-     * so must reflect the sum of both possible queue sizes.
+     * Completion queue can be filled by read work requests.
      */
-    rdma->cq = ibv_create_cq(rdma->verbs, (RDMA_SIGNALED_SEND_MAX * 3),
-            NULL, rdma->comp_channel, 0);
-    if (!rdma->cq) {
-        error_report("failed to allocate completion queue");
+    rdma->recv_cq = ibv_create_cq(rdma->verbs, (RDMA_SIGNALED_SEND_MAX * 3),
+                                  NULL, rdma->recv_comp_channel, 0);
+    if (!rdma->recv_cq) {
+        error_report("failed to allocate receive completion queue");
+        goto err_alloc_pd_cq;
+    }
+
+    /* create send completion channel */
+    rdma->send_comp_channel = ibv_create_comp_channel(rdma->verbs);
+    if (!rdma->send_comp_channel) {
+        error_report("failed to allocate send completion channel");
+        goto err_alloc_pd_cq;
+    }
+
+    rdma->send_cq = ibv_create_cq(rdma->verbs, (RDMA_SIGNALED_SEND_MAX * 3),
+                                  NULL, rdma->send_comp_channel, 0);
+    if (!rdma->send_cq) {
+        error_report("failed to allocate send completion queue");
         goto err_alloc_pd_cq;
     }
 
@@ -1083,11 +1098,19 @@ err_alloc_pd_cq:
     if (rdma->pd) {
         ibv_dealloc_pd(rdma->pd);
     }
-    if (rdma->comp_channel) {
-        ibv_destroy_comp_channel(rdma->comp_channel);
+    if (rdma->recv_comp_channel) {
+        ibv_destroy_comp_channel(rdma->recv_comp_channel);
+    }
+    if (rdma->send_comp_channel) {
+        ibv_destroy_comp_channel(rdma->send_comp_channel);
+    }
+    if (rdma->recv_cq) {
+        ibv_destroy_cq(rdma->recv_cq);
+        rdma->recv_cq = NULL;
     }
     rdma->pd = NULL;
-    rdma->comp_channel = NULL;
+    rdma->recv_comp_channel = NULL;
+    rdma->send_comp_channel = NULL;
     return -1;
 
 }
@@ -1104,8 +1127,8 @@ static int qemu_rdma_alloc_qp(RDMAContext *rdma)
     attr.cap.max_recv_wr = 3;
     attr.cap.max_send_sge = 1;
     attr.cap.max_recv_sge = 1;
-    attr.send_cq = rdma->cq;
-    attr.recv_cq = rdma->cq;
+    attr.send_cq = rdma->send_cq;
+    attr.recv_cq = rdma->recv_cq;
     attr.qp_type = IBV_QPT_RC;
 
     ret = rdma_create_qp(rdma->cm_id, rdma->pd, &attr);
@@ -1496,14 +1519,14 @@ static void qemu_rdma_signal_unregister(RDMAContext *rdma, uint64_t index,
  * (of any kind) has completed.
  * Return the work request ID that completed.
  */
-static uint64_t qemu_rdma_poll(RDMAContext *rdma, uint64_t *wr_id_out,
-                               uint32_t *byte_len)
+static uint64_t qemu_rdma_poll(RDMAContext *rdma, struct ibv_cq *cq,
+                               uint64_t *wr_id_out, uint32_t *byte_len)
 {
     int ret;
     struct ibv_wc wc;
     uint64_t wr_id;
 
-    ret = ibv_poll_cq(rdma->cq, 1, &wc);
+    ret = ibv_poll_cq(cq, 1, &wc);
 
     if (!ret) {
         *wr_id_out = RDMA_WRID_NONE;
@@ -1575,7 +1598,8 @@ static uint64_t qemu_rdma_poll(RDMAContext *rdma, uint64_t *wr_id_out,
 /* Wait for activity on the completion channel.
  * Returns 0 on success, none-0 on error.
  */
-static int qemu_rdma_wait_comp_channel(RDMAContext *rdma)
+static int qemu_rdma_wait_comp_channel(RDMAContext *rdma,
+                                       struct ibv_comp_channel *comp_channel)
 {
     struct rdma_cm_event *cm_event;
     int ret = -1;
@@ -1586,7 +1610,7 @@ static int qemu_rdma_wait_comp_channel(RDMAContext *rdma)
      */
     if (rdma->migration_started_on_destination &&
         migration_incoming_get_current()->state == MIGRATION_STATUS_ACTIVE) {
-        yield_until_fd_readable(rdma->comp_channel->fd);
+        yield_until_fd_readable(comp_channel->fd);
     } else {
         /* This is the source side, we're in a separate thread
          * or destination prior to migration_fd_process_incoming()
@@ -1597,7 +1621,7 @@ static int qemu_rdma_wait_comp_channel(RDMAContext *rdma)
          */
         while (!rdma->error_state  && !rdma->received_error) {
             GPollFD pfds[2];
-            pfds[0].fd = rdma->comp_channel->fd;
+            pfds[0].fd = comp_channel->fd;
             pfds[0].events = G_IO_IN | G_IO_HUP | G_IO_ERR;
             pfds[0].revents = 0;
 
@@ -1655,6 +1679,17 @@ static int qemu_rdma_wait_comp_channel(RDMAContext *rdma)
     return rdma->error_state;
 }
 
+static struct ibv_comp_channel *to_channel(RDMAContext *rdma, int wrid)
+{
+    return wrid < RDMA_WRID_RECV_CONTROL ? rdma->send_comp_channel :
+           rdma->recv_comp_channel;
+}
+
+static struct ibv_cq *to_cq(RDMAContext *rdma, int wrid)
+{
+    return wrid < RDMA_WRID_RECV_CONTROL ? rdma->send_cq : rdma->recv_cq;
+}
+
 /*
  * Block until the next work request has completed.
  *
@@ -1675,13 +1710,15 @@ static int qemu_rdma_block_for_wrid(RDMAContext *rdma, int wrid_requested,
     struct ibv_cq *cq;
     void *cq_ctx;
     uint64_t wr_id = RDMA_WRID_NONE, wr_id_in;
+    struct ibv_comp_channel *ch = to_channel(rdma, wrid_requested);
+    struct ibv_cq *poll_cq = to_cq(rdma, wrid_requested);
 
-    if (ibv_req_notify_cq(rdma->cq, 0)) {
+    if (ibv_req_notify_cq(poll_cq, 0)) {
         return -1;
     }
     /* poll cq first */
     while (wr_id != wrid_requested) {
-        ret = qemu_rdma_poll(rdma, &wr_id_in, byte_len);
+        ret = qemu_rdma_poll(rdma, poll_cq, &wr_id_in, byte_len);
         if (ret < 0) {
             return ret;
         }
@@ -1702,12 +1739,12 @@ static int qemu_rdma_block_for_wrid(RDMAContext *rdma, int wrid_requested,
     }
 
     while (1) {
-        ret = qemu_rdma_wait_comp_channel(rdma);
+        ret = qemu_rdma_wait_comp_channel(rdma, ch);
         if (ret) {
             goto err_block_for_wrid;
         }
 
-        ret = ibv_get_cq_event(rdma->comp_channel, &cq, &cq_ctx);
+        ret = ibv_get_cq_event(ch, &cq, &cq_ctx);
         if (ret) {
             perror("ibv_get_cq_event");
             goto err_block_for_wrid;
@@ -1721,7 +1758,7 @@ static int qemu_rdma_block_for_wrid(RDMAContext *rdma, int wrid_requested,
         }
 
         while (wr_id != wrid_requested) {
-            ret = qemu_rdma_poll(rdma, &wr_id_in, byte_len);
+            ret = qemu_rdma_poll(rdma, poll_cq, &wr_id_in, byte_len);
             if (ret < 0) {
                 goto err_block_for_wrid;
             }
@@ -2437,13 +2474,21 @@ static void qemu_rdma_cleanup(RDMAContext *rdma)
         rdma_destroy_qp(rdma->cm_id);
         rdma->qp = NULL;
     }
-    if (rdma->cq) {
-        ibv_destroy_cq(rdma->cq);
-        rdma->cq = NULL;
+    if (rdma->recv_cq) {
+        ibv_destroy_cq(rdma->recv_cq);
+        rdma->recv_cq = NULL;
+    }
+    if (rdma->send_cq) {
+        ibv_destroy_cq(rdma->send_cq);
+        rdma->send_cq = NULL;
+    }
+    if (rdma->recv_comp_channel) {
+        ibv_destroy_comp_channel(rdma->recv_comp_channel);
+        rdma->recv_comp_channel = NULL;
     }
-    if (rdma->comp_channel) {
-        ibv_destroy_comp_channel(rdma->comp_channel);
-        rdma->comp_channel = NULL;
+    if (rdma->send_comp_channel) {
+        ibv_destroy_comp_channel(rdma->send_comp_channel);
+        rdma->send_comp_channel = NULL;
     }
     if (rdma->pd) {
         ibv_dealloc_pd(rdma->pd);
@@ -3115,10 +3160,14 @@ static void qio_channel_rdma_set_aio_fd_handler(QIOChannel *ioc,
 {
     QIOChannelRDMA *rioc = QIO_CHANNEL_RDMA(ioc);
     if (io_read) {
-        aio_set_fd_handler(ctx, rioc->rdmain->comp_channel->fd,
+        aio_set_fd_handler(ctx, rioc->rdmain->recv_comp_channel->fd,
+                           false, io_read, io_write, NULL, opaque);
+        aio_set_fd_handler(ctx, rioc->rdmain->send_comp_channel->fd,
                            false, io_read, io_write, NULL, opaque);
     } else {
-        aio_set_fd_handler(ctx, rioc->rdmaout->comp_channel->fd,
+        aio_set_fd_handler(ctx, rioc->rdmaout->recv_comp_channel->fd,
+                           false, io_read, io_write, NULL, opaque);
+        aio_set_fd_handler(ctx, rioc->rdmaout->send_comp_channel->fd,
                            false, io_read, io_write, NULL, opaque);
     }
 }
@@ -3332,7 +3381,22 @@ static size_t qemu_rdma_save_page(QEMUFile *f, void *opaque,
      */
     while (1) {
         uint64_t wr_id, wr_id_in;
-        int ret = qemu_rdma_poll(rdma, &wr_id_in, NULL);
+        int ret = qemu_rdma_poll(rdma, rdma->recv_cq, &wr_id_in, NULL);
+        if (ret < 0) {
+            error_report("rdma migration: polling error! %d", ret);
+            goto err;
+        }
+
+        wr_id = wr_id_in & RDMA_WRID_TYPE_MASK;
+
+        if (wr_id == RDMA_WRID_NONE) {
+            break;
+        }
+    }
+
+    while (1) {
+        uint64_t wr_id, wr_id_in;
+        int ret = qemu_rdma_poll(rdma, rdma->send_cq, &wr_id_in, NULL);
         if (ret < 0) {
             error_report("rdma migration: polling error! %d", ret);
             goto err;
diff --git a/migration/trace-events b/migration/trace-events
index a8ae163707..b48d873b8a 100644
--- a/migration/trace-events
+++ b/migration/trace-events
@@ -333,6 +333,8 @@ get_ramblock_vfn_hash(const char *idstr, uint64_t vfn, uint32_t crc) "ramblock n
 calc_page_dirty_rate(const char *idstr, uint32_t new_crc, uint32_t old_crc) "ramblock name: %s, new crc: %" PRIu32 ", old crc: %" PRIu32
 skip_sample_ramblock(const char *idstr, uint64_t ramblock_size) "ramblock name: %s, ramblock size: %" PRIu64
 find_page_matched(const char *idstr) "ramblock %s addr or size changed"
+dirtyrate_calculate(int64_t dirtyrate) "dirty rate: %" PRIi64 " MB/s"
+dirtyrate_do_calculate_vcpu(int idx, uint64_t rate) "vcpu[%d]: %"PRIu64 " MB/s"
 
 # block.c
 migration_block_init_shared(const char *blk_device_name) "Start migration for %s with shared base image"
diff --git a/pc-bios/openbios-ppc b/pc-bios/openbios-ppc
index 91a73db9a3..67f32a8602 100644
--- a/pc-bios/openbios-ppc
+++ b/pc-bios/openbios-ppc
Binary files differdiff --git a/pc-bios/openbios-sparc32 b/pc-bios/openbios-sparc32
index a5b7389191..376b01c10b 100644
--- a/pc-bios/openbios-sparc32
+++ b/pc-bios/openbios-sparc32
Binary files differdiff --git a/pc-bios/openbios-sparc64 b/pc-bios/openbios-sparc64
index f7a501efc6..bbd746fde9 100644
--- a/pc-bios/openbios-sparc64
+++ b/pc-bios/openbios-sparc64
Binary files differdiff --git a/python/qemu/aqmp/__init__.py b/python/qemu/aqmp/__init__.py
index d1b0e4dc3d..880d5b6fa7 100644
--- a/python/qemu/aqmp/__init__.py
+++ b/python/qemu/aqmp/__init__.py
@@ -22,7 +22,6 @@ managing QMP events.
 # the COPYING file in the top-level directory.
 
 import logging
-import warnings
 
 from .error import AQMPError
 from .events import EventListener
@@ -31,17 +30,6 @@ from .protocol import ConnectError, Runstate, StateError
 from .qmp_client import ExecInterruptedError, ExecuteError, QMPClient
 
 
-_WMSG = """
-
-The Asynchronous QMP library is currently in development and its API
-should be considered highly fluid and subject to change. It should
-not be used by any other scripts checked into the QEMU tree.
-
-Proceed with caution!
-"""
-
-warnings.warn(_WMSG, FutureWarning)
-
 # Suppress logging unless an application engages it.
 logging.getLogger('qemu.aqmp').addHandler(logging.NullHandler())
 
diff --git a/python/qemu/aqmp/legacy.py b/python/qemu/aqmp/legacy.py
new file mode 100644
index 0000000000..9e7b9fb80b
--- /dev/null
+++ b/python/qemu/aqmp/legacy.py
@@ -0,0 +1,138 @@
+"""
+Sync QMP Wrapper
+
+This class pretends to be qemu.qmp.QEMUMonitorProtocol.
+"""
+
+import asyncio
+from typing import (
+    Awaitable,
+    List,
+    Optional,
+    TypeVar,
+    Union,
+)
+
+import qemu.qmp
+from qemu.qmp import QMPMessage, QMPReturnValue, SocketAddrT
+
+from .qmp_client import QMPClient
+
+
+# pylint: disable=missing-docstring
+
+
+class QEMUMonitorProtocol(qemu.qmp.QEMUMonitorProtocol):
+    def __init__(self, address: SocketAddrT,
+                 server: bool = False,
+                 nickname: Optional[str] = None):
+
+        # pylint: disable=super-init-not-called
+        self._aqmp = QMPClient(nickname)
+        self._aloop = asyncio.get_event_loop()
+        self._address = address
+        self._timeout: Optional[float] = None
+
+    _T = TypeVar('_T')
+
+    def _sync(
+            self, future: Awaitable[_T], timeout: Optional[float] = None
+    ) -> _T:
+        return self._aloop.run_until_complete(
+            asyncio.wait_for(future, timeout=timeout)
+        )
+
+    def _get_greeting(self) -> Optional[QMPMessage]:
+        if self._aqmp.greeting is not None:
+            # pylint: disable=protected-access
+            return self._aqmp.greeting._asdict()
+        return None
+
+    # __enter__ and __exit__ need no changes
+    # parse_address needs no changes
+
+    def connect(self, negotiate: bool = True) -> Optional[QMPMessage]:
+        self._aqmp.await_greeting = negotiate
+        self._aqmp.negotiate = negotiate
+
+        self._sync(
+            self._aqmp.connect(self._address)
+        )
+        return self._get_greeting()
+
+    def accept(self, timeout: Optional[float] = 15.0) -> QMPMessage:
+        self._aqmp.await_greeting = True
+        self._aqmp.negotiate = True
+
+        self._sync(
+            self._aqmp.accept(self._address),
+            timeout
+        )
+
+        ret = self._get_greeting()
+        assert ret is not None
+        return ret
+
+    def cmd_obj(self, qmp_cmd: QMPMessage) -> QMPMessage:
+        return dict(
+            self._sync(
+                # pylint: disable=protected-access
+
+                # _raw() isn't a public API, because turning off
+                # automatic ID assignment is discouraged. For
+                # compatibility with iotests *only*, do it anyway.
+                self._aqmp._raw(qmp_cmd, assign_id=False),
+                self._timeout
+            )
+        )
+
+    # Default impl of cmd() delegates to cmd_obj
+
+    def command(self, cmd: str, **kwds: object) -> QMPReturnValue:
+        return self._sync(
+            self._aqmp.execute(cmd, kwds),
+            self._timeout
+        )
+
+    def pull_event(self,
+                   wait: Union[bool, float] = False) -> Optional[QMPMessage]:
+        if not wait:
+            # wait is False/0: "do not wait, do not except."
+            if self._aqmp.events.empty():
+                return None
+
+        # If wait is 'True', wait forever. If wait is False/0, the events
+        # queue must not be empty; but it still needs some real amount
+        # of time to complete.
+        timeout = None
+        if wait and isinstance(wait, float):
+            timeout = wait
+
+        return dict(
+            self._sync(
+                self._aqmp.events.get(),
+                timeout
+            )
+        )
+
+    def get_events(self, wait: Union[bool, float] = False) -> List[QMPMessage]:
+        events = [dict(x) for x in self._aqmp.events.clear()]
+        if events:
+            return events
+
+        event = self.pull_event(wait)
+        return [event] if event is not None else []
+
+    def clear_events(self) -> None:
+        self._aqmp.events.clear()
+
+    def close(self) -> None:
+        self._sync(
+            self._aqmp.disconnect()
+        )
+
+    def settimeout(self, timeout: Optional[float]) -> None:
+        self._timeout = timeout
+
+    def send_fd_scm(self, fd: int) -> None:
+        self._aqmp.send_fd_scm(fd)
diff --git a/python/qemu/machine/machine.py b/python/qemu/machine/machine.py
index 056d340e35..a487c39745 100644
--- a/python/qemu/machine/machine.py
+++ b/python/qemu/machine/machine.py
@@ -41,7 +41,6 @@ from typing import (
 )
 
 from qemu.qmp import (  # pylint: disable=import-error
-    QEMUMonitorProtocol,
     QMPMessage,
     QMPReturnValue,
     SocketAddrT,
@@ -50,6 +49,12 @@ from qemu.qmp import (  # pylint: disable=import-error
 from . import console_socket
 
 
+if os.environ.get('QEMU_PYTHON_LEGACY_QMP'):
+    from qemu.qmp import QEMUMonitorProtocol
+else:
+    from qemu.aqmp.legacy import QEMUMonitorProtocol
+
+
 LOG = logging.getLogger(__name__)
 
 
@@ -170,6 +175,7 @@ class QEMUMachine:
         self._console_socket: Optional[socket.socket] = None
         self._remove_files: List[str] = []
         self._user_killed = False
+        self._quit_issued = False
 
     def __enter__(self: _T) -> _T:
         return self
@@ -341,9 +347,15 @@ class QEMUMachine:
         # Comprehensive reset for the failed launch case:
         self._early_cleanup()
 
-        if self._qmp_connection:
-            self._qmp.close()
-            self._qmp_connection = None
+        try:
+            self._close_qmp_connection()
+        except Exception as err:  # pylint: disable=broad-except
+            LOG.warning(
+                "Exception closing QMP connection: %s",
+                str(err) if str(err) else type(err).__name__
+            )
+        finally:
+            assert self._qmp_connection is None
 
         self._close_qemu_log_file()
 
@@ -368,6 +380,7 @@ class QEMUMachine:
                 command = ''
             LOG.warning(msg, -int(exitcode), command)
 
+        self._quit_issued = False
         self._user_killed = False
         self._launched = False
 
@@ -418,6 +431,31 @@ class QEMUMachine:
                                        close_fds=False)
         self._post_launch()
 
+    def _close_qmp_connection(self) -> None:
+        """
+        Close the underlying QMP connection, if any.
+
+        Dutifully report errors that occurred while closing, but assume
+        that any error encountered indicates an abnormal termination
+        process and not a failure to close.
+        """
+        if self._qmp_connection is None:
+            return
+
+        try:
+            self._qmp.close()
+        except EOFError:
+            # EOF can occur as an Exception here when using the Async
+            # QMP backend. It indicates that the server closed the
+            # stream. If we successfully issued 'quit' at any point,
+            # then this was expected. If the remote went away without
+            # our permission, it's worth reporting that as an abnormal
+            # shutdown case.
+            if not (self._user_killed or self._quit_issued):
+                raise
+        finally:
+            self._qmp_connection = None
+
     def _early_cleanup(self) -> None:
         """
         Perform any cleanup that needs to happen before the VM exits.
@@ -443,15 +481,13 @@ class QEMUMachine:
         self._subp.kill()
         self._subp.wait(timeout=60)
 
-    def _soft_shutdown(self, timeout: Optional[int],
-                       has_quit: bool = False) -> None:
+    def _soft_shutdown(self, timeout: Optional[int]) -> None:
         """
         Perform early cleanup, attempt to gracefully shut down the VM, and wait
         for it to terminate.
 
         :param timeout: Timeout in seconds for graceful shutdown.
                         A value of None is an infinite wait.
-        :param has_quit: When True, don't attempt to issue 'quit' QMP command
 
         :raise ConnectionReset: On QMP communication errors
         :raise subprocess.TimeoutExpired: When timeout is exceeded waiting for
@@ -460,21 +496,24 @@ class QEMUMachine:
         self._early_cleanup()
 
         if self._qmp_connection:
-            if not has_quit:
-                # Might raise ConnectionReset
-                self._qmp.cmd('quit')
+            try:
+                if not self._quit_issued:
+                    # May raise ExecInterruptedError or StateError if the
+                    # connection dies or has *already* died.
+                    self.qmp('quit')
+            finally:
+                # Regardless, we want to quiesce the connection.
+                self._close_qmp_connection()
 
         # May raise subprocess.TimeoutExpired
         self._subp.wait(timeout=timeout)
 
-    def _do_shutdown(self, timeout: Optional[int],
-                     has_quit: bool = False) -> None:
+    def _do_shutdown(self, timeout: Optional[int]) -> None:
         """
         Attempt to shutdown the VM gracefully; fallback to a hard shutdown.
 
         :param timeout: Timeout in seconds for graceful shutdown.
                         A value of None is an infinite wait.
-        :param has_quit: When True, don't attempt to issue 'quit' QMP command
 
         :raise AbnormalShutdown: When the VM could not be shut down gracefully.
             The inner exception will likely be ConnectionReset or
@@ -482,13 +521,13 @@ class QEMUMachine:
             may result in its own exceptions, likely subprocess.TimeoutExpired.
         """
         try:
-            self._soft_shutdown(timeout, has_quit)
+            self._soft_shutdown(timeout)
         except Exception as exc:
             self._hard_shutdown()
             raise AbnormalShutdown("Could not perform graceful shutdown") \
                 from exc
 
-    def shutdown(self, has_quit: bool = False,
+    def shutdown(self,
                  hard: bool = False,
                  timeout: Optional[int] = 30) -> None:
         """
@@ -498,7 +537,6 @@ class QEMUMachine:
         If the VM has not yet been launched, or shutdown(), wait(), or kill()
         have already been called, this method does nothing.
 
-        :param has_quit: When true, do not attempt to issue 'quit' QMP command.
         :param hard: When true, do not attempt graceful shutdown, and
                      suppress the SIGKILL warning log message.
         :param timeout: Optional timeout in seconds for graceful shutdown.
@@ -512,7 +550,7 @@ class QEMUMachine:
                 self._user_killed = True
                 self._hard_shutdown()
             else:
-                self._do_shutdown(timeout, has_quit)
+                self._do_shutdown(timeout)
         finally:
             self._post_shutdown()
 
@@ -529,7 +567,8 @@ class QEMUMachine:
         :param timeout: Optional timeout in seconds. Default 30 seconds.
                         A value of `None` is an infinite wait.
         """
-        self.shutdown(has_quit=True, timeout=timeout)
+        self._quit_issued = True
+        self.shutdown(timeout=timeout)
 
     def set_qmp_monitor(self, enabled: bool = True) -> None:
         """
@@ -574,7 +613,10 @@ class QEMUMachine:
             conv_keys = True
 
         qmp_args = self._qmp_args(conv_keys, args)
-        return self._qmp.cmd(cmd, args=qmp_args)
+        ret = self._qmp.cmd(cmd, args=qmp_args)
+        if cmd == 'quit' and 'error' not in ret and 'return' in ret:
+            self._quit_issued = True
+        return ret
 
     def command(self, cmd: str,
                 conv_keys: bool = True,
@@ -585,7 +627,10 @@ class QEMUMachine:
         On failure raise an exception.
         """
         qmp_args = self._qmp_args(conv_keys, args)
-        return self._qmp.command(cmd, **qmp_args)
+        ret = self._qmp.command(cmd, **qmp_args)
+        if cmd == 'quit':
+            self._quit_issued = True
+        return ret
 
     def get_qmp_event(self, wait: bool = False) -> Optional[QMPMessage]:
         """
diff --git a/python/tests/iotests-mypy.sh b/python/tests/iotests-mypy.sh
new file mode 100755
index 0000000000..ee76470819
--- /dev/null
+++ b/python/tests/iotests-mypy.sh
@@ -0,0 +1,4 @@
+#!/bin/sh -e
+
+cd ../tests/qemu-iotests/
+python3 -m linters --mypy
diff --git a/python/tests/iotests-pylint.sh b/python/tests/iotests-pylint.sh
new file mode 100755
index 0000000000..4cae03424b
--- /dev/null
+++ b/python/tests/iotests-pylint.sh
@@ -0,0 +1,4 @@
+#!/bin/sh -e
+
+cd ../tests/qemu-iotests/
+python3 -m linters --pylint
diff --git a/qapi/migration.json b/qapi/migration.json
index 9aa8bc5759..87146ceea2 100644
--- a/qapi/migration.json
+++ b/qapi/migration.json
@@ -1732,6 +1732,21 @@
   'data': { 'device-id': 'str' } }
 
 ##
+# @DirtyRateVcpu:
+#
+# Dirty rate of vcpu.
+#
+# @id: vcpu index.
+#
+# @dirty-rate: dirty rate.
+#
+# Since: 6.1
+#
+##
+{ 'struct': 'DirtyRateVcpu',
+  'data': { 'id': 'int', 'dirty-rate': 'int64' } }
+
+##
 # @DirtyRateStatus:
 #
 # An enumeration of dirtyrate status.
@@ -1749,6 +1764,23 @@
   'data': [ 'unstarted', 'measuring', 'measured'] }
 
 ##
+# @DirtyRateMeasureMode:
+#
+# An enumeration of mode of measuring dirtyrate.
+#
+# @page-sampling: calculate dirtyrate by sampling pages.
+#
+# @dirty-ring: calculate dirtyrate by dirty ring.
+#
+# @dirty-bitmap: calculate dirtyrate by dirty bitmap.
+#
+# Since: 6.1
+#
+##
+{ 'enum': 'DirtyRateMeasureMode',
+  'data': ['page-sampling', 'dirty-ring', 'dirty-bitmap'] }
+
+##
 # @DirtyRateInfo:
 #
 # Information about current dirty page rate of vm.
@@ -1766,6 +1798,12 @@
 # @sample-pages: page count per GB for sample dirty pages
 #                the default value is 512 (since 6.1)
 #
+# @mode: mode containing method of calculate dirtyrate includes
+#        'page-sampling' and 'dirty-ring' (Since 6.1)
+#
+# @vcpu-dirty-rate: dirtyrate for each vcpu if dirty-ring
+#                   mode specified (Since 6.1)
+#
 # Since: 5.2
 #
 ##
@@ -1774,7 +1812,9 @@
            'status': 'DirtyRateStatus',
            'start-time': 'int64',
            'calc-time': 'int64',
-           'sample-pages': 'uint64'} }
+           'sample-pages': 'uint64',
+           'mode': 'DirtyRateMeasureMode',
+           '*vcpu-dirty-rate': [ 'DirtyRateVcpu' ] } }
 
 ##
 # @calc-dirty-rate:
@@ -1786,6 +1826,9 @@
 # @sample-pages: page count per GB for sample dirty pages
 #                the default value is 512 (since 6.1)
 #
+# @mode: mechanism of calculating dirtyrate includes
+#        'page-sampling' and 'dirty-ring' (Since 6.1)
+#
 # Since: 5.2
 #
 # Example:
@@ -1794,7 +1837,8 @@
 #
 ##
 { 'command': 'calc-dirty-rate', 'data': {'calc-time': 'int64',
-                                         '*sample-pages': 'int'} }
+                                         '*sample-pages': 'int',
+                                         '*mode': 'DirtyRateMeasureMode'} }
 
 ##
 # @query-dirty-rate:
diff --git a/roms/openbios b/roms/openbios
-Subproject d657b653186c0fd6e062cab133497415c2a5a5b
+Subproject b9062deaaea7269369eaa46260d75edcaf276af
diff --git a/scripts/simplebench/bench_block_job.py b/scripts/simplebench/bench_block_job.py
index 4f03c12169..a403c35b08 100755
--- a/scripts/simplebench/bench_block_job.py
+++ b/scripts/simplebench/bench_block_job.py
@@ -28,6 +28,7 @@ import json
 sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', 'python'))
 from qemu.machine import QEMUMachine
 from qemu.qmp import QMPConnectError
+from qemu.aqmp import ConnectError
 
 
 def bench_block_job(cmd, cmd_args, qemu_args):
@@ -49,7 +50,7 @@ def bench_block_job(cmd, cmd_args, qemu_args):
         vm.launch()
     except OSError as e:
         return {'error': 'popen failed: ' + str(e)}
-    except (QMPConnectError, socket.timeout):
+    except (QMPConnectError, ConnectError, socket.timeout):
         return {'error': 'qemu failed: ' + str(vm.get_log())}
 
     try:
diff --git a/softmmu/memory.c b/softmmu/memory.c
index e5826faa0c..7340e19ff5 100644
--- a/softmmu/memory.c
+++ b/softmmu/memory.c
@@ -39,7 +39,7 @@
 static unsigned memory_region_transaction_depth;
 static bool memory_region_update_pending;
 static bool ioeventfd_update_pending;
-bool global_dirty_log;
+unsigned int global_dirty_tracking;
 
 static QTAILQ_HEAD(, MemoryListener) memory_listeners
     = QTAILQ_HEAD_INITIALIZER(memory_listeners);
@@ -1821,7 +1821,7 @@ uint8_t memory_region_get_dirty_log_mask(MemoryRegion *mr)
     uint8_t mask = mr->dirty_log_mask;
     RAMBlock *rb = mr->ram_block;
 
-    if (global_dirty_log && ((rb && qemu_ram_is_migratable(rb)) ||
+    if (global_dirty_tracking && ((rb && qemu_ram_is_migratable(rb)) ||
                              memory_region_is_iommu(mr))) {
         mask |= (1 << DIRTY_MEMORY_MIGRATION);
     }
@@ -2081,6 +2081,17 @@ int ram_discard_manager_replay_populated(const RamDiscardManager *rdm,
     return rdmc->replay_populated(rdm, section, replay_fn, opaque);
 }
 
+void ram_discard_manager_replay_discarded(const RamDiscardManager *rdm,
+                                          MemoryRegionSection *section,
+                                          ReplayRamDiscard replay_fn,
+                                          void *opaque)
+{
+    RamDiscardManagerClass *rdmc = RAM_DISCARD_MANAGER_GET_CLASS(rdm);
+
+    g_assert(rdmc->replay_discarded);
+    rdmc->replay_discarded(rdm, section, replay_fn, opaque);
+}
+
 void ram_discard_manager_register_listener(RamDiscardManager *rdm,
                                            RamDiscardListener *rdl,
                                            MemoryRegionSection *section)
@@ -2760,14 +2771,18 @@ void memory_global_after_dirty_log_sync(void)
 
 static VMChangeStateEntry *vmstate_change;
 
-void memory_global_dirty_log_start(void)
+void memory_global_dirty_log_start(unsigned int flags)
 {
     if (vmstate_change) {
         qemu_del_vm_change_state_handler(vmstate_change);
         vmstate_change = NULL;
     }
 
-    global_dirty_log = true;
+    assert(flags && !(flags & (~GLOBAL_DIRTY_MASK)));
+    assert(!(global_dirty_tracking & flags));
+    global_dirty_tracking |= flags;
+
+    trace_global_dirty_changed(global_dirty_tracking);
 
     MEMORY_LISTENER_CALL_GLOBAL(log_global_start, Forward);
 
@@ -2777,9 +2792,13 @@ void memory_global_dirty_log_start(void)
     memory_region_transaction_commit();
 }
 
-static void memory_global_dirty_log_do_stop(void)
+static void memory_global_dirty_log_do_stop(unsigned int flags)
 {
-    global_dirty_log = false;
+    assert(flags && !(flags & (~GLOBAL_DIRTY_MASK)));
+    assert((global_dirty_tracking & flags) == flags);
+    global_dirty_tracking &= ~flags;
+
+    trace_global_dirty_changed(global_dirty_tracking);
 
     /* Refresh DIRTY_MEMORY_MIGRATION bit.  */
     memory_region_transaction_begin();
@@ -2792,8 +2811,9 @@ static void memory_global_dirty_log_do_stop(void)
 static void memory_vm_change_state_handler(void *opaque, bool running,
                                            RunState state)
 {
+    unsigned int flags = (unsigned int)(uintptr_t)opaque;
     if (running) {
-        memory_global_dirty_log_do_stop();
+        memory_global_dirty_log_do_stop(flags);
 
         if (vmstate_change) {
             qemu_del_vm_change_state_handler(vmstate_change);
@@ -2802,18 +2822,19 @@ static void memory_vm_change_state_handler(void *opaque, bool running,
     }
 }
 
-void memory_global_dirty_log_stop(void)
+void memory_global_dirty_log_stop(unsigned int flags)
 {
     if (!runstate_is_running()) {
         if (vmstate_change) {
             return;
         }
         vmstate_change = qemu_add_vm_change_state_handler(
-                                memory_vm_change_state_handler, NULL);
+                                memory_vm_change_state_handler,
+                                (void *)(uintptr_t)flags);
         return;
     }
 
-    memory_global_dirty_log_do_stop();
+    memory_global_dirty_log_do_stop(flags);
 }
 
 static void listener_add_address_space(MemoryListener *listener,
@@ -2825,7 +2846,7 @@ static void listener_add_address_space(MemoryListener *listener,
     if (listener->begin) {
         listener->begin(listener);
     }
-    if (global_dirty_log) {
+    if (global_dirty_tracking) {
         if (listener->log_global_start) {
             listener->log_global_start(listener);
         }
diff --git a/softmmu/qdev-monitor.c b/softmmu/qdev-monitor.c
index 4851de51a5..e49d9773d2 100644
--- a/softmmu/qdev-monitor.c
+++ b/softmmu/qdev-monitor.c
@@ -42,6 +42,7 @@
 #include "qemu/cutils.h"
 #include "hw/qdev-properties.h"
 #include "hw/clock.h"
+#include "hw/boards.h"
 
 /*
  * Aliases were a bad idea from the start.  Let's keep them
@@ -254,6 +255,16 @@ static DeviceClass *qdev_get_device_class(const char **driver, Error **errp)
         return NULL;
     }
 
+    if (object_class_dynamic_cast(oc, TYPE_SYS_BUS_DEVICE)) {
+        /* sysbus devices need to be allowed by the machine */
+        MachineClass *mc = MACHINE_CLASS(object_get_class(qdev_get_machine()));
+        if (!device_type_is_dynamic_sysbus(mc, *driver)) {
+            error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "driver",
+                       "a dynamic sysbus device type for the machine");
+            return NULL;
+        }
+    }
+
     return dc;
 }
 
diff --git a/softmmu/trace-events b/softmmu/trace-events
index bf1469990e..9c88887b3c 100644
--- a/softmmu/trace-events
+++ b/softmmu/trace-events
@@ -19,6 +19,7 @@ memory_region_sync_dirty(const char *mr, const char *listener, int global) "mr '
 flatview_new(void *view, void *root) "%p (root %p)"
 flatview_destroy(void *view, void *root) "%p (root %p)"
 flatview_destroy_rcu(void *view, void *root) "%p (root %p)"
+global_dirty_changed(unsigned int bitmask) "bitmask 0x%"PRIx32
 
 # softmmu.c
 vm_stop_flush_all(int ret) "ret %d"
diff --git a/tests/qemu-iotests/040 b/tests/qemu-iotests/040
index f3677de9df..6af5ab9e76 100755
--- a/tests/qemu-iotests/040
+++ b/tests/qemu-iotests/040
@@ -92,10 +92,9 @@ class TestSingleDrive(ImageCommitTestCase):
         self.vm.add_device('virtio-scsi')
         self.vm.add_device("scsi-hd,id=scsi0,drive=drive0")
         self.vm.launch()
-        self.has_quit = False
 
     def tearDown(self):
-        self.vm.shutdown(has_quit=self.has_quit)
+        self.vm.shutdown()
         os.remove(test_img)
         os.remove(mid_img)
         os.remove(backing_img)
@@ -127,8 +126,6 @@ class TestSingleDrive(ImageCommitTestCase):
         result = self.vm.qmp('quit')
         self.assert_qmp(result, 'return', {})
 
-        self.has_quit = True
-
     # Same as above, but this time we add the filter after starting the job
     @iotests.skip_if_unsupported(['throttle'])
     def test_commit_plus_filter_and_quit(self):
@@ -147,8 +144,6 @@ class TestSingleDrive(ImageCommitTestCase):
         result = self.vm.qmp('quit')
         self.assert_qmp(result, 'return', {})
 
-        self.has_quit = True
-
     def test_device_not_found(self):
         result = self.vm.qmp('block-commit', device='nonexistent', top='%s' % mid_img)
         self.assert_qmp(result, 'error/class', 'DeviceNotFound')
diff --git a/tests/qemu-iotests/218 b/tests/qemu-iotests/218
index 325d8244fb..4922b4d3b6 100755
--- a/tests/qemu-iotests/218
+++ b/tests/qemu-iotests/218
@@ -187,4 +187,4 @@ with iotests.VM() as vm, \
     log(vm.qmp('quit'))
 
     with iotests.Timeout(5, 'Timeout waiting for VM to quit'):
-        vm.shutdown(has_quit=True)
+        vm.shutdown()
diff --git a/tests/qemu-iotests/255 b/tests/qemu-iotests/255
index c43aa9c67a..3d6d0e80cb 100755
--- a/tests/qemu-iotests/255
+++ b/tests/qemu-iotests/255
@@ -123,4 +123,4 @@ with iotests.FilePath('src.qcow2') as src_path, \
     vm.qmp_log('block-job-cancel', device='job0')
     vm.qmp_log('quit')
 
-    vm.shutdown(has_quit=True)
+    vm.shutdown()
diff --git a/tests/qemu-iotests/297 b/tests/qemu-iotests/297
index 91ec34d952..ee78a62735 100755
--- a/tests/qemu-iotests/297
+++ b/tests/qemu-iotests/297
@@ -17,89 +17,66 @@
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 import os
-import re
-import shutil
 import subprocess
 import sys
+from typing import List
 
 import iotests
+import linters
 
 
-# TODO: Empty this list!
-SKIP_FILES = (
-    '030', '040', '041', '044', '045', '055', '056', '057', '065', '093',
-    '096', '118', '124', '132', '136', '139', '147', '148', '149',
-    '151', '152', '155', '163', '165', '194', '196', '202',
-    '203', '205', '206', '207', '208', '210', '211', '212', '213', '216',
-    '218', '219', '224', '228', '234', '235', '236', '237', '238',
-    '240', '242', '245', '246', '248', '255', '256', '257', '258', '260',
-    '262', '264', '266', '274', '277', '280', '281', '295', '296', '298',
-    '299', '302', '303', '304', '307',
-    'nbd-fault-injector.py', 'qcow2.py', 'qcow2_format.py', 'qed.py'
-)
+# Looking for something?
+#
+#  List of files to exclude from linting: linters.py
+#  mypy configuration:                    mypy.ini
+#  pylint configuration:                  pylintrc
 
 
-def is_python_file(filename):
-    if not os.path.isfile(filename):
+def check_linter(linter: str) -> bool:
+    try:
+        linters.run_linter(linter, ['--version'], suppress_output=True)
+    except subprocess.CalledProcessError:
+        iotests.case_notrun(f"'{linter}' not found")
         return False
+    return True
 
-    if filename.endswith('.py'):
-        return True
 
-    with open(filename, encoding='utf-8') as f:
-        try:
-            first_line = f.readline()
-            return re.match('^#!.*python', first_line) is not None
-        except UnicodeDecodeError:  # Ignore binary files
-            return False
+def test_pylint(files: List[str]) -> None:
+    print('=== pylint ===')
+    sys.stdout.flush()
 
+    if not check_linter('pylint'):
+        return
 
-def run_linters():
-    named_tests = [f'tests/{entry}' for entry in os.listdir('tests')]
-    check_tests = set(os.listdir('.') + named_tests) - set(SKIP_FILES)
-    files = [filename for filename in check_tests if is_python_file(filename)]
+    linters.run_linter('pylint', files)
 
-    iotests.logger.debug('Files to be checked:')
-    iotests.logger.debug(', '.join(sorted(files)))
 
-    print('=== pylint ===')
+def test_mypy(files: List[str]) -> None:
+    print('=== mypy ===')
     sys.stdout.flush()
 
-    # Todo notes are fine, but fixme's or xxx's should probably just be
-    # fixed (in tests, at least)
+    if not check_linter('mypy'):
+        return
+
     env = os.environ.copy()
-    subprocess.run(('pylint-3', '--score=n', '--notes=FIXME,XXX', *files),
-                   env=env, check=False)
+    env['MYPYPATH'] = env['PYTHONPATH']
 
-    print('=== mypy ===')
-    sys.stdout.flush()
+    linters.run_linter('mypy', files, env=env, suppress_output=True)
 
-    env['MYPYPATH'] = env['PYTHONPATH']
-    p = subprocess.run(('mypy',
-                        '--warn-unused-configs',
-                        '--disallow-subclassing-any',
-                        '--disallow-any-generics',
-                        '--disallow-incomplete-defs',
-                        '--disallow-untyped-decorators',
-                        '--no-implicit-optional',
-                        '--warn-redundant-casts',
-                        '--warn-unused-ignores',
-                        '--no-implicit-reexport',
-                        '--namespace-packages',
-                        '--scripts-are-modules',
-                        *files),
-                       env=env,
-                       check=False,
-                       stdout=subprocess.PIPE,
-                       stderr=subprocess.STDOUT,
-                       universal_newlines=True)
-
-    if p.returncode != 0:
-        print(p.stdout)
-
-
-for linter in ('pylint-3', 'mypy'):
-    if shutil.which(linter) is None:
-        iotests.notrun(f'{linter} not found')
-
-iotests.script_main(run_linters)
+
+def main() -> None:
+    files = linters.get_test_files()
+
+    iotests.logger.debug('Files to be checked:')
+    iotests.logger.debug(', '.join(sorted(files)))
+
+    for test in (test_pylint, test_mypy):
+        try:
+            test(files)
+        except subprocess.CalledProcessError as exc:
+            # Linter failure will be caught by diffing the IO.
+            if exc.output:
+                print(exc.output)
+
+
+iotests.script_main(main)
diff --git a/tests/qemu-iotests/300 b/tests/qemu-iotests/300
index 10f9f2a8da..dbd28384ec 100755
--- a/tests/qemu-iotests/300
+++ b/tests/qemu-iotests/300
@@ -24,8 +24,6 @@ import random
 import re
 from typing import Dict, List, Optional
 
-from qemu.machine import machine
-
 import iotests
 
 
@@ -461,12 +459,11 @@ class TestBlockBitmapMappingErrors(TestDirtyBitmapMigration):
                       f"'{self.src_node_name}': Name is longer than 255 bytes",
                       log)
 
-        # Expect abnormal shutdown of the destination VM because of
-        # the failed migration
-        try:
-            self.vm_b.shutdown()
-        except machine.AbnormalShutdown:
-            pass
+        # Destination VM will terminate w/ error of its own accord
+        # due to the failed migration.
+        self.vm_b.wait()
+        rc = self.vm_b.exitcode()
+        assert rc is not None and rc > 0
 
     def test_aliased_bitmap_name_too_long(self) -> None:
         # Longer than the maximum for bitmap names
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
index e5fff6ddcf..e2f9d873ad 100644
--- a/tests/qemu-iotests/iotests.py
+++ b/tests/qemu-iotests/iotests.py
@@ -30,7 +30,7 @@ import struct
 import subprocess
 import sys
 import time
-from typing import (Any, Callable, Dict, Iterable,
+from typing import (Any, Callable, Dict, Iterable, Iterator,
                     List, Optional, Sequence, TextIO, Tuple, Type, TypeVar)
 import unittest
 
@@ -114,6 +114,24 @@ luks_default_key_secret_opt = 'key-secret=keysec0'
 sample_img_dir = os.environ['SAMPLE_IMG_DIR']
 
 
+@contextmanager
+def change_log_level(
+        logger_name: str, level: int = logging.CRITICAL) -> Iterator[None]:
+    """
+    Utility function for temporarily changing the log level of a logger.
+
+    This can be used to silence errors that are expected or uninteresting.
+    """
+    _logger = logging.getLogger(logger_name)
+    current_level = _logger.level
+    _logger.setLevel(level)
+
+    try:
+        yield
+    finally:
+        _logger.setLevel(current_level)
+
+
 def unarchive_sample_image(sample, fname):
     sample_fname = os.path.join(sample_img_dir, sample + '.bz2')
     with bz2.open(sample_fname) as f_in, open(fname, 'wb') as f_out:
diff --git a/tests/qemu-iotests/linters.py b/tests/qemu-iotests/linters.py
new file mode 100644
index 0000000000..65c4c4e827
--- /dev/null
+++ b/tests/qemu-iotests/linters.py
@@ -0,0 +1,105 @@
+# Copyright (C) 2020 Red Hat, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+import os
+import re
+import subprocess
+import sys
+from typing import List, Mapping, Optional
+
+
+# TODO: Empty this list!
+SKIP_FILES = (
+    '030', '040', '041', '044', '045', '055', '056', '057', '065', '093',
+    '096', '118', '124', '132', '136', '139', '147', '148', '149',
+    '151', '152', '155', '163', '165', '194', '196', '202',
+    '203', '205', '206', '207', '208', '210', '211', '212', '213', '216',
+    '218', '219', '224', '228', '234', '235', '236', '237', '238',
+    '240', '242', '245', '246', '248', '255', '256', '257', '258', '260',
+    '262', '264', '266', '274', '277', '280', '281', '295', '296', '298',
+    '299', '302', '303', '304', '307',
+    'nbd-fault-injector.py', 'qcow2.py', 'qcow2_format.py', 'qed.py'
+)
+
+
+def is_python_file(filename):
+    if not os.path.isfile(filename):
+        return False
+
+    if filename.endswith('.py'):
+        return True
+
+    with open(filename, encoding='utf-8') as f:
+        try:
+            first_line = f.readline()
+            return re.match('^#!.*python', first_line) is not None
+        except UnicodeDecodeError:  # Ignore binary files
+            return False
+
+
+def get_test_files() -> List[str]:
+    named_tests = [f'tests/{entry}' for entry in os.listdir('tests')]
+    check_tests = set(os.listdir('.') + named_tests) - set(SKIP_FILES)
+    return list(filter(is_python_file, check_tests))
+
+
+def run_linter(
+        tool: str,
+        args: List[str],
+        env: Optional[Mapping[str, str]] = None,
+        suppress_output: bool = False,
+) -> None:
+    """
+    Run a python-based linting tool.
+
+    :param suppress_output: If True, suppress all stdout/stderr output.
+    :raise CalledProcessError: If the linter process exits with failure.
+    """
+    subprocess.run(
+        ('python3', '-m', tool, *args),
+        env=env,
+        check=True,
+        stdout=subprocess.PIPE if suppress_output else None,
+        stderr=subprocess.STDOUT if suppress_output else None,
+        universal_newlines=True,
+    )
+
+
+def main() -> None:
+    """
+    Used by the Python CI system as an entry point to run these linters.
+    """
+    def show_usage() -> None:
+        print(f"Usage: {sys.argv[0]} < --mypy | --pylint >", file=sys.stderr)
+        sys.exit(1)
+
+    if len(sys.argv) != 2:
+        show_usage()
+
+    files = get_test_files()
+
+    if sys.argv[1] == '--pylint':
+        run_linter('pylint', files)
+    elif sys.argv[1] == '--mypy':
+        # mypy bug #9852; disable incremental checking as a workaround.
+        args = ['--no-incremental'] + files
+        run_linter('mypy', args)
+    else:
+        print(f"Unrecognized argument: '{sys.argv[1]}'", file=sys.stderr)
+        show_usage()
+
+
+if __name__ == '__main__':
+    main()
diff --git a/tests/qemu-iotests/mypy.ini b/tests/qemu-iotests/mypy.ini
new file mode 100644
index 0000000000..4c0339f558
--- /dev/null
+++ b/tests/qemu-iotests/mypy.ini
@@ -0,0 +1,12 @@
+[mypy]
+disallow_any_generics = True
+disallow_incomplete_defs = True
+disallow_subclassing_any = True
+disallow_untyped_decorators = True
+implicit_reexport = False
+namespace_packages = True
+no_implicit_optional = True
+scripts_are_modules = True
+warn_redundant_casts = True
+warn_unused_configs = True
+warn_unused_ignores = True
diff --git a/tests/qemu-iotests/pylintrc b/tests/qemu-iotests/pylintrc
index 8cb4e1d6a6..32ab77b8bb 100644
--- a/tests/qemu-iotests/pylintrc
+++ b/tests/qemu-iotests/pylintrc
@@ -31,6 +31,22 @@ disable=invalid-name,
         too-many-statements,
         consider-using-f-string,
 
+
+[REPORTS]
+
+# Activate the evaluation score.
+score=no
+
+
+[MISCELLANEOUS]
+
+# List of note tags to take in consideration, separated by a comma.
+# TODO notes are fine, but FIXMEs or XXXs should probably just be
+# fixed (in tests, at least).
+notes=FIXME,
+      XXX,
+
+
 [FORMAT]
 
 # Maximum number of characters on a single line.
diff --git a/tests/qemu-iotests/tests/mirror-top-perms b/tests/qemu-iotests/tests/mirror-top-perms
index 3d475aa3a5..0a51a613f3 100755
--- a/tests/qemu-iotests/tests/mirror-top-perms
+++ b/tests/qemu-iotests/tests/mirror-top-perms
@@ -21,11 +21,12 @@
 
 import os
 
-from qemu import qmp
+from qemu.aqmp import ConnectError
 from qemu.machine import machine
+from qemu.qmp import QMPConnectError
 
 import iotests
-from iotests import qemu_img
+from iotests import change_log_level, qemu_img
 
 
 image_size = 1 * 1024 * 1024
@@ -99,10 +100,14 @@ class TestMirrorTopPerms(iotests.QMPTestCase):
         self.vm_b.add_blockdev(f'file,node-name=drive0,filename={source}')
         self.vm_b.add_device('virtio-blk,drive=drive0,share-rw=on')
         try:
-            self.vm_b.launch()
-            print('ERROR: VM B launched successfully, this should not have '
-                  'happened')
-        except qmp.QMPConnectError:
+            # Silence AQMP errors temporarily.
+            # TODO: Remove this and just allow the errors to be logged when
+            # AQMP fully replaces QMP.
+            with change_log_level('qemu.aqmp'):
+                self.vm_b.launch()
+                print('ERROR: VM B launched successfully, '
+                      'this should not have happened')
+        except (QMPConnectError, ConnectError):
             assert 'Is another process using the image' in self.vm_b.get_log()
 
         result = self.vm.qmp('block-job-cancel',
diff --git a/tests/unit/meson.build b/tests/unit/meson.build
index 5ac2d9e943..acac3622ed 100644
--- a/tests/unit/meson.build
+++ b/tests/unit/meson.build
@@ -46,6 +46,7 @@ tests = {
   'test-uuid': [],
   'ptimer-test': ['ptimer-test-stubs.c', meson.project_source_root() / 'hw/core/ptimer.c'],
   'test-qapi-util': [],
+  'test-smp-parse': [qom, meson.project_source_root() / 'hw/core/machine-smp.c'],
 }
 
 if have_system or have_tools
diff --git a/tests/unit/test-smp-parse.c b/tests/unit/test-smp-parse.c
new file mode 100644
index 0000000000..cbe0c99049
--- /dev/null
+++ b/tests/unit/test-smp-parse.c
@@ -0,0 +1,594 @@
+/*
+ * SMP parsing unit-tests
+ *
+ * Copyright (c) 2021 Huawei Technologies Co., Ltd
+ *
+ * Authors:
+ *  Yanan Wang <wangyanan55@huawei.com>
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
+ * See the COPYING.LIB file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+#include "qom/object.h"
+#include "qemu/module.h"
+#include "qapi/error.h"
+
+#include "hw/boards.h"
+
+#define T true
+#define F false
+
+#define MIN_CPUS 1   /* set the min CPUs supported by the machine as 1 */
+#define MAX_CPUS 512 /* set the max CPUs supported by the machine as 512 */
+
+/*
+ * Used to define the generic 3-level CPU topology hierarchy
+ *  -sockets/cores/threads
+ */
+#define SMP_CONFIG_GENERIC(ha, a, hb, b, hc, c, hd, d, he, e) \
+        {                                                     \
+            .has_cpus    = ha, .cpus    = a,                  \
+            .has_sockets = hb, .sockets = b,                  \
+            .has_cores   = hc, .cores   = c,                  \
+            .has_threads = hd, .threads = d,                  \
+            .has_maxcpus = he, .maxcpus = e,                  \
+        }
+
+#define CPU_TOPOLOGY_GENERIC(a, b, c, d, e)                   \
+        {                                                     \
+            .cpus     = a,                                    \
+            .sockets  = b,                                    \
+            .cores    = c,                                    \
+            .threads  = d,                                    \
+            .max_cpus = e,                                    \
+        }
+
+/*
+ * Currently a 4-level topology hierarchy is supported on PC machines
+ *  -sockets/dies/cores/threads
+ */
+#define SMP_CONFIG_WITH_DIES(ha, a, hb, b, hc, c, hd, d, he, e, hf, f) \
+        {                                                     \
+            .has_cpus    = ha, .cpus    = a,                  \
+            .has_sockets = hb, .sockets = b,                  \
+            .has_dies    = hc, .dies    = c,                  \
+            .has_cores   = hd, .cores   = d,                  \
+            .has_threads = he, .threads = e,                  \
+            .has_maxcpus = hf, .maxcpus = f,                  \
+        }
+
+/**
+ * @config - the given SMP configuration
+ * @expect_prefer_sockets - the expected parsing result for the
+ * valid configuration, when sockets are preferred over cores
+ * @expect_prefer_cores - the expected parsing result for the
+ * valid configuration, when cores are preferred over sockets
+ * @expect_error - the expected error report when the given
+ * configuration is invalid
+ */
+typedef struct SMPTestData {
+    SMPConfiguration config;
+    CpuTopology expect_prefer_sockets;
+    CpuTopology expect_prefer_cores;
+    const char *expect_error;
+} SMPTestData;
+
+/* Type info of the tested machine */
+static const TypeInfo smp_machine_info = {
+    .name = TYPE_MACHINE,
+    .parent = TYPE_OBJECT,
+    .class_size = sizeof(MachineClass),
+    .instance_size = sizeof(MachineState),
+};
+
+/*
+ * List all the possible valid sub-collections of the generic 5
+ * topology parameters (i.e. cpus/maxcpus/sockets/cores/threads),
+ * then test the automatic calculation algorithm of the missing
+ * values in the parser.
+ */
+static struct SMPTestData data_generic_valid[] = {
+    {
+        /* config: no configuration provided
+         * expect: cpus=1,sockets=1,cores=1,threads=1,maxcpus=1 */
+        .config = SMP_CONFIG_GENERIC(F, 0, F, 0, F, 0, F, 0, F, 0),
+        .expect_prefer_sockets = CPU_TOPOLOGY_GENERIC(1, 1, 1, 1, 1),
+        .expect_prefer_cores   = CPU_TOPOLOGY_GENERIC(1, 1, 1, 1, 1),
+    }, {
+        /* config: -smp 8
+         * prefer_sockets: cpus=8,sockets=8,cores=1,threads=1,maxcpus=8
+         * prefer_cores: cpus=8,sockets=1,cores=8,threads=1,maxcpus=8 */
+        .config = SMP_CONFIG_GENERIC(T, 8, F, 0, F, 0, F, 0, F, 0),
+        .expect_prefer_sockets = CPU_TOPOLOGY_GENERIC(8, 8, 1, 1, 8),
+        .expect_prefer_cores   = CPU_TOPOLOGY_GENERIC(8, 1, 8, 1, 8),
+    }, {
+        /* config: -smp sockets=2
+         * expect: cpus=2,sockets=2,cores=1,threads=1,maxcpus=2 */
+        .config = SMP_CONFIG_GENERIC(F, 0, T, 2, F, 0, F, 0, F, 0),
+        .expect_prefer_sockets = CPU_TOPOLOGY_GENERIC(2, 2, 1, 1, 2),
+        .expect_prefer_cores   = CPU_TOPOLOGY_GENERIC(2, 2, 1, 1, 2),
+    }, {
+        /* config: -smp cores=4
+         * expect: cpus=4,sockets=1,cores=4,threads=1,maxcpus=4 */
+        .config = SMP_CONFIG_GENERIC(F, 0, F, 0, T, 4, F, 0, F, 0),
+        .expect_prefer_sockets = CPU_TOPOLOGY_GENERIC(4, 1, 4, 1, 4),
+        .expect_prefer_cores   = CPU_TOPOLOGY_GENERIC(4, 1, 4, 1, 4),
+    }, {
+        /* config: -smp threads=2
+         * expect: cpus=2,sockets=1,cores=1,threads=2,maxcpus=2 */
+        .config = SMP_CONFIG_GENERIC(F, 0, F, 0, F, 0, T, 2, F, 0),
+        .expect_prefer_sockets = CPU_TOPOLOGY_GENERIC(2, 1, 1, 2, 2),
+        .expect_prefer_cores   = CPU_TOPOLOGY_GENERIC(2, 1, 1, 2, 2),
+    }, {
+        /* config: -smp maxcpus=16
+         * prefer_sockets: cpus=16,sockets=16,cores=1,threads=1,maxcpus=16
+         * prefer_cores: cpus=16,sockets=1,cores=16,threads=1,maxcpus=16 */
+        .config = SMP_CONFIG_GENERIC(F, 0, F, 0, F, 0, F, 0, T, 16),
+        .expect_prefer_sockets = CPU_TOPOLOGY_GENERIC(16, 16, 1, 1, 16),
+        .expect_prefer_cores   = CPU_TOPOLOGY_GENERIC(16, 1, 16, 1, 16),
+    }, {
+        /* config: -smp 8,sockets=2
+         * expect: cpus=8,sockets=2,cores=4,threads=1,maxcpus=8 */
+        .config = SMP_CONFIG_GENERIC(T, 8, T, 2, F, 0, F, 0, F, 0),
+        .expect_prefer_sockets = CPU_TOPOLOGY_GENERIC(8, 2, 4, 1, 8),
+        .expect_prefer_cores   = CPU_TOPOLOGY_GENERIC(8, 2, 4, 1, 8),
+    }, {
+        /* config: -smp 8,cores=4
+         * expect: cpus=8,sockets=2,cores=4,threads=1,maxcpus=8 */
+        .config = SMP_CONFIG_GENERIC(T, 8, F, 0, T, 4, F, 0, F, 0),
+        .expect_prefer_sockets = CPU_TOPOLOGY_GENERIC(8, 2, 4, 1, 8),
+        .expect_prefer_cores   = CPU_TOPOLOGY_GENERIC(8, 2, 4, 1, 8),
+    }, {
+        /* config: -smp 8,threads=2
+         * prefer_sockets: cpus=8,sockets=4,cores=1,threads=2,maxcpus=8
+         * prefer_cores: cpus=8,sockets=1,cores=4,threads=2,maxcpus=8 */
+        .config = SMP_CONFIG_GENERIC(T, 8, F, 0, F, 0, T, 2, F, 0),
+        .expect_prefer_sockets = CPU_TOPOLOGY_GENERIC(8, 4, 1, 2, 8),
+        .expect_prefer_cores   = CPU_TOPOLOGY_GENERIC(8, 1, 4, 2, 8),
+    }, {
+        /* config: -smp 8,maxcpus=16
+         * prefer_sockets: cpus=8,sockets=16,cores=1,threads=1,maxcpus=16
+         * prefer_cores: cpus=8,sockets=1,cores=16,threads=1,maxcpus=16 */
+        .config = SMP_CONFIG_GENERIC(T, 8, F, 0, F, 0, F, 0, T, 16),
+        .expect_prefer_sockets = CPU_TOPOLOGY_GENERIC(8, 16, 1, 1, 16),
+        .expect_prefer_cores   = CPU_TOPOLOGY_GENERIC(8, 1, 16, 1, 16),
+    }, {
+        /* config: -smp sockets=2,cores=4
+         * expect: cpus=8,sockets=2,cores=4,threads=1,maxcpus=8 */
+        .config = SMP_CONFIG_GENERIC(F, 0, T, 2, T, 4, F, 0, F, 0),
+        .expect_prefer_sockets = CPU_TOPOLOGY_GENERIC(8, 2, 4, 1, 8),
+        .expect_prefer_cores   = CPU_TOPOLOGY_GENERIC(8, 2, 4, 1, 8),
+    }, {
+        /* config: -smp sockets=2,threads=2
+         * expect: cpus=4,sockets=2,cores=1,threads=2,maxcpus=4 */
+        .config = SMP_CONFIG_GENERIC(F, 0, T, 2, F, 0, T, 2, F, 0),
+        .expect_prefer_sockets = CPU_TOPOLOGY_GENERIC(4, 2, 1, 2, 4),
+        .expect_prefer_cores   = CPU_TOPOLOGY_GENERIC(4, 2, 1, 2, 4),
+    }, {
+        /* config: -smp sockets=2,maxcpus=16
+         * expect: cpus=16,sockets=2,cores=8,threads=1,maxcpus=16 */
+        .config = SMP_CONFIG_GENERIC(F, 0, T, 2, F, 0, F, 0, T, 16),
+        .expect_prefer_sockets = CPU_TOPOLOGY_GENERIC(16, 2, 8, 1, 16),
+        .expect_prefer_cores   = CPU_TOPOLOGY_GENERIC(16, 2, 8, 1, 16),
+    }, {
+        /* config: -smp cores=4,threads=2
+         * expect: cpus=8,sockets=1,cores=4,threads=2,maxcpus=8 */
+        .config = SMP_CONFIG_GENERIC(F, 0, F, 0, T, 4, T, 2, F, 0),
+        .expect_prefer_sockets = CPU_TOPOLOGY_GENERIC(8, 1, 4, 2, 8),
+        .expect_prefer_cores   = CPU_TOPOLOGY_GENERIC(8, 1, 4, 2, 8),
+    }, {
+        /* config: -smp cores=4,maxcpus=16
+         * expect: cpus=16,sockets=4,cores=4,threads=1,maxcpus=16 */
+        .config = SMP_CONFIG_GENERIC(F, 0, F, 0, T, 4, F, 0, T, 16),
+        .expect_prefer_sockets = CPU_TOPOLOGY_GENERIC(16, 4, 4, 1, 16),
+        .expect_prefer_cores   = CPU_TOPOLOGY_GENERIC(16, 4, 4, 1, 16),
+    }, {
+        /* config: -smp threads=2,maxcpus=16
+         * prefer_sockets: cpus=16,sockets=8,cores=1,threads=2,maxcpus=16
+         * prefer_cores: cpus=16,sockets=1,cores=8,threads=2,maxcpus=16 */
+        .config = SMP_CONFIG_GENERIC(F, 0, F, 0, F, 0, T, 2, T, 16),
+        .expect_prefer_sockets = CPU_TOPOLOGY_GENERIC(16, 8, 1, 2, 16),
+        .expect_prefer_cores   = CPU_TOPOLOGY_GENERIC(16, 1, 8, 2, 16),
+    }, {
+        /* config: -smp 8,sockets=2,cores=4
+         * expect: cpus=8,sockets=2,cores=4,threads=1,maxcpus=8 */
+        .config = SMP_CONFIG_GENERIC(T, 8, T, 2, T, 4, F, 0, F, 0),
+        .expect_prefer_sockets = CPU_TOPOLOGY_GENERIC(8, 2, 4, 1, 8),
+        .expect_prefer_cores   = CPU_TOPOLOGY_GENERIC(8, 2, 4, 1, 8),
+    }, {
+        /* config: -smp 8,sockets=2,threads=2
+         * expect: cpus=8,sockets=2,cores=2,threads=2,maxcpus=8 */
+        .config = SMP_CONFIG_GENERIC(T, 8, T, 2, F, 0, T, 2, F, 0),
+        .expect_prefer_sockets = CPU_TOPOLOGY_GENERIC(8, 2, 2, 2, 8),
+        .expect_prefer_cores   = CPU_TOPOLOGY_GENERIC(8, 2, 2, 2, 8),
+    }, {
+        /* config: -smp 8,sockets=2,maxcpus=16
+         * expect: cpus=8,sockets=2,cores=8,threads=1,maxcpus=16 */
+        .config = SMP_CONFIG_GENERIC(T, 8, T, 2, F, 0, F, 0, T, 16),
+        .expect_prefer_sockets = CPU_TOPOLOGY_GENERIC(8, 2, 8, 1, 16),
+        .expect_prefer_cores   = CPU_TOPOLOGY_GENERIC(8, 2, 8, 1, 16),
+    }, {
+        /* config: -smp 8,cores=4,threads=2
+         * expect: cpus=8,sockets=1,cores=4,threads=2,maxcpus=8 */
+        .config = SMP_CONFIG_GENERIC(T, 8, F, 0, T, 4, T, 2, F, 0),
+        .expect_prefer_sockets = CPU_TOPOLOGY_GENERIC(8, 1, 4, 2, 8),
+        .expect_prefer_cores   = CPU_TOPOLOGY_GENERIC(8, 1, 4, 2, 8),
+    }, {
+        /* config: -smp 8,cores=4,maxcpus=16
+         * expect: cpus=8,sockets=4,cores=4,threads=1,maxcpus=16 */
+        .config = SMP_CONFIG_GENERIC(T, 8, F, 0, T, 4, F, 0, T, 16),
+        .expect_prefer_sockets = CPU_TOPOLOGY_GENERIC(8, 4, 4, 1, 16),
+        .expect_prefer_cores   = CPU_TOPOLOGY_GENERIC(8, 4, 4, 1, 16),
+    }, {
+        /* config: -smp 8,threads=2,maxcpus=16
+         * prefer_sockets: cpus=8,sockets=8,cores=1,threads=2,maxcpus=16
+         * prefer_cores: cpus=8,sockets=1,cores=8,threads=2,maxcpus=16 */
+        .config = SMP_CONFIG_GENERIC(T, 8, F, 0, F, 0, T, 2, T, 16),
+        .expect_prefer_sockets = CPU_TOPOLOGY_GENERIC(8, 8, 1, 2, 16),
+        .expect_prefer_cores   = CPU_TOPOLOGY_GENERIC(8, 1, 8, 2, 16),
+    }, {
+        /* config: -smp sockets=2,cores=4,threads=2
+         * expect: cpus=16,sockets=2,cores=4,threads=2,maxcpus=16 */
+        .config = SMP_CONFIG_GENERIC(F, 0, T, 2, T, 4, T, 2, F, 0),
+        .expect_prefer_sockets = CPU_TOPOLOGY_GENERIC(16, 2, 4, 2, 16),
+        .expect_prefer_cores   = CPU_TOPOLOGY_GENERIC(16, 2, 4, 2, 16),
+    }, {
+        /* config: -smp sockets=2,cores=4,maxcpus=16
+         * expect: cpus=16,sockets=2,cores=4,threads=2,maxcpus=16 */
+        .config = SMP_CONFIG_GENERIC(F, 0, T, 2, T, 4, F, 0, T, 16),
+        .expect_prefer_sockets = CPU_TOPOLOGY_GENERIC(16, 2, 4, 2, 16),
+        .expect_prefer_cores   = CPU_TOPOLOGY_GENERIC(16, 2, 4, 2, 16),
+    }, {
+        /* config: -smp sockets=2,threads=2,maxcpus=16
+         * expect: cpus=16,sockets=2,cores=4,threads=2,maxcpus=16 */
+        .config = SMP_CONFIG_GENERIC(F, 0, T, 2, F, 0, T, 2, T, 16),
+        .expect_prefer_sockets = CPU_TOPOLOGY_GENERIC(16, 2, 4, 2, 16),
+        .expect_prefer_cores   = CPU_TOPOLOGY_GENERIC(16, 2, 4, 2, 16),
+    }, {
+        /* config: -smp cores=4,threads=2,maxcpus=16
+         * expect: cpus=16,sockets=2,cores=4,threads=2,maxcpus=16 */
+        .config = SMP_CONFIG_GENERIC(F, 0, F, 0, T, 4, T, 2, T, 16),
+        .expect_prefer_sockets = CPU_TOPOLOGY_GENERIC(16, 2, 4, 2, 16),
+        .expect_prefer_cores   = CPU_TOPOLOGY_GENERIC(16, 2, 4, 2, 16),
+    }, {
+        /* config: -smp 8,sockets=2,cores=4,threads=1
+         * expect: cpus=8,sockets=2,cores=4,threads=1,maxcpus=8 */
+        .config = SMP_CONFIG_GENERIC(T, 8, T, 2, T, 4, T, 1, F, 0),
+        .expect_prefer_sockets = CPU_TOPOLOGY_GENERIC(8, 2, 4, 1, 8),
+        .expect_prefer_cores   = CPU_TOPOLOGY_GENERIC(8, 2, 4, 1, 8),
+    }, {
+        /* config: -smp 8,sockets=2,cores=4,maxcpus=16
+         * expect: cpus=8,sockets=2,cores=4,threads=2,maxcpus=16 */
+        .config = SMP_CONFIG_GENERIC(T, 8, T, 2, T, 4, F, 0, T, 16),
+        .expect_prefer_sockets = CPU_TOPOLOGY_GENERIC(8, 2, 4, 2, 16),
+        .expect_prefer_cores   = CPU_TOPOLOGY_GENERIC(8, 2, 4, 2, 16),
+    }, {
+        /* config: -smp 8,sockets=2,threads=2,maxcpus=16
+         * expect: cpus=8,sockets=2,cores=4,threads=2,maxcpus=16 */
+        .config = SMP_CONFIG_GENERIC(T, 8, T, 2, F, 0, T, 2, T, 16),
+        .expect_prefer_sockets = CPU_TOPOLOGY_GENERIC(8, 2, 4, 2, 16),
+        .expect_prefer_cores   = CPU_TOPOLOGY_GENERIC(8, 2, 4, 2, 16),
+    }, {
+        /* config: -smp 8,cores=4,threads=2,maxcpus=16
+         * expect: cpus=8,sockets=2,cores=4,threads=2,maxcpus=16 */
+        .config = SMP_CONFIG_GENERIC(T, 8, F, 0, T, 4, T, 2, T, 16),
+        .expect_prefer_sockets = CPU_TOPOLOGY_GENERIC(8, 2, 4, 2, 16),
+        .expect_prefer_cores   = CPU_TOPOLOGY_GENERIC(8, 2, 4, 2, 16),
+    }, {
+        /* config: -smp sockets=2,cores=4,threads=2,maxcpus=16
+         * expect: cpus=16,sockets=2,cores=4,threads=2,maxcpus=16 */
+        .config = SMP_CONFIG_GENERIC(F, 0, T, 2, T, 4, T, 2, T, 16),
+        .expect_prefer_sockets = CPU_TOPOLOGY_GENERIC(16, 2, 4, 2, 16),
+        .expect_prefer_cores   = CPU_TOPOLOGY_GENERIC(16, 2, 4, 2, 16),
+    }, {
+        /* config: -smp 8,sockets=2,cores=4,threads=2,maxcpus=16
+         * expect: cpus=8,sockets=2,cores=4,threads=2,maxcpus=16 */
+        .config = SMP_CONFIG_GENERIC(T, 8, T, 2, T, 4, T, 2, T, 16),
+        .expect_prefer_sockets = CPU_TOPOLOGY_GENERIC(8, 2, 4, 2, 16),
+        .expect_prefer_cores   = CPU_TOPOLOGY_GENERIC(8, 2, 4, 2, 16),
+    },
+};
+
+static struct SMPTestData data_generic_invalid[] = {
+    {
+        /* config: -smp 2,dies=2 */
+        .config = SMP_CONFIG_WITH_DIES(T, 2, F, 0, T, 2, F, 0, F, 0, F, 0),
+        .expect_error = "dies not supported by this machine's CPU topology",
+    }, {
+        /* config: -smp 8,sockets=2,cores=4,threads=2,maxcpus=8 */
+        .config = SMP_CONFIG_GENERIC(T, 8, T, 2, T, 4, T, 2, T, 8),
+        .expect_error = "Invalid CPU topology: "
+                        "product of the hierarchy must match maxcpus: "
+                        "sockets (2) * cores (4) * threads (2) "
+                        "!= maxcpus (8)",
+    }, {
+        /* config: -smp 18,sockets=2,cores=4,threads=2,maxcpus=16 */
+        .config = SMP_CONFIG_GENERIC(T, 18, T, 2, T, 4, T, 2, T, 16),
+        .expect_error = "Invalid CPU topology: "
+                        "maxcpus must be equal to or greater than smp: "
+                        "sockets (2) * cores (4) * threads (2) "
+                        "== maxcpus (16) < smp_cpus (18)",
+    }, {
+        /* config: -smp 1
+         * should tweak the supported min CPUs to 2 for testing */
+        .config = SMP_CONFIG_GENERIC(T, 1, F, 0, F, 0, F, 0, F, 0),
+        .expect_error = "Invalid SMP CPUs 1. The min CPUs supported "
+                        "by machine '(null)' is 2",
+    }, {
+        /* config: -smp 512
+         * should tweak the supported max CPUs to 511 for testing */
+        .config = SMP_CONFIG_GENERIC(T, 512, F, 0, F, 0, F, 0, F, 0),
+        .expect_error = "Invalid SMP CPUs 512. The max CPUs supported "
+                        "by machine '(null)' is 511",
+    },
+};
+
+static struct SMPTestData data_with_dies_invalid[] = {
+    {
+        /* config: -smp 16,sockets=2,dies=2,cores=4,threads=2,maxcpus=16 */
+        .config = SMP_CONFIG_WITH_DIES(T, 16, T, 2, T, 2, T, 4, T, 2, T, 16),
+        .expect_error = "Invalid CPU topology: "
+                        "product of the hierarchy must match maxcpus: "
+                        "sockets (2) * dies (2) * cores (4) * threads (2) "
+                        "!= maxcpus (16)",
+    }, {
+        /* config: -smp 34,sockets=2,dies=2,cores=4,threads=2,maxcpus=32 */
+        .config = SMP_CONFIG_WITH_DIES(T, 34, T, 2, T, 2, T, 4, T, 2, T, 32),
+        .expect_error = "Invalid CPU topology: "
+                        "maxcpus must be equal to or greater than smp: "
+                        "sockets (2) * dies (2) * cores (4) * threads (2) "
+                        "== maxcpus (32) < smp_cpus (34)",
+    },
+};
+
+static char *smp_config_to_string(SMPConfiguration *config)
+{
+    return g_strdup_printf(
+        "(SMPConfiguration) {\n"
+        "    .has_cpus    = %5s, cpus    = %" PRId64 ",\n"
+        "    .has_sockets = %5s, sockets = %" PRId64 ",\n"
+        "    .has_dies    = %5s, dies    = %" PRId64 ",\n"
+        "    .has_cores   = %5s, cores   = %" PRId64 ",\n"
+        "    .has_threads = %5s, threads = %" PRId64 ",\n"
+        "    .has_maxcpus = %5s, maxcpus = %" PRId64 ",\n"
+        "}",
+        config->has_cpus ? "true" : "false", config->cpus,
+        config->has_sockets ? "true" : "false", config->sockets,
+        config->has_dies ? "true" : "false", config->dies,
+        config->has_cores ? "true" : "false", config->cores,
+        config->has_threads ? "true" : "false", config->threads,
+        config->has_maxcpus ? "true" : "false", config->maxcpus);
+}
+
+static char *cpu_topology_to_string(CpuTopology *topo)
+{
+    return g_strdup_printf(
+        "(CpuTopology) {\n"
+        "    .cpus     = %u,\n"
+        "    .sockets  = %u,\n"
+        "    .dies     = %u,\n"
+        "    .cores    = %u,\n"
+        "    .threads  = %u,\n"
+        "    .max_cpus = %u,\n"
+        "}",
+        topo->cpus, topo->sockets, topo->dies,
+        topo->cores, topo->threads, topo->max_cpus);
+}
+
+static void check_parse(MachineState *ms, SMPConfiguration *config,
+                        CpuTopology *expect_topo, const char *expect_err,
+                        bool is_valid)
+{
+    g_autofree char *config_str = smp_config_to_string(config);
+    g_autofree char *expect_topo_str = cpu_topology_to_string(expect_topo);
+    g_autofree char *output_topo_str = NULL;
+    Error *err = NULL;
+
+    /* call the generic parser smp_parse() */
+    smp_parse(ms, config, &err);
+
+    output_topo_str = cpu_topology_to_string(&ms->smp);
+
+    /* when the configuration is supposed to be valid */
+    if (is_valid) {
+        if ((err == NULL) &&
+            (ms->smp.cpus == expect_topo->cpus) &&
+            (ms->smp.sockets == expect_topo->sockets) &&
+            (ms->smp.dies == expect_topo->dies) &&
+            (ms->smp.cores == expect_topo->cores) &&
+            (ms->smp.threads == expect_topo->threads) &&
+            (ms->smp.max_cpus == expect_topo->max_cpus)) {
+            return;
+        }
+
+        if (err != NULL) {
+            g_printerr("Test smp_parse failed!\n"
+                       "Input configuration: %s\n"
+                       "Should be valid: yes\n"
+                       "Expected topology: %s\n\n"
+                       "Result is valid: no\n"
+                       "Output error report: %s\n",
+                       config_str, expect_topo_str, error_get_pretty(err));
+            goto end;
+        }
+
+        g_printerr("Test smp_parse failed!\n"
+                   "Input configuration: %s\n"
+                   "Should be valid: yes\n"
+                   "Expected topology: %s\n\n"
+                   "Result is valid: yes\n"
+                   "Output topology: %s\n",
+                   config_str, expect_topo_str, output_topo_str);
+        goto end;
+    }
+
+    /* when the configuration is supposed to be invalid */
+    if (err != NULL) {
+        if (expect_err == NULL ||
+            g_str_equal(expect_err, error_get_pretty(err))) {
+            error_free(err);
+            return;
+        }
+
+        g_printerr("Test smp_parse failed!\n"
+                   "Input configuration: %s\n"
+                   "Should be valid: no\n"
+                   "Expected error report: %s\n\n"
+                   "Result is valid: no\n"
+                   "Output error report: %s\n",
+                   config_str, expect_err, error_get_pretty(err));
+        goto end;
+    }
+
+    g_printerr("Test smp_parse failed!\n"
+               "Input configuration: %s\n"
+               "Should be valid: no\n"
+               "Expected error report: %s\n\n"
+               "Result is valid: yes\n"
+               "Output topology: %s\n",
+               config_str, expect_err, output_topo_str);
+
+end:
+    if (err != NULL) {
+        error_free(err);
+    }
+
+    abort();
+}
+
+static void smp_parse_test(MachineState *ms, SMPTestData *data, bool is_valid)
+{
+    MachineClass *mc = MACHINE_GET_CLASS(ms);
+
+    mc->smp_props.prefer_sockets = true;
+    check_parse(ms, &data->config, &data->expect_prefer_sockets,
+                data->expect_error, is_valid);
+
+    mc->smp_props.prefer_sockets = false;
+    check_parse(ms, &data->config, &data->expect_prefer_cores,
+                data->expect_error, is_valid);
+}
+
+/* The parsed results of the unsupported parameters should be 1 */
+static void unsupported_params_init(MachineClass *mc, SMPTestData *data)
+{
+    if (!mc->smp_props.dies_supported) {
+        data->expect_prefer_sockets.dies = 1;
+        data->expect_prefer_cores.dies = 1;
+    }
+}
+
+/* Reset the related machine properties before each sub-test */
+static void smp_machine_class_init(MachineClass *mc)
+{
+    mc->min_cpus = MIN_CPUS;
+    mc->max_cpus = MAX_CPUS;
+
+    mc->smp_props.prefer_sockets = true;
+    mc->smp_props.dies_supported = false;
+}
+
+static void test_generic(void)
+{
+    Object *obj = object_new(TYPE_MACHINE);
+    MachineState *ms = MACHINE(obj);
+    MachineClass *mc = MACHINE_GET_CLASS(obj);
+    SMPTestData *data = &(SMPTestData){{ }};
+    int i;
+
+    smp_machine_class_init(mc);
+
+    for (i = 0; i < ARRAY_SIZE(data_generic_valid); i++) {
+        *data = data_generic_valid[i];
+        unsupported_params_init(mc, data);
+
+        smp_parse_test(ms, data, true);
+
+        /* Unsupported parameters can be provided with their values as 1 */
+        data->config.has_dies = true;
+        data->config.dies = 1;
+        smp_parse_test(ms, data, true);
+    }
+
+    /* Reset the supported min CPUs and max CPUs */
+    mc->min_cpus = 2;
+    mc->max_cpus = 511;
+
+    for (i = 0; i < ARRAY_SIZE(data_generic_invalid); i++) {
+        *data = data_generic_invalid[i];
+        unsupported_params_init(mc, data);
+
+        smp_parse_test(ms, data, false);
+    }
+
+    object_unref(obj);
+}
+
+static void test_with_dies(void)
+{
+    Object *obj = object_new(TYPE_MACHINE);
+    MachineState *ms = MACHINE(obj);
+    MachineClass *mc = MACHINE_GET_CLASS(obj);
+    SMPTestData *data = &(SMPTestData){{ }};
+    unsigned int num_dies = 2;
+    int i;
+
+    smp_machine_class_init(mc);
+    mc->smp_props.dies_supported = true;
+
+    for (i = 0; i < ARRAY_SIZE(data_generic_valid); i++) {
+        *data = data_generic_valid[i];
+        unsupported_params_init(mc, data);
+
+        /* when dies parameter is omitted, it will be set as 1 */
+        data->expect_prefer_sockets.dies = 1;
+        data->expect_prefer_cores.dies = 1;
+
+        smp_parse_test(ms, data, true);
+
+        /* when dies parameter is specified */
+        data->config.has_dies = true;
+        data->config.dies = num_dies;
+        if (data->config.has_cpus) {
+            data->config.cpus *= num_dies;
+        }
+        if (data->config.has_maxcpus) {
+            data->config.maxcpus *= num_dies;
+        }
+
+        data->expect_prefer_sockets.dies = num_dies;
+        data->expect_prefer_sockets.cpus *= num_dies;
+        data->expect_prefer_sockets.max_cpus *= num_dies;
+        data->expect_prefer_cores.dies = num_dies;
+        data->expect_prefer_cores.cpus *= num_dies;
+        data->expect_prefer_cores.max_cpus *= num_dies;
+
+        smp_parse_test(ms, data, true);
+    }
+
+    for (i = 0; i < ARRAY_SIZE(data_with_dies_invalid); i++) {
+        *data = data_with_dies_invalid[i];
+        unsupported_params_init(mc, data);
+
+        smp_parse_test(ms, data, false);
+    }
+
+    object_unref(obj);
+}
+
+int main(int argc, char *argv[])
+{
+    g_test_init(&argc, &argv, NULL);
+
+    module_call_init(MODULE_INIT_QOM);
+    type_register_static(&smp_machine_info);
+
+    g_test_add_func("/test-smp-parse/generic", test_generic);
+    g_test_add_func("/test-smp-parse/with_dies", test_with_dies);
+
+    g_test_run();
+
+    return 0;
+}