summary refs log tree commit diff stats
path: root/hw
diff options
context:
space:
mode:
Diffstat (limited to 'hw')
-rw-r--r--hw/intc/grlib_irqmp.c17
-rw-r--r--hw/pci-bridge/Makefile.objs2
-rw-r--r--hw/pci-bridge/simba.c101
-rw-r--r--hw/pci-host/Makefile.objs2
-rw-r--r--hw/pci-host/sabre.c (renamed from hw/pci-host/apb.c)270
-rw-r--r--hw/pci-host/trace-events11
-rw-r--r--hw/sparc64/sparc64.c85
-rw-r--r--hw/sparc64/sun4u.c109
-rw-r--r--hw/sparc64/trace-events18
9 files changed, 363 insertions, 252 deletions
diff --git a/hw/intc/grlib_irqmp.c b/hw/intc/grlib_irqmp.c
index 94659ee256..d6f9cb3692 100644
--- a/hw/intc/grlib_irqmp.c
+++ b/hw/intc/grlib_irqmp.c
@@ -106,6 +106,15 @@ static void grlib_irqmp_check_irqs(IRQMPState *state)
     }
 }
 
+static void grlib_irqmp_ack_mask(IRQMPState *state, uint32_t mask)
+{
+    /* Clear registers */
+    state->pending  &= ~mask;
+    state->force[0] &= ~mask; /* Only CPU 0 (No SMP support) */
+
+    grlib_irqmp_check_irqs(state);
+}
+
 void grlib_irqmp_ack(DeviceState *dev, int intno)
 {
     IRQMP        *irqmp = GRLIB_IRQMP(dev);
@@ -120,11 +129,7 @@ void grlib_irqmp_ack(DeviceState *dev, int intno)
 
     trace_grlib_irqmp_ack(intno);
 
-    /* Clear registers */
-    state->pending  &= ~mask;
-    state->force[0] &= ~mask; /* Only CPU 0 (No SMP support) */
-
-    grlib_irqmp_check_irqs(state);
+    grlib_irqmp_ack_mask(state, mask);
 }
 
 void grlib_irqmp_set_irq(void *opaque, int irq, int level)
@@ -251,7 +256,7 @@ static void grlib_irqmp_write(void *opaque, hwaddr addr,
 
     case CLEAR_OFFSET:
         value &= ~1; /* clean up the value */
-        state->pending &= ~value;
+        grlib_irqmp_ack_mask(state, value);
         return;
 
     case MP_STATUS_OFFSET:
diff --git a/hw/pci-bridge/Makefile.objs b/hw/pci-bridge/Makefile.objs
index 1b05023662..47065f87d9 100644
--- a/hw/pci-bridge/Makefile.objs
+++ b/hw/pci-bridge/Makefile.objs
@@ -6,3 +6,5 @@ common-obj-$(CONFIG_IOH3420) += ioh3420.o
 common-obj-$(CONFIG_I82801B11) += i82801b11.o
 # NewWorld PowerMac
 common-obj-$(CONFIG_DEC_PCI) += dec.o
+# Sun4u
+common-obj-$(CONFIG_SIMBA) += simba.o
diff --git a/hw/pci-bridge/simba.c b/hw/pci-bridge/simba.c
new file mode 100644
index 0000000000..dea4c8c5e7
--- /dev/null
+++ b/hw/pci-bridge/simba.c
@@ -0,0 +1,101 @@
+/*
+ * QEMU Simba PCI bridge
+ *
+ * Copyright (c) 2006 Fabrice Bellard
+ * Copyright (c) 2012,2013 Artyom Tarasenko
+ * Copyright (c) 2018 Mark Cave-Ayland
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "qemu/osdep.h"
+#include "hw/pci/pci.h"
+#include "hw/pci/pci_bridge.h"
+#include "hw/pci/pci_bus.h"
+#include "hw/pci-bridge/simba.h"
+
+/*
+ * Chipset docs:
+ * APB: "Advanced PCI Bridge (APB) User's Manual",
+ * http://www.sun.com/processors/manuals/805-1251.pdf
+ */
+
+static void simba_pci_bridge_realize(PCIDevice *dev, Error **errp)
+{
+    /*
+     * command register:
+     * According to PCI bridge spec, after reset
+     *   bus master bit is off
+     *   memory space enable bit is off
+     * According to manual (805-1251.pdf).
+     *   the reset value should be zero unless the boot pin is tied high
+     *   (which is true) and thus it should be PCI_COMMAND_MEMORY.
+     */
+    SimbaPCIBridge *br = SIMBA_PCI_BRIDGE(dev);
+
+    pci_bridge_initfn(dev, TYPE_PCI_BUS);
+
+    pci_set_word(dev->config + PCI_COMMAND, PCI_COMMAND_MEMORY);
+    pci_set_word(dev->config + PCI_STATUS,
+                 PCI_STATUS_FAST_BACK | PCI_STATUS_66MHZ |
+                 PCI_STATUS_DEVSEL_MEDIUM);
+
+    /* Allow 32-bit IO addresses */
+    pci_set_word(dev->config + PCI_IO_BASE, PCI_IO_RANGE_TYPE_32);
+    pci_set_word(dev->config + PCI_IO_LIMIT, PCI_IO_RANGE_TYPE_32);
+    pci_set_word(dev->wmask + PCI_IO_BASE_UPPER16, 0xffff);
+    pci_set_word(dev->wmask + PCI_IO_LIMIT_UPPER16, 0xffff);
+
+    pci_bridge_update_mappings(PCI_BRIDGE(br));
+}
+
+static void simba_pci_bridge_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+    k->realize = simba_pci_bridge_realize;
+    k->exit = pci_bridge_exitfn;
+    k->vendor_id = PCI_VENDOR_ID_SUN;
+    k->device_id = PCI_DEVICE_ID_SUN_SIMBA;
+    k->revision = 0x11;
+    k->config_write = pci_bridge_write_config;
+    k->is_bridge = 1;
+    set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
+    dc->reset = pci_bridge_reset;
+    dc->vmsd = &vmstate_pci_device;
+}
+
+static const TypeInfo simba_pci_bridge_info = {
+    .name          = TYPE_SIMBA_PCI_BRIDGE,
+    .parent        = TYPE_PCI_BRIDGE,
+    .class_init    = simba_pci_bridge_class_init,
+    .instance_size = sizeof(SimbaPCIBridge),
+    .interfaces = (InterfaceInfo[]) {
+        { INTERFACE_CONVENTIONAL_PCI_DEVICE },
+        { },
+    },
+};
+
+static void simba_register_types(void)
+{
+    type_register_static(&simba_pci_bridge_info);
+}
+
+type_init(simba_register_types)
diff --git a/hw/pci-host/Makefile.objs b/hw/pci-host/Makefile.objs
index 9c7909cf44..4b69f737b5 100644
--- a/hw/pci-host/Makefile.objs
+++ b/hw/pci-host/Makefile.objs
@@ -11,7 +11,7 @@ common-obj-$(CONFIG_PPCE500_PCI) += ppce500.o
 # ARM devices
 common-obj-$(CONFIG_VERSATILE_PCI) += versatile.o
 
