mirror of
https://github.com/izzy2lost/xemu.git
synced 2026-07-06 00:20:22 -07:00
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>
This commit is contained in:
@@ -195,11 +195,6 @@ Use a MTD drive to add a PNOR to the machine, and get a NVRAM :
|
||||
|
||||
-drive file=./witherspoon.pnor,format=raw,if=mtd
|
||||
|
||||
CAVEATS
|
||||
-------
|
||||
|
||||
* No support for multiple HW threads (SMT=1). Same as pseries.
|
||||
|
||||
Maintainer contact information
|
||||
------------------------------
|
||||
|
||||
|
||||
+22
-4
@@ -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,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
+12
-8
@@ -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,
|
||||
},
|
||||
};
|
||||
|
||||
+2
-2
@@ -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,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -656,6 +656,9 @@
|
||||
/* Ethernet Unit Registers */
|
||||
/****************************************/
|
||||
|
||||
#define MV64340_ETH_PHY_ADDR 0x2000
|
||||
#define MV64340_ETH_SMI 0x2004
|
||||
|
||||
/*******************************************/
|
||||
/* CUNIT Registers */
|
||||
/*******************************************/
|
||||
|
||||
+31
-1
@@ -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");
|
||||
|
||||
+22
-4
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+238
-44
@@ -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);
|
||||
|
||||
+23
-10
@@ -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;
|
||||
}
|
||||
|
||||
+26
-23
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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]),
|
||||
|
||||
+16
-12
@@ -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,
|
||||
|
||||
+81
-111
@@ -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;
|
||||
}
|
||||
snprintf(buf, sizeof(buf), "pcie%d-io", id);
|
||||
memory_region_init(&s->iomem, OBJECT(s), buf, UINT64_MAX);
|
||||
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-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);
|
||||
}
|
||||
|
||||
+5
-5
@@ -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,
|
||||
|
||||
+25
-14
@@ -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,16 +423,25 @@ static void sam460ex_init(MachineState *machine)
|
||||
usb_create_simple(usb_bus_find(-1), "usb-kbd");
|
||||
usb_create_simple(usb_bus_find(-1), "usb-mouse");
|
||||
|
||||
/* 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,
|
||||
qdev_get_gpio_in(uic[1], 0));
|
||||
pci_bus = PCI_BUS(qdev_get_child_bus(dev, "pci.0"));
|
||||
/* 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);
|
||||
|
||||
memory_region_init_alias(isa, NULL, "isa_mmio", get_system_io(),
|
||||
0, 0x10000);
|
||||
memory_region_add_subregion(get_system_memory(), 0xc08000000, isa);
|
||||
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 */
|
||||
/* All PCI irqs are connected to the same UIC pin (cf. UBoot source) */
|
||||
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"));
|
||||
|
||||
/* PCI devices */
|
||||
pci_create_simple(pci_bus, PCI_DEVFN(6, 0), "sm501");
|
||||
@@ -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);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user