summary refs log tree commit diff stats
path: root/hw
diff options
context:
space:
mode:
Diffstat (limited to 'hw')
-rw-r--r--hw/i386/kvm/ioapic.c1
-rw-r--r--hw/intc/Makefile.objs1
-rw-r--r--hw/intc/openpic.c89
-rw-r--r--hw/intc/openpic_kvm.c264
-rw-r--r--hw/misc/macio/macio.c47
-rw-r--r--hw/nvram/spapr_nvram.c4
-rw-r--r--hw/ppc/e500.c125
-rw-r--r--hw/ppc/mac_newworld.c24
-rw-r--r--hw/ppc/mac_oldworld.c2
-rw-r--r--hw/ppc/mpc8544_guts.c32
-rw-r--r--hw/ppc/ppc_booke.c24
-rw-r--r--hw/ppc/spapr.c3
-rw-r--r--hw/ppc/spapr_events.c2
-rw-r--r--hw/ppc/spapr_hcall.c2
-rw-r--r--hw/ppc/spapr_pci.c13
-rw-r--r--hw/ppc/spapr_rtas.c21
-rw-r--r--hw/ppc/spapr_vio.c6
-rw-r--r--hw/ppc/xics.c12
18 files changed, 553 insertions, 119 deletions
diff --git a/hw/i386/kvm/ioapic.c b/hw/i386/kvm/ioapic.c
index a3bd519b4d..abfac3da7a 100644
--- a/hw/i386/kvm/ioapic.c
+++ b/hw/i386/kvm/ioapic.c
@@ -40,6 +40,7 @@ void kvm_pc_setup_irq_routing(bool pci_enabled)
                 }
             }
         }
+        kvm_irqchip_commit_routes(s);
     }
 }
 
diff --git a/hw/intc/Makefile.objs b/hw/intc/Makefile.objs
index 3e68d2eba8..2ba49d0e41 100644
--- a/hw/intc/Makefile.objs
+++ b/hw/intc/Makefile.objs
@@ -20,4 +20,5 @@ obj-$(CONFIG_GRLIB) += grlib_irqmp.o
 obj-$(CONFIG_IOAPIC) += ioapic.o
 obj-$(CONFIG_OMAP) += omap_intc.o
 obj-$(CONFIG_OPENPIC) += openpic.o
+obj-$(CONFIG_OPENPIC_KVM) += openpic_kvm.o
 obj-$(CONFIG_SH4) += sh_intc.o
diff --git a/hw/intc/openpic.c b/hw/intc/openpic.c
index c78871445b..a26c641699 100644
--- a/hw/intc/openpic.c
+++ b/hw/intc/openpic.c
@@ -57,11 +57,7 @@ static const int debug_openpic = 0;
     } while (0)
 
 #define MAX_CPU     32
-#define MAX_SRC     256
-#define MAX_TMR     4
-#define MAX_IPI     4
 #define MAX_MSI     8
-#define MAX_IRQ     (MAX_SRC + MAX_IPI + MAX_TMR)
 #define VID         0x03 /* MPIC version ID */
 
 /* OpenPIC capability flags */
@@ -78,7 +74,7 @@ static const int debug_openpic = 0;
 #define OPENPIC_SUMMARY_REG_START   0x3800
 #define OPENPIC_SUMMARY_REG_SIZE    0x800
 #define OPENPIC_SRC_REG_START        0x10000
-#define OPENPIC_SRC_REG_SIZE         (MAX_SRC * 0x20)
+#define OPENPIC_SRC_REG_SIZE         (OPENPIC_MAX_SRC * 0x20)
 #define OPENPIC_CPU_REG_START        0x20000
 #define OPENPIC_CPU_REG_SIZE         0x100 + ((MAX_CPU - 1) * 0x1000)
 
@@ -86,8 +82,8 @@ static const int debug_openpic = 0;
 #define RAVEN_MAX_CPU      2
 #define RAVEN_MAX_EXT     48
 #define RAVEN_MAX_IRQ     64
-#define RAVEN_MAX_TMR      MAX_TMR
-#define RAVEN_MAX_IPI      MAX_IPI
+#define RAVEN_MAX_TMR      OPENPIC_MAX_TMR
+#define RAVEN_MAX_IPI      OPENPIC_MAX_IPI
 
 /* Interrupt definitions */
 #define RAVEN_FE_IRQ     (RAVEN_MAX_EXT)     /* Internal functional IRQ */
@@ -209,7 +205,7 @@ typedef struct IRQQueue {
     /* Round up to the nearest 64 IRQs so that the queue length
      * won't change when moving between 32 and 64 bit hosts.
      */
-    unsigned long queue[BITS_TO_LONGS((MAX_IRQ + 63) & ~63)];
+    unsigned long queue[BITS_TO_LONGS((OPENPIC_MAX_IRQ + 63) & ~63)];
     int next;
     int priority;
 } IRQQueue;
@@ -255,8 +251,13 @@ typedef struct IRQDest {
     uint32_t outputs_active[OPENPIC_OUTPUT_NB];
 } IRQDest;
 
