aboutsummaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2017-09-27 18:20:31 +0100
committerPeter Maydell <peter.maydell@linaro.org>2017-09-27 18:20:31 +0100
commit1d8934408135ac03b1c753c3b0a819cf7f387d60 (patch)
treed40d97fc11bd6d41ea983cf433e49f50607caaa9 /hw
parentcfe4cade054c0e0d00d0185cdc433a9e3ce3e2e4 (diff)
parente451b85f1bf3c8140be51e2b03eb71ab96c246a5 (diff)
Merge remote-tracking branch 'remotes/dgibson/tags/ppc-for-2.11-20170927' into staging
ppc patch queue 2017-09-27 Contains * a number of Mac machine type fixes * a number of embedded machine type fixes (preliminary to adding the Sam460ex board) * a important fix for handling of migration with KVM PR * assorted other minor fixes and cleanups # gpg: Signature made Wed 27 Sep 2017 08:40:48 BST # gpg: using RSA key 0x6C38CACA20D9B392 # gpg: Good signature from "David Gibson <david@gibson.dropbear.id.au>" # gpg: aka "David Gibson (Red Hat) <dgibson@redhat.com>" # gpg: aka "David Gibson (ozlabs.org) <dgibson@ozlabs.org>" # gpg: aka "David Gibson (kernel.org) <dwg@kernel.org>" # Primary key fingerprint: 75F4 6586 AE61 A66C C44E 87DC 6C38 CACA 20D9 B392 * remotes/dgibson/tags/ppc-for-2.11-20170927: (26 commits) macio: use object link between MACIO_IDE and MAC_DBDMA object macio: pass channel into MACIOIDEState via qdev property mac_dbdma: remove DBDMA_init() function mac_dbdma: QOMify mac_dbdma: remove unused IO fields from DBDMAState spapr: fix the value of SDR1 in kvmppc_put_books_sregs() ppc/pnv: check for OPAL firmware file presence ppc: remove all unused CPU definitions ppc: remove unused CPU definitions spapr_pci: make index property mandatory macio: convert pmac_ide_ops from old_mmio ppc/pnv: Improve macro parenthesization spapr: introduce helpers to migrate HPT chunks and the end marker ppc/kvm: generalize the use of kvmppc_get_htab_fd() ppc/kvm: change kvmppc_get_htab_fd() to return -errno on error ppc: Fix OpenPIC model ppc/ide/macio: Add missing registers ppc/mac: More rework of the DBDMA emulation ppc/mac: Advertise a high clock frequency for NewWorld Macs ppc: QOMify g3beige machine ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'hw')
-rw-r--r--hw/ide/macio.c206
-rw-r--r--hw/intc/openpic.c35
-rw-r--r--hw/misc/macio/mac_dbdma.c242
-rw-r--r--hw/misc/macio/macio.c21
-rw-r--r--hw/ppc/mac.h10
-rw-r--r--hw/ppc/mac_newworld.c4
-rw-r--r--hw/ppc/mac_oldworld.c17
-rw-r--r--hw/ppc/pnv.c6
-rw-r--r--hw/ppc/ppc405_uc.c12
-rw-r--r--hw/ppc/spapr.c68
-rw-r--r--hw/ppc/spapr_cpu_core.c16
-rw-r--r--hw/ppc/spapr_hcall.c45
-rw-r--r--hw/ppc/spapr_pci.c62
-rw-r--r--hw/usb/hcd-ehci-sysbus.c25
-rw-r--r--hw/usb/hcd-ehci.h1
-rw-r--r--hw/usb/hcd-ohci.c15
16 files changed, 499 insertions, 286 deletions
diff --git a/hw/ide/macio.c b/hw/ide/macio.c
index 9742c005d1..ce194c6cec 100644
--- a/hw/ide/macio.c
+++ b/hw/ide/macio.c
@@ -255,114 +255,100 @@ static void pmac_ide_flush(DBDMA_io *io)
}
/* PowerMac IDE memory IO */
-static void pmac_ide_writeb (void *opaque,
- hwaddr addr, uint32_t val)
+static uint64_t pmac_ide_read(void *opaque, hwaddr addr, unsigned size)
{
MACIOIDEState *d = opaque;
-
- addr = (addr & 0xFFF) >> 4;
- switch (addr) {
- case 1 ... 7:
- ide_ioport_write(&d->bus, addr, val);
- break;
- case 8:
- case 22:
- ide_cmd_write(&d->bus, 0, val);
+ uint64_t retval = 0xffffffff;
+ int reg = addr >> 4;
+
+ switch (reg) {
+ case 0x0:
+ if (size == 2) {
+ retval = ide_data_readw(&d->bus, 0);
+ } else if (size == 4) {
+ retval = ide_data_readl(&d->bus, 0);
+ }
break;
- default:
+ case 0x1 ... 0x7:
+ if (size == 1) {
+ retval = ide_ioport_read(&d->bus, reg);
+ }
break;
- }
-}
-
-static uint32_t pmac_ide_readb (void *opaque,hwaddr addr)
-{
- uint8_t retval;
- MACIOIDEState *d = opaque;
-
- addr = (addr & 0xFFF) >> 4;
- switch (addr) {
- case 1 ... 7:
- retval = ide_ioport_read(&d->bus, addr);
+ case 0x8:
+ case 0x16:
+ if (size == 1) {
+ retval = ide_status_read(&d->bus, 0);
+ }
break;
- case 8:
- case 22:
- retval = ide_status_read(&d->bus, 0);
+ case 0x20:
+ if (size == 4) {
+ retval = d->timing_reg;
+ }
break;
- default:
- retval = 0xFF;
+ case 0x30:
+ /* This is an interrupt state register that only exists
+ * in the KeyLargo and later variants. Bit 0x8000_0000
+ * latches the DMA interrupt and has to be written to
+ * clear. Bit 0x4000_0000 is an image of the disk
+ * interrupt. MacOS X relies on this and will hang if
+ * we don't provide at least the disk interrupt
+ */
+ if (size == 4) {
+ retval = d->irq_reg;
+ }
break;
}
- return retval;
-}
-
-static void pmac_ide_writew (void *opaque,
- hwaddr addr, uint32_t val)
-{
- MACIOIDEState *d = opaque;
-
- addr = (addr & 0xFFF) >> 4;
- val = bswap16(val);
- if (addr == 0) {
- ide_data_writew(&d->bus, 0, val);
- }
-}
-
-static uint32_t pmac_ide_readw (void *opaque,hwaddr addr)
-{
- uint16_t retval;
- MACIOIDEState *d = opaque;
- addr = (addr & 0xFFF) >> 4;
- if (addr == 0) {
- retval = ide_data_readw(&d->bus, 0);
- } else {
- retval = 0xFFFF;
- }
- retval = bswap16(retval);
return retval;
}
-static void pmac_ide_writel (void *opaque,
- hwaddr addr, uint32_t val)
-{
- MACIOIDEState *d = opaque;
-
- addr = (addr & 0xFFF) >> 4;
- val = bswap32(val);
- if (addr == 0) {
- ide_data_writel(&d->bus, 0, val);
- }
-}
-static uint32_t pmac_ide_readl (void *opaque,hwaddr addr)
+static void pmac_ide_write(void *opaque, hwaddr addr, uint64_t val,
+ unsigned size)
{
- uint32_t retval;
MACIOIDEState *d = opaque;
-
- addr = (addr & 0xFFF) >> 4;
- if (addr == 0) {
- retval = ide_data_readl(&d->bus, 0);
- } else {
- retval = 0xFFFFFFFF;
+ int reg = addr >> 4;
+
+ switch (reg) {
+ case 0x0:
+ if (size == 2) {
+ ide_data_writew(&d->bus, 0, val);
+ } else if (size == 4) {
+ ide_data_writel(&d->bus, 0, val);
+ }
+ break;
+ case 0x1 ... 0x7:
+ if (size == 1) {
+ ide_ioport_write(&d->bus, reg, val);
+ }
+ break;
+ case 0x8:
+ case 0x16:
+ if (size == 1) {
+ ide_cmd_write(&d->bus, 0, val);
+ }
+ break;
+ case 0x20:
+ if (size == 4) {
+ d->timing_reg = val;
+ }
+ break;
+ case 0x30:
+ if (size == 4) {
+ if (val & 0x80000000u) {
+ d->irq_reg &= 0x7fffffff;
+ }
+ }
+ break;
}
- retval = bswap32(retval);
- return retval;
}
static const MemoryRegionOps pmac_ide_ops = {
- .old_mmio = {
- .write = {
- pmac_ide_writeb,
- pmac_ide_writew,
- pmac_ide_writel,
- },
- .read = {
- pmac_ide_readb,
- pmac_ide_readw,
- pmac_ide_readl,
- },
- },
- .endianness = DEVICE_NATIVE_ENDIAN,
+ .read = pmac_ide_read,
+ .write = pmac_ide_write,
+ .valid.min_access_size = 1,
+ .valid.max_access_size = 4,
+ .endianness = DEVICE_LITTLE_ENDIAN,
};
static const VMStateDescription vmstate_pmac = {
@@ -426,13 +412,32 @@ static void macio_ide_realizefn(DeviceState *dev, Error **errp)
{
MACIOIDEState *s = MACIO_IDE(dev);
- ide_init2(&s->bus, s->irq);
+ ide_init2(&s->bus, s->ide_irq);
/* Register DMA callbacks */
s->dma.ops = &dbdma_ops;
s->bus.dma = &s->dma;
}
+static void pmac_ide_irq(void *opaque, int n, int level)
+{
+ MACIOIDEState *s = opaque;
+ uint32_t mask = 0x80000000u >> n;
+
+ /* We need to reflect the IRQ state in the irq register */
+ if (level) {
+ s->irq_reg |= mask;
+ } else {
+ s->irq_reg &= ~mask;
+ }
+
+ if (n) {
+ qemu_set_irq(s->real_ide_irq, level);
+ } else {
+ qemu_set_irq(s->real_dma_irq, level);
+ }
+}
+
static void macio_ide_initfn(Object *obj)
{
SysBusDevice *d = SYS_BUS_DEVICE(obj);
@@ -441,16 +446,28 @@ static void macio_ide_initfn(Object *obj)
ide_bus_new(&s->bus, sizeof(s->bus), DEVICE(obj), 0, 2);
memory_region_init_io(&s->mem, obj, &pmac_ide_ops, s, "pmac-ide", 0x1000);
sysbus_init_mmio(d, &s->mem);
- sysbus_init_irq(d, &s->irq);
- sysbus_init_irq(d, &s->dma_irq);
+ sysbus_init_irq(d, &s->real_ide_irq);
+ sysbus_init_irq(d, &s->real_dma_irq);
+ s->dma_irq = qemu_allocate_irq(pmac_ide_irq, s, 0);
+ s->ide_irq = qemu_allocate_irq(pmac_ide_irq, s, 1);
+
+ object_property_add_link(obj, "dbdma", TYPE_MAC_DBDMA,
+ (Object **) &s->dbdma,
+ qdev_prop_allow_set_link_before_realize, 0, NULL);
}
+static Property macio_ide_properties[] = {
+ DEFINE_PROP_UINT32("channel", MACIOIDEState, channel, 0),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
static void macio_ide_class_init(ObjectClass *oc, void *data)
{
DeviceClass *dc = DEVICE_CLASS(oc);
dc->realize = macio_ide_realizefn;
dc->reset = macio_ide_reset;
+ dc->props = macio_ide_properties;
dc->vmsd = &vmstate_pmac;
set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
}
@@ -480,10 +497,9 @@ void macio_ide_init_drives(MACIOIDEState *s, DriveInfo **hd_table)
}
}
-void macio_ide_register_dma(MACIOIDEState *s, void *dbdma, int channel)
+void macio_ide_register_dma(MACIOIDEState *s)
{
- s->dbdma = dbdma;
- DBDMA_register_channel(dbdma, channel, s->dma_irq,
+ DBDMA_register_channel(s->dbdma, s->channel, s->dma_irq,
pmac_ide_transfer, pmac_ide_flush, s);
}
diff --git a/hw/intc/openpic.c b/hw/intc/openpic.c
index 9dd285b923..10d6e871fb 100644
--- a/hw/intc/openpic.c
+++ b/hw/intc/openpic.c
@@ -92,6 +92,16 @@ static int get_current_cpu(void);
#define RAVEN_MAX_TMR OPENPIC_MAX_TMR
#define RAVEN_MAX_IPI OPENPIC_MAX_IPI
+/* KeyLargo */
+#define KEYLARGO_MAX_CPU 4
+#define KEYLARGO_MAX_EXT 64
+#define KEYLARGO_MAX_IPI 4
+#define KEYLARGO_MAX_IRQ (64 + KEYLARGO_MAX_IPI)
+#define KEYLARGO_MAX_TMR 0
+#define KEYLARGO_IPI_IRQ (KEYLARGO_MAX_EXT) /* First IPI IRQ */
+/* Timers don't exist but this makes the code happy... */
+#define KEYLARGO_TMR_IRQ (KEYLARGO_IPI_IRQ + KEYLARGO_MAX_IPI)
+
/* Interrupt definitions */
#define RAVEN_FE_IRQ (RAVEN_MAX_EXT) /* Internal functional IRQ */
#define RAVEN_ERR_IRQ (RAVEN_MAX_EXT + 1) /* Error IRQ */
@@ -120,6 +130,7 @@ static FslMpicInfo fsl_mpic_42 = {
#define VID_REVISION_1_3 3
#define VIR_GENERIC 0x00000000 /* Generic Vendor ID */
+#define VIR_MPIC2A 0x00004614 /* IBM MPIC-2A */
#define GCR_RESET 0x80000000
#define GCR_MODE_PASS 0x00000000
@@ -329,6 +340,8 @@ typedef struct OpenPICState {
uint32_t nb_cpus;
/* Timer registers */
OpenPICTimer timers[OPENPIC_MAX_TMR];
+ uint32_t max_tmr;
+
/* Shared MSI registers */
OpenPICMSI msi[MAX_MSI];
uint32_t max_irq;
@@ -1717,6 +1730,28 @@ static void openpic_realize(DeviceState *dev, Error **errp)
map_list(opp, list_le, &list_count);
break;
+
+ case OPENPIC_MODEL_KEYLARGO:
+ opp->nb_irqs = KEYLARGO_MAX_EXT;
+ opp->vid = VID_REVISION_1_2;
+ opp->vir = VIR_GENERIC;
+ opp->vector_mask = 0xFF;
+ opp->tfrr_reset = 4160000;
+ opp->ivpr_reset = IVPR_MASK_MASK | IVPR_MODE_MASK;
+ opp->idr_reset = 0;
+ opp->max_irq = KEYLARGO_MAX_IRQ;
+ opp->irq_ipi0 = KEYLARGO_IPI_IRQ;
+ opp->irq_tim0 = KEYLARGO_TMR_IRQ;
+ opp->brr1 = -1;
+ opp->mpic_mode_mask = GCR_MODE_MIXED;
+
+ if (opp->nb_cpus != 1) {
+ error_setg(errp, "Only UP supported today");
+ return;
+ }
+
+ map_list(opp, list_le, &list_count);
+ break;
}
for (i = 0; i < opp->nb_cpus; i++) {
diff --git a/hw/misc/macio/mac_dbdma.c b/hw/misc/macio/mac_dbdma.c
index 15452b9a28..0eddf2e700 100644
--- a/hw/misc/macio/mac_dbdma.c
+++ b/hw/misc/macio/mac_dbdma.c
@@ -96,9 +96,8 @@ static void dbdma_cmdptr_load(DBDMA_channel *ch)
static void dbdma_cmdptr_save(DBDMA_channel *ch)
{
- DBDMA_DPRINTFCH(ch, "dbdma_cmdptr_save 0x%08x\n",
- ch->regs[DBDMA_CMDPTR_LO]);
- DBDMA_DPRINTFCH(ch, "xfer_status 0x%08x res_count 0x%04x\n",
+ DBDMA_DPRINTFCH(ch, "-> update 0x%08x stat=0x%08x, res=0x%04x\n",
+ ch->regs[DBDMA_CMDPTR_LO],
le16_to_cpu(ch->current.xfer_status),
le16_to_cpu(ch->current.res_count));
dma_memory_write(&address_space_memory, ch->regs[DBDMA_CMDPTR_LO],
@@ -166,15 +165,14 @@ static int conditional_wait(DBDMA_channel *ch)
uint16_t sel_mask, sel_value;
uint32_t status;
int cond;
-
- DBDMA_DPRINTFCH(ch, "conditional_wait\n");
+ int res = 0;
wait = le16_to_cpu(current->command) & WAIT_MASK;
-
switch(wait) {
case WAIT_NEVER: /* don't wait */
return 0;
case WAIT_ALWAYS: /* always wait */
+ DBDMA_DPRINTFCH(ch, " [WAIT_ALWAYS]\n");
return 1;
}
@@ -187,15 +185,19 @@ static int conditional_wait(DBDMA_channel *ch)
switch(wait) {
case WAIT_IFSET: /* wait if condition bit is 1 */
- if (cond)
- return 1;
- return 0;
+ if (cond) {
+ res = 1;
+ }
+ DBDMA_DPRINTFCH(ch, " [WAIT_IFSET=%d]\n", res);
+ break;
case WAIT_IFCLR: /* wait if condition bit is 0 */
- if (!cond)
- return 1;
- return 0;
+ if (!cond) {
+ res = 1;
+ }
+ DBDMA_DPRINTFCH(ch, " [WAIT_IFCLR=%d]\n", res);
+ break;
}
- return 0;
+ return res;
}
static void next(DBDMA_channel *ch)
@@ -226,8 +228,6 @@ static void conditional_branch(DBDMA_channel *ch)
uint32_t status;
int cond;
- DBDMA_DPRINTFCH(ch, "conditional_branch\n");
-
/* check if we must branch */
br = le16_to_cpu(current->command) & BR_MASK;
@@ -237,6 +237,7 @@ static void conditional_branch(DBDMA_channel *ch)
next(ch);
return;
case BR_ALWAYS: /* always branch */
+ DBDMA_DPRINTFCH(ch, " [BR_ALWAYS]\n");
branch(ch);
return;
}
@@ -250,16 +251,22 @@ static void conditional_branch(DBDMA_channel *ch)
switch(br) {
case BR_IFSET: /* branch if condition bit is 1 */
- if (cond)
+ if (cond) {
+ DBDMA_DPRINTFCH(ch, " [BR_IFSET = 1]\n");
branch(ch);
- else
+ } else {
+ DBDMA_DPRINTFCH(ch, " [BR_IFSET = 0]\n");
next(ch);
+ }
return;
case BR_IFCLR: /* branch if condition bit is 0 */
- if (!cond)
+ if (!cond) {
+ DBDMA_DPRINTFCH(ch, " [BR_IFCLR = 1]\n");
branch(ch);
- else
+ } else {
+ DBDMA_DPRINTFCH(ch, " [BR_IFCLR = 0]\n");
next(ch);
+ }
return;
}
}
@@ -428,7 +435,7 @@ wait:
static void stop(DBDMA_channel *ch)
{
- ch->regs[DBDMA_STATUS] &= ~(ACTIVE|DEAD|FLUSH);
+ ch->regs[DBDMA_STATUS] &= ~(ACTIVE);
/* the stop command does not increment command pointer */
}
@@ -471,18 +478,22 @@ static void channel_run(DBDMA_channel *ch)
switch (cmd) {
case OUTPUT_MORE:
+ DBDMA_DPRINTFCH(ch, "* OUTPUT_MORE *\n");
start_output(ch, key, phy_addr, req_count, 0);
return;
case OUTPUT_LAST:
+ DBDMA_DPRINTFCH(ch, "* OUTPUT_LAST *\n");
start_output(ch, key, phy_addr, req_count, 1);
return;
case INPUT_MORE:
+ DBDMA_DPRINTFCH(ch, "* INPUT_MORE *\n");
start_input(ch, key, phy_addr, req_count, 0);
return;
case INPUT_LAST:
+ DBDMA_DPRINTFCH(ch, "* INPUT_LAST *\n");
start_input(ch, key, phy_addr, req_count, 1);
return;
}
@@ -508,10 +519,12 @@ static void channel_run(DBDMA_channel *ch)
switch (cmd) {
case LOAD_WORD:
+ DBDMA_DPRINTFCH(ch, "* LOAD_WORD *\n");
load_word(ch, key, phy_addr, req_count);
return;
case STORE_WORD:
+ DBDMA_DPRINTFCH(ch, "* STORE_WORD *\n");
store_word(ch, key, phy_addr, req_count);
return;
}
@@ -562,43 +575,117 @@ void DBDMA_register_channel(void *dbdma, int nchan, qemu_irq irq,
ch->io.opaque = opaque;
}
-static void
-dbdma_control_write(DBDMA_channel *ch)
+static void dbdma_control_write(DBDMA_channel *ch)
{
uint16_t mask, value;
uint32_t status;
+ bool do_flush = false;
mask = (ch->regs[DBDMA_CONTROL] >> 16) & 0xffff;
value = ch->regs[DBDMA_CONTROL] & 0xffff;
- value &= (RUN | PAUSE | FLUSH | WAKE | DEVSTAT);
-
+ /* This is the status register which we'll update
+ * appropriately and store back
+ */
status = ch->regs[DBDMA_STATUS];
- status = (value & mask) | (status & ~mask);
+ /* RUN and PAUSE are bits under SW control only
+ * FLUSH and WAKE are set by SW and cleared by HW
+ * DEAD, ACTIVE and BT are only under HW control
+ *
+ * We handle ACTIVE separately at the end of the
+ * logic to ensure all cases are covered.
+ */
- if (status & WAKE)
- status |= ACTIVE;
- if (status & RUN) {
- status |= ACTIVE;
- status &= ~DEAD;
+ /* Setting RUN will tentatively activate the channel
+ */
+ if ((mask & RUN) && (value & RUN)) {
+ status |= RUN;
+ DBDMA_DPRINTFCH(ch, " Setting RUN !\n");
+ }
+
+ /* Clearing RUN 1->0 will stop the channel */
+ if ((mask & RUN) && !(value & RUN)) {
+ /* This has the side effect of clearing the DEAD bit */
+ status &= ~(DEAD | RUN);
+ DBDMA_DPRINTFCH(ch, " Clearing RUN !\n");
+ }
+
+ /* Setting WAKE wakes up an idle channel if it's running
+ *
+ * Note: The doc doesn't say so but assume that only works
+ * on a channel whose RUN bit is set.
+ *
+ * We set WAKE in status, it's not terribly useful as it will
+ * be cleared on the next command fetch but it seems to mimmic
+ * the HW behaviour and is useful for the way we handle
+ * ACTIVE further down.
+ */
+ if ((mask & WAKE) && (value & WAKE) && (status & RUN)) {
+ status |= WAKE;
+ DBDMA_DPRINTFCH(ch, " Setting WAKE !\n");
+ }
+
+ /* PAUSE being set will deactivate (or prevent activation)
+ * of the channel. We just copy it over for now, ACTIVE will
+ * be re-evaluated later.
+ */
+ if (mask & PAUSE) {
+ status = (status & ~PAUSE) | (value & PAUSE);
+ DBDMA_DPRINTFCH(ch, " %sing PAUSE !\n",
+ (value & PAUSE) ? "sett" : "clear");
}
- if (status & PAUSE)
+
+ /* FLUSH is its own thing */
+ if ((mask & FLUSH) && (value & FLUSH)) {
+ DBDMA_DPRINTFCH(ch, " Setting FLUSH !\n");
+ /* We set flush directly in the status register, we do *NOT*
+ * set it in "status" so that it gets naturally cleared when
+ * we update the status register further down. That way it
+ * will be set only during the HW flush operation so it is
+ * visible to any completions happening during that time.
+ */
+ ch->regs[DBDMA_STATUS] |= FLUSH;
+ do_flush = true;
+ }
+
+ /* If either RUN or PAUSE is clear, so should ACTIVE be,
+ * otherwise, ACTIVE will be set if we modified RUN, PAUSE or
+ * set WAKE. That means that PAUSE was just cleared, RUN was
+ * just set or WAKE was just set.
+ */
+ if ((status & PAUSE) || !(status & RUN)) {
status &= ~ACTIVE;
- if ((ch->regs[DBDMA_STATUS] & RUN) && !(status & RUN)) {
- /* RUN is cleared */
- status &= ~(ACTIVE|DEAD);
+ DBDMA_DPRINTFCH(ch, " -> ACTIVE down !\n");
+
+ /* We stopped processing, we want the underlying HW command
+ * to complete *before* we clear the ACTIVE bit. Otherwise
+ * we can get into a situation where the command status will
+ * have RUN or ACTIVE not set which is going to confuse the
+ * MacOS driver.
+ */
+ do_flush = true;
+ } else if (mask & (RUN | PAUSE)) {
+ status |= ACTIVE;
+ DBDMA_DPRINTFCH(ch, " -> ACTIVE up !\n");
+ } else if ((mask & WAKE) && (value & WAKE)) {
+ status |= ACTIVE;
+ DBDMA_DPRINTFCH(ch, " -> ACTIVE up !\n");
}
- if ((status & FLUSH) && ch->flush) {
+ DBDMA_DPRINTFCH(ch, " new status=0x%08x\n", status);
+
+ /* If we need to flush the underlying HW, do it now, this happens
+ * both on FLUSH commands and when stopping the channel for safety.
+ */
+ if (do_flush && ch->flush) {
ch->flush(&ch->io);
- status &= ~FLUSH;
}
- DBDMA_DPRINTFCH(ch, " status 0x%08x\n", status);
-
+ /* Finally update the status register image */
ch->regs[DBDMA_STATUS] = status;
+ /* If active, make sure the BH gets to run */
if (status & ACTIVE) {
DBDMA_kick(dbdma_from_ch(ch));
}
@@ -666,13 +753,9 @@ static uint64_t dbdma_read(void *opaque, hwaddr addr,
value = ch->regs[reg];
- DBDMA_DPRINTFCH(ch, "readl 0x" TARGET_FMT_plx " => 0x%08x\n", addr, value);
- DBDMA_DPRINTFCH(ch, "channel 0x%x reg 0x%x\n",
- (uint32_t)addr >> DBDMA_CHANNEL_SHIFT, reg);
-
switch(reg) {
case DBDMA_CONTROL:
- value = 0;
+ value = ch->regs[DBDMA_STATUS];
break;
case DBDMA_STATUS:
case DBDMA_CMDPTR_LO:
@@ -698,6 +781,10 @@ static uint64_t dbdma_read(void *opaque, hwaddr addr,
break;
}
+ DBDMA_DPRINTFCH(ch, "readl 0x" TARGET_FMT_plx " => 0x%08x\n", addr, value);
+ DBDMA_DPRINTFCH(ch, "channel 0x%x reg 0x%x\n",
+ (uint32_t)addr >> DBDMA_CHANNEL_SHIFT, reg);
+
return value;
}
@@ -764,51 +851,49 @@ static const VMStateDescription vmstate_dbdma = {
}
};
-static void dbdma_reset(void *opaque)
+static void mac_dbdma_reset(DeviceState *d)
{
- DBDMAState *s = opaque;
+ DBDMAState *s = MAC_DBDMA(d);
int i;
- for (i = 0; i < DBDMA_CHANNELS; i++)
+ for (i = 0; i < DBDMA_CHANNELS; i++) {
memset(s->channels[i].regs, 0, DBDMA_SIZE);
+ }
}
static void dbdma_unassigned_rw(DBDMA_io *io)
{
DBDMA_channel *ch = io->channel;
- qemu_log_mask(LOG_GUEST_ERROR, "%s: use of unassigned channel %d\n",
- __func__, ch->channel);
- ch->io.processing = false;
-}
-
-static void dbdma_unassigned_flush(DBDMA_io *io)
-{
- DBDMA_channel *ch = io->channel;
dbdma_cmd *current = &ch->current;
uint16_t cmd;
qemu_log_mask(LOG_GUEST_ERROR, "%s: use of unassigned channel %d\n",
__func__, ch->channel);
+ ch->io.processing = false;
cmd = le16_to_cpu(current->command) & COMMAND_MASK;
if (cmd == OUTPUT_MORE || cmd == OUTPUT_LAST ||
cmd == INPUT_MORE || cmd == INPUT_LAST) {
- current->xfer_status = cpu_to_le16(ch->regs[DBDMA_STATUS] | FLUSH);
+ current->xfer_status = cpu_to_le16(ch->regs[DBDMA_STATUS]);
current->res_count = cpu_to_le16(io->len);
dbdma_cmdptr_save(ch);
}
}
-void* DBDMA_init (MemoryRegion **dbdma_mem)
+static void dbdma_unassigned_flush(DBDMA_io *io)
{
- DBDMAState *s;
- int i;
+ DBDMA_channel *ch = io->channel;
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: use of unassigned channel %d\n",
+ __func__, ch->channel);
+}
- s = g_malloc0(sizeof(DBDMAState));
+static void mac_dbdma_init(Object *obj)
+{
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
+ DBDMAState *s = MAC_DBDMA(obj);
+ int i;
for (i = 0; i < DBDMA_CHANNELS; i++) {
- DBDMA_io *io = &s->channels[i].io;
DBDMA_channel *ch = &s->channels[i];
- qemu_iovec_init(&io->iov, 1);
ch->rw = dbdma_unassigned_rw;
ch->flush = dbdma_unassigned_flush;
@@ -816,12 +901,37 @@ void* DBDMA_init (MemoryRegion **dbdma_mem)
ch->io.channel = ch;
}
- memory_region_init_io(&s->mem, NULL, &dbdma_ops, s, "dbdma", 0x1000);
- *dbdma_mem = &s->mem;
- vmstate_register(NULL, -1, &vmstate_dbdma, s);
- qemu_register_reset(dbdma_reset, s);
+ memory_region_init_io(&s->mem, obj, &dbdma_ops, s, "dbdma", 0x1000);
+ sysbus_init_mmio(sbd, &s->mem);
+}
+
+static void mac_dbdma_realize(DeviceState *dev, Error **errp)
+{
+ DBDMAState *s = MAC_DBDMA(dev);
s->bh = qemu_bh_new(DBDMA_run_bh, s);
+}
+
+static void mac_dbdma_class_init(ObjectClass *oc, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(oc);
+
+ dc->realize = mac_dbdma_realize;
+ dc->reset = mac_dbdma_reset;
+ dc->vmsd = &vmstate_dbdma;
+}
+
+static const TypeInfo mac_dbdma_type_info = {
+ .name = TYPE_MAC_DBDMA,
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(DBDMAState),
+ .instance_init = mac_dbdma_init,
+ .class_init = mac_dbdma_class_init
+};
- return s;
+static void mac_dbdma_register_types(void)
+{
+ type_register_static(&mac_dbdma_type_info);
}
+
+type_init(mac_dbdma_register_types)
diff --git a/hw/misc/macio/macio.c b/hw/misc/macio/macio.c
index 5d57f45dc6..9aa7e7559b 100644
--- a/hw/misc/macio/macio.c
+++ b/hw/misc/macio/macio.c
@@ -41,7 +41,7 @@ typedef struct MacIOState
MemoryRegion bar;
CUDAState cuda;
- void *dbdma;
+ DBDMAState *dbdma;
MemoryRegion *pic_mem;
MemoryRegion *escc_mem;
uint64_t frequency;
@@ -127,10 +127,15 @@ static void macio_common_realize(PCIDevice *d, Error **errp)
MacIOState *s = MACIO(d);
SysBusDevice *sysbus_dev;
Error *err = NULL;
- MemoryRegion *dbdma_mem;
- s->dbdma = DBDMA_init(&dbdma_mem);
- memory_region_add_subregion(&s->bar, 0x08000, dbdma_mem);
+ object_property_set_bool(OBJECT(s->dbdma), true, "realized", &err);
+ if (err) {
+ error_propagate(errp, err);
+ return;
+ }
+ sysbus_dev = SYS_BUS_DEVICE(s->dbdma);
+ memory_region_add_subregion(&s->bar, 0x08000,
+ sysbus_mmio_get_region(sysbus_dev, 0));
object_property_set_bool(OBJECT(&s->cuda), true, "realized", &err);
if (err) {
@@ -154,7 +159,10 @@ static void macio_realize_ide(MacIOState *s, MACIOIDEState *ide,
sysbus_dev = SYS_BUS_DEVICE(ide);
sysbus_connect_irq(sysbus_dev, 0, irq0);
sysbus_connect_irq(sysbus_dev, 1, irq1);
- macio_ide_register_dma(ide, s->dbdma, dmaid);
+ qdev_prop_set_uint32(DEVICE(ide), "channel", dmaid);
+ object_property_set_link(OBJECT(ide), OBJECT(s->dbdma), "dbdma", errp);
+ macio_ide_register_dma(ide);
+
object_property_set_bool(OBJECT(ide), true, "realized", errp);
}
@@ -334,6 +342,9 @@ static void macio_instance_init(Object *obj)
object_initialize(&s->cuda, sizeof(s->cuda), TYPE_CUDA);
qdev_set_parent_bus(DEVICE(&s->cuda), sysbus_get_default());
object_property_add_child(obj, "cuda", OBJECT(&s->cuda), NULL);
+
+ s->dbdma = MAC_DBDMA(object_new(TYPE_MAC_DBDMA));
+ object_property_add_child(obj, "dbdma", OBJECT(s->dbdma), NULL);
}
static const VMStateDescription vmstate_macio_oldworld = {
diff --git a/hw/ppc/mac.h b/hw/ppc/mac.h
index 20cbddb4e4..b501af1653 100644
--- a/hw/ppc/mac.h
+++ b/hw/ppc/mac.h
@@ -131,8 +131,10 @@ typedef struct MACIOIDEState {
/*< private >*/
SysBusDevice parent_obj;
/*< public >*/
-
- qemu_irq irq;
+ uint32_t channel;
+ qemu_irq real_ide_irq;
+ qemu_irq real_dma_irq;
+ qemu_irq ide_irq;
qemu_irq dma_irq;
MemoryRegion mem;
@@ -140,10 +142,12 @@ typedef struct MACIOIDEState {
IDEDMA dma;
void *dbdma;
bool dma_active;
+ uint32_t timing_reg;
+ uint32_t irq_reg;
} MACIOIDEState;
void macio_ide_init_drives(MACIOIDEState *ide, DriveInfo **hd_table);
-void macio_ide_register_dma(MACIOIDEState *ide, void *dbdma, int channel);
+void macio_ide_register_dma(MACIOIDEState *ide);
void macio_init(PCIDevice *dev,
MemoryRegion *pic_mem,
diff --git a/hw/ppc/mac_newworld.c b/hw/ppc/mac_newworld.c
index d013c412d6..6d0ace20ca 100644
--- a/hw/ppc/mac_newworld.c
+++ b/hw/ppc/mac_newworld.c
@@ -77,7 +77,7 @@
#define MAX_IDE_BUS 2
#define CFG_ADDR 0xf0000510
#define TBFREQ (100UL * 1000UL * 1000UL)
-#define CLOCKFREQ (266UL * 1000UL * 1000UL)
+#define CLOCKFREQ (900UL * 1000UL * 1000UL)
#define BUSFREQ (100UL * 1000UL * 1000UL)
#define NDRV_VGA_FILENAME "qemu_vga.ndrv"
@@ -342,7 +342,7 @@ static void ppc_core99_init(MachineState *machine)
pic = g_new0(qemu_irq, 64);
dev = qdev_create(NULL, TYPE_OPENPIC);
- qdev_prop_set_uint32(dev, "model", OPENPIC_MODEL_RAVEN);
+ qdev_prop_set_uint32(dev, "model", OPENPIC_MODEL_KEYLARGO);
qdev_init_nofail(dev);
s = SYS_BUS_DEVICE(dev);
pic_mem = s->mmio[0].memory;
diff --git a/hw/ppc/mac_oldworld.c b/hw/ppc/mac_oldworld.c
index 61838c3e6f..bc7c8b7bd7 100644
--- a/hw/ppc/mac_oldworld.c
+++ b/hw/ppc/mac_oldworld.c
@@ -371,8 +371,10 @@ static int heathrow_kvm_type(const char *arg)
return 2;
}
-static void heathrow_machine_init(MachineClass *mc)
+static void heathrow_class_init(ObjectClass *oc, void *data)
{
+ MachineClass *mc = MACHINE_CLASS(oc);
+
mc->desc = "Heathrow based PowerMAC";
mc->init = ppc_heathrow_init;
mc->block_default_type = IF_IDE;
@@ -385,4 +387,15 @@ static void heathrow_machine_init(MachineClass *mc)
mc->kvm_type = heathrow_kvm_type;
}
-DEFINE_MACHINE("g3beige", heathrow_machine_init)
+static const TypeInfo ppc_heathrow_machine_info = {
+ .name = MACHINE_TYPE_NAME("g3beige"),
+ .parent = TYPE_MACHINE,
+ .class_init = heathrow_class_init
+};
+
+static void ppc_heathrow_register_types(void)
+{
+ type_register_static(&ppc_heathrow_machine_info);
+}
+
+type_init(ppc_heathrow_register_types);
diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c
index 47221158d4..d46d91c76f 100644
--- a/hw/ppc/pnv.c
+++ b/hw/ppc/pnv.c
@@ -570,10 +570,14 @@ static void ppc_powernv_init(MachineState *machine)
}
fw_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
+ if (!fw_filename) {
+ error_report("Could not find OPAL firmware '%s'", bios_name);
+ exit(1);
+ }
fw_size = load_image_targphys(fw_filename, FW_LOAD_ADDR, FW_MAX_SIZE);
if (fw_size < 0) {
- error_report("Could not load OPAL '%s'", fw_filename);
+ error_report("Could not load OPAL firmware '%s'", fw_filename);
exit(1);
}
g_free(fw_filename);
diff --git a/hw/ppc/ppc405_uc.c b/hw/ppc/ppc405_uc.c
index e621d0aec5..8e58065f5f 100644
--- a/hw/ppc/ppc405_uc.c
+++ b/hw/ppc/ppc405_uc.c
@@ -105,9 +105,12 @@ ram_addr_t ppc405_set_bootinfo (CPUPPCState *env, ppc4xx_bd_info_t *bd,
/*****************************************************************************/
/* Peripheral local bus arbitrer */
enum {
- PLB0_BESR = 0x084,
- PLB0_BEAR = 0x086,
- PLB0_ACR = 0x087,
+ PLB3A0_ACR = 0x077,
+ PLB4A0_ACR = 0x081,
+ PLB0_BESR = 0x084,
+ PLB0_BEAR = 0x086,
+ PLB0_ACR = 0x087,
+ PLB4A1_ACR = 0x089,
};
typedef struct ppc4xx_plb_t ppc4xx_plb_t;
@@ -179,9 +182,12 @@ void ppc4xx_plb_init(CPUPPCState *env)
ppc4xx_plb_t *plb;
plb = g_malloc0(sizeof(ppc4xx_plb_t));
+ ppc_dcr_register(env, PLB3A0_ACR, plb, &dcr_read_plb, &dcr_write_plb);
+ ppc_dcr_register(env, PLB4A0_ACR, plb, &dcr_read_plb, &dcr_write_plb);
ppc_dcr_register(env, PLB0_ACR, plb, &dcr_read_plb, &dcr_write_plb);
ppc_dcr_register(env, PLB0_BEAR, plb, &dcr_read_plb, &dcr_write_plb);
ppc_dcr_register(env, PLB0_BESR, plb, &dcr_read_plb, &dcr_write_plb);
+ ppc_dcr_register(env, PLB4A1_ACR, plb, &dcr_read_plb, &dcr_write_plb);
qemu_register_reset(ppc4xx_plb_reset, plb);
}
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index 17ea77618c..ff87f155d5 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -1211,14 +1211,15 @@ static uint64_t spapr_get_patbe(PPCVirtualHypervisor *vhyp)
*/
static int get_htab_fd(sPAPRMachineState *spapr)
{
+ Error *local_err = NULL;
+
if (spapr->htab_fd >= 0) {
return spapr->htab_fd;
}
- spapr->htab_fd = kvmppc_get_htab_fd(false);
+ spapr->htab_fd = kvmppc_get_htab_fd(false, 0, &local_err);
if (spapr->htab_fd < 0) {
- error_report("Unable to open fd for reading hash table from KVM: %s",
- strerror(errno));
+ error_report_err(local_err);
}
return spapr->htab_fd;
@@ -1239,6 +1240,19 @@ static hwaddr spapr_hpt_mask(PPCVirtualHypervisor *vhyp)
return HTAB_SIZE(spapr) / HASH_PTEG_SIZE_64 - 1;
}
+static target_ulong spapr_encode_hpt_for_kvm_pr(PPCVirtualHypervisor *vhyp)
+{
+ sPAPRMachineState *spapr = SPAPR_MACHINE(vhyp);
+
+ assert(kvm_enabled());
+
+ if (!spapr->htab) {
+ return 0;
+ }
+
+ return (target_ulong)(uintptr_t)spapr->htab | (spapr->htab_shift - 18);
+}
+
static const ppc_hash_pte64_t *spapr_map_hptes(PPCVirtualHypervisor *vhyp,
hwaddr ptex, int n)
{
@@ -1708,6 +1722,23 @@ static int htab_save_setup(QEMUFile *f, void *opaque)
return 0;
}
+static void htab_save_chunk(QEMUFile *f, sPAPRMachineState *spapr,
+ int chunkstart, int n_valid, int n_invalid)
+{
+ qemu_put_be32(f, chunkstart);
+ qemu_put_be16(f, n_valid);
+ qemu_put_be16(f, n_invalid);
+ qemu_put_buffer(f, HPTE(spapr->htab, chunkstart),
+ HASH_PTE_SIZE_64 * n_valid);
+}
+
+static void htab_save_end_marker(QEMUFile *f)
+{
+ qemu_put_be32(f, 0);
+ qemu_put_be16(f, 0);
+ qemu_put_be16(f, 0);
+}
+
static void htab_save_first_pass(QEMUFile *f, sPAPRMachineState *spapr,
int64_t max_ns)
{
@@ -1739,11 +1770,7 @@ static void htab_save_first_pass(QEMUFile *f, sPAPRMachineState *spapr,
if (index > chunkstart) {
int n_valid = index - chunkstart;
- qemu_put_be32(f, chunkstart);
- qemu_put_be16(f, n_valid);
- qemu_put_be16(f, 0);
- qemu_put_buffer(f, HPTE(spapr->htab, chunkstart),
- HASH_PTE_SIZE_64 * n_valid);
+ htab_save_chunk(f, spapr, chunkstart, n_valid, 0);
if (has_timeout &&
(qemu_clock_get_ns(QEMU_CLOCK_REALTIME) - starttime) > max_ns) {
@@ -1805,11 +1832,7 @@ static int htab_save_later_pass(QEMUFile *f, sPAPRMachineState *spapr,
int n_valid = invalidstart - chunkstart;
int n_invalid = index - invalidstart;
- qemu_put_be32(f, chunkstart);
- qemu_put_be16(f, n_valid);
- qemu_put_be16(f, n_invalid);
- qemu_put_buffer(f, HPTE(spapr->htab, chunkstart),
- HASH_PTE_SIZE_64 * n_valid);
+ htab_save_chunk(f, spapr, chunkstart, n_valid, n_invalid);
sent += index - chunkstart;
if (!final && (qemu_clock_get_ns(QEMU_CLOCK_REALTIME) - starttime) > max_ns) {
@@ -1872,10 +1895,7 @@ static int htab_save_iterate(QEMUFile *f, void *opaque)
rc = htab_save_later_pass(f, spapr, MAX_ITERATION_NS);
}
- /* End marker */
- qemu_put_be32(f, 0);
- qemu_put_be16(f, 0);
- qemu_put_be16(f, 0);
+ htab_save_end_marker(f);
return rc;
}
@@ -1915,9 +1935,7 @@ static int htab_save_complete(QEMUFile *f, void *opaque)
}
/* End marker */
- qemu_put_be32(f, 0);
- qemu_put_be16(f, 0);
- qemu_put_be16(f, 0);
+ htab_save_end_marker(f);
return 0;
}
@@ -1927,6 +1945,7 @@ static int htab_load(QEMUFile *f, void *opaque, int version_id)
sPAPRMachineState *spapr = opaque;
uint32_t section_hdr;
int fd = -1;
+ Error *local_err = NULL;
if (version_id < 1 || version_id > 1) {
error_report("htab_load() bad version");
@@ -1941,8 +1960,6 @@ static int htab_load(QEMUFile *f, void *opaque, int version_id)
}
if (section_hdr) {
- Error *local_err = NULL;
-
/* First section gives the htab size */
spapr_reallocate_hpt(spapr, section_hdr, &local_err);
if (local_err) {
@@ -1955,10 +1972,10 @@ static int htab_load(QEMUFile *f, void *opaque, int version_id)
if (!spapr->htab) {
assert(kvm_enabled());
- fd = kvmppc_get_htab_fd(true);
+ fd = kvmppc_get_htab_fd(true, 0, &local_err);
if (fd < 0) {
- error_report("Unable to open fd to restore KVM hash table: %s",
- strerror(errno));
+ error_report_err(local_err);
+ return fd;
}
}
@@ -3600,6 +3617,7 @@ static void spapr_machine_class_init(ObjectClass *oc, void *data)
vhc->unmap_hptes = spapr_unmap_hptes;
vhc->store_hpte = spapr_store_hpte;
vhc->get_patbe = spapr_get_patbe;
+ vhc->encode_hpt_for_kvm_pr = spapr_encode_hpt_for_kvm_pr;
xic->ics_get = spapr_ics_get;
xic->ics_resend = spapr_ics_resend;
xic->icp_get = spapr_icp_get;
diff --git a/hw/ppc/spapr_cpu_core.c b/hw/ppc/spapr_cpu_core.c
index c08ee7571a..3e20b1d886 100644
--- a/hw/ppc/spapr_cpu_core.c
+++ b/hw/ppc/spapr_cpu_core.c
@@ -18,6 +18,7 @@
#include "hw/ppc/ppc.h"
#include "target/ppc/mmu-hash64.h"
#include "sysemu/numa.h"
+#include "sysemu/hw_accel.h"
#include "qemu/error-report.h"
void spapr_cpu_parse_features(sPAPRMachineState *spapr)
@@ -73,7 +74,6 @@ void spapr_cpu_parse_features(sPAPRMachineState *spapr)
static void spapr_cpu_reset(void *opaque)
{
- sPAPRMachineState *spapr = SPAPR_MACHINE(qdev_get_machine());
PowerPCCPU *cpu = opaque;
CPUState *cs = CPU(cpu);
CPUPPCState *env = &cpu->env;
@@ -86,20 +86,6 @@ static void spapr_cpu_reset(void *opaque)
cs->halted = 1;
env->spr[SPR_HIOR] = 0;
-
- /*
- * This is a hack for the benefit of KVM PR - it abuses the SDR1
- * slot in kvm_sregs to communicate the userspace address of the
- * HPT
- */
- if (kvm_enabled()) {
- env->spr[SPR_SDR1] = (target_ulong)(uintptr_t)spapr->htab
- | (spapr->htab_shift - 18);
- if (kvmppc_put_books_sregs(cpu) < 0) {
- error_report("Unable to update SDR1 in KVM");
- exit(1);
- }
- }
}
static void spapr_cpu_destroy(PowerPCCPU *cpu)
diff --git a/hw/ppc/spapr_hcall.c b/hw/ppc/spapr_hcall.c
index 57bb411394..8d72bb7c1c 100644
--- a/hw/ppc/spapr_hcall.c
+++ b/hw/ppc/spapr_hcall.c
@@ -686,6 +686,37 @@ static int rehash_hpt(PowerPCCPU *cpu,
return H_SUCCESS;
}
+static void do_push_sregs_to_kvm_pr(CPUState *cs, run_on_cpu_data data)
+{
+ int ret;
+
+ cpu_synchronize_state(cs);
+
+ ret = kvmppc_put_books_sregs(POWERPC_CPU(cs));
+ if (ret < 0) {
+ error_report("failed to push sregs to KVM: %s", strerror(-ret));
+ exit(1);
+ }
+}
+
+static void push_sregs_to_kvm_pr(sPAPRMachineState *spapr)
+{
+ CPUState *cs;
+
+ /*
+ * This is a hack for the benefit of KVM PR - it abuses the SDR1
+ * slot in kvm_sregs to communicate the userspace address of the
+ * HPT
+ */
+ if (!kvm_enabled() || !spapr->htab) {
+ return;
+ }
+
+ CPU_FOREACH(cs) {
+ run_on_cpu(cs, do_push_sregs_to_kvm_pr, RUN_ON_CPU_NULL);
+ }
+}
+
static target_ulong h_resize_hpt_commit(PowerPCCPU *cpu,
sPAPRMachineState *spapr,
target_ulong opcode,
@@ -733,12 +764,7 @@ static target_ulong h_resize_hpt_commit(PowerPCCPU *cpu,
spapr->htab = pending->hpt;
spapr->htab_shift = pending->shift;
- if (kvm_enabled()) {
- /* For KVM PR, update the HPT pointer */
- target_ulong sdr1 = (target_ulong)(uintptr_t)spapr->htab
- | (spapr->htab_shift - 18);
- kvmppc_update_sdr1(sdr1);
- }
+ push_sregs_to_kvm_pr(spapr);
pending->hpt = NULL; /* so it's not free()d */
}
@@ -1564,12 +1590,7 @@ static target_ulong h_client_architecture_support(PowerPCCPU *cpu,
* the point this is called, nothing should have been
* entered into the existing HPT */
spapr_reallocate_hpt(spapr, maxshift, &error_fatal);
- if (kvm_enabled()) {
- /* For KVM PR, update the HPT pointer */
- target_ulong sdr1 = (target_ulong)(uintptr_t)spapr->htab
- | (spapr->htab_shift - 18);
- kvmppc_update_sdr1(sdr1);
- }
+ push_sregs_to_kvm_pr(spapr);
}
}
diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c
index cf54160526..6126c80044 100644
--- a/hw/ppc/spapr_pci.c
+++ b/hw/ppc/spapr_pci.c
@@ -1523,16 +1523,6 @@ static void spapr_phb_realize(DeviceState *dev, Error **errp)
sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
Error *local_err = NULL;
- if ((sphb->buid != (uint64_t)-1) || (sphb->dma_liobn[0] != (uint32_t)-1)
- || (sphb->dma_liobn[1] != (uint32_t)-1 && windows_supported == 2)
- || (sphb->mem_win_addr != (hwaddr)-1)
- || (sphb->mem64_win_addr != (hwaddr)-1)
- || (sphb->io_win_addr != (hwaddr)-1)) {
- error_setg(errp, "Either \"index\" or other parameters must"
- " be specified for PAPR PHB, not both");
- return;
- }
-
smc->phb_placement(spapr, sphb->index,
&sphb->buid, &sphb->io_win_addr,
&sphb->mem_win_addr, &sphb->mem64_win_addr,
@@ -1541,46 +1531,20 @@ static void spapr_phb_realize(DeviceState *dev, Error **errp)
error_propagate(errp, local_err);
return;
}
- }
-
- if (sphb->buid == (uint64_t)-1) {
- error_setg(errp, "BUID not specified for PHB");
- return;
- }
-
- if ((sphb->dma_liobn[0] == (uint32_t)-1) ||
- ((sphb->dma_liobn[1] == (uint32_t)-1) && (windows_supported > 1))) {
- error_setg(errp, "LIOBN(s) not specified for PHB");
- return;
- }
-
- if (sphb->mem_win_addr == (hwaddr)-1) {
- error_setg(errp, "Memory window address not specified for PHB");
- return;
- }
-
- if (sphb->io_win_addr == (hwaddr)-1) {
- error_setg(errp, "IO window address not specified for PHB");
+ } else {
+ error_setg(errp, "\"index\" for PAPR PHB is mandatory");
return;
}
if (sphb->mem64_win_size != 0) {
- if (sphb->mem64_win_addr == (hwaddr)-1) {
- error_setg(errp,
- "64-bit memory window address not specified for PHB");
- return;
- }
-
if (sphb->mem_win_size > SPAPR_PCI_MEM32_WIN_SIZE) {
error_setg(errp, "32-bit memory window of size 0x%"HWADDR_PRIx
" (max 2 GiB)", sphb->mem_win_size);
return;
}
- if (sphb->mem64_win_pciaddr == (hwaddr)-1) {
- /* 64-bit window defaults to identity mapping */
- sphb->mem64_win_pciaddr = sphb->mem64_win_addr;
- }
+ /* 64-bit window defaults to identity mapping */
+ sphb->mem64_win_pciaddr = sphb->mem64_win_addr;
} else if (sphb->mem_win_size > SPAPR_PCI_MEM32_WIN_SIZE) {
/*
* For compatibility with old configuration, if no 64-bit MMIO
@@ -1622,18 +1586,16 @@ static void spapr_phb_realize(DeviceState *dev, Error **errp)
memory_region_add_subregion(get_system_memory(), sphb->mem_win_addr,
&sphb->mem32window);
- if (sphb->mem64_win_pciaddr != (hwaddr)-1) {
+ if (sphb->mem64_win_size != 0) {
namebuf = g_strdup_printf("%s.mmio64-alias", sphb->dtbusname);
memory_region_init_alias(&sphb->mem64window, OBJECT(sphb),
namebuf, &sphb->memspace,
sphb->mem64_win_pciaddr, sphb->mem64_win_size);
g_free(namebuf);
- if (sphb->mem64_win_addr != (hwaddr)-1) {
- memory_region_add_subregion(get_system_memory(),
- sphb->mem64_win_addr,
- &sphb->mem64window);
- }
+ memory_region_add_subregion(get_system_memory(),
+ sphb->mem64_win_addr,
+ &sphb->mem64window);
}
/* Initialize IO regions */
@@ -1789,18 +1751,10 @@ static void spapr_phb_reset(DeviceState *qdev)
static Property spapr_phb_properties[] = {
DEFINE_PROP_UINT32("index", sPAPRPHBState, index, -1),
- DEFINE_PROP_UINT64("buid", sPAPRPHBState, buid, -1),
- DEFINE_PROP_UINT32("liobn", sPAPRPHBState, dma_liobn[0], -1),
- DEFINE_PROP_UINT32("liobn64", sPAPRPHBState, dma_liobn[1], -1),
- DEFINE_PROP_UINT64("mem_win_addr", sPAPRPHBState, mem_win_addr, -1),
DEFINE_PROP_UINT64("mem_win_size", sPAPRPHBState, mem_win_size,
SPAPR_PCI_MEM32_WIN_SIZE),
- DEFINE_PROP_UINT64("mem64_win_addr", sPAPRPHBState, mem64_win_addr, -1),
DEFINE_PROP_UINT64("mem64_win_size", sPAPRPHBState, mem64_win_size,
SPAPR_PCI_MEM64_WIN_SIZE),
- DEFINE_PROP_UINT64("mem64_win_pciaddr", sPAPRPHBState, mem64_win_pciaddr,
- -1),
- DEFINE_PROP_UINT64("io_win_addr", sPAPRPHBState, io_win_addr, -1),
DEFINE_PROP_UINT64("io_win_size", sPAPRPHBState, io_win_size,
SPAPR_PCI_IO_WIN_SIZE),
DEFINE_PROP_BOOL("dynamic-reconfiguration", sPAPRPHBState, dr_enabled,
diff --git a/hw/usb/hcd-ehci-sysbus.c b/hw/usb/hcd-ehci-sysbus.c
index 6c20604d07..3b83beb140 100644
--- a/hw/usb/hcd-ehci-sysbus.c
+++ b/hw/usb/hcd-ehci-sysbus.c
@@ -142,6 +142,30 @@ static const TypeInfo ehci_tegra2_type_info = {
.class_init = ehci_tegra2_class_init,
};
+static void ehci_ppc4xx_init(Object *o)
+{
+ EHCISysBusState *s = SYS_BUS_EHCI(o);
+
+ s->ehci.companion_enable = true;
+}
+
+static void ehci_ppc4xx_class_init(ObjectClass *oc, void *data)
+{
+ SysBusEHCIClass *sec = SYS_BUS_EHCI_CLASS(oc);
+ DeviceClass *dc = DEVICE_CLASS(oc);
+
+ sec->capsbase = 0x0;
+ sec->opregbase = 0x10;
+ set_bit(DEVICE_CATEGORY_USB, dc->categories);
+}
+
+static const TypeInfo ehci_ppc4xx_type_info = {
+ .name = TYPE_PPC4xx_EHCI,
+ .parent = TYPE_SYS_BUS_EHCI,
+ .class_init = ehci_ppc4xx_class_init,
+ .instance_init = ehci_ppc4xx_init,
+};
+
/*
* Faraday FUSBH200 USB 2.0 EHCI
*/
@@ -224,6 +248,7 @@ static void ehci_sysbus_register_types(void)
type_register_static(&ehci_xlnx_type_info);
type_register_static(&ehci_exynos4210_type_info);
type_register_static(&ehci_tegra2_type_info);
+ type_register_static(&ehci_ppc4xx_type_info);
type_register_static(&ehci_fusbh200_type_info);
}
diff --git a/hw/usb/hcd-ehci.h b/hw/usb/hcd-ehci.h
index 821f1ded43..0bc364b286 100644
--- a/hw/usb/hcd-ehci.h
+++ b/hw/usb/hcd-ehci.h
@@ -344,6 +344,7 @@ typedef struct EHCIPCIState {
#define TYPE_SYS_BUS_EHCI "sysbus-ehci-usb"
#define TYPE_EXYNOS4210_EHCI "exynos4210-ehci-usb"
#define TYPE_TEGRA2_EHCI "tegra2-ehci-usb"
+#define TYPE_PPC4xx_EHCI "ppc4xx-ehci-usb"
#define TYPE_FUSBH200_EHCI "fusbh200-ehci-usb"
#define SYS_BUS_EHCI(obj) \
diff --git a/hw/usb/hcd-ohci.c b/hw/usb/hcd-ohci.c
index 267982e160..17beeddb09 100644
--- a/hw/usb/hcd-ohci.c
+++ b/hw/usb/hcd-ohci.c
@@ -1999,7 +1999,9 @@ typedef struct {
/*< public >*/
OHCIState ohci;
+ char *masterbus;
uint32_t num_ports;
+ uint32_t firstport;
dma_addr_t dma_offset;
} OHCISysBusState;
@@ -2007,10 +2009,15 @@ static void ohci_realize_pxa(DeviceState *dev, Error **errp)
{
OHCISysBusState *s = SYSBUS_OHCI(dev);
SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
+ Error *err = NULL;
- /* Cannot fail as we pass NULL for masterbus */
- usb_ohci_init(&s->ohci, dev, s->num_ports, s->dma_offset, NULL, 0,
- &address_space_memory, &error_abort);
+ usb_ohci_init(&s->ohci, dev, s->num_ports, s->dma_offset,
+ s->masterbus, s->firstport,
+ &address_space_memory, &err);
+ if (err) {
+ error_propagate(errp, err);
+ return;
+ }
sysbus_init_irq(sbd, &s->ohci.irq);
sysbus_init_mmio(sbd, &s->ohci.mem);
}
@@ -2142,7 +2149,9 @@ static const TypeInfo ohci_pci_info = {
};
static Property ohci_sysbus_properties[] = {
+ DEFINE_PROP_STRING("masterbus", OHCISysBusState, masterbus),
DEFINE_PROP_UINT32("num-ports", OHCISysBusState, num_ports, 3),
+ DEFINE_PROP_UINT32("firstport", OHCISysBusState, firstport, 0),
DEFINE_PROP_DMAADDR("dma-offset", OHCISysBusState, dma_offset, 0),
DEFINE_PROP_END_OF_LIST(),
};