aboutsummaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
authorRichard Henderson <richard.henderson@linaro.org>2023-07-07 22:23:17 +0100
committerRichard Henderson <richard.henderson@linaro.org>2023-07-07 22:23:17 +0100
commit276d72ca1b9017916cadc7c170d0d6b31633a9e5 (patch)
tree69a311d02bd13f90cd3b402f7f8f58ed6d337759 /hw
parent3b08e40b7abfe8be6020c4c27c93ad85590b9213 (diff)
parentbdb97596f663e9af9741353417c651f0d581de29 (diff)
downloadqemu-276d72ca1b9017916cadc7c170d0d6b31633a9e5.zip
qemu-276d72ca1b9017916cadc7c170d0d6b31633a9e5.tar.gz
qemu-276d72ca1b9017916cadc7c170d0d6b31633a9e5.tar.bz2
Merge tag 'pull-ppc-20230707-1' of https://gitlab.com/danielhb/qemu into staging
ppc patch queue for 2023-07-07: In this last queue for 8.1 we have a lot of fixes and improvements all around: SMT support for powerNV, XIVE fixes, PPC440 cleanups, exception handling cleanups and kvm_pph.h cleanups just to name a few. Thanks everyone in the qemu-ppc community for all the contributions for the next QEMU 8.1 release. # -----BEGIN PGP SIGNATURE----- # # iIwEABYKADQWIQQX6/+ZI9AYAK8oOBk82cqW3gMxZAUCZKgihBYcZGFuaWVsaGI0 # MTNAZ21haWwuY29tAAoJEDzZypbeAzFksr0A/jrvSDSDxB5mR7bo0dNGndLXcdTo # ZGr6k6pcMpr7RDOAAQDVeaw7f8djQ4Aaelk6v1wPs5bYfNY2ElF4NsqHJFX2Cg== # =8lDs # -----END PGP SIGNATURE----- # gpg: Signature made Fri 07 Jul 2023 03:34:44 PM BST # gpg: using EDDSA key 17EBFF9923D01800AF2838193CD9CA96DE033164 # gpg: issuer "danielhb413@gmail.com" # gpg: Good signature from "Daniel Henrique Barboza <danielhb413@gmail.com>" [unknown] # gpg: WARNING: This key is not certified with a trusted signature! # gpg: There is no indication that the signature belongs to the owner. # Primary key fingerprint: 17EB FF99 23D0 1800 AF28 3819 3CD9 CA96 DE03 3164 * tag 'pull-ppc-20230707-1' of https://gitlab.com/danielhb/qemu: (59 commits) ppc/pnv: Add QME region for P10 target/ppc: Remove pointless checks of CONFIG_USER_ONLY in 'kvm_ppc.h' target/ppc: Restrict 'kvm_ppc.h' to sysemu in cpu_init.c target/ppc: Define TYPE_HOST_POWERPC_CPU in cpu-qom.h target/ppc: Move CPU QOM definitions to cpu-qom.h target/ppc: Reorder #ifdef'ry in kvm_ppc.h target/ppc: Have 'kvm_ppc.h' include 'sysemu/kvm.h' target/ppc: Machine check on invalid real address access on POWER9/10 tests/qtest: Add xscom tests for powernv10 machine ppc/pnv: Set P10 core xscom region size to match hardware ppc/pnv: Log all unimp warnings with similar message ppc440_pcix: Rename QOM type define abd move it to common header ppc4xx_pci: Add define for ppc4xx-host-bridge type name ppc4xx_pci: Rename QOM type name define ppc440_pcix: Stop using system io region for PCI bus ppc440_pcix: Don't use iomem for regs ppc/sam460ex: Remove address_space_mem local variable ppc440: Remove ppc460ex_pcie_init legacy init function ppc440: Add busnum property to PCIe controller model ppc440: Stop using system io region for PCIe buses ... Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Diffstat (limited to 'hw')
-rw-r--r--hw/intc/pnv_xive2.c26
-rw-r--r--hw/intc/trace-events4
-rw-r--r--hw/intc/xive.c20
-rw-r--r--hw/intc/xive2.c4
-rw-r--r--hw/net/sungem.c52
-rw-r--r--hw/net/trace-events2
-rw-r--r--hw/pci-host/mv64361.c6
-rw-r--r--hw/pci-host/mv643xx.h3
-rw-r--r--hw/ppc/pegasos2.c32
-rw-r--r--hw/ppc/pnv.c26
-rw-r--r--hw/ppc/pnv_core.c282
-rw-r--r--hw/ppc/pnv_psi.c33
-rw-r--r--hw/ppc/ppc.c49
-rw-r--r--hw/ppc/ppc440.h1
-rw-r--r--hw/ppc/ppc440_bamboo.c3
-rw-r--r--hw/ppc/ppc440_pcix.c28
-rw-r--r--hw/ppc/ppc440_uc.c192
-rw-r--r--hw/ppc/ppc4xx_pci.c10
-rw-r--r--hw/ppc/sam460ex.c33
-rw-r--r--hw/ppc/spapr_cpu_core.c2
20 files changed, 568 insertions, 240 deletions
diff --git a/hw/intc/pnv_xive2.c b/hw/intc/pnv_xive2.c
index ed438a2..bbb44a5 100644
--- a/hw/intc/pnv_xive2.c
+++ b/hw/intc/pnv_xive2.c
@@ -1590,6 +1590,18 @@ static uint32_t pnv_xive2_ic_tm_get_pir(PnvXive2 *xive, hwaddr offset)
return xive->chip->chip_id << 8 | offset >> xive->ic_shift;
}
+static uint32_t pnv_xive2_ic_tm_get_hw_page_offset(PnvXive2 *xive,
+ hwaddr offset)
+{
+ /*
+ * Indirect TIMA accesses are similar to direct accesses for
+ * privilege ring 0. So remove any traces of the hw thread ID from
+ * the offset in the IC BAR as it could be interpreted as the ring
+ * privilege when calling the underlying direct access functions.
+ */
+ return offset & ((1ull << xive->ic_shift) - 1);
+}
+
static XiveTCTX *pnv_xive2_get_indirect_tctx(PnvXive2 *xive, uint32_t pir)
{
PnvChip *chip = xive->chip;
@@ -1612,14 +1624,17 @@ static uint64_t pnv_xive2_ic_tm_indirect_read(void *opaque, hwaddr offset,
unsigned size)
{
PnvXive2 *xive = PNV_XIVE2(opaque);
+ XivePresenter *xptr = XIVE_PRESENTER(xive);
+ hwaddr hw_page_offset;
uint32_t pir;
XiveTCTX *tctx;
uint64_t val = -1;
pir = pnv_xive2_ic_tm_get_pir(xive, offset);
+ hw_page_offset = pnv_xive2_ic_tm_get_hw_page_offset(xive, offset);
tctx = pnv_xive2_get_indirect_tctx(xive, pir);
if (tctx) {
- val = xive_tctx_tm_read(NULL, tctx, offset, size);
+ val = xive_tctx_tm_read(xptr, tctx, hw_page_offset, size);
}
return val;
@@ -1629,13 +1644,16 @@ static void pnv_xive2_ic_tm_indirect_write(void *opaque, hwaddr offset,
uint64_t val, unsigned size)
{
PnvXive2 *xive = PNV_XIVE2(opaque);
+ XivePresenter *xptr = XIVE_PRESENTER(xive);
+ hwaddr hw_page_offset;
uint32_t pir;
XiveTCTX *tctx;
pir = pnv_xive2_ic_tm_get_pir(xive, offset);
+ hw_page_offset = pnv_xive2_ic_tm_get_hw_page_offset(xive, offset);
tctx = pnv_xive2_get_indirect_tctx(xive, pir);
if (tctx) {
- xive_tctx_tm_write(NULL, tctx, offset, val, size);
+ xive_tctx_tm_write(xptr, tctx, hw_page_offset, val, size);
}
}
@@ -1644,11 +1662,11 @@ static const MemoryRegionOps pnv_xive2_ic_tm_indirect_ops = {
.write = pnv_xive2_ic_tm_indirect_write,
.endianness = DEVICE_BIG_ENDIAN,
.valid = {
- .min_access_size = 8,
+ .min_access_size = 1,
.max_access_size = 8,
},
.impl = {
- .min_access_size = 8,
+ .min_access_size = 1,
.max_access_size = 8,
},
};
diff --git a/hw/intc/trace-events b/hw/intc/trace-events
index 5c6094c..36ff71f 100644
--- a/hw/intc/trace-events
+++ b/hw/intc/trace-events
@@ -265,8 +265,8 @@ xive_source_esb_read(uint64_t addr, uint32_t srcno, uint64_t value) "@0x%"PRIx64
xive_source_esb_write(uint64_t addr, uint32_t srcno, uint64_t value) "@0x%"PRIx64" IRQ 0x%x val=0x%"PRIx64
xive_router_end_notify(uint8_t end_blk, uint32_t end_idx, uint32_t end_data) "END 0x%02x/0x%04x -> enqueue 0x%08x"
xive_router_end_escalate(uint8_t end_blk, uint32_t end_idx, uint8_t esc_blk, uint32_t esc_idx, uint32_t end_data) "END 0x%02x/0x%04x -> escalate END 0x%02x/0x%04x data 0x%08x"
-xive_tctx_tm_write(uint64_t offset, unsigned int size, uint64_t value) "@0x%"PRIx64" sz=%d val=0x%" PRIx64
-xive_tctx_tm_read(uint64_t offset, unsigned int size, uint64_t value) "@0x%"PRIx64" sz=%d val=0x%" PRIx64
+xive_tctx_tm_write(uint32_t index, uint64_t offset, unsigned int size, uint64_t value) "target=%d @0x%"PRIx64" sz=%d val=0x%" PRIx64
+xive_tctx_tm_read(uint32_t index, uint64_t offset, unsigned int size, uint64_t value) "target=%d @0x%"PRIx64" sz=%d val=0x%" PRIx64
xive_presenter_notify(uint8_t nvt_blk, uint32_t nvt_idx, uint8_t ring) "found NVT 0x%x/0x%x ring=0x%x"
xive_end_source_read(uint8_t end_blk, uint32_t end_idx, uint64_t addr) "END 0x%x/0x%x @0x%"PRIx64
diff --git a/hw/intc/xive.c b/hw/intc/xive.c
index 84c079b..56670b2 100644
--- a/hw/intc/xive.c
+++ b/hw/intc/xive.c
@@ -566,7 +566,7 @@ void xive_tctx_tm_write(XivePresenter *xptr, XiveTCTX *tctx, hwaddr offset,
{
const XiveTmOp *xto;
- trace_xive_tctx_tm_write(offset, size, value);
+ trace_xive_tctx_tm_write(tctx->cs->cpu_index, offset, size, value);
/*
* TODO: check V bit in Q[0-3]W2
@@ -639,7 +639,7 @@ uint64_t xive_tctx_tm_read(XivePresenter *xptr, XiveTCTX *tctx, hwaddr offset,
*/
ret = xive_tm_raw_read(tctx, offset, size);
out:
- trace_xive_tctx_tm_read(offset, size, ret);
+ trace_xive_tctx_tm_read(tctx->cs->cpu_index, offset, size, ret);
return ret;
}
@@ -1175,11 +1175,11 @@ static const MemoryRegionOps xive_source_esb_ops = {
.write = xive_source_esb_write,
.endianness = DEVICE_BIG_ENDIAN,
.valid = {
- .min_access_size = 8,
+ .min_access_size = 1,
.max_access_size = 8,
},
.impl = {
- .min_access_size = 8,
+ .min_access_size = 1,
.max_access_size = 8,
},
};
@@ -1232,8 +1232,7 @@ static void xive_source_reset(void *dev)
/* Do not clear the LSI bitmap */
- /* PQs are initialized to 0b01 (Q=1) which corresponds to "ints off" */
- memset(xsrc->status, XIVE_ESB_OFF, xsrc->nr_irqs);
+ memset(xsrc->status, xsrc->reset_pq, xsrc->nr_irqs);
}
static void xive_source_realize(DeviceState *dev, Error **errp)
@@ -1287,6 +1286,11 @@ static Property xive_source_properties[] = {
DEFINE_PROP_UINT64("flags", XiveSource, esb_flags, 0),
DEFINE_PROP_UINT32("nr-irqs", XiveSource, nr_irqs, 0),
DEFINE_PROP_UINT32("shift", XiveSource, esb_shift, XIVE_ESB_64K_2PAGE),
+ /*
+ * By default, PQs are initialized to 0b01 (Q=1) which corresponds
+ * to "ints off"
+ */
+ DEFINE_PROP_UINT8("reset-pq", XiveSource, reset_pq, XIVE_ESB_OFF),
DEFINE_PROP_LINK("xive", XiveSource, xive, TYPE_XIVE_NOTIFIER,
XiveNotifier *),
DEFINE_PROP_END_OF_LIST(),
@@ -2002,11 +2006,11 @@ static const MemoryRegionOps xive_end_source_ops = {
.write = xive_end_source_write,
.endianness = DEVICE_BIG_ENDIAN,
.valid = {
- .min_access_size = 8,
+ .min_access_size = 1,
.max_access_size = 8,
},
.impl = {
- .min_access_size = 8,
+ .min_access_size = 1,
.max_access_size = 8,
},
};
diff --git a/hw/intc/xive2.c b/hw/intc/xive2.c
index 4d9ff41..c37ef25 100644
--- a/hw/intc/xive2.c
+++ b/hw/intc/xive2.c
@@ -954,11 +954,11 @@ static const MemoryRegionOps xive2_end_source_ops = {
.write = xive2_end_source_write,
.endianness = DEVICE_BIG_ENDIAN,
.valid = {
- .min_access_size = 8,
+ .min_access_size = 1,
.max_access_size = 8,
},
.impl = {
- .min_access_size = 8,
+ .min_access_size = 1,
.max_access_size = 8,
},
};
diff --git a/hw/net/sungem.c b/hw/net/sungem.c
index 103376c..510b370 100644
--- a/hw/net/sungem.c
+++ b/hw/net/sungem.c
@@ -107,6 +107,15 @@ OBJECT_DECLARE_SIMPLE_TYPE(SunGEMState, SUNGEM)
#define RXDMA_FTAG 0x0110UL /* RX FIFO Tag */
#define RXDMA_FSZ 0x0120UL /* RX FIFO Size */
+/* WOL Registers */
+#define SUNGEM_MMIO_WOL_SIZE 0x14
+
+#define WOL_MATCH0 0x0000UL
+#define WOL_MATCH1 0x0004UL
+#define WOL_MATCH2 0x0008UL
+#define WOL_MCOUNT 0x000CUL
+#define WOL_WAKECSR 0x0010UL
+
/* MAC Registers */
#define SUNGEM_MMIO_MAC_SIZE 0x200
@@ -168,6 +177,7 @@ OBJECT_DECLARE_SIMPLE_TYPE(SunGEMState, SUNGEM)
#define SUNGEM_MMIO_PCS_SIZE 0x60
#define PCS_MIISTAT 0x0004UL /* PCS MII Status Register */
#define PCS_ISTAT 0x0018UL /* PCS Interrupt Status Reg */
+
#define PCS_SSTATE 0x005CUL /* Serialink State Register */
/* Descriptors */
@@ -200,6 +210,7 @@ struct SunGEMState {
MemoryRegion greg;
MemoryRegion txdma;
MemoryRegion rxdma;
+ MemoryRegion wol;
MemoryRegion mac;
MemoryRegion mif;
MemoryRegion pcs;
@@ -1062,6 +1073,43 @@ static const MemoryRegionOps sungem_mmio_rxdma_ops = {
},
};
+static void sungem_mmio_wol_write(void *opaque, hwaddr addr, uint64_t val,
+ unsigned size)
+{
+ trace_sungem_mmio_wol_write(addr, val);
+
+ switch (addr) {
+ case WOL_WAKECSR:
+ if (val != 0) {
+ qemu_log_mask(LOG_UNIMP, "sungem: WOL not supported\n");
+ }
+ break;
+ default:
+ qemu_log_mask(LOG_UNIMP, "sungem: WOL not supported\n");
+ }
+}
+
+static uint64_t sungem_mmio_wol_read(void *opaque, hwaddr addr, unsigned size)
+{
+ uint32_t val = -1;
+
+ qemu_log_mask(LOG_UNIMP, "sungem: WOL not supported\n");
+
+ trace_sungem_mmio_wol_read(addr, val);
+
+ return val;
+}
+
+static const MemoryRegionOps sungem_mmio_wol_ops = {
+ .read = sungem_mmio_wol_read,
+ .write = sungem_mmio_wol_write,
+ .endianness = DEVICE_LITTLE_ENDIAN,
+ .impl = {
+ .min_access_size = 4,
+ .max_access_size = 4,
+ },
+};
+
static void sungem_mmio_mac_write(void *opaque, hwaddr addr, uint64_t val,
unsigned size)
{
@@ -1330,6 +1378,10 @@ static void sungem_realize(PCIDevice *pci_dev, Error **errp)
"sungem.rxdma", SUNGEM_MMIO_RXDMA_SIZE);
memory_region_add_subregion(&s->sungem, 0x4000, &s->rxdma);
+ memory_region_init_io(&s->wol, OBJECT(s), &sungem_mmio_wol_ops, s,
+ "sungem.wol", SUNGEM_MMIO_WOL_SIZE);
+ memory_region_add_subregion(&s->sungem, 0x3000, &s->wol);
+
memory_region_init_io(&s->mac, OBJECT(s), &sungem_mmio_mac_ops, s,
"sungem.mac", SUNGEM_MMIO_MAC_SIZE);
memory_region_add_subregion(&s->sungem, 0x6000, &s->mac);
diff --git a/hw/net/trace-events b/hw/net/trace-events
index 3eeacc5..6b5ba66 100644
--- a/hw/net/trace-events
+++ b/hw/net/trace-events
@@ -351,6 +351,8 @@ sungem_mmio_txdma_write(uint64_t addr, uint64_t val) "MMIO txdma write to 0x%"PR
sungem_mmio_txdma_read(uint64_t addr, uint64_t val) "MMIO txdma read from 0x%"PRIx64" val=0x%"PRIx64
sungem_mmio_rxdma_write(uint64_t addr, uint64_t val) "MMIO rxdma write to 0x%"PRIx64" val=0x%"PRIx64
sungem_mmio_rxdma_read(uint64_t addr, uint64_t val) "MMIO rxdma read from 0x%"PRIx64" val=0x%"PRIx64
+sungem_mmio_wol_write(uint64_t addr, uint64_t val) "MMIO wol write to 0x%"PRIx64" val=0x%"PRIx64
+sungem_mmio_wol_read(uint64_t addr, uint64_t val) "MMIO wol read from 0x%"PRIx64" val=0x%"PRIx64
sungem_mmio_mac_write(uint64_t addr, uint64_t val) "MMIO mac write to 0x%"PRIx64" val=0x%"PRIx64
sungem_mmio_mac_read(uint64_t addr, uint64_t val) "MMIO mac read from 0x%"PRIx64" val=0x%"PRIx64
sungem_mmio_mif_write(uint64_t addr, uint64_t val) "MMIO mif write to 0x%"PRIx64" val=0x%"PRIx64
diff --git a/hw/pci-host/mv64361.c b/hw/pci-host/mv64361.c
index 19e8031..01bd8c8 100644
--- a/hw/pci-host/mv64361.c
+++ b/hw/pci-host/mv64361.c
@@ -541,6 +541,12 @@ static uint64_t mv64361_read(void *opaque, hwaddr addr, unsigned int size)
}
}
break;
+ case MV64340_ETH_PHY_ADDR:
+ ret = 0x98;
+ break;
+ case MV64340_ETH_SMI:
+ ret = BIT(27);
+ break;
case MV64340_CUNIT_ARBITER_CONTROL_REG:
ret = 0x11ff0000 | (s->gpp_int_level << 10);
break;
diff --git a/hw/pci-host/mv643xx.h b/hw/pci-host/mv643xx.h
index cd26a43..f2e1bae 100644
--- a/hw/pci-host/mv643xx.h
+++ b/hw/pci-host/mv643xx.h
@@ -656,6 +656,9 @@
/* Ethernet Unit Registers */
/****************************************/
+#define MV64340_ETH_PHY_ADDR 0x2000
+#define MV64340_ETH_SMI 0x2004
+
/*******************************************/
/* CUNIT Registers */
/*******************************************/
diff --git a/hw/ppc/pegasos2.c b/hw/ppc/pegasos2.c
index af5489d..9c99441 100644
--- a/hw/ppc/pegasos2.c
+++ b/hw/ppc/pegasos2.c
@@ -44,6 +44,8 @@
#define PROM_ADDR 0xfff00000
#define PROM_SIZE 0x80000
+#define INITRD_MIN_ADDR 0x600000
+
#define KVMPPC_HCALL_BASE 0xf000
#define KVMPPC_H_RTAS (KVMPPC_HCALL_BASE + 0x0)
#define KVMPPC_H_VOF_CLIENT (KVMPPC_HCALL_BASE + 0x5)
@@ -80,6 +82,8 @@ struct Pegasos2MachineState {
uint64_t kernel_addr;
uint64_t kernel_entry;
uint64_t kernel_size;
+ uint64_t initrd_addr;
+ uint64_t initrd_size;
};
static void *build_fdt(MachineState *machine, int *fdt_size);
@@ -117,7 +121,8 @@ static void pegasos2_init(MachineState *machine)
I2CBus *i2c_bus;
const char *fwname = machine->firmware ?: PROM_FILENAME;
char *filename;
- int i, sz;
+ int i;
+ ssize_t sz;
uint8_t *spd_data;
/* init CPU */
@@ -213,6 +218,20 @@ static void pegasos2_init(MachineState *machine)
warn_report("Using Virtual OpenFirmware but no -kernel option.");
}
+ if (machine->initrd_filename) {
+ pm->initrd_addr = pm->kernel_addr + pm->kernel_size + 64 * KiB;
+ pm->initrd_addr = ROUND_UP(pm->initrd_addr, 4);
+ pm->initrd_addr = MAX(pm->initrd_addr, INITRD_MIN_ADDR);
+ sz = load_image_targphys(machine->initrd_filename, pm->initrd_addr,
+ machine->ram_size - pm->initrd_addr);
+ if (sz <= 0) {
+ error_report("Could not load initrd '%s'",
+ machine->initrd_filename);
+ exit(1);
+ }
+ pm->initrd_size = sz;
+ }
+
if (!pm->vof && machine->kernel_cmdline && machine->kernel_cmdline[0]) {
warn_report("Option -append may be ineffective with -bios.");
}
@@ -335,6 +354,11 @@ static void pegasos2_machine_reset(MachineState *machine, ShutdownCause reason)
error_report("Memory for kernel is in use");
exit(1);
}
+ if (pm->initrd_size &&
+ vof_claim(pm->vof, pm->initrd_addr, pm->initrd_size, 0) == -1) {
+ error_report("Memory for initrd is in use");
+ exit(1);
+ }
fdt = build_fdt(machine, &sz);
/* FIXME: VOF assumes entry is same as load address */
d[0] = cpu_to_be64(pm->kernel_entry);
@@ -966,6 +990,12 @@ static void *build_fdt(MachineState *machine, int *fdt_size)
qemu_fdt_setprop_string(fdt, "/memory@0", "name", "memory");
qemu_fdt_add_subnode(fdt, "/chosen");
+ if (pm->initrd_addr && pm->initrd_size) {
+ qemu_fdt_setprop_cell(fdt, "/chosen", "linux,initrd-end",
+ pm->initrd_addr + pm->initrd_size);
+ qemu_fdt_setprop_cell(fdt, "/chosen", "linux,initrd-start",
+ pm->initrd_addr);
+ }
qemu_fdt_setprop_string(fdt, "/chosen", "bootargs",
machine->kernel_cmdline ?: "");
qemu_fdt_setprop_string(fdt, "/chosen", "name", "chosen");
diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c
index fc08317..eb54f93 100644
--- a/hw/ppc/pnv.c
+++ b/hw/ppc/pnv.c
@@ -887,6 +887,18 @@ static void pnv_init(MachineState *machine)
pnv->num_chips =
machine->smp.max_cpus / (machine->smp.cores * machine->smp.threads);
+
+ if (machine->smp.threads > 8) {
+ error_report("Cannot support more than 8 threads/core "
+ "on a powernv machine");
+ exit(1);
+ }
+ if (!is_power_of_2(machine->smp.threads)) {
+ error_report("Cannot support %d threads/core on a powernv"
+ "machine because it must be a power of 2",
+ machine->smp.threads);
+ exit(1);
+ }
/*
* TODO: should we decide on how many chips we can create based
* on #cores and Venice vs. Murano vs. Naples chip type etc...,
@@ -1429,14 +1441,15 @@ static void pnv_chip_power9_instance_init(Object *obj)
}
static void pnv_chip_quad_realize_one(PnvChip *chip, PnvQuad *eq,
- PnvCore *pnv_core)
+ PnvCore *pnv_core,
+ const char *type)
{
char eq_name[32];
int core_id = CPU_CORE(pnv_core)->core_id;
snprintf(eq_name, sizeof(eq_name), "eq[%d]", core_id);
object_initialize_child_with_props(OBJECT(chip), eq_name, eq,
- sizeof(*eq), TYPE_PNV_QUAD,
+ sizeof(*eq), type,
&error_fatal, NULL);
object_property_set_int(OBJECT(eq), "quad-id", core_id, &error_fatal);
@@ -1454,7 +1467,8 @@ static void pnv_chip_quad_realize(Pnv9Chip *chip9, Error **errp)
for (i = 0; i < chip9->nr_quads; i++) {
PnvQuad *eq = &chip9->quads[i];
- pnv_chip_quad_realize_one(chip, eq, chip->cores[i * 4]);
+ pnv_chip_quad_realize_one(chip, eq, chip->cores[i * 4],
+ PNV_QUAD_TYPE_NAME("power9"));
pnv_xscom_add_subregion(chip, PNV9_XSCOM_EQ_BASE(eq->quad_id),
&eq->xscom_regs);
@@ -1666,10 +1680,14 @@ static void pnv_chip_power10_quad_realize(Pnv10Chip *chip10, Error **errp)
for (i = 0; i < chip10->nr_quads; i++) {
PnvQuad *eq = &chip10->quads[i];
- pnv_chip_quad_realize_one(chip, eq, chip->cores[i * 4]);
+ pnv_chip_quad_realize_one(chip, eq, chip->cores[i * 4],
+ PNV_QUAD_TYPE_NAME("power10"));
pnv_xscom_add_subregion(chip, PNV10_XSCOM_EQ_BASE(eq->quad_id),
&eq->xscom_regs);
+
+ pnv_xscom_add_subregion(chip, PNV10_XSCOM_QME_BASE(eq->quad_id),
+ &eq->xscom_qme_regs);
}
}
diff --git a/hw/ppc/pnv_core.c b/hw/ppc/pnv_core.c
index 0bc3ad4..9b39d52 100644
--- a/hw/ppc/pnv_core.c
+++ b/hw/ppc/pnv_core.c
@@ -85,8 +85,8 @@ static uint64_t pnv_core_power8_xscom_read(void *opaque, hwaddr addr,
val = 0x24f000000000000ull;
break;
default:
- qemu_log_mask(LOG_UNIMP, "Warning: reading reg=0x%" HWADDR_PRIx "\n",
- addr);
+ qemu_log_mask(LOG_UNIMP, "%s: unimp read 0x%08x\n", __func__,
+ offset);
}
return val;
@@ -95,8 +95,10 @@ static uint64_t pnv_core_power8_xscom_read(void *opaque, hwaddr addr,
static void pnv_core_power8_xscom_write(void *opaque, hwaddr addr, uint64_t val,
unsigned int width)
{
- qemu_log_mask(LOG_UNIMP, "Warning: writing to reg=0x%" HWADDR_PRIx "\n",
- addr);
+ uint32_t offset = addr >> 3;
+
+ qemu_log_mask(LOG_UNIMP, "%s: unimp write 0x%08x\n", __func__,
+ offset);
}
static const MemoryRegionOps pnv_core_power8_xscom_ops = {
@@ -116,6 +118,8 @@ static const MemoryRegionOps pnv_core_power8_xscom_ops = {
#define PNV9_XSCOM_EC_PPM_SPECIAL_WKUP_HYP 0xf010d
#define PNV9_XSCOM_EC_PPM_SPECIAL_WKUP_OTR 0xf010a
+#define PNV9_XSCOM_EC_CORE_THREAD_STATE 0x10ab3
+
static uint64_t pnv_core_power9_xscom_read(void *opaque, hwaddr addr,
unsigned int width)
{
@@ -134,9 +138,12 @@ static uint64_t pnv_core_power9_xscom_read(void *opaque, hwaddr addr,
case PNV9_XSCOM_EC_PPM_SPECIAL_WKUP_OTR:
val = 0x0;
break;
+ case PNV9_XSCOM_EC_CORE_THREAD_STATE:
+ val = 0;
+ break;
default:
- qemu_log_mask(LOG_UNIMP, "Warning: reading reg=0x%" HWADDR_PRIx "\n",
- addr);
+ qemu_log_mask(LOG_UNIMP, "%s: unimp read 0x%08x\n", __func__,
+ offset);
}
return val;
@@ -152,8 +159,8 @@ static void pnv_core_power9_xscom_write(void *opaque, hwaddr addr, uint64_t val,
case PNV9_XSCOM_EC_PPM_SPECIAL_WKUP_OTR:
break;
default:
- qemu_log_mask(LOG_UNIMP, "Warning: writing to reg=0x%" HWADDR_PRIx "\n",
- addr);
+ qemu_log_mask(LOG_UNIMP, "%s: unimp write 0x%08x\n", __func__,
+ offset);
}
}
@@ -167,12 +174,59 @@ static const MemoryRegionOps pnv_core_power9_xscom_ops = {
.endianness = DEVICE_BIG_ENDIAN,
};
-static void pnv_core_cpu_realize(PnvCore *pc, PowerPCCPU *cpu, Error **errp)
+/*
+ * POWER10 core controls
+ */
+
+#define PNV10_XSCOM_EC_CORE_THREAD_STATE 0x412
+
+static uint64_t pnv_core_power10_xscom_read(void *opaque, hwaddr addr,
+ unsigned int width)
+{
+ uint32_t offset = addr >> 3;
+ uint64_t val = 0;
+
+ switch (offset) {
+ case PNV10_XSCOM_EC_CORE_THREAD_STATE:
+ val = 0;
+ break;
+ default:
+ qemu_log_mask(LOG_UNIMP, "%s: unimp read 0x%08x\n", __func__,
+ offset);
+ }
+
+ return val;
+}
+
+static void pnv_core_power10_xscom_write(void *opaque, hwaddr addr,
+ uint64_t val, unsigned int width)
+{
+ uint32_t offset = addr >> 3;
+
+ switch (offset) {
+ default:
+ qemu_log_mask(LOG_UNIMP, "%s: unimp write 0x%08x\n", __func__,
+ offset);
+ }
+}
+
+static const MemoryRegionOps pnv_core_power10_xscom_ops = {
+ .read = pnv_core_power10_xscom_read,
+ .write = pnv_core_power10_xscom_write,
+ .valid.min_access_size = 8,
+ .valid.max_access_size = 8,
+ .impl.min_access_size = 8,
+ .impl.max_access_size = 8,
+ .endianness = DEVICE_BIG_ENDIAN,
+};
+
+static void pnv_core_cpu_realize(PnvCore *pc, PowerPCCPU *cpu, Error **errp,
+ int thread_index)
{
CPUPPCState *env = &cpu->env;
int core_pir;
- int thread_index = 0; /* TODO: TCG supports only one thread */
ppc_spr_t *pir = &env->spr_cb[SPR_PIR];
+ ppc_spr_t *tir = &env->spr_cb[SPR_TIR];
Error *local_err = NULL;
PnvChipClass *pcc = PNV_CHIP_GET_CLASS(pc->chip);
@@ -188,11 +242,7 @@ static void pnv_core_cpu_realize(PnvCore *pc, PowerPCCPU *cpu, Error **errp)
core_pir = object_property_get_uint(OBJECT(pc), "pir", &error_abort);
- /*
- * The PIR of a thread is the core PIR + the thread index. We will
- * need to find a way to get the thread index when TCG supports
- * more than 1. We could use the object name ?
- */
+ tir->default_value = thread_index;
pir->default_value = core_pir + thread_index;
/* Set time-base frequency to 512 MHz */
@@ -241,16 +291,15 @@ static void pnv_core_realize(DeviceState *dev, Error **errp)
}
for (j = 0; j < cc->nr_threads; j++) {
- pnv_core_cpu_realize(pc, pc->threads[j], &local_err);
+ pnv_core_cpu_realize(pc, pc->threads[j], &local_err, j);
if (local_err) {
goto err;
}
}
snprintf(name, sizeof(name), "xscom-core.%d", cc->core_id);
- /* TODO: check PNV_XSCOM_EX_SIZE for p10 */
pnv_xscom_region_init(&pc->xscom_regs, OBJECT(dev), pcc->xscom_ops,
- pc, name, PNV_XSCOM_EX_SIZE);
+ pc, name, pcc->xscom_size);
qemu_register_reset(pnv_core_reset, pc);
return;
@@ -302,6 +351,7 @@ static void pnv_core_power8_class_init(ObjectClass *oc, void *data)
PnvCoreClass *pcc = PNV_CORE_CLASS(oc);
pcc->xscom_ops = &pnv_core_power8_xscom_ops;
+ pcc->xscom_size = PNV_XSCOM_EX_SIZE;
}
static void pnv_core_power9_class_init(ObjectClass *oc, void *data)
@@ -309,14 +359,15 @@ static void pnv_core_power9_class_init(ObjectClass *oc, void *data)
PnvCoreClass *pcc = PNV_CORE_CLASS(oc);
pcc->xscom_ops = &pnv_core_power9_xscom_ops;
+ pcc->xscom_size = PNV_XSCOM_EX_SIZE;
}
static void pnv_core_power10_class_init(ObjectClass *oc, void *data)
{
PnvCoreClass *pcc = PNV_CORE_CLASS(oc);
- /* TODO: Use the P9 XSCOMs for now on P10 */
- pcc->xscom_ops = &pnv_core_power9_xscom_ops;
+ pcc->xscom_ops = &pnv_core_power10_xscom_ops;
+ pcc->xscom_size = PNV10_XSCOM_EC_SIZE;
}
static void pnv_core_class_init(ObjectClass *oc, void *data)
@@ -360,8 +411,8 @@ DEFINE_TYPES(pnv_core_infos)
#define P9X_EX_NCU_SPEC_BAR 0x11010
-static uint64_t pnv_quad_xscom_read(void *opaque, hwaddr addr,
- unsigned int width)
+static uint64_t pnv_quad_power9_xscom_read(void *opaque, hwaddr addr,
+ unsigned int width)
{
uint32_t offset = addr >> 3;
uint64_t val = -1;
@@ -372,15 +423,15 @@ static uint64_t pnv_quad_xscom_read(void *opaque, hwaddr addr,
val = 0;
break;
default:
- qemu_log_mask(LOG_UNIMP, "%s: writing @0x%08x\n", __func__,
+ qemu_log_mask(LOG_UNIMP, "%s: unimp read 0x%08x\n", __func__,
offset);
}
return val;
}
-static void pnv_quad_xscom_write(void *opaque, hwaddr addr, uint64_t val,
- unsigned int width)
+static void pnv_quad_power9_xscom_write(void *opaque, hwaddr addr, uint64_t val,
+ unsigned int width)
{
uint32_t offset = addr >> 3;
@@ -389,14 +440,14 @@ static void pnv_quad_xscom_write(void *opaque, hwaddr addr, uint64_t val,
case P9X_EX_NCU_SPEC_BAR + 0x400: /* Second EX */
break;
default:
- qemu_log_mask(LOG_UNIMP, "%s: writing @0x%08x\n", __func__,
+ qemu_log_mask(LOG_UNIMP, "%s: unimp write 0x%08x\n", __func__,
offset);
}
}
-static const MemoryRegionOps pnv_quad_xscom_ops = {
- .read = pnv_quad_xscom_read,
- .write = pnv_quad_xscom_write,
+static const MemoryRegionOps pnv_quad_power9_xscom_ops = {
+ .read = pnv_quad_power9_xscom_read,
+ .write = pnv_quad_power9_xscom_write,
.valid.min_access_size = 8,
.valid.max_access_size = 8,
.impl.min_access_size = 8,
@@ -404,14 +455,124 @@ static const MemoryRegionOps pnv_quad_xscom_ops = {
.endianness = DEVICE_BIG_ENDIAN,
};
-static void pnv_quad_realize(DeviceState *dev, Error **errp)
+/*
+ * POWER10 Quads
+ */
+
+static uint64_t pnv_quad_power10_xscom_read(void *opaque, hwaddr addr,
+ unsigned int width)
+{
+ uint32_t offset = addr >> 3;
+ uint64_t val = -1;
+
+ switch (offset) {
+ default:
+ qemu_log_mask(LOG_UNIMP, "%s: unimp read 0x%08x\n", __func__,
+ offset);
+ }
+
+ return val;
+}
+
+static void pnv_quad_power10_xscom_write(void *opaque, hwaddr addr,
+ uint64_t val, unsigned int width)
+{
+ uint32_t offset = addr >> 3;
+
+ switch (offset) {
+ default:
+ qemu_log_mask(LOG_UNIMP, "%s: unimp write 0x%08x\n", __func__,
+ offset);
+ }
+}
+
+static const MemoryRegionOps pnv_quad_power10_xscom_ops = {
+ .read = pnv_quad_power10_xscom_read,
+ .write = pnv_quad_power10_xscom_write,
+ .valid.min_access_size = 8,
+ .valid.max_access_size = 8,
+ .impl.min_access_size = 8,
+ .impl.max_access_size = 8,
+ .endianness = DEVICE_BIG_ENDIAN,
+};
+
+#define P10_QME_SPWU_HYP 0x83c
+#define P10_QME_SSH_HYP 0x82c
+
+static uint64_t pnv_qme_power10_xscom_read(void *opaque, hwaddr addr,
+ unsigned int width)
+{
+ uint32_t offset = addr >> 3;
+ uint64_t val = -1;
+
+ /*
+ * Forth nibble selects the core within a quad, mask it to process read
+ * for any core.
+ */
+ switch (offset & ~0xf000) {
+ case P10_QME_SPWU_HYP:
+ case P10_QME_SSH_HYP:
+ return 0;
+ default:
+ qemu_log_mask(LOG_UNIMP, "%s: unimp read 0x%08x\n", __func__,
+ offset);
+ }
+
+ return val;
+}
+
+static void pnv_qme_power10_xscom_write(void *opaque, hwaddr addr,
+ uint64_t val, unsigned int width)
+{
+ uint32_t offset = addr >> 3;
+
+ switch (offset) {
+ default:
+ qemu_log_mask(LOG_UNIMP, "%s: unimp write 0x%08x\n", __func__,
+ offset);
+ }
+}
+
+static const MemoryRegionOps pnv_qme_power10_xscom_ops = {
+ .read = pnv_qme_power10_xscom_read,
+ .write = pnv_qme_power10_xscom_write,
+ .valid.min_access_size = 8,
+ .valid.max_access_size = 8,
+ .impl.min_access_size = 8,
+ .impl.max_access_size = 8,
+ .endianness = DEVICE_BIG_ENDIAN,
+};
+
+static void pnv_quad_power9_realize(DeviceState *dev, Error **errp)
{
PnvQuad *eq = PNV_QUAD(dev);
+ PnvQuadClass *pqc = PNV_QUAD_GET_CLASS(eq);
char name[32];
snprintf(name, sizeof(name), "xscom-quad.%d", eq->quad_id);
- pnv_xscom_region_init(&eq->xscom_regs, OBJECT(dev), &pnv_quad_xscom_ops,
- eq, name, PNV9_XSCOM_EQ_SIZE);
+ pnv_xscom_region_init(&eq->xscom_regs, OBJECT(dev),
+ pqc->xscom_ops,
+ eq, name,
+ pqc->xscom_size);
+}
+
+static void pnv_quad_power10_realize(DeviceState *dev, Error **errp)
+{
+ PnvQuad *eq = PNV_QUAD(dev);
+ PnvQuadClass *pqc = PNV_QUAD_GET_CLASS(eq);
+ char name[32];
+
+ snprintf(name, sizeof(name), "xscom-quad.%d", eq->quad_id);
+ pnv_xscom_region_init(&eq->xscom_regs, OBJECT(dev),
+ pqc->xscom_ops,
+ eq, name,
+ pqc->xscom_size);
+
+ snprintf(name, sizeof(name), "xscom-qme.%d", eq->quad_id);
+ pnv_xscom_region_init(&eq->xscom_qme_regs, OBJECT(dev),
+ pqc->xscom_qme_ops,
+ eq, name,
+ pqc->xscom_qme_size);
}
static Property pnv_quad_properties[] = {
@@ -419,25 +580,58 @@ static Property pnv_quad_properties[] = {
DEFINE_PROP_END_OF_LIST(),
};
+static void pnv_quad_power9_class_init(ObjectClass *oc, void *data)
+{
+ PnvQuadClass *pqc = PNV_QUAD_CLASS(oc);
+ DeviceClass *dc = DEVICE_CLASS(oc);
+
+ dc->realize = pnv_quad_power9_realize;
+
+ pqc->xscom_ops = &pnv_quad_power9_xscom_ops;
+ pqc->xscom_size = PNV9_XSCOM_EQ_SIZE;
+}
+
+static void pnv_quad_power10_class_init(ObjectClass *oc, void *data)
+{
+ PnvQuadClass *pqc = PNV_QUAD_CLASS(oc);
+ DeviceClass *dc = DEVICE_CLASS(oc);
+
+ dc->realize = pnv_quad_power10_realize;
+
+ pqc->xscom_ops = &pnv_quad_power10_xscom_ops;
+ pqc->xscom_size = PNV10_XSCOM_EQ_SIZE;
+
+ pqc->xscom_qme_ops = &pnv_qme_power10_xscom_ops;
+ pqc->xscom_qme_size = PNV10_XSCOM_QME_SIZE;
+}
+
static void pnv_quad_class_init(ObjectClass *oc, void *data)
{
DeviceClass *dc = DEVICE_CLASS(oc);
- dc->realize = pnv_quad_realize;
device_class_set_props(dc, pnv_quad_properties);
dc->user_creatable = false;
}
-static const TypeInfo pnv_quad_info = {
- .name = TYPE_PNV_QUAD,
- .parent = TYPE_DEVICE,
- .instance_size = sizeof(PnvQuad),
- .class_init = pnv_quad_class_init,
+static const TypeInfo pnv_quad_infos[] = {
+ {
+ .name = TYPE_PNV_QUAD,
+ .parent = TYPE_DEVICE,
+ .instance_size = sizeof(PnvQuad),
+ .class_size = sizeof(PnvQuadClass),
+ .class_init = pnv_quad_class_init,
+ .abstract = true,
+ },
+ {
+ .parent = TYPE_PNV_QUAD,
+ .name = PNV_QUAD_TYPE_NAME("power9"),
+ .class_init = pnv_quad_power9_class_init,
+ },
+ {
+ .parent = TYPE_PNV_QUAD,
+ .name = PNV_QUAD_TYPE_NAME("power10"),
+ .class_init = pnv_quad_power10_class_init,
+ },
};
-static void pnv_core_register_types(void)
-{
- type_register_static(&pnv_quad_info);
-}
-
-type_init(pnv_core_register_types)
+DEFINE_TYPES(pnv_quad_infos);
diff --git a/hw/ppc/pnv_psi.c b/hw/ppc/pnv_psi.c
index 8aa09ab..daaa2f0 100644
--- a/hw/ppc/pnv_psi.c
+++ b/hw/ppc/pnv_psi.c
@@ -121,8 +121,12 @@
#define PSIHB9_BAR_MASK 0x00fffffffff00000ull
#define PSIHB9_FSPBAR_MASK 0x00ffffff00000000ull
+/* mmio address to xscom address */
#define PSIHB_REG(addr) (((addr) >> 3) + PSIHB_XSCOM_BAR)
+/* xscom address to mmio address */
+#define PSIHB_MMIO(reg) ((reg - PSIHB_XSCOM_BAR) << 3)
+
static void pnv_psi_set_bar(PnvPsi *psi, uint64_t bar)
{
PnvPsiClass *ppc = PNV_PSI_GET_CLASS(psi);
@@ -769,24 +773,31 @@ static const MemoryRegionOps pnv_psi_p9_mmio_ops = {
static uint64_t pnv_psi_p9_xscom_read(void *opaque, hwaddr addr, unsigned size)
{
- /* No read are expected */
- qemu_log_mask(LOG_GUEST_ERROR, "PSI: xscom read at 0x%" PRIx64 "\n", addr);
- return -1;
+ uint32_t reg = addr >> 3;
+ uint64_t val = -1;
+
+ if (reg < PSIHB_XSCOM_BAR) {
+ /* FIR, not modeled */
+ qemu_log_mask(LOG_UNIMP, "PSI: xscom read at 0x%08x\n", reg);
+ } else {
+ val = pnv_psi_p9_mmio_read(opaque, PSIHB_MMIO(reg), size);
+ }
+ return val;
}
static void pnv_psi_p9_xscom_write(void *opaque, hwaddr addr,
uint64_t val, unsigned size)
{
PnvPsi *psi = PNV_PSI(opaque);
+ uint32_t reg = addr >> 3;
- /* XSCOM is only used to set the PSIHB MMIO region */
- switch (addr >> 3) {
- case PSIHB_XSCOM_BAR:
+ if (reg < PSIHB_XSCOM_BAR) {
+ /* FIR, not modeled */
+ qemu_log_mask(LOG_UNIMP, "PSI: xscom write at 0x%08x\n", reg);
+ } else if (reg == PSIHB_XSCOM_BAR) {
pnv_psi_set_bar(psi, val);
- break;
- default:
- qemu_log_mask(LOG_GUEST_ERROR, "PSI: xscom write at 0x%" PRIx64 "\n",
- addr);
+ } else {
+ pnv_psi_p9_mmio_write(opaque, PSIHB_MMIO(reg), val, size);
}
}
@@ -852,6 +863,8 @@ static void pnv_psi_power9_realize(DeviceState *dev, Error **errp)
object_property_set_int(OBJECT(xsrc), "nr-irqs", PSIHB9_NUM_IRQS,
&error_fatal);
object_property_set_link(OBJECT(xsrc), "xive", OBJECT(psi), &error_abort);
+ object_property_set_int(OBJECT(xsrc), "reset-pq", XIVE_ESB_RESET,
+ &error_abort);
if (!qdev_realize(DEVICE(xsrc), NULL, errp)) {
return;
}
diff --git a/hw/ppc/ppc.c b/hw/ppc/ppc.c
index 82e4408..0e0a3d9 100644
--- a/hw/ppc/ppc.c
+++ b/hw/ppc/ppc.c
@@ -535,23 +535,24 @@ static inline void cpu_ppc_store_tb(ppc_tb_t *tb_env, uint64_t vmclk,
void cpu_ppc_store_tbl (CPUPPCState *env, uint32_t value)
{
ppc_tb_t *tb_env = env->tb_env;
+ int64_t clock = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
uint64_t tb;
- tb = cpu_ppc_get_tb(tb_env, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), tb_env->tb_offset);
+ tb = cpu_ppc_get_tb(tb_env, clock, tb_env->tb_offset);
tb &= 0xFFFFFFFF00000000ULL;
- cpu_ppc_store_tb(tb_env, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL),
- &tb_env->tb_offset, tb | (uint64_t)value);
+ cpu_ppc_store_tb(tb_env, clock, &tb_env->tb_offset, tb | (uint64_t)value);
}
static inline void _cpu_ppc_store_tbu(CPUPPCState *env, uint32_t value)
{
ppc_tb_t *tb_env = env->tb_env;
+ int64_t clock = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
uint64_t tb;
- tb = cpu_ppc_get_tb(tb_env, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), tb_env->tb_offset);
+ tb = cpu_ppc_get_tb(tb_env, clock, tb_env->tb_offset);
tb &= 0x00000000FFFFFFFFULL;
- cpu_ppc_store_tb(tb_env, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL),
- &tb_env->tb_offset, ((uint64_t)value << 32) | tb);
+ cpu_ppc_store_tb(tb_env, clock, &tb_env->tb_offset,
+ ((uint64_t)value << 32) | tb);
}
void cpu_ppc_store_tbu (CPUPPCState *env, uint32_t value)
@@ -584,23 +585,24 @@ uint32_t cpu_ppc_load_atbu (CPUPPCState *env)
void cpu_ppc_store_atbl (CPUPPCState *env, uint32_t value)
{
ppc_tb_t *tb_env = env->tb_env;
+ int64_t clock = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
uint64_t tb;
- tb = cpu_ppc_get_tb(tb_env, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), tb_env->atb_offset);
+ tb = cpu_ppc_get_tb(tb_env, clock, tb_env->atb_offset);
tb &= 0xFFFFFFFF00000000ULL;
- cpu_ppc_store_tb(tb_env, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL),
- &tb_env->atb_offset, tb | (uint64_t)value);
+ cpu_ppc_store_tb(tb_env, clock, &tb_env->atb_offset, tb | (uint64_t)value);
}
void cpu_ppc_store_atbu (CPUPPCState *env, uint32_t value)
{
ppc_tb_t *tb_env = env->tb_env;
+ int64_t clock = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
uint64_t tb;
- tb = cpu_ppc_get_tb(tb_env, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), tb_env->atb_offset);
+ tb = cpu_ppc_get_tb(tb_env, clock, tb_env->atb_offset);
tb &= 0x00000000FFFFFFFFULL;
- cpu_ppc_store_tb(tb_env, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL),
- &tb_env->atb_offset, ((uint64_t)value << 32) | tb);
+ cpu_ppc_store_tb(tb_env, clock, &tb_env->atb_offset,
+ ((uint64_t)value << 32) | tb);
}
uint64_t cpu_ppc_load_vtb(CPUPPCState *env)
@@ -622,14 +624,13 @@ void cpu_ppc_store_vtb(CPUPPCState *env, uint64_t value)
void cpu_ppc_store_tbu40(CPUPPCState *env, uint64_t value)
{
ppc_tb_t *tb_env = env->tb_env;
+ int64_t clock = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
uint64_t tb;
- tb = cpu_ppc_get_tb(tb_env, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL),
- tb_env->tb_offset);
+ tb = cpu_ppc_get_tb(tb_env, clock, tb_env->tb_offset);
tb &= 0xFFFFFFUL;
tb |= (value & ~0xFFFFFFUL);
- cpu_ppc_store_tb(tb_env, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL),
- &tb_env->tb_offset, tb);
+ cpu_ppc_store_tb(tb_env, clock, &tb_env->tb_offset, tb);
}
static void cpu_ppc_tb_stop (CPUPPCState *env)
@@ -788,8 +789,8 @@ static void __cpu_ppc_store_decr(PowerPCCPU *cpu, uint64_t *nextp,
QEMUTimer *timer,
void (*raise_excp)(void *),
void (*lower_excp)(PowerPCCPU *),
- target_ulong decr, target_ulong value,
- int nr_bits)
+ uint32_t flags, target_ulong decr,
+ target_ulong value, int nr_bits)
{
CPUPPCState *env = &cpu->env;
ppc_tb_t *tb_env = env->tb_env;
@@ -819,15 +820,15 @@ static void __cpu_ppc_store_decr(PowerPCCPU *cpu, uint64_t *nextp,
* On MSB edge based DEC implementations the MSB going from 0 -> 1 triggers
* an edge interrupt, so raise it here too.
*/
- if (((tb_env->flags & PPC_DECR_UNDERFLOW_LEVEL) && signed_value < 0) ||
- ((tb_env->flags & PPC_DECR_UNDERFLOW_TRIGGERED) && signed_value < 0
+ if (((flags & PPC_DECR_UNDERFLOW_LEVEL) && signed_value < 0) ||
+ ((flags & PPC_DECR_UNDERFLOW_TRIGGERED) && signed_value < 0
&& signed_decr >= 0)) {
(*raise_excp)(cpu);
return;
}
/* On MSB level based systems a 0 for the MSB stops interrupt delivery */
- if (signed_value >= 0 && (tb_env->flags & PPC_DECR_UNDERFLOW_LEVEL)) {
+ if (signed_value >= 0 && (flags & PPC_DECR_UNDERFLOW_LEVEL)) {
(*lower_excp)(cpu);
}
@@ -846,8 +847,8 @@ static inline void _cpu_ppc_store_decr(PowerPCCPU *cpu, target_ulong decr,
ppc_tb_t *tb_env = cpu->env.tb_env;
__cpu_ppc_store_decr(cpu, &tb_env->decr_next, tb_env->decr_timer,
- tb_env->decr_timer->cb, &cpu_ppc_decr_lower, decr,
- value, nr_bits);
+ tb_env->decr_timer->cb, &cpu_ppc_decr_lower,
+ tb_env->flags, decr, value, nr_bits);
}
void cpu_ppc_store_decr(CPUPPCState *env, target_ulong value)
@@ -876,8 +877,10 @@ static inline void _cpu_ppc_store_hdecr(PowerPCCPU *cpu, target_ulong hdecr,
ppc_tb_t *tb_env = cpu->env.tb_env;
if (tb_env->hdecr_timer != NULL) {
+ /* HDECR (Book3S 64bit) is edge-based, not level like DECR */
__cpu_ppc_store_decr(cpu, &tb_env->hdecr_next, tb_env->hdecr_timer,
tb_env->hdecr_timer->cb, &cpu_ppc_hdecr_lower,
+ PPC_DECR_UNDERFLOW_TRIGGERED,
hdecr, value, nr_bits);
}
}
diff --git a/hw/ppc/ppc440.h b/hw/ppc/ppc440.h
index 7c24db8..909373f 100644
--- a/hw/ppc/ppc440.h
+++ b/hw/ppc/ppc440.h
@@ -18,6 +18,5 @@ void ppc4xx_cpr_init(CPUPPCState *env);
void ppc4xx_sdr_init(CPUPPCState *env);
void ppc4xx_ahb_init(CPUPPCState *env);
void ppc4xx_dma_init(CPUPPCState *env, int dcr_base);
-void ppc460ex_pcie_init(CPUPPCState *env);
#endif /* PPC440_H */
diff --git a/hw/ppc/ppc440_bamboo.c b/hw/ppc/ppc440_bamboo.c
index f061b8c..45f409c 100644
--- a/hw/ppc/ppc440_bamboo.c
+++ b/hw/ppc/ppc440_bamboo.c
@@ -205,8 +205,7 @@ static void bamboo_init(MachineState *machine)
ppc4xx_sdram_ddr_enable(PPC4xx_SDRAM_DDR(dev));
/* PCI */
- dev = sysbus_create_varargs(TYPE_PPC4xx_PCI_HOST_BRIDGE,
- PPC440EP_PCI_CONFIG,
+ dev = sysbus_create_varargs(TYPE_PPC4xx_PCI_HOST, PPC440EP_PCI_CONFIG,
qdev_get_gpio_in(uicdev, pci_irq_nrs[0]),
qdev_get_gpio_in(uicdev, pci_irq_nrs[1]),
qdev_get_gpio_in(uicdev, pci_irq_nrs[2]),
diff --git a/hw/ppc/ppc440_pcix.c b/hw/ppc/ppc440_pcix.c
index f10f93c..672090d 100644
--- a/hw/ppc/ppc440_pcix.c
+++ b/hw/ppc/ppc440_pcix.c
@@ -23,6 +23,7 @@
#include "qemu/error-report.h"
#include "qemu/log.h"
#include "qemu/module.h"
+#include "qemu/units.h"
#include "hw/irq.h"
#include "hw/ppc/ppc.h"
#include "hw/ppc/ppc4xx.h"
@@ -44,8 +45,7 @@ struct PLBInMap {
MemoryRegion mr;
};
-#define TYPE_PPC440_PCIX_HOST_BRIDGE "ppc440-pcix-host"
-OBJECT_DECLARE_SIMPLE_TYPE(PPC440PCIXState, PPC440_PCIX_HOST_BRIDGE)
+OBJECT_DECLARE_SIMPLE_TYPE(PPC440PCIXState, PPC440_PCIX_HOST)
#define PPC440_PCIX_NR_POMS 3
#define PPC440_PCIX_NR_PIMS 3
@@ -64,6 +64,7 @@ struct PPC440PCIXState {
MemoryRegion container;
MemoryRegion iomem;
MemoryRegion busmem;
+ MemoryRegion regs;
};
#define PPC440_REG_BASE 0x80000
@@ -397,7 +398,7 @@ static const MemoryRegionOps pci_reg_ops = {
static void ppc440_pcix_reset(DeviceState *dev)
{
- struct PPC440PCIXState *s = PPC440_PCIX_HOST_BRIDGE(dev);
+ struct PPC440PCIXState *s = PPC440_PCIX_HOST(dev);
int i;
for (i = 0; i < PPC440_PCIX_NR_POMS; i++) {
@@ -487,15 +488,17 @@ static void ppc440_pcix_realize(DeviceState *dev, Error **errp)
PCIHostState *h;
h = PCI_HOST_BRIDGE(dev);
- s = PPC440_PCIX_HOST_BRIDGE(dev);
+ s = PPC440_PCIX_HOST(dev);
sysbus_init_irq(sbd, &s->irq);
- memory_region_init(&s->busmem, OBJECT(dev), "pci bus memory", UINT64_MAX);
+ memory_region_init(&s->busmem, OBJECT(dev), "pci-mem", UINT64_MAX);
+ memory_region_init(&s->iomem, OBJECT(dev), "pci-io", 64 * KiB);
h->bus = pci_register_root_bus(dev, NULL, ppc440_pcix_set_irq,
- ppc440_pcix_map_irq, &s->irq, &s->busmem,
- get_system_io(), PCI_DEVFN(0, 0), 1, TYPE_PCI_BUS);
+ ppc440_pcix_map_irq, &s->irq, &s->busmem, &s->iomem,
+ PCI_DEVFN(0, 0), 1, TYPE_PCI_BUS);
- s->dev = pci_create_simple(h->bus, PCI_DEVFN(0, 0), "ppc4xx-host-bridge");
+ s->dev = pci_create_simple(h->bus, PCI_DEVFN(0, 0),
+ TYPE_PPC4xx_HOST_BRIDGE);
memory_region_init(&s->bm, OBJECT(s), "bm-ppc440-pcix", UINT64_MAX);
memory_region_add_subregion(&s->bm, 0x0, &s->busmem);
@@ -507,12 +510,13 @@ static void ppc440_pcix_realize(DeviceState *dev, Error **errp)
h, "pci-conf-idx", 4);
memory_region_init_io(&h->data_mem, OBJECT(s), &pci_host_data_le_ops,
h, "pci-conf-data", 4);
- memory_region_init_io(&s->iomem, OBJECT(s), &pci_reg_ops, s,
- "pci.reg", PPC440_REG_SIZE);
+ memory_region_init_io(&s->regs, OBJECT(s), &pci_reg_ops, s, "pci-reg",
+ PPC440_REG_SIZE);
memory_region_add_subregion(&s->container, PCIC0_CFGADDR, &h->conf_mem);
memory_region_add_subregion(&s->container, PCIC0_CFGDATA, &h->data_mem);
- memory_region_add_subregion(&s->container, PPC440_REG_BASE, &s->iomem);
+ memory_region_add_subregion(&s->container, PPC440_REG_BASE, &s->regs);
sysbus_init_mmio(sbd, &s->container);
+ sysbus_init_mmio(sbd, &s->iomem);
}
static void ppc440_pcix_class_init(ObjectClass *klass, void *data)
@@ -524,7 +528,7 @@ static void ppc440_pcix_class_init(ObjectClass *klass, void *data)
}
static const TypeInfo ppc440_pcix_info = {
- .name = TYPE_PPC440_PCIX_HOST_BRIDGE,
+ .name = TYPE_PPC440_PCIX_HOST,
.parent = TYPE_PCI_HOST_BRIDGE,
.instance_size = sizeof(PPC440PCIXState),
.class_init = ppc440_pcix_class_init,
diff --git a/hw/ppc/ppc440_uc.c b/hw/ppc/ppc440_uc.c
index 6512639..4181c84 100644
--- a/hw/ppc/ppc440_uc.c
+++ b/hw/ppc/ppc440_uc.c
@@ -17,6 +17,7 @@
#include "hw/qdev-properties.h"
#include "hw/pci/pci.h"
#include "sysemu/reset.h"
+#include "cpu.h"
#include "ppc440.h"
/*****************************************************************************/
@@ -769,15 +770,17 @@ void ppc4xx_dma_init(CPUPPCState *env, int dcr_base)
*/
#include "hw/pci/pcie_host.h"
-#define TYPE_PPC460EX_PCIE_HOST "ppc460ex-pcie-host"
OBJECT_DECLARE_SIMPLE_TYPE(PPC460EXPCIEState, PPC460EX_PCIE_HOST)
struct PPC460EXPCIEState {
- PCIExpressHost host;
+ PCIExpressHost parent_obj;
+ MemoryRegion busmem;
MemoryRegion iomem;
qemu_irq irq[4];
+ int32_t num;
int32_t dcrn_base;
+ PowerPCCPU *cpu;
uint64_t cfg_base;
uint32_t cfg_mask;
@@ -795,9 +798,6 @@ struct PPC460EXPCIEState {
uint32_t cfg;
};
-#define DCRN_PCIE0_BASE 0x100
-#define DCRN_PCIE1_BASE 0x120
-
enum {
PEGPL_CFGBAH = 0x0,
PEGPL_CFGBAL,
@@ -826,78 +826,78 @@ enum {
static uint32_t dcr_read_pcie(void *opaque, int dcrn)
{
- PPC460EXPCIEState *state = opaque;
+ PPC460EXPCIEState *s = opaque;
uint32_t ret = 0;
- switch (dcrn - state->dcrn_base) {
+ switch (dcrn - s->dcrn_base) {
case PEGPL_CFGBAH:
- ret = state->cfg_base >> 32;
+ ret = s->cfg_base >> 32;
break;
case PEGPL_CFGBAL:
- ret = state->cfg_base;
+ ret = s->cfg_base;
break;
case PEGPL_CFGMSK:
- ret = state->cfg_mask;
+ ret = s->cfg_mask;
break;
case PEGPL_MSGBAH:
- ret = state->msg_base >> 32;
+ ret = s->msg_base >> 32;
break;
case PEGPL_MSGBAL:
- ret = state->msg_base;
+ ret = s->msg_base;
break;
case PEGPL_MSGMSK:
- ret = state->msg_mask;
+ ret = s->msg_mask;
break;
case PEGPL_OMR1BAH:
- ret = state->omr1_base >> 32;
+ ret = s->omr1_base >> 32;
break;
case PEGPL_OMR1BAL:
- ret = state->omr1_base;
+ ret = s->omr1_base;
break;
case PEGPL_OMR1MSKH:
- ret = state->omr1_mask >> 32;
+ ret = s->omr1_mask >> 32;
break;
case PEGPL_OMR1MSKL:
- ret = state->omr1_mask;
+ ret = s->omr1_mask;
break;
case PEGPL_OMR2BAH:
- ret = state->omr2_base >> 32;
+ ret = s->omr2_base >> 32;
break;
case PEGPL_OMR2BAL:
- ret = state->omr2_base;
+ ret = s->omr2_base;
break;
case PEGPL_OMR2MSKH:
- ret = state->omr2_mask >> 32;
+ ret = s->omr2_mask >> 32;
break;
case PEGPL_OMR2MSKL:
- ret = state->omr3_mask;
+ ret = s->omr3_mask;
break;
case PEGPL_OMR3BAH:
- ret = state->omr3_base >> 32;
+ ret = s->omr3_base >> 32;
break;
case PEGPL_OMR3BAL:
- ret = state->omr3_base;
+ ret = s->omr3_base;
break;
case PEGPL_OMR3MSKH:
- ret = state->omr3_mask >> 32;
+ ret = s->omr3_mask >> 32;
break;
case PEGPL_OMR3MSKL:
- ret = state->omr3_mask;
+ ret = s->omr3_mask;
break;
case PEGPL_REGBAH:
- ret = state->reg_base >> 32;
+ ret = s->reg_base >> 32;
break;
case PEGPL_REGBAL:
- ret = state->reg_base;
+ ret = s->reg_base;
break;
case PEGPL_REGMSK:
- ret = state->reg_mask;
+ ret = s->reg_mask;
break;
case PEGPL_SPECIAL:
- ret = state->special;
+ ret = s->special;
break;
case PEGPL_CFG:
- ret = state->cfg;
+ ret = s->cfg;
break;
}
@@ -1000,37 +1000,72 @@ static void ppc460ex_set_irq(void *opaque, int irq_num, int level)
qemu_set_irq(s->irq[irq_num], level);
}
+#define PPC440_PCIE_DCR(s, dcrn) \
+ ppc_dcr_register(&(s)->cpu->env, (s)->dcrn_base + (dcrn), (s), \
+ &dcr_read_pcie, &dcr_write_pcie)
+
+
+static void ppc460ex_pcie_register_dcrs(PPC460EXPCIEState *s)
+{
+ PPC440_PCIE_DCR(s, PEGPL_CFGBAH);
+ PPC440_PCIE_DCR(s, PEGPL_CFGBAL);
+ PPC440_PCIE_DCR(s, PEGPL_CFGMSK);
+ PPC440_PCIE_DCR(s, PEGPL_MSGBAH);
+ PPC440_PCIE_DCR(s, PEGPL_MSGBAL);
+ PPC440_PCIE_DCR(s, PEGPL_MSGMSK);
+ PPC440_PCIE_DCR(s, PEGPL_OMR1BAH);
+ PPC440_PCIE_DCR(s, PEGPL_OMR1BAL);
+ PPC440_PCIE_DCR(s, PEGPL_OMR1MSKH);
+ PPC440_PCIE_DCR(s, PEGPL_OMR1MSKL);
+ PPC440_PCIE_DCR(s, PEGPL_OMR2BAH);
+ PPC440_PCIE_DCR(s, PEGPL_OMR2BAL);
+ PPC440_PCIE_DCR(s, PEGPL_OMR2MSKH);
+ PPC440_PCIE_DCR(s, PEGPL_OMR2MSKL);
+ PPC440_PCIE_DCR(s, PEGPL_OMR3BAH);
+ PPC440_PCIE_DCR(s, PEGPL_OMR3BAL);
+ PPC440_PCIE_DCR(s, PEGPL_OMR3MSKH);
+ PPC440_PCIE_DCR(s, PEGPL_OMR3MSKL);
+ PPC440_PCIE_DCR(s, PEGPL_REGBAH);
+ PPC440_PCIE_DCR(s, PEGPL_REGBAL);
+ PPC440_PCIE_DCR(s, PEGPL_REGMSK);
+ PPC440_PCIE_DCR(s, PEGPL_SPECIAL);
+ PPC440_PCIE_DCR(s, PEGPL_CFG);
+}
+
static void ppc460ex_pcie_realize(DeviceState *dev, Error **errp)
{
PPC460EXPCIEState *s = PPC460EX_PCIE_HOST(dev);
PCIHostState *pci = PCI_HOST_BRIDGE(dev);
- int i, id;
- char buf[16];
+ int i;
+ char buf[20];
- switch (s->dcrn_base) {
- case DCRN_PCIE0_BASE:
- id = 0;
- break;
- case DCRN_PCIE1_BASE:
- id = 1;
- break;
- default:
- error_setg(errp, "invalid PCIe DCRN base");
+ if (!s->cpu) {
+ error_setg(errp, "cpu link property must be set");
+ return;
+ }
+ if (s->num < 0 || s->dcrn_base < 0) {
+ error_setg(errp, "busnum and dcrn-base properties must be set");
return;
}
- snprintf(buf, sizeof(buf), "pcie%d-io", id);
- memory_region_init(&s->iomem, OBJECT(s), buf, UINT64_MAX);
+ snprintf(buf, sizeof(buf), "pcie%d-mem", s->num);
+ memory_region_init(&s->busmem, OBJECT(s), buf, UINT64_MAX);
+ snprintf(buf, sizeof(buf), "pcie%d-io", s->num);
+ memory_region_init(&s->iomem, OBJECT(s), buf, 64 * KiB);
for (i = 0; i < 4; i++) {
sysbus_init_irq(SYS_BUS_DEVICE(dev), &s->irq[i]);
}
- snprintf(buf, sizeof(buf), "pcie.%d", id);
+ snprintf(buf, sizeof(buf), "pcie.%d", s->num);
pci->bus = pci_register_root_bus(DEVICE(s), buf, ppc460ex_set_irq,
- pci_swizzle_map_irq_fn, s, &s->iomem,
- get_system_io(), 0, 4, TYPE_PCIE_BUS);
+ pci_swizzle_map_irq_fn, s, &s->busmem,
+ &s->iomem, 0, 4, TYPE_PCIE_BUS);
+ ppc460ex_pcie_register_dcrs(s);
}
static Property ppc460ex_pcie_props[] = {
+ DEFINE_PROP_INT32("busnum", PPC460EXPCIEState, num, -1),
DEFINE_PROP_INT32("dcrn-base", PPC460EXPCIEState, dcrn_base, -1),
+ DEFINE_PROP_LINK("cpu", PPC460EXPCIEState, cpu, TYPE_POWERPC_CPU,
+ PowerPCCPU *),
DEFINE_PROP_END_OF_LIST(),
};
@@ -1057,68 +1092,3 @@ static void ppc460ex_pcie_register(void)
}
type_init(ppc460ex_pcie_register)
-
-static void ppc460ex_pcie_register_dcrs(PPC460EXPCIEState *s, CPUPPCState *env)
-{
- ppc_dcr_register(env, s->dcrn_base + PEGPL_CFGBAH, s,
- &dcr_read_pcie, &dcr_write_pcie);
- ppc_dcr_register(env, s->dcrn_base + PEGPL_CFGBAL, s,
- &dcr_read_pcie, &dcr_write_pcie);
- ppc_dcr_register(env, s->dcrn_base + PEGPL_CFGMSK, s,
- &dcr_read_pcie, &dcr_write_pcie);
- ppc_dcr_register(env, s->dcrn_base + PEGPL_MSGBAH, s,
- &dcr_read_pcie, &dcr_write_pcie);
- ppc_dcr_register(env, s->dcrn_base + PEGPL_MSGBAL, s,
- &dcr_read_pcie, &dcr_write_pcie);
- ppc_dcr_register(env, s->dcrn_base + PEGPL_MSGMSK, s,
- &dcr_read_pcie, &dcr_write_pcie);
- ppc_dcr_register(env, s->dcrn_base + PEGPL_OMR1BAH, s,
- &dcr_read_pcie, &dcr_write_pcie);
- ppc_dcr_register(env, s->dcrn_base + PEGPL_OMR1BAL, s,
- &dcr_read_pcie, &dcr_write_pcie);
- ppc_dcr_register(env, s->dcrn_base + PEGPL_OMR1MSKH, s,
- &dcr_read_pcie, &dcr_write_pcie);
- ppc_dcr_register(env, s->dcrn_base + PEGPL_OMR1MSKL, s,
- &dcr_read_pcie, &dcr_write_pcie);
- ppc_dcr_register(env, s->dcrn_base + PEGPL_OMR2BAH, s,
- &dcr_read_pcie, &dcr_write_pcie);
- ppc_dcr_register(env, s->dcrn_base + PEGPL_OMR2BAL, s,
- &dcr_read_pcie, &dcr_write_pcie);
- ppc_dcr_register(env, s->dcrn_base + PEGPL_OMR2MSKH, s,
- &dcr_read_pcie, &dcr_write_pcie);
- ppc_dcr_register(env, s->dcrn_base + PEGPL_OMR2MSKL, s,
- &dcr_read_pcie, &dcr_write_pcie);
- ppc_dcr_register(env, s->dcrn_base + PEGPL_OMR3BAH, s,
- &dcr_read_pcie, &dcr_write_pcie);
- ppc_dcr_register(env, s->dcrn_base + PEGPL_OMR3BAL, s,
- &dcr_read_pcie, &dcr_write_pcie);
- ppc_dcr_register(env, s->dcrn_base + PEGPL_OMR3MSKH, s,
- &dcr_read_pcie, &dcr_write_pcie);
- ppc_dcr_register(env, s->dcrn_base + PEGPL_OMR3MSKL, s,
- &dcr_read_pcie, &dcr_write_pcie);
- ppc_dcr_register(env, s->dcrn_base + PEGPL_REGBAH, s,
- &dcr_read_pcie, &dcr_write_pcie);
- ppc_dcr_register(env, s->dcrn_base + PEGPL_REGBAL, s,
- &dcr_read_pcie, &dcr_write_pcie);
- ppc_dcr_register(env, s->dcrn_base + PEGPL_REGMSK, s,
- &dcr_read_pcie, &dcr_write_pcie);
- ppc_dcr_register(env, s->dcrn_base + PEGPL_SPECIAL, s,
- &dcr_read_pcie, &dcr_write_pcie);
- ppc_dcr_register(env, s->dcrn_base + PEGPL_CFG, s,
- &dcr_read_pcie, &dcr_write_pcie);
-}
-
-void ppc460ex_pcie_init(CPUPPCState *env)
-{
- DeviceState *dev;
-
- dev = qdev_new(TYPE_PPC460EX_PCIE_HOST);
- qdev_prop_set_int32(dev, "dcrn-base", DCRN_PCIE0_BASE);
- sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
- ppc460ex_pcie_register_dcrs(PPC460EX_PCIE_HOST(dev), env);
-
- dev = qdev_new(TYPE_PPC460EX_PCIE_HOST);
- qdev_prop_set_int32(dev, "dcrn-base", DCRN_PCIE1_BASE);
- sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
- ppc460ex_pcie_register_dcrs(PPC460EX_PCIE_HOST(dev), env);
-}
diff --git a/hw/ppc/ppc4xx_pci.c b/hw/ppc/ppc4xx_pci.c
index 1d4a50f..6652119 100644
--- a/hw/ppc/ppc4xx_pci.c
+++ b/hw/ppc/ppc4xx_pci.c
@@ -46,7 +46,7 @@ struct PCITargetMap {
uint32_t la;
};
-OBJECT_DECLARE_SIMPLE_TYPE(PPC4xxPCIState, PPC4xx_PCI_HOST_BRIDGE)
+OBJECT_DECLARE_SIMPLE_TYPE(PPC4xxPCIState, PPC4xx_PCI_HOST)
#define PPC4xx_PCI_NR_PMMS 3
#define PPC4xx_PCI_NR_PTMS 2
@@ -321,7 +321,7 @@ static void ppc4xx_pcihost_realize(DeviceState *dev, Error **errp)
int i;
h = PCI_HOST_BRIDGE(dev);
- s = PPC4xx_PCI_HOST_BRIDGE(dev);
+ s = PPC4xx_PCI_HOST(dev);
for (i = 0; i < ARRAY_SIZE(s->irq); i++) {
sysbus_init_irq(sbd, &s->irq[i]);
@@ -333,7 +333,7 @@ static void ppc4xx_pcihost_realize(DeviceState *dev, Error **errp)
TYPE_PCI_BUS);
h->bus = b;
- pci_create_simple(b, 0, "ppc4xx-host-bridge");
+ pci_create_simple(b, 0, TYPE_PPC4xx_HOST_BRIDGE);
/* XXX split into 2 memory regions, one for config space, one for regs */
memory_region_init(&s->container, OBJECT(s), "pci-container", PCI_ALL_SIZE);
@@ -367,7 +367,7 @@ static void ppc4xx_host_bridge_class_init(ObjectClass *klass, void *data)
}
static const TypeInfo ppc4xx_host_bridge_info = {
- .name = "ppc4xx-host-bridge",
+ .name = TYPE_PPC4xx_HOST_BRIDGE,
.parent = TYPE_PCI_DEVICE,
.instance_size = sizeof(PCIDevice),
.class_init = ppc4xx_host_bridge_class_init,
@@ -386,7 +386,7 @@ static void ppc4xx_pcihost_class_init(ObjectClass *klass, void *data)
}
static const TypeInfo ppc4xx_pcihost_info = {
- .name = TYPE_PPC4xx_PCI_HOST_BRIDGE,
+ .name = TYPE_PPC4xx_PCI_HOST,
.parent = TYPE_PCI_HOST_BRIDGE,
.instance_size = sizeof(PPC4xxPCIState),
.class_init = ppc4xx_pcihost_class_init,
diff --git a/hw/ppc/sam460ex.c b/hw/ppc/sam460ex.c
index cf065aa..1e615b8 100644
--- a/hw/ppc/sam460ex.c
+++ b/hw/ppc/sam460ex.c
@@ -45,6 +45,9 @@
/* dd bs=1 skip=$(($(stat -c '%s' updater/updater-460) - 0x80000)) \
if=updater/updater-460 of=u-boot-sam460-20100605.bin */
+#define PCIE0_DCRN_BASE 0x100
+#define PCIE1_DCRN_BASE 0x120
+
/* from Sam460 U-Boot include/configs/Sam460ex.h */
#define FLASH_BASE 0xfff00000
#define FLASH_BASE_H 0x4
@@ -266,8 +269,6 @@ static void main_cpu_reset(void *opaque)
static void sam460ex_init(MachineState *machine)
{
- MemoryRegion *address_space_mem = get_system_memory();
- MemoryRegion *isa = g_new(MemoryRegion, 1);
MemoryRegion *l2cache_ram = g_new(MemoryRegion, 1);
DeviceState *uic[4];
int i;
@@ -406,7 +407,8 @@ static void sam460ex_init(MachineState *machine)
/* FIXME: remove this after fixing l2sram mapping in ppc440_uc.c? */
memory_region_init_ram(l2cache_ram, NULL, "ppc440.l2cache_ram", 256 * KiB,
&error_abort);
- memory_region_add_subregion(address_space_mem, 0x400000000LL, l2cache_ram);
+ memory_region_add_subregion(get_system_memory(), 0x400000000LL,
+ l2cache_ram);
/* USB */
sysbus_create_simple(TYPE_PPC4xx_EHCI, 0x4bffd0400,
@@ -421,17 +423,26 @@ static void sam460ex_init(MachineState *machine)
usb_create_simple(usb_bus_find(-1), "usb-kbd");
usb_create_simple(usb_bus_find(-1), "usb-mouse");
+ /* PCIe buses */
+ dev = qdev_new(TYPE_PPC460EX_PCIE_HOST);
+ qdev_prop_set_int32(dev, "busnum", 0);
+ qdev_prop_set_int32(dev, "dcrn-base", PCIE0_DCRN_BASE);
+ object_property_set_link(OBJECT(dev), "cpu", OBJECT(cpu), &error_abort);
+ sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
+
+ dev = qdev_new(TYPE_PPC460EX_PCIE_HOST);
+ qdev_prop_set_int32(dev, "busnum", 1);
+ qdev_prop_set_int32(dev, "dcrn-base", PCIE1_DCRN_BASE);
+ object_property_set_link(OBJECT(dev), "cpu", OBJECT(cpu), &error_abort);
+ sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
+
/* PCI bus */
- ppc460ex_pcie_init(env);
/* All PCI irqs are connected to the same UIC pin (cf. UBoot source) */
- dev = sysbus_create_simple("ppc440-pcix-host", 0xc0ec00000,
+ dev = sysbus_create_simple(TYPE_PPC440_PCIX_HOST, 0xc0ec00000,
qdev_get_gpio_in(uic[1], 0));
+ sysbus_mmio_map(SYS_BUS_DEVICE(dev), 1, 0xc08000000);
pci_bus = PCI_BUS(qdev_get_child_bus(dev, "pci.0"));
- memory_region_init_alias(isa, NULL, "isa_mmio", get_system_io(),
- 0, 0x10000);
- memory_region_add_subregion(get_system_memory(), 0xc08000000, isa);
-
/* PCI devices */
pci_create_simple(pci_bus, PCI_DEVFN(6, 0), "sm501");
/* SoC has a single SATA port but we don't emulate that yet
@@ -444,13 +455,13 @@ static void sam460ex_init(MachineState *machine)
/* SoC has 4 UARTs
* but board has only one wired and two are present in fdt */
if (serial_hd(0) != NULL) {
- serial_mm_init(address_space_mem, 0x4ef600300, 0,
+ serial_mm_init(get_system_memory(), 0x4ef600300, 0,
qdev_get_gpio_in(uic[1], 1),
PPC_SERIAL_MM_BAUDBASE, serial_hd(0),
DEVICE_BIG_ENDIAN);
}
if (serial_hd(1) != NULL) {
- serial_mm_init(address_space_mem, 0x4ef600400, 0,
+ serial_mm_init(get_system_memory(), 0x4ef600400, 0,
qdev_get_gpio_in(uic[0], 1),
PPC_SERIAL_MM_BAUDBASE, serial_hd(1),
DEVICE_BIG_ENDIAN);
diff --git a/hw/ppc/spapr_cpu_core.c b/hw/ppc/spapr_cpu_core.c
index a4e3c2f..b482d97 100644
--- a/hw/ppc/spapr_cpu_core.c
+++ b/hw/ppc/spapr_cpu_core.c
@@ -270,6 +270,8 @@ static bool spapr_realize_vcpu(PowerPCCPU *cpu, SpaprMachineState *spapr,
env->spr_cb[SPR_PIR].default_value = cs->cpu_index;
env->spr_cb[SPR_TIR].default_value = thread_index;
+ cpu_ppc_set_1lpar(cpu);
+
/* Set time-base frequency to 512 MHz. vhyp must be set first. */
cpu_ppc_tb_init(env, SPAPR_TIMEBASE_FREQ);