+#define OPENPIC(obj) OBJECT_CHECK(OpenPICState, (obj), TYPE_OPENPIC)
+
 typedef struct OpenPICState {
-    SysBusDevice busdev;
+    /*< private >*/
+    SysBusDevice parent_obj;
+    /*< public >*/
+
     MemoryRegion mem;
 
     /* Behavior control */
@@ -283,7 +284,7 @@ typedef struct OpenPICState {
     uint32_t spve; /* Spurious vector register */
     uint32_t tfrr; /* Timer frequency reporting register */
     /* Source registers */
-    IRQSource src[MAX_IRQ];
+    IRQSource src[OPENPIC_MAX_IRQ];
     /* Local registers per output pin */
     IRQDest dst[MAX_CPU];
     uint32_t nb_cpus;
@@ -291,7 +292,7 @@ typedef struct OpenPICState {
     struct {
         uint32_t tccr;  /* Global timer current count register */
         uint32_t tbcr;  /* Global timer base count register */
-    } timers[MAX_TMR];
+    } timers[OPENPIC_MAX_TMR];
     /* Shared MSI registers */
     struct {
         uint32_t msir;   /* Shared Message Signaled Interrupt Register */
@@ -503,7 +504,7 @@ static void openpic_set_irq(void *opaque, int n_IRQ, int level)
     OpenPICState *opp = opaque;
     IRQSource *src;
 
-    if (n_IRQ >= MAX_IRQ) {
+    if (n_IRQ >= OPENPIC_MAX_IRQ) {
         fprintf(stderr, "%s: IRQ %d out of range\n", __func__, n_IRQ);
         abort();
     }
@@ -537,7 +538,7 @@ static void openpic_set_irq(void *opaque, int n_IRQ, int level)
 
 static void openpic_reset(DeviceState *d)
 {
-    OpenPICState *opp = FROM_SYSBUS(typeof(*opp), SYS_BUS_DEVICE(d));
+    OpenPICState *opp = OPENPIC(d);
     int i;
 
     opp->gcr = GCR_RESET;
@@ -576,7 +577,7 @@ static void openpic_reset(DeviceState *d)
         opp->dst[i].servicing.next = -1;
     }
     /* Initialise timers */
-    for (i = 0; i < MAX_TMR; i++) {
+    for (i = 0; i < OPENPIC_MAX_TMR; i++) {
         opp->timers[i].tccr = 0;
         opp->timers[i].tbcr = TBCR_CI;
     }
@@ -703,7 +704,7 @@ static void openpic_gcr_write(OpenPICState *opp, uint64_t val)
     bool mpic_proxy = false;
 
     if (val & GCR_RESET) {
-        openpic_reset(&opp->busdev.qdev);
+        openpic_reset(DEVICE(opp));
         return;
     }
 
@@ -1182,7 +1183,7 @@ static uint32_t openpic_iack(OpenPICState *opp, IRQDest *dst, int cpu)
         IRQ_resetbit(&dst->raised, irq);
     }
 
-    if ((irq >= opp->irq_ipi0) &&  (irq < (opp->irq_ipi0 + MAX_IPI))) {
+    if ((irq >= opp->irq_ipi0) &&  (irq < (opp->irq_ipi0 + OPENPIC_MAX_IPI))) {
         src->destmask &= ~(1 << cpu);
         if (src->destmask && !src->level) {
             /* trigger on CPUs that didn't know about it yet */
@@ -1381,7 +1382,7 @@ static void openpic_save(QEMUFile* f, void *opaque)
                         sizeof(opp->dst[i].outputs_active));
     }
 
-    for (i = 0; i < MAX_TMR; i++) {
+    for (i = 0; i < OPENPIC_MAX_TMR; i++) {
         qemu_put_be32s(f, &opp->timers[i].tccr);
         qemu_put_be32s(f, &opp->timers[i].tbcr);
     }
@@ -1440,7 +1441,7 @@ static int openpic_load(QEMUFile* f, void *opaque, int version_id)
                         sizeof(opp->dst[i].outputs_active));
     }
 
-    for (i = 0; i < MAX_TMR; i++) {
+    for (i = 0; i < OPENPIC_MAX_TMR; i++) {
         qemu_get_be32s(f, &opp->timers[i].tccr);
         qemu_get_be32s(f, &opp->timers[i].tbcr);
     }
@@ -1473,7 +1474,7 @@ typedef struct MemReg {
 static void fsl_common_init(OpenPICState *opp)
 {
     int i;
-    int virq = MAX_SRC;
+    int virq = OPENPIC_MAX_SRC;
 
     opp->vid = VID_REVISION_1_2;
     opp->vir = VIR_GENERIC;
@@ -1481,14 +1482,14 @@ static void fsl_common_init(OpenPICState *opp)
     opp->tfrr_reset = 0;
     opp->ivpr_reset = IVPR_MASK_MASK;
     opp->idr_reset = 1 << 0;
-    opp->max_irq = MAX_IRQ;
+    opp->max_irq = OPENPIC_MAX_IRQ;
 
     opp->irq_ipi0 = virq;
-    virq += MAX_IPI;
+    virq += OPENPIC_MAX_IPI;
     opp->irq_tim0 = virq;
-    virq += MAX_TMR;
+    virq += OPENPIC_MAX_TMR;
 
-    assert(virq <= MAX_IRQ);
+    assert(virq <= OPENPIC_MAX_IRQ);
 
     opp->irq_msi = 224;
 
@@ -1498,13 +1499,13 @@ static void fsl_common_init(OpenPICState *opp)
     }
 
     /* Internal interrupts, including message and MSI */
-    for (i = 16; i < MAX_SRC; i++) {
+    for (i = 16; i < OPENPIC_MAX_SRC; i++) {
         opp->src[i].type = IRQ_TYPE_FSLINT;
         opp->src[i].level = true;
     }
 
     /* timers and IPIs */
-    for (i = MAX_SRC; i < virq; i++) {
+    for (i = OPENPIC_MAX_SRC; i < virq; i++) {
         opp->src[i].type = IRQ_TYPE_FSLSPECIAL;
         opp->src[i].level = false;
     }
@@ -1526,9 +1527,17 @@ static void map_list(OpenPICState *opp, const MemReg *list, int *count)
     }
 }
 
-static int openpic_init(SysBusDevice *dev)
+static void openpic_init(Object *obj)
 {
-    OpenPICState *opp = FROM_SYSBUS(typeof (*opp), dev);
+    OpenPICState *opp = OPENPIC(obj);
+
+    memory_region_init(&opp->mem, "openpic", 0x40000);
+}
+
+static void openpic_realize(DeviceState *dev, Error **errp)
+{
+    SysBusDevice *d = SYS_BUS_DEVICE(dev);
+    OpenPICState *opp = OPENPIC(dev);
     int i, j;
     int list_count = 0;
     static const MemReg list_le[] = {
@@ -1561,8 +1570,6 @@ static int openpic_init(SysBusDevice *dev)
         {NULL}
     };
 
-    memory_region_init(&opp->mem, "openpic", 0x40000);
-
     switch (opp->model) {
     case OPENPIC_MODEL_FSL_MPIC_20:
     default:
@@ -1605,9 +1612,9 @@ static int openpic_init(SysBusDevice *dev)
         opp->brr1 = -1;
         opp->mpic_mode_mask = GCR_MODE_MIXED;
 
-        /* Only UP supported today */
         if (opp->nb_cpus != 1) {
-            return -EINVAL;
+            error_setg(errp, "Only UP supported today");
+            return;
         }
 
         map_list(opp, list_le, &list_count);
@@ -1617,17 +1624,15 @@ static int openpic_init(SysBusDevice *dev)
     for (i = 0; i < opp->nb_cpus; i++) {
         opp->dst[i].irqs = g_new(qemu_irq, OPENPIC_OUTPUT_NB);
         for (j = 0; j < OPENPIC_OUTPUT_NB; j++) {
-            sysbus_init_irq(dev, &opp->dst[i].irqs[j]);
+            sysbus_init_irq(d, &opp->dst[i].irqs[j]);
         }
     }
 
-    register_savevm(&opp->busdev.qdev, "openpic", 0, 2,
+    register_savevm(dev, "openpic", 0, 2,
                     openpic_save, openpic_load, opp);
 
-    sysbus_init_mmio(dev, &opp->mem);
-    qdev_init_gpio_in(&dev->qdev, openpic_set_irq, opp->max_irq);
-
-    return 0;
+    sysbus_init_mmio(d, &opp->mem);
+    qdev_init_gpio_in(dev, openpic_set_irq, opp->max_irq);
 }
 
 static Property openpic_properties[] = {
@@ -1636,20 +1641,20 @@ static Property openpic_properties[] = {
     DEFINE_PROP_END_OF_LIST(),
 };
 
-static void openpic_class_init(ObjectClass *klass, void *data)
+static void openpic_class_init(ObjectClass *oc, void *data)
 {
-    DeviceClass *dc = DEVICE_CLASS(klass);
-    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+    DeviceClass *dc = DEVICE_CLASS(oc);
 
-    k->init = openpic_init;
+    dc->realize = openpic_realize;
     dc->props = openpic_properties;
     dc->reset = openpic_reset;
 }
 
 static const TypeInfo openpic_info = {
-    .name          = "openpic",
+    .name          = TYPE_OPENPIC,
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(OpenPICState),
+    .instance_init = openpic_init,
     .class_init    = openpic_class_init,
 };
 
diff --git a/hw/intc/openpic_kvm.c b/hw/intc/openpic_kvm.c
new file mode 100644
index 0000000000..6775879e0f
--- /dev/null
+++ b/hw/intc/openpic_kvm.c
@@ -0,0 +1,264 @@
+/*
+ * KVM in-kernel OpenPIC
+ *
+ * Copyright 2013 Freescale Semiconductor, Inc.
+ *
+ * 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 <sys/ioctl.h>
+#include "exec/address-spaces.h"
+#include "hw/hw.h"
+#include "hw/ppc/openpic.h"
+#include "hw/pci/msi.h"
+#include "hw/sysbus.h"
+#include "sysemu/kvm.h"
+#include "qemu/log.h"
+
+#define KVM_OPENPIC(obj) \
+    OBJECT_CHECK(KVMOpenPICState, (obj), TYPE_KVM_OPENPIC)
+
+typedef struct KVMOpenPICState {
+    /*< private >*/
+    SysBusDevice parent_obj;
+    /*< public >*/
+
+    MemoryRegion mem;
+    MemoryListener mem_listener;
+    uint32_t fd;
+    uint32_t model;
+} KVMOpenPICState;
+
+static void kvm_openpic_set_irq(void *opaque, int n_IRQ, int level)
+{
+    kvm_set_irq(kvm_state, n_IRQ, level);
+}
+
+static void kvm_openpic_reset(DeviceState *d)
+{
+    qemu_log_mask(LOG_UNIMP, "%s: unimplemented\n", __func__);
+}
+
+static void kvm_openpic_write(void *opaque, hwaddr addr, uint64_t val,
+                              unsigned size)
+{
+    KVMOpenPICState *opp = opaque;
+    struct kvm_device_attr attr;
+    uint32_t val32 = val;
+    int ret;
+
+    attr.group = KVM_DEV_MPIC_GRP_REGISTER;
+    attr.attr = addr;
+    attr.addr = (uint64_t)(unsigned long)&val32;
+
+    ret = ioctl(opp->fd, KVM_SET_DEVICE_ATTR, &attr);
+    if (ret < 0) {
+        qemu_log_mask(LOG_UNIMP, "%s: %s %" PRIx64 "\n", __func__,
+                      strerror(errno), attr.attr);
+    }
+}
+
+static uint64_t kvm_openpic_read(void *opaque, hwaddr addr, unsigned size)
+{
+    KVMOpenPICState *opp = opaque;
+    struct kvm_device_attr attr;
+    uint32_t val = 0xdeadbeef;
+    int ret;
+
+    attr.group = KVM_DEV_MPIC_GRP_REGISTER;
+    attr.attr = addr;
+    attr.addr = (uint64_t)(unsigned long)&val;
+
+    ret = ioctl(opp->fd, KVM_GET_DEVICE_ATTR, &attr);
+    if (ret < 0) {
+        qemu_log_mask(LOG_UNIMP, "%s: %s %" PRIx64 "\n", __func__,
+                      strerror(errno), attr.attr);
+        return 0;
+    }
+
+    return val;
+}
+
+static const MemoryRegionOps kvm_openpic_mem_ops = {
+    .write = kvm_openpic_write,
+    .read  = kvm_openpic_read,
+    .endianness = DEVICE_BIG_ENDIAN,
+    .impl = {
+        .min_access_size = 4,
+        .max_access_size = 4,
+    },
+};
+
+static void kvm_openpic_region_add(MemoryListener *listener,
+                                   MemoryRegionSection *section)
+{
+    KVMOpenPICState *opp = container_of(listener, KVMOpenPICState,
+                                        mem_listener);
+    struct kvm_device_attr attr;
+    uint64_t reg_base;
+    int ret;
+
+    if (section->address_space != &address_space_memory) {
+        abort();
+    }
+
+    reg_base = section->offset_within_address_space;
+
+    attr.group = KVM_DEV_MPIC_GRP_MISC;
+    attr.attr = KVM_DEV_MPIC_BASE_ADDR;
+    attr.addr = (uint64_t)(unsigned long)&reg_base;
+
+    ret = ioctl(opp->fd, KVM_SET_DEVICE_ATTR, &attr);
+    if (ret < 0) {
+        fprintf(stderr, "%s: %s %" PRIx64 "\n", __func__,
+                strerror(errno), reg_base);
+    }
+}
+
+static void kvm_openpic_region_del(MemoryListener *listener,
+                                   MemoryRegionSection *section)
+{
+    KVMOpenPICState *opp = container_of(listener, KVMOpenPICState,
+                                        mem_listener);
+    struct kvm_device_attr attr;
+    uint64_t reg_base = 0;
+    int ret;
+
+    attr.group = KVM_DEV_MPIC_GRP_MISC;
+    attr.attr = KVM_DEV_MPIC_BASE_ADDR;
+    attr.addr = (uint64_t)(unsigned long)&reg_base;
+
+    ret = ioctl(opp->fd, KVM_SET_DEVICE_ATTR, &attr);
+    if (ret < 0) {
+        fprintf(stderr, "%s: %s %" PRIx64 "\n", __func__,
+                strerror(errno), reg_base);
+    }
+}
+
+static void kvm_openpic_init(Object *obj)
+{
+    KVMOpenPICState *opp = KVM_OPENPIC(obj);
+
+    memory_region_init_io(&opp->mem, &kvm_openpic_mem_ops, opp,
+                          "kvm-openpic", 0x40000);
+}
+
+static void kvm_openpic_realize(DeviceState *dev, Error **errp)
+{
+    SysBusDevice *d = SYS_BUS_DEVICE(dev);
+    KVMOpenPICState *opp = KVM_OPENPIC(dev);
+    KVMState *s = kvm_state;
+    int kvm_openpic_model;
+    struct kvm_create_device cd = {0};
+    int ret, i;
+
+    if (!kvm_check_extension(s, KVM_CAP_DEVICE_CTRL)) {
+        error_setg(errp, "Kernel is lacking Device Control API");
+        return;
+    }
+
+    switch (opp->model) {
+    case OPENPIC_MODEL_FSL_MPIC_20:
+        kvm_openpic_model = KVM_DEV_TYPE_FSL_MPIC_20;
+        break;
+
+    case OPENPIC_MODEL_FSL_MPIC_42:
+        kvm_openpic_model = KVM_DEV_TYPE_FSL_MPIC_42;
+        break;
+
+    default:
+        error_setg(errp, "Unsupported OpenPIC model %" PRIu32, opp->model);
+        return;
+    }
+
+    cd.type = kvm_openpic_model;
+    ret = kvm_vm_ioctl(s, KVM_CREATE_DEVICE, &cd);
+    if (ret < 0) {
+        error_setg(errp, "Can't create device %d: %s",
+                   cd.type, strerror(errno));
+        return;
+    }
+    opp->fd = cd.fd;
+
+    sysbus_init_mmio(d, &opp->mem);
+    qdev_init_gpio_in(dev, kvm_openpic_set_irq, OPENPIC_MAX_IRQ);
+
+    opp->mem_listener.region_add = kvm_openpic_region_add;
+    opp->mem_listener.region_add = kvm_openpic_region_del;
+    memory_listener_register(&opp->mem_listener, &address_space_memory);
+
+    /* indicate pic capabilities */
+    msi_supported = true;
+    kvm_kernel_irqchip = true;
+    kvm_async_interrupts_allowed = true;
+
+    /* set up irq routing */
+    kvm_init_irq_routing(kvm_state);
+    for (i = 0; i < 256; ++i) {
+        kvm_irqchip_add_irq_route(kvm_state, i, 0, i);
+    }
+
+    kvm_irqfds_allowed = true;
+    kvm_msi_via_irqfd_allowed = true;
+    kvm_gsi_routing_allowed = true;
+
+    kvm_irqchip_commit_routes(s);
+}
+
+int kvm_openpic_connect_vcpu(DeviceState *d, CPUState *cs)
+{
+    KVMOpenPICState *opp = KVM_OPENPIC(d);
+    struct kvm_enable_cap encap = {};
+
+    encap.cap = KVM_CAP_IRQ_MPIC;
+    encap.args[0] = opp->fd;
+    encap.args[1] = cs->cpu_index;
+
+    return kvm_vcpu_ioctl(cs, KVM_ENABLE_CAP, &encap);
+}
+
+static Property kvm_openpic_properties[] = {
+    DEFINE_PROP_UINT32("model", KVMOpenPICState, model,
+                       OPENPIC_MODEL_FSL_MPIC_20),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void kvm_openpic_class_init(ObjectClass *oc, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(oc);
+
+    dc->realize = kvm_openpic_realize;
+    dc->props = kvm_openpic_properties;
+    dc->reset = kvm_openpic_reset;
+}
+
+static const TypeInfo kvm_openpic_info = {
+    .name          = TYPE_KVM_OPENPIC,
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(KVMOpenPICState),
+    .instance_init = kvm_openpic_init,
+    .class_init    = kvm_openpic_class_init,
+};
+
+static void kvm_openpic_register_types(void)
+{
+    type_register_static(&kvm_openpic_info);
+}
+
+type_init(kvm_openpic_register_types)
diff --git a/hw/misc/macio/macio.c b/hw/misc/macio/macio.c
index 2f389dd7cc..fd4c8e5f99 100644
--- a/hw/misc/macio/macio.c
+++ b/hw/misc/macio/macio.c
@@ -69,12 +69,59 @@ typedef struct NewWorldMacIOState {
     MACIOIDEState ide[2];
 } NewWorldMacIOState;
 
+/*
+ * The mac-io has two interfaces to the ESCC. One is called "escc-legacy",
+ * while the other one is the normal, current ESCC interface.
+ *
+ * The magic below creates memory aliases to spawn the escc-legacy device
+ * purely by rerouting the respective registers to our escc region. This
+ * works because the only difference between the two memory regions is the
+ * register layout, not their semantics.
+ *
+ * Reference: ftp://ftp.software.ibm.com/rs6000/technology/spec/chrp/inwork/CHRP_IORef_1.0.pdf
+ */
+static void macio_escc_legacy_setup(MacIOState *macio_state)
+{
+    MemoryRegion *escc_legacy = g_new(MemoryRegion, 1);
+    MemoryRegion *bar = &macio_state->bar;
+    int i;
+    static const int maps[] = {
+        0x00, 0x00,
+        0x02, 0x20,
+        0x04, 0x10,
+        0x06, 0x30,
+        0x08, 0x40,
+        0x0A, 0x50,
+        0x60, 0x60,
+        0x70, 0x70,
+        0x80, 0x70,
+        0x90, 0x80,
+        0xA0, 0x90,
+        0xB0, 0xA0,
+        0xC0, 0xB0,
+        0xD0, 0xC0,
+        0xE0, 0xD0,
+        0xF0, 0xE0,
+    };
+
+    memory_region_init(escc_legacy, "escc-legacy", 256);
+    for (i = 0; i < ARRAY_SIZE(maps); i += 2) {
+        MemoryRegion *port = g_new(MemoryRegion, 1);
+        memory_region_init_alias(port, "escc-legacy-port", macio_state->escc_mem,
+                                 maps[i+1], 0x2);
+        memory_region_add_subregion(escc_legacy, maps[i], port);
+    }
+
+    memory_region_add_subregion(bar, 0x12000, escc_legacy);
+}
+
 static void macio_bar_setup(MacIOState *macio_state)
 {
     MemoryRegion *bar = &macio_state->bar;
 
     if (macio_state->escc_mem) {
         memory_region_add_subregion(bar, 0x13000, macio_state->escc_mem);
+        macio_escc_legacy_setup(macio_state);
     }
 }
 
diff --git a/hw/nvram/spapr_nvram.c b/hw/nvram/spapr_nvram.c
index 1eb05c9075..eb4500e26f 100644
--- a/hw/nvram/spapr_nvram.c
+++ b/hw/nvram/spapr_nvram.c
@@ -44,7 +44,7 @@ typedef struct sPAPRNVRAM {
 #define DEFAULT_NVRAM_SIZE 65536
 #define MAX_NVRAM_SIZE (UINT16_MAX * 16)
 
-static void rtas_nvram_fetch(sPAPREnvironment *spapr,
+static void rtas_nvram_fetch(PowerPCCPU *cpu, sPAPREnvironment *spapr,
                              uint32_t token, uint32_t nargs,
                              target_ulong args,
                              uint32_t nret, target_ulong rets)
@@ -91,7 +91,7 @@ static void rtas_nvram_fetch(sPAPREnvironment *spapr,
     rtas_st(rets, 1, (alen < 0) ? 0 : alen);
 }
 
-static void rtas_nvram_store(sPAPREnvironment *spapr,
+static void rtas_nvram_store(PowerPCCPU *cpu, sPAPREnvironment *spapr,
                              uint32_t token, uint32_t nargs,
                              target_ulong args,
                              uint32_t nret, target_ulong rets)
diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c
index c9ae51211e..38f799031a 100644
--- a/hw/ppc/e500.c
+++ b/hw/ppc/e500.c
@@ -472,6 +472,107 @@ static void ppce500_cpu_reset(void *opaque)
     mmubooke_create_initial_mapping(env);
 }
 
+static DeviceState *ppce500_init_mpic_qemu(PPCE500Params *params,
+                                           qemu_irq **irqs)
+{
+    DeviceState *dev;
+    SysBusDevice *s;
+    int i, j, k;
+
+    dev = qdev_create(NULL, TYPE_OPENPIC);
+    qdev_prop_set_uint32(dev, "model", params->mpic_version);
+    qdev_prop_set_uint32(dev, "nb_cpus", smp_cpus);
+
+    qdev_init_nofail(dev);
+    s = SYS_BUS_DEVICE(dev);
+
+    k = 0;
+    for (i = 0; i < smp_cpus; i++) {
+        for (j = 0; j < OPENPIC_OUTPUT_NB; j++) {
+            sysbus_connect_irq(s, k++, irqs[i][j]);
+        }
+    }
+
+    return dev;
+}
+
+static DeviceState *ppce500_init_mpic_kvm(PPCE500Params *params,
+                                          qemu_irq **irqs)
+{
+    DeviceState *dev;
+    CPUPPCState *env;
+    CPUState *cs;
+    int r;
+
+    dev = qdev_create(NULL, TYPE_KVM_OPENPIC);
+    qdev_prop_set_uint32(dev, "model", params->mpic_version);
+
+    r = qdev_init(dev);
+    if (r) {
+        return NULL;
+    }
+
+    for (env = first_cpu; env != NULL; env = env->next_cpu) {
+        cs = ENV_GET_CPU(env);
+
+        if (kvm_openpic_connect_vcpu(dev, cs)) {
+            fprintf(stderr, "%s: failed to connect vcpu to irqchip\n",
+                    __func__);
+            abort();
+        }
+    }
+
+    return dev;
+}
+
+static qemu_irq *ppce500_init_mpic(PPCE500Params *params, MemoryRegion *ccsr,
+                                   qemu_irq **irqs)
+{
+    QemuOptsList *list;
+    qemu_irq *mpic;
+    DeviceState *dev = NULL;
+    SysBusDevice *s;
+    int i;
+
+    mpic = g_new(qemu_irq, 256);
+
+    if (kvm_enabled()) {
+        bool irqchip_allowed = true, irqchip_required = false;
+
+        list = qemu_find_opts("machine");
+        if (!QTAILQ_EMPTY(&list->head)) {
+            irqchip_allowed = qemu_opt_get_bool(QTAILQ_FIRST(&list->head),
+                                                "kernel_irqchip", true);
+            irqchip_required = qemu_opt_get_bool(QTAILQ_FIRST(&list->head),
+                                                 "kernel_irqchip", false);
+        }
+
+        if (irqchip_allowed) {
+            dev = ppce500_init_mpic_kvm(params, irqs);
+        }
+
+        if (irqchip_required && !dev) {
+            fprintf(stderr, "%s: irqchip requested but unavailable\n",
+                    __func__);
+            abort();
+        }
+    }
+
+    if (!dev) {
+        dev = ppce500_init_mpic_qemu(params, irqs);
+    }
+
+    for (i = 0; i < 256; i++) {
+        mpic[i] = qdev_get_gpio_in(dev, i);
+    }
+
+    s = SYS_BUS_DEVICE(dev);
+    memory_region_add_subregion(ccsr, MPC8544_MPIC_REGS_OFFSET,
+                                s->mmio[0].memory);
+
+    return mpic;
+}
+
 void ppce500_init(PPCE500Params *params)
 {
     MemoryRegion *address_space_mem = get_system_memory();
@@ -487,7 +588,7 @@ void ppce500_init(PPCE500Params *params)
     target_ulong initrd_base = 0;
     target_long initrd_size = 0;
     target_ulong cur_base = 0;
-    int i = 0, j, k;
+    int i;
     unsigned int pci_irq_nrs[4] = {1, 2, 3, 4};
     qemu_irq **irqs, *mpic;
     DeviceState *dev;
@@ -563,27 +664,7 @@ void ppce500_init(PPCE500Params *params)
     memory_region_add_subregion(address_space_mem, MPC8544_CCSRBAR_BASE,
                                 ccsr_addr_space);
 
-    /* MPIC */
-    mpic = g_new(qemu_irq, 256);
-    dev = qdev_create(NULL, "openpic");
-    qdev_prop_set_uint32(dev, "nb_cpus", smp_cpus);
-    qdev_prop_set_uint32(dev, "model", params->mpic_version);
-    qdev_init_nofail(dev);
-    s = SYS_BUS_DEVICE(dev);
-
-    k = 0;
-    for (i = 0; i < smp_cpus; i++) {
-        for (j = 0; j < OPENPIC_OUTPUT_NB; j++) {
-            sysbus_connect_irq(s, k++, irqs[i][j]);
-        }
-    }
-
-    for (i = 0; i < 256; i++) {
-        mpic[i] = qdev_get_gpio_in(dev, i);
-    }
-
-    memory_region_add_subregion(ccsr_addr_space, MPC8544_MPIC_REGS_OFFSET,
-                                s->mmio[0].memory);
+    mpic = ppce500_init_mpic(params, ccsr_addr_space, irqs);
 
     /* Serial */
     if (serial_hds[0]) {
diff --git a/hw/ppc/mac_newworld.c b/hw/ppc/mac_newworld.c
index ce44e95d53..3badfa3adb 100644
--- a/hw/ppc/mac_newworld.c
+++ b/hw/ppc/mac_newworld.c
@@ -87,6 +87,9 @@ static void unin_write(void *opaque, hwaddr addr, uint64_t value,
                        unsigned size)
 {
     UNIN_DPRINTF("write addr " TARGET_FMT_plx " val %"PRIx64"\n", addr, value);
+    if (addr == 0x0) {
+        *(int*)opaque = value;
+    }
 }
 
 static uint64_t unin_read(void *opaque, hwaddr addr, unsigned size)
@@ -94,6 +97,11 @@ static uint64_t unin_read(void *opaque, hwaddr addr, unsigned size)
     uint32_t value;
 
     value = 0;
+    switch (addr) {
+    case 0:
+        value = *(int*)opaque;
+    }
+
     UNIN_DPRINTF("readl addr " TARGET_FMT_plx " val %x\n", addr, value);
 
     return value;
@@ -144,6 +152,7 @@ static void ppc_core99_init(QEMUMachineInitArgs *args)
     char *filename;
     qemu_irq *pic, **openpic_irqs;
     MemoryRegion *unin_memory = g_new(MemoryRegion, 1);
+    MemoryRegion *unin2_memory = g_new(MemoryRegion, 1);
     int linux_boot, i, j, k;
     MemoryRegion *ram = g_new(MemoryRegion, 1), *bios = g_new(MemoryRegion, 1);
     hwaddr kernel_base, initrd_base, cmdline_base = 0;
@@ -162,6 +171,7 @@ static void ppc_core99_init(QEMUMachineInitArgs *args)
     int machine_arch;
     SysBusDevice *s;
     DeviceState *dev;
+    int *token = g_new(int, 1);
 
     linux_boot = (kernel_filename != NULL);
 
@@ -279,10 +289,13 @@ static void ppc_core99_init(QEMUMachineInitArgs *args)
     /* Register 8 MB of ISA IO space */
     isa_mmio_init(0xf2000000, 0x00800000);
 
-    /* UniN init */
-    memory_region_init_io(unin_memory, &unin_ops, NULL, "unin", 0x1000);
+    /* UniN init: XXX should be a real device */
+    memory_region_init_io(unin_memory, &unin_ops, token, "unin", 0x1000);
     memory_region_add_subregion(get_system_memory(), 0xf8000000, unin_memory);
 
+    memory_region_init_io(unin2_memory, &unin_ops, token, "unin", 0x1000);
+    memory_region_add_subregion(get_system_memory(), 0xf3000000, unin2_memory);
+
     openpic_irqs = g_malloc0(smp_cpus * sizeof(qemu_irq *));
     openpic_irqs[0] =
         g_malloc0(smp_cpus * sizeof(qemu_irq) * OPENPIC_OUTPUT_NB);
@@ -329,7 +342,7 @@ static void ppc_core99_init(QEMUMachineInitArgs *args)
 
     pic = g_new(qemu_irq, 64);
 
-    dev = qdev_create(NULL, "openpic");
+    dev = qdev_create(NULL, TYPE_OPENPIC);
     qdev_prop_set_uint32(dev, "model", OPENPIC_MODEL_RAVEN);
     qdev_init_nofail(dev);
     s = SYS_BUS_DEVICE(dev);
@@ -449,6 +462,8 @@ static void ppc_core99_init(QEMUMachineInitArgs *args)
     } else {
         fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_TBFREQ, get_ticks_per_sec());
     }
+    /* Mac OS X requires a "known good" clock-frequency value; pass it one. */
+    fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_CLOCKFREQ, 266000000);
 
     qemu_register_boot_set(fw_cfg_boot_set, fw_cfg);
 }
@@ -458,9 +473,6 @@ static QEMUMachine core99_machine = {
     .desc = "Mac99 based PowerMAC",
     .init = ppc_core99_init,
     .max_cpus = MAX_CPUS,
-#ifdef TARGET_PPC64
-    .is_default = 1,
-#endif
     DEFAULT_MACHINE_OPTIONS,
 };
 
diff --git a/hw/ppc/mac_oldworld.c b/hw/ppc/mac_oldworld.c
index 3acca94432..8faff300ff 100644
--- a/hw/ppc/mac_oldworld.c
+++ b/hw/ppc/mac_oldworld.c
@@ -333,6 +333,8 @@ static void ppc_heathrow_init(QEMUMachineInitArgs *args)
     } else {
         fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_TBFREQ, get_ticks_per_sec());
     }
+    /* Mac OS X requires a "known good" clock-frequency value; pass it one. */
+    fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_CLOCKFREQ, 266000000);
 
     qemu_register_boot_set(fw_cfg_boot_set, fw_cfg);
 }
diff --git a/hw/ppc/mpc8544_guts.c b/hw/ppc/mpc8544_guts.c
index 193beab2c2..d41f615522 100644
--- a/hw/ppc/mpc8544_guts.c
+++ b/hw/ppc/mpc8544_guts.c
@@ -51,8 +51,14 @@
 #define MPC8544_GUTS_ADDR_SRDS2CR1    0xF10
 #define MPC8544_GUTS_ADDR_SRDS2CR3    0xF18
 
+#define TYPE_MPC8544_GUTS "mpc8544-guts"
+#define MPC8544_GUTS(obj) OBJECT_CHECK(GutsState, (obj), TYPE_MPC8544_GUTS)
+
 struct GutsState {
-    SysBusDevice busdev;
+    /*< private >*/
+    SysBusDevice parent_obj;
+    /*< public >*/
+
     MemoryRegion iomem;
 };
 
@@ -108,31 +114,21 @@ static const MemoryRegionOps mpc8544_guts_ops = {
     },
 };
 
-static int mpc8544_guts_initfn(SysBusDevice *dev)
+static void mpc8544_guts_initfn(Object *obj)
 {
-    GutsState *s;
-
-    s = FROM_SYSBUS(GutsState, SYS_BUS_DEVICE(dev));
+    SysBusDevice *d = SYS_BUS_DEVICE(obj);
+    GutsState *s = MPC8544_GUTS(obj);
 
     memory_region_init_io(&s->iomem, &mpc8544_guts_ops, s,
-                          "mpc6544.guts", MPC8544_GUTS_MMIO_SIZE);
-    sysbus_init_mmio(dev, &s->iomem);
-
-    return 0;
-}
-
-static void mpc8544_guts_class_init(ObjectClass *klass, void *data)
-{
-    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
-
-    k->init = mpc8544_guts_initfn;
+                          "mpc8544.guts", MPC8544_GUTS_MMIO_SIZE);
+    sysbus_init_mmio(d, &s->iomem);
 }
 
 static const TypeInfo mpc8544_guts_info = {
-    .name          = "mpc8544-guts",
+    .name          = TYPE_MPC8544_GUTS,
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(GutsState),
-    .class_init    = mpc8544_guts_class_init,
+    .instance_init = mpc8544_guts_initfn,
 };
 
 static void mpc8544_guts_register_types(void)
diff --git a/hw/ppc/ppc_booke.c b/hw/ppc/ppc_booke.c
index e41b036b8e..000c27f2e8 100644
--- a/hw/ppc/ppc_booke.c
+++ b/hw/ppc/ppc_booke.c
@@ -131,17 +131,33 @@ static void booke_update_fixed_timer(CPUPPCState         *env,
                                      struct QEMUTimer *timer)
 {
     ppc_tb_t *tb_env = env->tb_env;
-    uint64_t lapse;
+    uint64_t delta_tick, ticks = 0;
     uint64_t tb;
-    uint64_t period = 1 << (target_bit + 1);
+    uint64_t period;
     uint64_t now;
 
     now = qemu_get_clock_ns(vm_clock);
     tb  = cpu_ppc_get_tb(tb_env, now, tb_env->tb_offset);
+    period = 1ULL << target_bit;
+    delta_tick = period - (tb & (period - 1));
 
-    lapse = period - ((tb - (1 << target_bit)) & (period - 1));
+    /* the timer triggers only when the selected bit toggles from 0 to 1 */
+    if (tb & period) {
+        ticks = period;
+    }
 
-    *next = now + muldiv64(lapse, get_ticks_per_sec(), tb_env->tb_freq);
+    if (ticks + delta_tick < ticks) {
+        /* Overflow, so assume the biggest number we can express. */
+        ticks = UINT64_MAX;
+    } else {
+        ticks += delta_tick;
+    }
+
+    *next = now + muldiv64(ticks, get_ticks_per_sec(), tb_env->tb_freq);
+    if ((*next < now) || (*next > INT64_MAX)) {
+        /* Overflow, so assume the biggest number the qemu timer supports. */
+        *next = INT64_MAX;
+    }
 
     /* XXX: If expire time is now. We can't run the callback because we don't
      * have access to it. So we just set the timer one nanosecond later.
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index 218ea23da8..fe34291ffd 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -670,7 +670,7 @@ static void spapr_cpu_reset(void *opaque)
     env->external_htab = spapr->htab;
     env->htab_base = -1;
     env->htab_mask = HTAB_SIZE(spapr) - 1;
-    env->spr[SPR_SDR1] = (unsigned long)spapr->htab |
+    env->spr[SPR_SDR1] = (target_ulong)(uintptr_t)spapr->htab |
         (spapr->htab_shift - 18);
 }
 
@@ -971,6 +971,7 @@ static void ppc_spapr_init(QEMUMachineInitArgs *args)
 static QEMUMachine spapr_machine = {
     .name = "pseries",
     .desc = "pSeries Logical Partition (PAPR compliant)",
+    .is_default = 1,
     .init = ppc_spapr_init,
     .reset = ppc_spapr_reset,
     .block_default_type = IF_SCSI,
diff --git a/hw/ppc/spapr_events.c b/hw/ppc/spapr_events.c
index c0d7e62f32..a69390e54e 100644
--- a/hw/ppc/spapr_events.c
+++ b/hw/ppc/spapr_events.c
@@ -277,7 +277,7 @@ static void spapr_powerdown_req(Notifier *n, void *opaque)
     qemu_irq_pulse(xics_get_qirq(spapr->icp, spapr->epow_irq));
 }
 
-static void check_exception(sPAPREnvironment *spapr,
+static void check_exception(PowerPCCPU *cpu, sPAPREnvironment *spapr,
                             uint32_t token, uint32_t nargs,
                             target_ulong args,
                             uint32_t nret, target_ulong rets)
diff --git a/hw/ppc/spapr_hcall.c b/hw/ppc/spapr_hcall.c
index 8f0b7e8076..e6f321d538 100644
--- a/hw/ppc/spapr_hcall.c
+++ b/hw/ppc/spapr_hcall.c
@@ -525,7 +525,7 @@ static target_ulong h_rtas(PowerPCCPU *cpu, sPAPREnvironment *spapr,
     uint32_t nargs = ldl_be_phys(rtas_r3 + 4);
     uint32_t nret = ldl_be_phys(rtas_r3 + 8);
 
-    return spapr_rtas_call(spapr, token, nargs, rtas_r3 + 12,
+    return spapr_rtas_call(cpu, spapr, token, nargs, rtas_r3 + 12,
                            nret, rtas_r3 + 12 + 4*nargs);
 }
 
diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c
index 04e836257c..c8c12c8241 100644
--- a/hw/ppc/spapr_pci.c
+++ b/hw/ppc/spapr_pci.c
@@ -119,7 +119,7 @@ static void finish_read_pci_config(sPAPREnvironment *spapr, uint64_t buid,
     rtas_st(rets, 1, val);
 }
 
-static void rtas_ibm_read_pci_config(sPAPREnvironment *spapr,
+static void rtas_ibm_read_pci_config(PowerPCCPU *cpu, sPAPREnvironment *spapr,
                                      uint32_t token, uint32_t nargs,
                                      target_ulong args,
                                      uint32_t nret, target_ulong rets)
@@ -139,7 +139,7 @@ static void rtas_ibm_read_pci_config(sPAPREnvironment *spapr,
     finish_read_pci_config(spapr, buid, addr, size, rets);
 }
 
-static void rtas_read_pci_config(sPAPREnvironment *spapr,
+static void rtas_read_pci_config(PowerPCCPU *cpu, sPAPREnvironment *spapr,
                                  uint32_t token, uint32_t nargs,
                                  target_ulong args,
                                  uint32_t nret, target_ulong rets)
@@ -185,7 +185,7 @@ static void finish_write_pci_config(sPAPREnvironment *spapr, uint64_t buid,
     rtas_st(rets, 0, 0);
 }
 
-static void rtas_ibm_write_pci_config(sPAPREnvironment *spapr,
+static void rtas_ibm_write_pci_config(PowerPCCPU *cpu, sPAPREnvironment *spapr,
                                       uint32_t token, uint32_t nargs,
                                       target_ulong args,
                                       uint32_t nret, target_ulong rets)
@@ -206,7 +206,7 @@ static void rtas_ibm_write_pci_config(sPAPREnvironment *spapr,
     finish_write_pci_config(spapr, buid, addr, size, val, rets);
 }
 
-static void rtas_write_pci_config(sPAPREnvironment *spapr,
+static void rtas_write_pci_config(PowerPCCPU *cpu, sPAPREnvironment *spapr,
                                   uint32_t token, uint32_t nargs,
                                   target_ulong args,
                                   uint32_t nret, target_ulong rets)
@@ -277,7 +277,7 @@ static void spapr_msi_setmsg(PCIDevice *pdev, hwaddr addr,
     }
 }
 
-static void rtas_ibm_change_msi(sPAPREnvironment *spapr,
+static void rtas_ibm_change_msi(PowerPCCPU *cpu, sPAPREnvironment *spapr,
                                 uint32_t token, uint32_t nargs,
                                 target_ulong args, uint32_t nret,
                                 target_ulong rets)
@@ -374,7 +374,8 @@ static void rtas_ibm_change_msi(sPAPREnvironment *spapr,
     trace_spapr_pci_rtas_ibm_change_msi(func, req_num);
 }
 
-static void rtas_ibm_query_interrupt_source_number(sPAPREnvironment *spapr,
+static void rtas_ibm_query_interrupt_source_number(PowerPCCPU *cpu,
+                                                   sPAPREnvironment *spapr,
                                                    uint32_t token,
                                                    uint32_t nargs,
                                                    target_ulong args,
diff --git a/hw/ppc/spapr_rtas.c b/hw/ppc/spapr_rtas.c
index 42ed7dc093..394ce05ba2 100644
--- a/hw/ppc/spapr_rtas.c
+++ b/hw/ppc/spapr_rtas.c
@@ -38,7 +38,7 @@
 #define TOKEN_BASE      0x2000
 #define TOKEN_MAX       0x100
 
-static void rtas_display_character(sPAPREnvironment *spapr,
+static void rtas_display_character(PowerPCCPU *cpu, sPAPREnvironment *spapr,
                                    uint32_t token, uint32_t nargs,
                                    target_ulong args,
                                    uint32_t nret, target_ulong rets)
@@ -54,7 +54,7 @@ static void rtas_display_character(sPAPREnvironment *spapr,
     }
 }
 
-static void rtas_get_time_of_day(sPAPREnvironment *spapr,
+static void rtas_get_time_of_day(PowerPCCPU *cpu, sPAPREnvironment *spapr,
                                  uint32_t token, uint32_t nargs,
                                  target_ulong args,
                                  uint32_t nret, target_ulong rets)
@@ -78,7 +78,7 @@ static void rtas_get_time_of_day(sPAPREnvironment *spapr,
     rtas_st(rets, 7, 0); /* we don't do nanoseconds */
 }
 
-static void rtas_set_time_of_day(sPAPREnvironment *spapr,
+static void rtas_set_time_of_day(PowerPCCPU *cpu, sPAPREnvironment *spapr,
                                  uint32_t token, uint32_t nargs,
                                  target_ulong args,
                                  uint32_t nret, target_ulong rets)
@@ -99,7 +99,7 @@ static void rtas_set_time_of_day(sPAPREnvironment *spapr,
     rtas_st(rets, 0, 0); /* Success */
 }
 
-static void rtas_power_off(sPAPREnvironment *spapr,
+static void rtas_power_off(PowerPCCPU *cpu, sPAPREnvironment *spapr,
                            uint32_t token, uint32_t nargs, target_ulong args,
                            uint32_t nret, target_ulong rets)
 {
@@ -111,7 +111,7 @@ static void rtas_power_off(sPAPREnvironment *spapr,
     rtas_st(rets, 0, 0);
 }
 
-static void rtas_system_reboot(sPAPREnvironment *spapr,
+static void rtas_system_reboot(PowerPCCPU *cpu, sPAPREnvironment *spapr,
                                uint32_t token, uint32_t nargs,
                                target_ulong args,
                                uint32_t nret, target_ulong rets)
@@ -124,7 +124,8 @@ static void rtas_system_reboot(sPAPREnvironment *spapr,
     rtas_st(rets, 0, 0);
 }
 
-static void rtas_query_cpu_stopped_state(sPAPREnvironment *spapr,
+static void rtas_query_cpu_stopped_state(PowerPCCPU *cpu_,
+                                         sPAPREnvironment *spapr,
                                          uint32_t token, uint32_t nargs,
                                          target_ulong args,
                                          uint32_t nret, target_ulong rets)
@@ -154,7 +155,7 @@ static void rtas_query_cpu_stopped_state(sPAPREnvironment *spapr,
     rtas_st(rets, 0, -3);
 }
 
-static void rtas_start_cpu(sPAPREnvironment *spapr,
+static void rtas_start_cpu(PowerPCCPU *cpu_, sPAPREnvironment *spapr,
                            uint32_t token, uint32_t nargs,
                            target_ulong args,
                            uint32_t nret, target_ulong rets)
@@ -208,7 +209,7 @@ static struct rtas_call {
 
 struct rtas_call *rtas_next = rtas_table;
 
-target_ulong spapr_rtas_call(sPAPREnvironment *spapr,
+target_ulong spapr_rtas_call(PowerPCCPU *cpu, sPAPREnvironment *spapr,
                              uint32_t token, uint32_t nargs, target_ulong args,
                              uint32_t nret, target_ulong rets)
 {
@@ -217,7 +218,7 @@ target_ulong spapr_rtas_call(sPAPREnvironment *spapr,
         struct rtas_call *call = rtas_table + (token - TOKEN_BASE);
 
         if (call->fn) {
-            call->fn(spapr, token, nargs, args, nret, rets);
+            call->fn(cpu, spapr, token, nargs, args, nret, rets);
             return H_SUCCESS;
         }
     }
@@ -227,7 +228,7 @@ target_ulong spapr_rtas_call(sPAPREnvironment *spapr,
      * machines) without looking it up in the device tree.  This
      * special case makes this work */
     if (token == 0xa) {
-        rtas_display_character(spapr, 0xa, nargs, args, nret, rets);
+        rtas_display_character(cpu, spapr, 0xa, nargs, args, nret, rets);
         return H_SUCCESS;
     }
 
diff --git a/hw/ppc/spapr_vio.c b/hw/ppc/spapr_vio.c
index 3c5a655ad7..9c18741cea 100644
--- a/hw/ppc/spapr_vio.c
+++ b/hw/ppc/spapr_vio.c
@@ -321,7 +321,8 @@ static void spapr_vio_quiesce_one(VIOsPAPRDevice *dev)
     free_crq(dev);
 }
 
-static void rtas_set_tce_bypass(sPAPREnvironment *spapr, uint32_t token,
+static void rtas_set_tce_bypass(PowerPCCPU *cpu, sPAPREnvironment *spapr,
+                                uint32_t token,
                                 uint32_t nargs, target_ulong args,
                                 uint32_t nret, target_ulong rets)
 {
@@ -351,7 +352,8 @@ static void rtas_set_tce_bypass(sPAPREnvironment *spapr, uint32_t token,
     rtas_st(rets, 0, 0);
 }
 
-static void rtas_quiesce(sPAPREnvironment *spapr, uint32_t token,
+static void rtas_quiesce(PowerPCCPU *cpu, sPAPREnvironment *spapr,
+                         uint32_t token,
                          uint32_t nargs, target_ulong args,
                          uint32_t nret, target_ulong rets)
 {
diff --git a/hw/ppc/xics.c b/hw/ppc/xics.c
index 1b25075d14..091912e2ca 100644
--- a/hw/ppc/xics.c
+++ b/hw/ppc/xics.c
@@ -400,7 +400,8 @@ static target_ulong h_eoi(PowerPCCPU *cpu, sPAPREnvironment *spapr,
     return H_SUCCESS;
 }
 
-static void rtas_set_xive(sPAPREnvironment *spapr, uint32_t token,
+static void rtas_set_xive(PowerPCCPU *cpu, sPAPREnvironment *spapr,
+                          uint32_t token,
                           uint32_t nargs, target_ulong args,
                           uint32_t nret, target_ulong rets)
 {
@@ -427,7 +428,8 @@ static void rtas_set_xive(sPAPREnvironment *spapr, uint32_t token,
     rtas_st(rets, 0, 0); /* Success */
 }
 
-static void rtas_get_xive(sPAPREnvironment *spapr, uint32_t token,
+static void rtas_get_xive(PowerPCCPU *cpu, sPAPREnvironment *spapr,
+                          uint32_t token,
                           uint32_t nargs, target_ulong args,
                           uint32_t nret, target_ulong rets)
 {
@@ -451,7 +453,8 @@ static void rtas_get_xive(sPAPREnvironment *spapr, uint32_t token,
     rtas_st(rets, 2, ics->irqs[nr - ics->offset].priority);
 }
 
-static void rtas_int_off(sPAPREnvironment *spapr, uint32_t token,
+static void rtas_int_off(PowerPCCPU *cpu, sPAPREnvironment *spapr,
+                         uint32_t token,
                          uint32_t nargs, target_ulong args,
                          uint32_t nret, target_ulong rets)
 {
@@ -476,7 +479,8 @@ static void rtas_int_off(sPAPREnvironment *spapr, uint32_t token,
     rtas_st(rets, 0, 0); /* Success */
 }
 
-static void rtas_int_on(sPAPREnvironment *spapr, uint32_t token,
+static void rtas_int_on(PowerPCCPU *cpu, sPAPREnvironment *spapr,
+                        uint32_t token,
                         uint32_t nargs, target_ulong args,
                         uint32_t nret, target_ulong rets)
 {