-common-obj-$(CONFIG_PCI_APB) += apb.o
+common-obj-$(CONFIG_PCI_SABRE) += sabre.o
 common-obj-$(CONFIG_FULONG) += bonito.o
 common-obj-$(CONFIG_PCI_PIIX) += piix.o
 common-obj-$(CONFIG_PCI_Q35) += q35.o
diff --git a/hw/pci-host/apb.c b/hw/pci-host/sabre.c
index ec676f94b6..2268a41dd9 100644
--- a/hw/pci-host/apb.c
+++ b/hw/pci-host/sabre.c
@@ -1,8 +1,9 @@
 /*
- * QEMU Ultrasparc APB PCI host
+ * QEMU Ultrasparc Sabre PCI host (PBM)
  *
  * Copyright (c) 2006 Fabrice Bellard
  * Copyright (c) 2012,2013 Artyom Tarasenko
+ * Copyright (c) 2018 Mark Cave-Ayland
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to deal
@@ -23,39 +24,24 @@
  * THE SOFTWARE.
  */
 
-/* XXX This file and most of its contents are somewhat misnamed.  The
-   Ultrasparc PCI host is called the PCI Bus Module (PBM).  The APB is
-   the secondary PCI bridge.  */
-
 #include "qemu/osdep.h"
 #include "hw/sysbus.h"
 #include "hw/pci/pci.h"
 #include "hw/pci/pci_host.h"
 #include "hw/pci/pci_bridge.h"
 #include "hw/pci/pci_bus.h"
-#include "hw/pci-host/apb.h"
+#include "hw/pci-bridge/simba.h"
+#include "hw/pci-host/sabre.h"
 #include "sysemu/sysemu.h"
 #include "exec/address-spaces.h"
 #include "qapi/error.h"
 #include "qemu/log.h"
-
-/* debug APB */
-//#define DEBUG_APB
-
-#ifdef DEBUG_APB
-#define APB_DPRINTF(fmt, ...) \
-do { printf("APB: " fmt , ## __VA_ARGS__); } while (0)
-#else
-#define APB_DPRINTF(fmt, ...)
-#endif
+#include "trace.h"
 
 /*
  * Chipset docs:
  * PBM: "UltraSPARC IIi User's Manual",
  * http://www.sun.com/processors/manuals/805-0087.pdf
- *
- * APB: "Advanced PCI Bridge (APB) User's Manual",
- * http://www.sun.com/processors/manuals/805-1251.pdf
  */
 
 #define PBM_PCI_IMR_MASK    0x7fffffff
@@ -72,22 +58,20 @@ do { printf("APB: " fmt , ## __VA_ARGS__); } while (0)
 
 #define NO_IRQ_REQUEST (MAX_IVEC + 1)
 
-static inline void pbm_set_request(APBState *s, unsigned int irq_num)
+static inline void sabre_set_request(SabreState *s, unsigned int irq_num)
 {
-    APB_DPRINTF("%s: request irq %d\n", __func__, irq_num);
-
+    trace_sabre_set_request(irq_num);
     s->irq_request = irq_num;
     qemu_set_irq(s->ivec_irqs[irq_num], 1);
 }
 
-static inline void pbm_check_irqs(APBState *s)
+static inline void sabre_check_irqs(SabreState *s)
 {
-
     unsigned int i;
 
     /* Previous request is not acknowledged, resubmit */
     if (s->irq_request != NO_IRQ_REQUEST) {
-        pbm_set_request(s, s->irq_request);
+        sabre_set_request(s, s->irq_request);
         return;
     }
     /* no request pending */
@@ -97,7 +81,7 @@ static inline void pbm_check_irqs(APBState *s)
     for (i = 0; i < 32; i++) {
         if (s->pci_irq_in & (1ULL << i)) {
             if (s->pci_irq_map[i >> 2] & PBM_PCI_IMR_ENABLED) {
-                pbm_set_request(s, i);
+                sabre_set_request(s, i);
                 return;
             }
         }
@@ -105,33 +89,33 @@ static inline void pbm_check_irqs(APBState *s)
     for (i = 32; i < 64; i++) {
         if (s->pci_irq_in & (1ULL << i)) {
             if (s->obio_irq_map[i - 32] & PBM_PCI_IMR_ENABLED) {
-                pbm_set_request(s, i);
+                sabre_set_request(s, i);
                 break;
             }
         }
     }
 }
 
-static inline void pbm_clear_request(APBState *s, unsigned int irq_num)
+static inline void sabre_clear_request(SabreState *s, unsigned int irq_num)
 {
-    APB_DPRINTF("%s: clear request irq %d\n", __func__, irq_num);
+    trace_sabre_clear_request(irq_num);
     qemu_set_irq(s->ivec_irqs[irq_num], 0);
     s->irq_request = NO_IRQ_REQUEST;
 }
 
-static AddressSpace *pbm_pci_dma_iommu(PCIBus *bus, void *opaque, int devfn)
+static AddressSpace *sabre_pci_dma_iommu(PCIBus *bus, void *opaque, int devfn)
 {
     IOMMUState *is = opaque;
 
     return &is->iommu_as;
 }
 
-static void apb_config_writel (void *opaque, hwaddr addr,
+static void sabre_config_write(void *opaque, hwaddr addr,
                                uint64_t val, unsigned size)
 {
-    APBState *s = opaque;
+    SabreState *s = opaque;
 
-    APB_DPRINTF("%s: addr " TARGET_FMT_plx " val %" PRIx64 "\n", __func__, addr, val);
+    trace_sabre_config_write(addr, val);
 
     switch (addr & 0xffff) {
     case 0x30 ... 0x4f: /* DMA error registers */
@@ -143,9 +127,9 @@ static void apb_config_writel (void *opaque, hwaddr addr,
             s->pci_irq_map[ino] &= PBM_PCI_IMR_MASK;
             s->pci_irq_map[ino] |= val & ~PBM_PCI_IMR_MASK;
             if ((s->irq_request == ino) && !(val & ~PBM_PCI_IMR_MASK)) {
-                pbm_clear_request(s, ino);
+                sabre_clear_request(s, ino);
             }
-            pbm_check_irqs(s);
+            sabre_check_irqs(s);
         }
         break;
     case 0x1000 ... 0x107f: /* OBIO interrupt control */
@@ -155,17 +139,17 @@ static void apb_config_writel (void *opaque, hwaddr addr,
             s->obio_irq_map[ino] |= val & ~PBM_PCI_IMR_MASK;
             if ((s->irq_request == (ino | 0x20))
                  && !(val & ~PBM_PCI_IMR_MASK)) {
-                pbm_clear_request(s, ino | 0x20);
+                sabre_clear_request(s, ino | 0x20);
             }
-            pbm_check_irqs(s);
+            sabre_check_irqs(s);
         }
         break;
     case 0x1400 ... 0x14ff: /* PCI interrupt clear */
         if (addr & 4) {
             unsigned int ino = (addr & 0xff) >> 5;
             if ((s->irq_request / 4)  == ino) {
-                pbm_clear_request(s, s->irq_request);
-                pbm_check_irqs(s);
+                sabre_clear_request(s, s->irq_request);
+                sabre_check_irqs(s);
             }
         }
         break;
@@ -173,8 +157,8 @@ static void apb_config_writel (void *opaque, hwaddr addr,
         if (addr & 4) {
             unsigned int ino = ((addr & 0xff) >> 3) | 0x20;
             if (s->irq_request == ino) {
-                pbm_clear_request(s, ino);
-                pbm_check_irqs(s);
+                sabre_clear_request(s, ino);
+                sabre_check_irqs(s);
             }
         }
         break;
@@ -204,10 +188,10 @@ static void apb_config_writel (void *opaque, hwaddr addr,
     }
 }
 
-static uint64_t apb_config_readl (void *opaque,
+static uint64_t sabre_config_read(void *opaque,
                                   hwaddr addr, unsigned size)
 {
-    APBState *s = opaque;
+    SabreState *s = opaque;
     uint32_t val;
 
     switch (addr & 0xffff) {
@@ -255,47 +239,47 @@ static uint64_t apb_config_readl (void *opaque,
         val = 0;
         break;
     }
-    APB_DPRINTF("%s: addr " TARGET_FMT_plx " -> %x\n", __func__, addr, val);
+    trace_sabre_config_read(addr, val);
 
     return val;
 }
 
-static const MemoryRegionOps apb_config_ops = {
-    .read = apb_config_readl,
-    .write = apb_config_writel,
+static const MemoryRegionOps sabre_config_ops = {
+    .read = sabre_config_read,
+    .write = sabre_config_write,
     .endianness = DEVICE_BIG_ENDIAN,
 };
 
-static void apb_pci_config_write(void *opaque, hwaddr addr,
-                                 uint64_t val, unsigned size)
+static void sabre_pci_config_write(void *opaque, hwaddr addr,
+                                   uint64_t val, unsigned size)
 {
-    APBState *s = opaque;
+    SabreState *s = opaque;
     PCIHostState *phb = PCI_HOST_BRIDGE(s);
 
-    APB_DPRINTF("%s: addr " TARGET_FMT_plx " val %" PRIx64 "\n", __func__, addr, val);
+    trace_sabre_pci_config_write(addr, val);
     pci_data_write(phb->bus, addr, val, size);
 }
 
-static uint64_t apb_pci_config_read(void *opaque, hwaddr addr,
-                                    unsigned size)
+static uint64_t sabre_pci_config_read(void *opaque, hwaddr addr,
+                                      unsigned size)
 {
     uint32_t ret;
-    APBState *s = opaque;
+    SabreState *s = opaque;
     PCIHostState *phb = PCI_HOST_BRIDGE(s);
 
     ret = pci_data_read(phb->bus, addr, size);
-    APB_DPRINTF("%s: addr " TARGET_FMT_plx " -> %x\n", __func__, addr, ret);
+    trace_sabre_pci_config_read(addr, ret);
     return ret;
 }
 
-/* The APB host has an IRQ line for each IRQ line of each slot.  */
-static int pci_apb_map_irq(PCIDevice *pci_dev, int irq_num)
+/* The sabre host has an IRQ line for each IRQ line of each slot.  */
+static int pci_sabre_map_irq(PCIDevice *pci_dev, int irq_num)
 {
     /* Return the irq as swizzled by the PBM */
     return irq_num;
 }
 
-static int pci_pbmA_map_irq(PCIDevice *pci_dev, int irq_num)
+static int pci_simbaA_map_irq(PCIDevice *pci_dev, int irq_num)
 {
     /* The on-board devices have fixed (legacy) OBIO intnos */
     switch (PCI_SLOT(pci_dev->devfn)) {
@@ -313,22 +297,23 @@ static int pci_pbmA_map_irq(PCIDevice *pci_dev, int irq_num)
     return ((PCI_SLOT(pci_dev->devfn) << 2) + irq_num) & 0x1f;
 }
 
-static int pci_pbmB_map_irq(PCIDevice *pci_dev, int irq_num)
+static int pci_simbaB_map_irq(PCIDevice *pci_dev, int irq_num)
 {
     return (0x10 + (PCI_SLOT(pci_dev->devfn) << 2) + irq_num) & 0x1f;
 }
 
-static void pci_apb_set_irq(void *opaque, int irq_num, int level)
+static void pci_sabre_set_irq(void *opaque, int irq_num, int level)
 {
-    APBState *s = opaque;
+    SabreState *s = opaque;
+
+    trace_sabre_pci_set_irq(irq_num, level);
 
-    APB_DPRINTF("%s: set irq_in %d level %d\n", __func__, irq_num, level);
     /* PCI IRQ map onto the first 32 INO.  */
     if (irq_num < 32) {
         if (level) {
             s->pci_irq_in |= 1ULL << irq_num;
             if (s->pci_irq_map[irq_num >> 2] & PBM_PCI_IMR_ENABLED) {
-                pbm_set_request(s, irq_num);
+                sabre_set_request(s, irq_num);
             }
         } else {
             s->pci_irq_in &= ~(1ULL << irq_num);
@@ -336,11 +321,11 @@ static void pci_apb_set_irq(void *opaque, int irq_num, int level)
     } else {
         /* OBIO IRQ map onto the next 32 INO.  */
         if (level) {
-            APB_DPRINTF("%s: set irq %d level %d\n", __func__, irq_num, level);
+            trace_sabre_pci_set_obio_irq(irq_num, level);
             s->pci_irq_in |= 1ULL << irq_num;
             if ((s->irq_request == NO_IRQ_REQUEST)
                 && (s->obio_irq_map[irq_num - 32] & PBM_PCI_IMR_ENABLED)) {
-                pbm_set_request(s, irq_num);
+                sabre_set_request(s, irq_num);
             }
         } else {
             s->pci_irq_in &= ~(1ULL << irq_num);
@@ -348,38 +333,9 @@ static void pci_apb_set_irq(void *opaque, int irq_num, int level)
     }
 }
 
-static void apb_pci_bridge_realize(PCIDevice *dev, Error **errp)
+static void sabre_reset(DeviceState *d)
 {
-    /*
-     * command register:
-     * According to PCI bridge spec, after reset
-     *   bus master bit is off
-     *   memory space enable bit is off
-     * According to manual (805-1251.pdf).
-     *   the reset value should be zero unless the boot pin is tied high
-     *   (which is true) and thus it should be PCI_COMMAND_MEMORY.
-     */
-    PBMPCIBridge *br = PBM_PCI_BRIDGE(dev);
-
-    pci_bridge_initfn(dev, TYPE_PCI_BUS);
-
-    pci_set_word(dev->config + PCI_COMMAND, PCI_COMMAND_MEMORY);
-    pci_set_word(dev->config + PCI_STATUS,
-                 PCI_STATUS_FAST_BACK | PCI_STATUS_66MHZ |
-                 PCI_STATUS_DEVSEL_MEDIUM);
-
-    /* Allow 32-bit IO addresses */
-    pci_set_word(dev->config + PCI_IO_BASE, PCI_IO_RANGE_TYPE_32);
-    pci_set_word(dev->config + PCI_IO_LIMIT, PCI_IO_RANGE_TYPE_32);
-    pci_set_word(dev->wmask + PCI_IO_BASE_UPPER16, 0xffff);
-    pci_set_word(dev->wmask + PCI_IO_LIMIT_UPPER16, 0xffff);
-
-    pci_bridge_update_mappings(PCI_BRIDGE(br));
-}
-
-static void pci_pbm_reset(DeviceState *d)
-{
-    APBState *s = APB_DEVICE(d);
+    SabreState *s = SABRE_DEVICE(d);
     PCIDevice *pci_dev;
     unsigned int i;
     uint16_t cmd;
@@ -410,19 +366,19 @@ static void pci_pbm_reset(DeviceState *d)
 }
 
 static const MemoryRegionOps pci_config_ops = {
-    .read = apb_pci_config_read,
-    .write = apb_pci_config_write,
+    .read = sabre_pci_config_read,
+    .write = sabre_pci_config_write,
     .endianness = DEVICE_LITTLE_ENDIAN,
 };
 
-static void pci_pbm_realize(DeviceState *dev, Error **errp)
+static void sabre_realize(DeviceState *dev, Error **errp)
 {
-    APBState *s = APB_DEVICE(dev);
+    SabreState *s = SABRE_DEVICE(dev);
     PCIHostState *phb = PCI_HOST_BRIDGE(dev);
     SysBusDevice *sbd = SYS_BUS_DEVICE(s);
     PCIDevice *pci_dev;
 
-    /* apb_config */
+    /* sabre_config */
     sysbus_mmio_map(sbd, 0, s->special_base);
     /* PCI configuration space */
     sysbus_mmio_map(sbd, 1, s->special_base + 0x1000000ULL);
@@ -434,35 +390,35 @@ static void pci_pbm_realize(DeviceState *dev, Error **errp)
                                 &s->pci_mmio);
 
     phb->bus = pci_register_root_bus(dev, "pci",
-                                     pci_apb_set_irq, pci_apb_map_irq, s,
+                                     pci_sabre_set_irq, pci_sabre_map_irq, s,
                                      &s->pci_mmio,
                                      &s->pci_ioport,
                                      0, 32, TYPE_PCI_BUS);
 
-    pci_create_simple(phb->bus, 0, "pbm-pci");
+    pci_create_simple(phb->bus, 0, TYPE_SABRE_PCI_DEVICE);
 
-    /* APB IOMMU */
-    memory_region_add_subregion_overlap(&s->apb_config, 0x200,
+    /* IOMMU */
+    memory_region_add_subregion_overlap(&s->sabre_config, 0x200,
                     sysbus_mmio_get_region(SYS_BUS_DEVICE(s->iommu), 0), 1);
-    pci_setup_iommu(phb->bus, pbm_pci_dma_iommu, s->iommu);
+    pci_setup_iommu(phb->bus, sabre_pci_dma_iommu, s->iommu);
 
     /* APB secondary busses */
     pci_dev = pci_create_multifunction(phb->bus, PCI_DEVFN(1, 0), true,
-                                   TYPE_PBM_PCI_BRIDGE);
+                                       TYPE_SIMBA_PCI_BRIDGE);
     s->bridgeB = PCI_BRIDGE(pci_dev);
-    pci_bridge_map_irq(s->bridgeB, "pciB", pci_pbmB_map_irq);
+    pci_bridge_map_irq(s->bridgeB, "pciB", pci_simbaB_map_irq);
     qdev_init_nofail(&pci_dev->qdev);
 
     pci_dev = pci_create_multifunction(phb->bus, PCI_DEVFN(1, 1), true,
-                                   TYPE_PBM_PCI_BRIDGE);
+                                       TYPE_SIMBA_PCI_BRIDGE);
     s->bridgeA = PCI_BRIDGE(pci_dev);
-    pci_bridge_map_irq(s->bridgeA, "pciA", pci_pbmA_map_irq);
+    pci_bridge_map_irq(s->bridgeA, "pciA", pci_simbaA_map_irq);
     qdev_init_nofail(&pci_dev->qdev);
 }
 
-static void pci_pbm_init(Object *obj)
+static void sabre_init(Object *obj)
 {
-    APBState *s = APB_DEVICE(obj);
+    SabreState *s = SABRE_DEVICE(obj);
     SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
     unsigned int i;
 
@@ -475,7 +431,7 @@ static void pci_pbm_init(Object *obj)
     for (i = 0; i < 32; i++) {
         s->obio_irq_map[i] = ((0x1f << 6) | 0x20) + i;
     }
-    qdev_init_gpio_in_named(DEVICE(s), pci_apb_set_irq, "pbm-irq", MAX_IVEC);
+    qdev_init_gpio_in_named(DEVICE(s), pci_sabre_set_irq, "pbm-irq", MAX_IVEC);
     qdev_init_gpio_out_named(DEVICE(s), s->ivec_irqs, "ivec-irq", MAX_IVEC);
     s->irq_request = NO_IRQ_REQUEST;
     s->pci_irq_in = 0ULL;
@@ -486,25 +442,26 @@ static void pci_pbm_init(Object *obj)
                              qdev_prop_allow_set_link_before_realize,
                              0, NULL);
 
-    /* apb_config */
-    memory_region_init_io(&s->apb_config, OBJECT(s), &apb_config_ops, s,
-                          "apb-config", 0x10000);
+    /* sabre_config */
+    memory_region_init_io(&s->sabre_config, OBJECT(s), &sabre_config_ops, s,
+                          "sabre-config", 0x10000);
     /* at region 0 */
-    sysbus_init_mmio(sbd, &s->apb_config);
+    sysbus_init_mmio(sbd, &s->sabre_config);
 
     memory_region_init_io(&s->pci_config, OBJECT(s), &pci_config_ops, s,
-                          "apb-pci-config", 0x1000000);
+                          "sabre-pci-config", 0x1000000);
     /* at region 1 */
     sysbus_init_mmio(sbd, &s->pci_config);
 
     /* pci_ioport */
-    memory_region_init(&s->pci_ioport, OBJECT(s), "apb-pci-ioport", 0x1000000);
+    memory_region_init(&s->pci_ioport, OBJECT(s), "sabre-pci-ioport",
+                       0x1000000);
 
     /* at region 2 */
     sysbus_init_mmio(sbd, &s->pci_ioport);
 }
 
-static void pbm_pci_host_realize(PCIDevice *d, Error **errp)
+static void sabre_pci_realize(PCIDevice *d, Error **errp)
 {
     pci_set_word(d->config + PCI_COMMAND,
                  PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
@@ -513,12 +470,12 @@ static void pbm_pci_host_realize(PCIDevice *d, Error **errp)
                  PCI_STATUS_DEVSEL_MEDIUM);
 }
 
-static void pbm_pci_host_class_init(ObjectClass *klass, void *data)
+static void sabre_pci_class_init(ObjectClass *klass, void *data)
 {
     PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
     DeviceClass *dc = DEVICE_CLASS(klass);
 
-    k->realize = pbm_pci_host_realize;
+    k->realize = sabre_pci_realize;
     k->vendor_id = PCI_VENDOR_ID_SUN;
     k->device_id = PCI_DEVICE_ID_SUN_SABRE;
     k->class_id = PCI_CLASS_BRIDGE_HOST;
@@ -529,74 +486,45 @@ static void pbm_pci_host_class_init(ObjectClass *klass, void *data)
     dc->user_creatable = false;
 }
 
-static const TypeInfo pbm_pci_host_info = {
-    .name          = "pbm-pci",
+static const TypeInfo sabre_pci_info = {
+    .name          = TYPE_SABRE_PCI_DEVICE,
     .parent        = TYPE_PCI_DEVICE,
-    .instance_size = sizeof(PCIDevice),
-    .class_init    = pbm_pci_host_class_init,
+    .instance_size = sizeof(SabrePCIState),
+    .class_init    = sabre_pci_class_init,
     .interfaces = (InterfaceInfo[]) {
         { INTERFACE_CONVENTIONAL_PCI_DEVICE },
         { },
     },
 };
 
-static Property pbm_pci_host_properties[] = {
-    DEFINE_PROP_UINT64("special-base", APBState, special_base, 0),
-    DEFINE_PROP_UINT64("mem-base", APBState, mem_base, 0),
+static Property sabre_properties[] = {
+    DEFINE_PROP_UINT64("special-base", SabreState, special_base, 0),
+    DEFINE_PROP_UINT64("mem-base", SabreState, mem_base, 0),
     DEFINE_PROP_END_OF_LIST(),
 };
 
-static void pbm_host_class_init(ObjectClass *klass, void *data)
+static void sabre_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
 
-    dc->realize = pci_pbm_realize;
-    dc->reset = pci_pbm_reset;
-    dc->props = pbm_pci_host_properties;
+    dc->realize = sabre_realize;
+    dc->reset = sabre_reset;
+    dc->props = sabre_properties;
     set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
 }
 
-static const TypeInfo pbm_host_info = {
-    .name          = TYPE_APB,
+static const TypeInfo sabre_info = {
+    .name          = TYPE_SABRE,
     .parent        = TYPE_PCI_HOST_BRIDGE,
-    .instance_size = sizeof(APBState),
-    .instance_init = pci_pbm_init,
-    .class_init    = pbm_host_class_init,
-};
-
-static void pbm_pci_bridge_class_init(ObjectClass *klass, void *data)
-{
-    DeviceClass *dc = DEVICE_CLASS(klass);
-    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
-
-    k->realize = apb_pci_bridge_realize;
-    k->exit = pci_bridge_exitfn;
-    k->vendor_id = PCI_VENDOR_ID_SUN;
-    k->device_id = PCI_DEVICE_ID_SUN_SIMBA;
-    k->revision = 0x11;
-    k->config_write = pci_bridge_write_config;
-    k->is_bridge = 1;
-    set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
-    dc->reset = pci_bridge_reset;
-    dc->vmsd = &vmstate_pci_device;
-}
-
-static const TypeInfo pbm_pci_bridge_info = {
-    .name          = TYPE_PBM_PCI_BRIDGE,
-    .parent        = TYPE_PCI_BRIDGE,
-    .class_init    = pbm_pci_bridge_class_init,
-    .instance_size = sizeof(PBMPCIBridge),
-    .interfaces = (InterfaceInfo[]) {
-        { INTERFACE_CONVENTIONAL_PCI_DEVICE },
-        { },
-    },
+    .instance_size = sizeof(SabreState),
+    .instance_init = sabre_init,
+    .class_init    = sabre_class_init,
 };
 
-static void pbm_register_types(void)
+static void sabre_register_types(void)
 {
-    type_register_static(&pbm_host_info);
-    type_register_static(&pbm_pci_host_info);
-    type_register_static(&pbm_pci_bridge_info);
+    type_register_static(&sabre_info);
+    type_register_static(&sabre_pci_info);
 }
 
-type_init(pbm_register_types)
+type_init(sabre_register_types)
diff --git a/hw/pci-host/trace-events b/hw/pci-host/trace-events
new file mode 100644
index 0000000000..32dfc84692
--- /dev/null
+++ b/hw/pci-host/trace-events
@@ -0,0 +1,11 @@
+# See docs/devel/tracing.txt for syntax documentation.
+
+# hw/pci-host/sabre.c
+sabre_set_request(int irq_num) "request irq %d"
+sabre_clear_request(int irq_num) "clear request irq %d"
+sabre_config_write(uint64_t addr, uint64_t val) "addr 0x%"PRIx64" val 0x%"PRIx64
+sabre_config_read(uint64_t addr, uint64_t val) "addr 0x%"PRIx64" val 0x%"PRIx64
+sabre_pci_config_write(uint64_t addr, uint64_t val) "addr 0x%"PRIx64" val 0x%"PRIx64
+sabre_pci_config_read(uint64_t addr, uint64_t val) "addr 0x%"PRIx64" val 0x%"PRIx64
+sabre_pci_set_irq(int irq_num, int level) "set irq_in %d level %d"
+sabre_pci_set_obio_irq(int irq_num, int level) "set irq %d level %d"
diff --git a/hw/sparc64/sparc64.c b/hw/sparc64/sparc64.c
index 95a06f00b2..408388945e 100644
--- a/hw/sparc64/sparc64.c
+++ b/hw/sparc64/sparc64.c
@@ -28,25 +28,9 @@
 #include "hw/char/serial.h"
 #include "hw/sparc/sparc64.h"
 #include "qemu/timer.h"
+#include "trace.h"
 
 
-//#define DEBUG_IRQ
-//#define DEBUG_TIMER
-
-#ifdef DEBUG_IRQ
-#define CPUIRQ_DPRINTF(fmt, ...)                                \
-    do { printf("CPUIRQ: " fmt , ## __VA_ARGS__); } while (0)
-#else
-#define CPUIRQ_DPRINTF(fmt, ...)
-#endif
-
-#ifdef DEBUG_TIMER
-#define TIMER_DPRINTF(fmt, ...)                                  \
-    do { printf("TIMER: " fmt , ## __VA_ARGS__); } while (0)
-#else
-#define TIMER_DPRINTF(fmt, ...)
-#endif
-
 #define TICK_MAX             0x7fffffffffffffffULL
 
 void cpu_check_irqs(CPUSPARCState *env)
@@ -73,8 +57,7 @@ void cpu_check_irqs(CPUSPARCState *env)
        is (2 << psrpil). */
     if (pil < (2 << env->psrpil)) {
         if (cs->interrupt_request & CPU_INTERRUPT_HARD) {
-            CPUIRQ_DPRINTF("Reset CPU IRQ (current interrupt %x)\n",
-                           env->interrupt_index);
+            trace_sparc64_cpu_check_irqs_reset_irq(env->interrupt_index);
             env->interrupt_index = 0;
             cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
         }
@@ -92,22 +75,21 @@ void cpu_check_irqs(CPUSPARCState *env)
 
                 if (unlikely(env->tl > 0 && cpu_tsptr(env)->tt > new_interrupt
                   && ((cpu_tsptr(env)->tt & 0x1f0) == TT_EXTINT))) {
-                    CPUIRQ_DPRINTF("Not setting CPU IRQ: TL=%d "
-                                   "current %x >= pending %x\n",
-                                   env->tl, cpu_tsptr(env)->tt, new_interrupt);
+                    trace_sparc64_cpu_check_irqs_noset_irq(env->tl,
+                                                      cpu_tsptr(env)->tt,
+                                                      new_interrupt);
                 } else if (old_interrupt != new_interrupt) {
                     env->interrupt_index = new_interrupt;
-                    CPUIRQ_DPRINTF("Set CPU IRQ %d old=%x new=%x\n", i,
-                                   old_interrupt, new_interrupt);
+                    trace_sparc64_cpu_check_irqs_set_irq(i, old_interrupt,
+                                                         new_interrupt);
                     cpu_interrupt(cs, CPU_INTERRUPT_HARD);
                 }
                 break;
             }
         }
     } else if (cs->interrupt_request & CPU_INTERRUPT_HARD) {
-        CPUIRQ_DPRINTF("Interrupts disabled, pil=%08x pil_in=%08x softint=%08x "
-                       "current interrupt %x\n",
-                       pil, env->pil_in, env->softint, env->interrupt_index);
+        trace_sparc64_cpu_check_irqs_disabled(pil, env->pil_in, env->softint,
+                                              env->interrupt_index);
         env->interrupt_index = 0;
         cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
     }
@@ -131,7 +113,7 @@ void sparc64_cpu_set_ivec_irq(void *opaque, int irq, int level)
 
     if (level) {
         if (!(env->ivec_status & 0x20)) {
-            CPUIRQ_DPRINTF("Raise IVEC IRQ %d\n", irq);
+            trace_sparc64_cpu_ivec_raise_irq(irq);
             cs = CPU(cpu);
             cs->halted = 0;
             env->interrupt_index = TT_IVEC;
@@ -143,7 +125,7 @@ void sparc64_cpu_set_ivec_irq(void *opaque, int irq, int level)
         }
     } else {
         if (env->ivec_status & 0x20) {
-            CPUIRQ_DPRINTF("Lower IVEC IRQ %d\n", irq);
+            trace_sparc64_cpu_ivec_lower_irq(irq);
             cs = CPU(cpu);
             env->ivec_status &= ~0x20;
             cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
@@ -216,10 +198,10 @@ static void tick_irq(void *opaque)
     CPUTimer *timer = env->tick;
 
     if (timer->disabled) {
-        CPUIRQ_DPRINTF("tick_irq: softint disabled\n");
+        trace_sparc64_cpu_tick_irq_disabled();
         return;
     } else {
-        CPUIRQ_DPRINTF("tick: fire\n");
+        trace_sparc64_cpu_tick_irq_fire();
     }
 
     env->softint |= SOFTINT_TIMER;
@@ -234,10 +216,10 @@ static void stick_irq(void *opaque)
     CPUTimer *timer = env->stick;
 
     if (timer->disabled) {
-        CPUIRQ_DPRINTF("stick_irq: softint disabled\n");
+        trace_sparc64_cpu_stick_irq_disabled();
         return;
     } else {
-        CPUIRQ_DPRINTF("stick: fire\n");
+        trace_sparc64_cpu_stick_irq_fire();
     }
 
     env->softint |= SOFTINT_STIMER;
@@ -252,10 +234,10 @@ static void hstick_irq(void *opaque)
     CPUTimer *timer = env->hstick;
 
     if (timer->disabled) {
-        CPUIRQ_DPRINTF("hstick_irq: softint disabled\n");
+        trace_sparc64_cpu_hstick_irq_disabled();
         return;
     } else {
-        CPUIRQ_DPRINTF("hstick: fire\n");
+        trace_sparc64_cpu_hstick_irq_fire();
     }
 
     env->softint |= SOFTINT_STIMER;
@@ -280,9 +262,9 @@ void cpu_tick_set_count(CPUTimer *timer, uint64_t count)
     int64_t vm_clock_offset = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) -
                     cpu_to_timer_ticks(real_count, timer->frequency);
 
-    TIMER_DPRINTF("%s set_count count=0x%016lx (npt %s) p=%p\n",
-                  timer->name, real_count,
-                  timer->npt ? "disabled" : "enabled", timer);
+    trace_sparc64_cpu_tick_set_count(timer->name, real_count,
+                                     timer->npt ? "disabled" : "enabled",
+                                     timer);
 
     timer->npt = npt_bit ? 1 : 0;
     timer->clock_offset = vm_clock_offset;
@@ -294,9 +276,9 @@ uint64_t cpu_tick_get_count(CPUTimer *timer)
                     qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) - timer->clock_offset,
                     timer->frequency);
 
-    TIMER_DPRINTF("%s get_count count=0x%016lx (npt %s) p=%p\n",
-           timer->name, real_count,
-           timer->npt ? "disabled" : "enabled", timer);
+    trace_sparc64_cpu_tick_get_count(timer->name, real_count,
+                                     timer->npt ? "disabled" : "enabled",
+                                     timer);
 
     if (timer->npt) {
         real_count |= timer->npt_mask;
@@ -319,18 +301,19 @@ void cpu_tick_set_limit(CPUTimer *timer, uint64_t limit)
         expires = now + 1;
     }
 
-    TIMER_DPRINTF("%s set_limit limit=0x%016lx (%s) p=%p "
-                  "called with limit=0x%016lx at 0x%016lx (delta=0x%016lx)\n",
-                  timer->name, real_limit,
-                  timer->disabled ? "disabled" : "enabled",
-                  timer, limit,
-                  timer_to_cpu_ticks(now - timer->clock_offset,
-                                     timer->frequency),
-                  timer_to_cpu_ticks(expires - now, timer->frequency));
+    trace_sparc64_cpu_tick_set_limit(timer->name, real_limit,
+                                     timer->disabled ? "disabled" : "enabled",
+                                     timer, limit,
+                                     timer_to_cpu_ticks(
+                                         now - timer->clock_offset,
+                                         timer->frequency
+                                     ),
+                                     timer_to_cpu_ticks(
+                                         expires - now, timer->frequency
+                                     ));
 
     if (!real_limit) {
-        TIMER_DPRINTF("%s set_limit limit=ZERO - not starting timer\n",
-                timer->name);
+        trace_sparc64_cpu_tick_set_limit_zero(timer->name);
         timer_del(timer->qtimer);
     } else if (timer->disabled) {
         timer_del(timer->qtimer);
diff --git a/hw/sparc64/sun4u.c b/hw/sparc64/sun4u.c
index ec45ec2801..a23cb26b0d 100644
--- a/hw/sparc64/sun4u.c
+++ b/hw/sparc64/sun4u.c
@@ -30,7 +30,7 @@
 #include "hw/pci/pci_bridge.h"
 #include "hw/pci/pci_bus.h"
 #include "hw/pci/pci_host.h"
-#include "hw/pci-host/apb.h"
+#include "hw/pci-host/sabre.h"
 #include "hw/i386/pc.h"
 #include "hw/char/serial.h"
 #include "hw/timer/m48t59.h"
@@ -55,9 +55,9 @@
 #define CMDLINE_ADDR         0x003ff000
 #define PROM_SIZE_MAX        (4 * 1024 * 1024)
 #define PROM_VADDR           0x000ffd00000ULL
-#define APB_SPECIAL_BASE     0x1fe00000000ULL
-#define APB_MEM_BASE         0x1ff00000000ULL
-#define APB_PCI_IO_BASE      (APB_SPECIAL_BASE + 0x02000000ULL)
+#define PBM_SPECIAL_BASE     0x1fe00000000ULL
+#define PBM_MEM_BASE         0x1ff00000000ULL
+#define PBM_PCI_IO_BASE      (PBM_SPECIAL_BASE + 0x02000000ULL)
 #define PROM_FILENAME        "openbios-sparc64"
 #define NVRAM_SIZE           0x2000
 #define MAX_IDE_BUS          2
@@ -205,6 +205,59 @@ typedef struct ResetData {
     uint64_t prom_addr;
 } ResetData;
 
+#define TYPE_SUN4U_POWER "power"
+#define SUN4U_POWER(obj) OBJECT_CHECK(PowerDevice, (obj), TYPE_SUN4U_POWER)
+
+typedef struct PowerDevice {
+    SysBusDevice parent_obj;
+
+    MemoryRegion power_mmio;
+} PowerDevice;
+
+/* Power */
+static void power_mem_write(void *opaque, hwaddr addr,
+                            uint64_t val, unsigned size)
+{
+    /* According to a real Ultra 5, bit 24 controls the power */
+    if (val & 0x1000000) {
+        qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
+    }
+}
+
+static const MemoryRegionOps power_mem_ops = {
+    .write = power_mem_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+    .valid = {
+        .min_access_size = 4,
+        .max_access_size = 4,
+    },
+};
+
+static void power_realize(DeviceState *dev, Error **errp)
+{
+    PowerDevice *d = SUN4U_POWER(dev);
+    SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
+
+    memory_region_init_io(&d->power_mmio, OBJECT(dev), &power_mem_ops, d,
+                          "power", sizeof(uint32_t));
+
+    sysbus_init_mmio(sbd, &d->power_mmio);
+}
+
+static void power_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
+    dc->realize = power_realize;
+}
+
+static const TypeInfo power_info = {
+    .name          = TYPE_SUN4U_POWER,
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(PowerDevice),
+    .class_init    = power_class_init,
+};
+
 static void ebus_isa_irq_handler(void *opaque, int n, int level)
 {
     EbusState *s = EBUS(opaque);
@@ -221,6 +274,7 @@ static void ebus_isa_irq_handler(void *opaque, int n, int level)
 static void ebus_realize(PCIDevice *pci_dev, Error **errp)
 {
     EbusState *s = EBUS(pci_dev);
+    SysBusDevice *sbd;
     DeviceState *dev;
     qemu_irq *isa_irq;
     DriveInfo *fd[MAX_FD];
@@ -270,6 +324,13 @@ static void ebus_realize(PCIDevice *pci_dev, Error **errp)
     qdev_prop_set_uint32(dev, "dma", -1);
     qdev_init_nofail(dev);
 
+    /* Power */
+    dev = qdev_create(NULL, TYPE_SUN4U_POWER);
+    qdev_init_nofail(dev);
+    sbd = SYS_BUS_DEVICE(dev);
+    memory_region_add_subregion(pci_address_space_io(pci_dev), 0x7240,
+                                sysbus_mmio_get_region(sbd, 0));
+
     /* PCI */
     pci_dev->config[0x04] = 0x06; // command = bus master, pci mem
     pci_dev->config[0x05] = 0x00;
@@ -282,7 +343,7 @@ static void ebus_realize(PCIDevice *pci_dev, Error **errp)
                              0, 0x1000000);
     pci_register_bar(pci_dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->bar0);
     memory_region_init_alias(&s->bar1, OBJECT(s), "bar1", get_system_io(),
-                             0, 0x4000);
+                             0, 0x8000);
     pci_register_bar(pci_dev, 1, PCI_BASE_ADDRESS_SPACE_IO, &s->bar1);
 }
 
@@ -465,7 +526,7 @@ static void sun4uv_init(MemoryRegion *address_space_mem,
     Nvram *nvram;
     unsigned int i;
     uint64_t initrd_addr, initrd_size, kernel_addr, kernel_size, kernel_entry;
-    APBState *apb;
+    SabreState *sabre;
     PCIBus *pci_bus, *pci_busA, *pci_busB;
     PCIDevice *ebus, *pci_dev;
     SysBusDevice *s;
@@ -488,24 +549,25 @@ static void sun4uv_init(MemoryRegion *address_space_mem,
 
     prom_init(hwdef->prom_addr, bios_name);
 
-    /* Init APB (PCI host bridge) */
-    apb = APB_DEVICE(qdev_create(NULL, TYPE_APB));
-    qdev_prop_set_uint64(DEVICE(apb), "special-base", APB_SPECIAL_BASE);
-    qdev_prop_set_uint64(DEVICE(apb), "mem-base", APB_MEM_BASE);
-    object_property_set_link(OBJECT(apb), OBJECT(iommu), "iommu", &error_abort);
-    qdev_init_nofail(DEVICE(apb));
+    /* Init sabre (PCI host bridge) */
+    sabre = SABRE_DEVICE(qdev_create(NULL, TYPE_SABRE));
+    qdev_prop_set_uint64(DEVICE(sabre), "special-base", PBM_SPECIAL_BASE);
+    qdev_prop_set_uint64(DEVICE(sabre), "mem-base", PBM_MEM_BASE);
+    object_property_set_link(OBJECT(sabre), OBJECT(iommu), "iommu",
+                             &error_abort);
+    qdev_init_nofail(DEVICE(sabre));
 
     /* Wire up PCI interrupts to CPU */
     for (i = 0; i < IVEC_MAX; i++) {
-        qdev_connect_gpio_out_named(DEVICE(apb), "ivec-irq", i,
+        qdev_connect_gpio_out_named(DEVICE(sabre), "ivec-irq", i,
             qdev_get_gpio_in_named(DEVICE(cpu), "ivec-irq", i));
     }
 
-    pci_bus = PCI_HOST_BRIDGE(apb)->bus;
-    pci_busA = pci_bridge_get_sec_bus(apb->bridgeA);
-    pci_busB = pci_bridge_get_sec_bus(apb->bridgeB);
+    pci_bus = PCI_HOST_BRIDGE(sabre)->bus;
+    pci_busA = pci_bridge_get_sec_bus(sabre->bridgeA);
+    pci_busB = pci_bridge_get_sec_bus(sabre->bridgeB);
 
-    /* Only in-built Simba PBMs can exist on the root bus, slot 0 on busA is
+    /* Only in-built Simba APBs can exist on the root bus, slot 0 on busA is
        reserved (leaving no slots free after on-board devices) however slots
        0-3 are free on busB */
     pci_bus->slot_reserved_mask = 0xfffffffc;
@@ -517,17 +579,17 @@ static void sun4uv_init(MemoryRegion *address_space_mem,
                          hwdef->console_serial_base);
     qdev_init_nofail(DEVICE(ebus));
 
-    /* Wire up "well-known" ISA IRQs to APB legacy obio IRQs */
+    /* Wire up "well-known" ISA IRQs to PBM legacy obio IRQs */
     qdev_connect_gpio_out_named(DEVICE(ebus), "isa-irq", 7,
-        qdev_get_gpio_in_named(DEVICE(apb), "pbm-irq", OBIO_LPT_IRQ));
+        qdev_get_gpio_in_named(DEVICE(sabre), "pbm-irq", OBIO_LPT_IRQ));
     qdev_connect_gpio_out_named(DEVICE(ebus), "isa-irq", 6,
-        qdev_get_gpio_in_named(DEVICE(apb), "pbm-irq", OBIO_FDD_IRQ));
+        qdev_get_gpio_in_named(DEVICE(sabre), "pbm-irq", OBIO_FDD_IRQ));
     qdev_connect_gpio_out_named(DEVICE(ebus), "isa-irq", 1,
-        qdev_get_gpio_in_named(DEVICE(apb), "pbm-irq", OBIO_KBD_IRQ));
+        qdev_get_gpio_in_named(DEVICE(sabre), "pbm-irq", OBIO_KBD_IRQ));
     qdev_connect_gpio_out_named(DEVICE(ebus), "isa-irq", 12,
-        qdev_get_gpio_in_named(DEVICE(apb), "pbm-irq", OBIO_MSE_IRQ));
+        qdev_get_gpio_in_named(DEVICE(sabre), "pbm-irq", OBIO_MSE_IRQ));
     qdev_connect_gpio_out_named(DEVICE(ebus), "isa-irq", 4,
-        qdev_get_gpio_in_named(DEVICE(apb), "pbm-irq", OBIO_SER_IRQ));
+        qdev_get_gpio_in_named(DEVICE(sabre), "pbm-irq", OBIO_SER_IRQ));
 
     pci_dev = pci_create_simple(pci_busA, PCI_DEVFN(2, 0), "VGA");
 
@@ -693,6 +755,7 @@ static const TypeInfo sun4v_type = {
 
 static void sun4u_register_types(void)
 {
+    type_register_static(&power_info);
     type_register_static(&ebus_info);
     type_register_static(&prom_info);
     type_register_static(&ram_info);
diff --git a/hw/sparc64/trace-events b/hw/sparc64/trace-events
index 2ee2d75f70..ce597a6e9d 100644
--- a/hw/sparc64/trace-events
+++ b/hw/sparc64/trace-events
@@ -7,3 +7,21 @@ ebus_isa_irq_handler(int n, int level) "Set ISA IRQ %d level %d"
 sun4u_iommu_mem_read(uint64_t addr, uint64_t val, int size) "addr: 0x%"PRIx64" val: 0x%"PRIx64" size: %d"
 sun4u_iommu_mem_write(uint64_t addr, uint64_t val, int size) "addr: 0x%"PRIx64" val: 0x%"PRIx64" size: %d"
 sun4u_iommu_translate(uint64_t addr, uint64_t trans_addr, uint64_t tte) "xlate 0x%"PRIx64" => pa 0x%"PRIx64" tte: 0x%"PRIx64
+
+# hw/sparc64/sparc64.c
+sparc64_cpu_check_irqs_reset_irq(int intno) "Reset CPU IRQ (current interrupt 0x%x)"
+sparc64_cpu_check_irqs_noset_irq(uint32_t tl, uint32_t tt, int intno) "Not setting CPU IRQ: TL=%d current 0x%x >= pending 0x%x"
+sparc64_cpu_check_irqs_set_irq(unsigned int i, int old, int new) "Set CPU IRQ %d old=0x%x new=0x%x"
+sparc64_cpu_check_irqs_disabled(uint32_t pil, uint32_t pil_in, uint32_t softint, int intno) "Interrupts disabled, pil=0x%08x pil_in=0x%08x softint=0x%08x current interrupt 0x%x"
+sparc64_cpu_ivec_raise_irq(int irq) "Raise IVEC IRQ %d"
+sparc64_cpu_ivec_lower_irq(int irq) "Lower IVEC IRQ %d"
+sparc64_cpu_tick_irq_disabled(void) "tick_irq: softint disabled"
+sparc64_cpu_tick_irq_fire(void) "tick_irq: fire"
+sparc64_cpu_stick_irq_disabled(void) "stick_irq: softint disabled"
+sparc64_cpu_stick_irq_fire(void) "stick_irq: fire"
+sparc64_cpu_hstick_irq_disabled(void) "hstick_irq: softint disabled"
+sparc64_cpu_hstick_irq_fire(void) "hstick_irq: fire"
+sparc64_cpu_tick_set_count(const char *name, uint64_t real_count, const char *npt, void *p) "%s set_count count=0x%"PRIx64" (npt %s) p=%p"
+sparc64_cpu_tick_get_count(const char *name, uint64_t real_count, const char *npt, void *p) "%s get_count count=0x%"PRIx64" (npt %s) p=%p"
+sparc64_cpu_tick_set_limit(const char *name, uint64_t real_limit, const char *dis, void *p, uint64_t limit, uint64_t t, uint64_t dt) "%s set_limit limit=0x%"PRIx64 " (%s) p=%p called with limit=0x%"PRIx64" at 0x%"PRIx64" (delta=0x%"PRIx64")"
+sparc64_cpu_tick_set_limit_zero(const char *name) "%s set_limit limit=ZERO - not starting timer"