summaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
authorRichard Henderson <richard.henderson@linaro.org>2021-12-17 09:55:14 -0800
committerRichard Henderson <richard.henderson@linaro.org>2021-12-17 09:55:14 -0800
commit93dc314c9225e103487ae22b62da1ac59ac86325 (patch)
tree275f2baa8247550f15991852ff3d662c307f252c /hw
parent48c03a0e13f49e8dff9a8ac37fff43e00a0a9bb3 (diff)
parent0e6232bc3cb96bdf6fac1b5d7659aa9887afe657 (diff)
downloadqemu-93dc314c9225e103487ae22b62da1ac59ac86325.zip
Merge tag 'pull-ppc-20211217' of https://github.com/legoater/qemu into staging
ppc 7.0 queue: * General cleanup for Mac machines (Peter) * Fixes for FPU exceptions (Lucas) * Support for new ISA31 instructions (Matheus) * Fixes for ivshmem (Daniel) * Cleanups for PowerNV PHB (Christophe and Cedric) * Updates of PowerNV and pSeries documentation (Leonardo and Daniel) * Fixes for PowerNV (Daniel) * Large cleanup of FPU implementation (Richard) * Removal of SoftTLBs support for PPC74x CPUs (Fabiano) * Fixes for exception models in MPCx and 60x CPUs (Fabiano) * Removal of 401/403 CPUs (Cedric) * Deprecation of taihu machine (Thomas) * Large rework of PPC405 machine (Cedric) * Fixes for VSX instructions (Victor and Matheus) * Fix for e6500 CPU (Fabiano) * Initial support for PMU (Daniel) # gpg: Signature made Fri 17 Dec 2021 09:20:31 AM PST # gpg: using RSA key A0F66548F04895EBFE6B0B6051A343C7CFFBECA1 # gpg: Good signature from "Cédric Le Goater <clg@kaod.org>" [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: A0F6 6548 F048 95EB FE6B 0B60 51A3 43C7 CFFB ECA1 * tag 'pull-ppc-20211217' of https://github.com/legoater/qemu: (101 commits) ppc/pnv: Use QOM hierarchy to scan PEC PHB4 devices ppc/pnv: Move realize of PEC stacks under the PEC model ppc/pnv: Remove "system-memory" property from PHB4 PEC ppc/pnv: Compute the PHB index from the PHB4 PEC model ppc/pnv: Introduce a num_stack class attribute ppc/pnv: Introduce a "chip" property under the PHB4 model ppc/pnv: Introduce version and device_id class atributes for PHB4 devices ppc/pnv: Introduce a num_pecs class attribute for PHB4 PEC devices ppc/pnv: Use QOM hierarchy to scan PHB3 devices ppc/pnv: Move mapping of the PHB3 CQ regions under pnv_pbcq_realize() ppc/pnv: Drop the "num-phbs" property ppc/pnv: Use the chip class to check the index of PHB3 devices ppc/pnv: Introduce a "chip" property under PHB3 PPC64/TCG: Implement 'rfebb' instruction target/ppc/power8-pmu.c: add PM_RUN_INST_CMPL (0xFA) event target/ppc: enable PMU instruction count target/ppc: enable PMU counter overflow with cycle events target/ppc: PMU: update counters on MMCR1 write target/ppc: PMU: update counters on PMCs r/w target/ppc: PMU basic cycle count for pseries TCG ... Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Diffstat (limited to 'hw')
-rw-r--r--hw/misc/ivshmem.c2
-rw-r--r--hw/pci-host/pnv_phb3.c3
-rw-r--r--hw/pci-host/pnv_phb3_pbcq.c11
-rw-r--r--hw/pci-host/pnv_phb4.c1
-rw-r--r--hw/pci-host/pnv_phb4_pec.c75
-rw-r--r--hw/ppc/mac.h3
-rw-r--r--hw/ppc/mac_newworld.c3
-rw-r--r--hw/ppc/mac_oldworld.c3
-rw-r--r--hw/ppc/pnv.c177
-rw-r--r--hw/ppc/ppc.c2
-rw-r--r--hw/ppc/ppc405.h14
-rw-r--r--hw/ppc/ppc405_boards.c245
-rw-r--r--hw/ppc/ppc405_uc.c225
-rw-r--r--hw/ppc/spapr_cpu_core.c1
-rw-r--r--hw/ppc/trace-events23
15 files changed, 445 insertions, 343 deletions
diff --git a/hw/misc/ivshmem.c b/hw/misc/ivshmem.c
index 1ba4a98377..299837e5c1 100644
--- a/hw/misc/ivshmem.c
+++ b/hw/misc/ivshmem.c
@@ -243,7 +243,7 @@ static uint64_t ivshmem_io_read(void *opaque, hwaddr addr,
static const MemoryRegionOps ivshmem_mmio_ops = {
.read = ivshmem_io_read,
.write = ivshmem_io_write,
- .endianness = DEVICE_NATIVE_ENDIAN,
+ .endianness = DEVICE_LITTLE_ENDIAN,
.impl = {
.min_access_size = 4,
.max_access_size = 4,
diff --git a/hw/pci-host/pnv_phb3.c b/hw/pci-host/pnv_phb3.c
index a7f9685005..9c4451ca0d 100644
--- a/hw/pci-host/pnv_phb3.c
+++ b/hw/pci-host/pnv_phb3.c
@@ -993,7 +993,7 @@ static void pnv_phb3_realize(DeviceState *dev, Error **errp)
PnvMachineState *pnv = PNV_MACHINE(qdev_get_machine());
int i;
- if (phb->phb_id >= PNV8_CHIP_PHB3_MAX) {
+ if (phb->phb_id >= PNV_CHIP_GET_CLASS(phb->chip)->num_phbs) {
error_setg(errp, "invalid PHB index: %d", phb->phb_id);
return;
}
@@ -1092,6 +1092,7 @@ static const char *pnv_phb3_root_bus_path(PCIHostState *host_bridge,
static Property pnv_phb3_properties[] = {
DEFINE_PROP_UINT32("index", PnvPHB3, phb_id, 0),
DEFINE_PROP_UINT32("chip-id", PnvPHB3, chip_id, 0),
+ DEFINE_PROP_LINK("chip", PnvPHB3, chip, TYPE_PNV_CHIP, PnvChip *),
DEFINE_PROP_END_OF_LIST(),
};
diff --git a/hw/pci-host/pnv_phb3_pbcq.c b/hw/pci-host/pnv_phb3_pbcq.c
index a0526aa1ec..c7426cd27a 100644
--- a/hw/pci-host/pnv_phb3_pbcq.c
+++ b/hw/pci-host/pnv_phb3_pbcq.c
@@ -284,6 +284,17 @@ static void pnv_pbcq_realize(DeviceState *dev, Error **errp)
pnv_xscom_region_init(&pbcq->xscom_spci_regs, OBJECT(dev),
&pnv_pbcq_spci_xscom_ops, pbcq, name,
PNV_XSCOM_PBCQ_SPCI_SIZE);
+
+ /* Populate the XSCOM address space. */
+ pnv_xscom_add_subregion(phb->chip,
+ PNV_XSCOM_PBCQ_NEST_BASE + 0x400 * phb->phb_id,
+ &pbcq->xscom_nest_regs);
+ pnv_xscom_add_subregion(phb->chip,
+ PNV_XSCOM_PBCQ_PCI_BASE + 0x400 * phb->phb_id,
+ &pbcq->xscom_pci_regs);
+ pnv_xscom_add_subregion(phb->chip,
+ PNV_XSCOM_PBCQ_SPCI_BASE + 0x040 * phb->phb_id,
+ &pbcq->xscom_spci_regs);
}
static int pnv_pbcq_dt_xscom(PnvXScomInterface *dev, void *fdt,
diff --git a/hw/pci-host/pnv_phb4.c b/hw/pci-host/pnv_phb4.c
index 5c375a9f28..40b793201a 100644
--- a/hw/pci-host/pnv_phb4.c
+++ b/hw/pci-host/pnv_phb4.c
@@ -1205,6 +1205,7 @@ static void pnv_phb4_realize(DeviceState *dev, Error **errp)
&phb->pci_mmio, &phb->pci_io,
0, 4, TYPE_PNV_PHB4_ROOT_BUS);
pci_setup_iommu(pci->bus, pnv_phb4_dma_iommu, phb);
+ pci->bus->flags |= PCI_BUS_EXTENDED_CONFIG_SPACE;
/* Add a single Root port */
qdev_prop_set_uint8(DEVICE(&phb->root), "chassis", phb->chip_id);
diff --git a/hw/pci-host/pnv_phb4_pec.c b/hw/pci-host/pnv_phb4_pec.c
index 741ddc90ed..24a3adcae3 100644
--- a/hw/pci-host/pnv_phb4_pec.c
+++ b/hw/pci-host/pnv_phb4_pec.c
@@ -124,7 +124,7 @@ static uint64_t pnv_pec_stk_nest_xscom_read(void *opaque, hwaddr addr,
static void pnv_pec_stk_update_map(PnvPhb4PecStack *stack)
{
PnvPhb4PecState *pec = stack->pec;
- MemoryRegion *sysmem = pec->system_memory;
+ MemoryRegion *sysmem = get_system_memory();
uint64_t bar_en = stack->nest_regs[PEC_NEST_STK_BAR_EN];
uint64_t bar, mask, size;
char name[64];
@@ -374,20 +374,41 @@ static void pnv_pec_instance_init(Object *obj)
}
}
+static int pnv_pec_phb_offset(PnvPhb4PecState *pec)
+{
+ PnvPhb4PecClass *pecc = PNV_PHB4_PEC_GET_CLASS(pec);
+ int index = pec->index;
+ int offset = 0;
+
+ while (index--) {
+ offset += pecc->num_stacks[index];
+ }
+
+ return offset;
+}
+
static void pnv_pec_realize(DeviceState *dev, Error **errp)
{
PnvPhb4PecState *pec = PNV_PHB4_PEC(dev);
+ PnvPhb4PecClass *pecc = PNV_PHB4_PEC_GET_CLASS(pec);
char name[64];
int i;
- assert(pec->system_memory);
+ if (pec->index >= PNV_CHIP_GET_CLASS(pec->chip)->num_pecs) {
+ error_setg(errp, "invalid PEC index: %d", pec->index);
+ return;
+ }
+
+ pec->num_stacks = pecc->num_stacks[pec->index];
/* Create stacks */
for (i = 0; i < pec->num_stacks; i++) {
PnvPhb4PecStack *stack = &pec->stacks[i];
Object *stk_obj = OBJECT(stack);
+ int phb_id = pnv_pec_phb_offset(pec) + i;
object_property_set_int(stk_obj, "stack-no", i, &error_abort);
+ object_property_set_int(stk_obj, "phb-id", phb_id, &error_abort);
object_property_set_link(stk_obj, "pec", OBJECT(pec), &error_abort);
if (!qdev_realize(DEVICE(stk_obj), NULL, errp)) {
return;
@@ -460,10 +481,9 @@ static int pnv_pec_dt_xscom(PnvXScomInterface *dev, void *fdt,
static Property pnv_pec_properties[] = {
DEFINE_PROP_UINT32("index", PnvPhb4PecState, index, 0),
- DEFINE_PROP_UINT32("num-stacks", PnvPhb4PecState, num_stacks, 0),
DEFINE_PROP_UINT32("chip-id", PnvPhb4PecState, chip_id, 0),
- DEFINE_PROP_LINK("system-memory", PnvPhb4PecState, system_memory,
- TYPE_MEMORY_REGION, MemoryRegion *),
+ DEFINE_PROP_LINK("chip", PnvPhb4PecState, chip, TYPE_PNV_CHIP,
+ PnvChip *),
DEFINE_PROP_END_OF_LIST(),
};
@@ -477,6 +497,13 @@ static uint32_t pnv_pec_xscom_nest_base(PnvPhb4PecState *pec)
return PNV9_XSCOM_PEC_NEST_BASE + 0x400 * pec->index;
}
+/*
+ * PEC0 -> 1 stack
+ * PEC1 -> 2 stacks
+ * PEC2 -> 3 stacks
+ */
+static const uint32_t pnv_pec_num_stacks[] = { 1, 2, 3 };
+
static void pnv_pec_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
@@ -499,6 +526,9 @@ static void pnv_pec_class_init(ObjectClass *klass, void *data)
pecc->compat_size = sizeof(compat);
pecc->stk_compat = stk_compat;
pecc->stk_compat_size = sizeof(stk_compat);
+ pecc->version = PNV_PHB4_VERSION;
+ pecc->device_id = PNV_PHB4_DEVICE_ID;
+ pecc->num_stacks = pnv_pec_num_stacks;
}
static const TypeInfo pnv_pec_type_info = {
@@ -519,12 +549,17 @@ static void pnv_pec_stk_instance_init(Object *obj)
PnvPhb4PecStack *stack = PNV_PHB4_PEC_STACK(obj);
object_initialize_child(obj, "phb", &stack->phb, TYPE_PNV_PHB4);
+ object_property_add_alias(obj, "phb-id", OBJECT(&stack->phb), "index");
}
static void pnv_pec_stk_realize(DeviceState *dev, Error **errp)
{
PnvPhb4PecStack *stack = PNV_PHB4_PEC_STACK(dev);
PnvPhb4PecState *pec = stack->pec;
+ PnvPhb4PecClass *pecc = PNV_PHB4_PEC_GET_CLASS(pec);
+ PnvChip *chip = pec->chip;
+ uint32_t pec_nest_base;
+ uint32_t pec_pci_base;
char name[64];
assert(pec);
@@ -548,10 +583,32 @@ static void pnv_pec_stk_realize(DeviceState *dev, Error **errp)
pnv_xscom_region_init(&stack->phb_regs_mr, OBJECT(&stack->phb),
&pnv_phb4_xscom_ops, &stack->phb, name, 0x40);
- /*
- * Let the machine/chip realize the PHB object to customize more
- * easily some fields
- */
+ object_property_set_int(OBJECT(&stack->phb), "chip-id", pec->chip_id,
+ &error_fatal);
+ object_property_set_int(OBJECT(&stack->phb), "version", pecc->version,
+ &error_fatal);
+ object_property_set_int(OBJECT(&stack->phb), "device-id", pecc->device_id,
+ &error_fatal);
+ object_property_set_link(OBJECT(&stack->phb), "stack", OBJECT(stack),
+ &error_abort);
+ if (!sysbus_realize(SYS_BUS_DEVICE(&stack->phb), errp)) {
+ return;
+ }
+
+ pec_nest_base = pecc->xscom_nest_base(pec);
+ pec_pci_base = pecc->xscom_pci_base(pec);
+
+ /* Populate the XSCOM address space. */
+ pnv_xscom_add_subregion(chip,
+ pec_nest_base + 0x40 * (stack->stack_no + 1),
+ &stack->nest_regs_mr);
+ pnv_xscom_add_subregion(chip,
+ pec_pci_base + 0x40 * (stack->stack_no + 1),
+ &stack->pci_regs_mr);
+ pnv_xscom_add_subregion(chip,
+ pec_pci_base + PNV9_XSCOM_PEC_PCI_STK0 +
+ 0x40 * stack->stack_no,
+ &stack->phb_regs_mr);
}
static Property pnv_pec_stk_properties[] = {
diff --git a/hw/ppc/mac.h b/hw/ppc/mac.h
index 22c8408078..a1fa8f8e41 100644
--- a/hw/ppc/mac.h
+++ b/hw/ppc/mac.h
@@ -36,9 +36,6 @@
#include "hw/pci-host/uninorth.h"
#include "qom/object.h"
-/* SMP is not enabled, for now */
-#define MAX_CPUS 1
-
#define NVRAM_SIZE 0x2000
#define PROM_FILENAME "openbios-ppc"
diff --git a/hw/ppc/mac_newworld.c b/hw/ppc/mac_newworld.c
index 7bb7ac3997..4bddb529c2 100644
--- a/hw/ppc/mac_newworld.c
+++ b/hw/ppc/mac_newworld.c
@@ -581,7 +581,8 @@ static void core99_machine_class_init(ObjectClass *oc, void *data)
mc->desc = "Mac99 based PowerMAC";
mc->init = ppc_core99_init;
mc->block_default_type = IF_IDE;
- mc->max_cpus = MAX_CPUS;
+ /* SMP is not supported currently */
+ mc->max_cpus = 1;
mc->default_boot_order = "cd";
mc->default_display = "std";
mc->kvm_type = core99_kvm_type;
diff --git a/hw/ppc/mac_oldworld.c b/hw/ppc/mac_oldworld.c
index de2be960e6..7016979a7c 100644
--- a/hw/ppc/mac_oldworld.c
+++ b/hw/ppc/mac_oldworld.c
@@ -423,7 +423,8 @@ static void heathrow_class_init(ObjectClass *oc, void *data)
mc->desc = "Heathrow based PowerMAC";
mc->init = ppc_heathrow_init;
mc->block_default_type = IF_IDE;
- mc->max_cpus = MAX_CPUS;
+ /* SMP is not supported currently */
+ mc->max_cpus = 1;
#ifndef TARGET_PPC64
mc->is_default = true;
#endif
diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c
index 71e45515f1..29ee0d0f08 100644
--- a/hw/ppc/pnv.c
+++ b/hw/ppc/pnv.c
@@ -522,7 +522,7 @@ static void *pnv_dt_create(MachineState *machine)
buf = qemu_uuid_unparse_strdup(&qemu_uuid);
_FDT((fdt_setprop_string(fdt, 0, "vm,uuid", buf)));
if (qemu_uuid_set) {
- _FDT((fdt_property_string(fdt, "system-id", buf)));
+ _FDT((fdt_setprop_string(fdt, 0, "system-id", buf)));
}
g_free(buf);
@@ -638,32 +638,47 @@ static ISABus *pnv_isa_create(PnvChip *chip, Error **errp)
return PNV_CHIP_GET_CLASS(chip)->isa_create(chip, errp);
}
+static int pnv_chip_power8_pic_print_info_child(Object *child, void *opaque)
+{
+ Monitor *mon = opaque;
+ PnvPHB3 *phb3 = (PnvPHB3 *) object_dynamic_cast(child, TYPE_PNV_PHB3);
+
+ if (phb3) {
+ pnv_phb3_msi_pic_print_info(&phb3->msis, mon);
+ ics_pic_print_info(&phb3->lsis, mon);
+ }
+ return 0;
+}
+
static void pnv_chip_power8_pic_print_info(PnvChip *chip, Monitor *mon)
{
Pnv8Chip *chip8 = PNV8_CHIP(chip);
- int i;
ics_pic_print_info(&chip8->psi.ics, mon);
- for (i = 0; i < chip->num_phbs; i++) {
- pnv_phb3_msi_pic_print_info(&chip8->phbs[i].msis, mon);
- ics_pic_print_info(&chip8->phbs[i].lsis, mon);
+ object_child_foreach(OBJECT(chip),
+ pnv_chip_power8_pic_print_info_child, mon);
+}
+
+static int pnv_chip_power9_pic_print_info_child(Object *child, void *opaque)
+{
+ Monitor *mon = opaque;
+ PnvPHB4 *phb4 = (PnvPHB4 *) object_dynamic_cast(child, TYPE_PNV_PHB4);
+
+ if (phb4) {
+ pnv_phb4_pic_print_info(phb4, mon);
}
+ return 0;
}
static void pnv_chip_power9_pic_print_info(PnvChip *chip, Monitor *mon)
{
Pnv9Chip *chip9 = PNV9_CHIP(chip);
- int i, j;
pnv_xive_pic_print_info(&chip9->xive, mon);
pnv_psi_pic_print_info(&chip9->psi, mon);
- for (i = 0; i < PNV9_CHIP_MAX_PEC; i++) {
- PnvPhb4PecState *pec = &chip9->pecs[i];
- for (j = 0; j < pec->num_stacks; j++) {
- pnv_phb4_pic_print_info(&pec->stacks[j].phb, mon);
- }
- }
+ object_child_foreach_recursive(OBJECT(chip),
+ pnv_chip_power9_pic_print_info_child, mon);
}
static uint64_t pnv_chip_power8_xscom_core_base(PnvChip *chip,
@@ -742,6 +757,11 @@ static void pnv_init(MachineState *machine)
DriveInfo *pnor = drive_get(IF_MTD, 0, 0);
DeviceState *dev;
+ if (kvm_enabled()) {
+ error_report("The powernv machine does not work with KVM acceleration");
+ exit(EXIT_FAILURE);
+ }
+
/* allocate RAM */
if (machine->ram_size < mc->default_ram_size) {
char *sz = size_to_str(mc->default_ram_size);
@@ -1221,25 +1241,15 @@ static void pnv_chip_power8_realize(DeviceState *dev, Error **errp)
/* PHB3 controllers */
for (i = 0; i < chip->num_phbs; i++) {
PnvPHB3 *phb = &chip8->phbs[i];
- PnvPBCQState *pbcq = &phb->pbcq;
object_property_set_int(OBJECT(phb), "index", i, &error_fatal);
object_property_set_int(OBJECT(phb), "chip-id", chip->chip_id,
&error_fatal);
+ object_property_set_link(OBJECT(phb), "chip", OBJECT(chip),
+ &error_fatal);
if (!sysbus_realize(SYS_BUS_DEVICE(phb), errp)) {
return;
}
-
- /* Populate the XSCOM address space. */
- pnv_xscom_add_subregion(chip,
- PNV_XSCOM_PBCQ_NEST_BASE + 0x400 * phb->phb_id,
- &pbcq->xscom_nest_regs);
- pnv_xscom_add_subregion(chip,
- PNV_XSCOM_PBCQ_PCI_BASE + 0x400 * phb->phb_id,
- &pbcq->xscom_pci_regs);
- pnv_xscom_add_subregion(chip,
- PNV_XSCOM_PBCQ_SPCI_BASE + 0x040 * phb->phb_id,
- &pbcq->xscom_spci_regs);
}
}
@@ -1340,15 +1350,13 @@ static void pnv_chip_power9_instance_init(Object *obj)
object_initialize_child(obj, "homer", &chip9->homer, TYPE_PNV9_HOMER);
- for (i = 0; i < PNV9_CHIP_MAX_PEC; i++) {
+ /* Number of PECs is the chip default */
+ chip->num_pecs = pcc->num_pecs;
+
+ for (i = 0; i < chip->num_pecs; i++) {
object_initialize_child(obj, "pec[*]", &chip9->pecs[i],
TYPE_PNV_PHB4_PEC);
}
-
- /*
- * Number of PHBs is the chip default
- */
- chip->num_phbs = pcc->num_phbs;
}
static void pnv_chip_quad_realize(Pnv9Chip *chip9, Error **errp)
@@ -1378,30 +1386,22 @@ static void pnv_chip_quad_realize(Pnv9Chip *chip9, Error **errp)
}
}
-static void pnv_chip_power9_phb_realize(PnvChip *chip, Error **errp)
+static void pnv_chip_power9_pec_realize(PnvChip *chip, Error **errp)
{
Pnv9Chip *chip9 = PNV9_CHIP(chip);
- int i, j;
- int phb_id = 0;
+ int i;
- for (i = 0; i < PNV9_CHIP_MAX_PEC; i++) {
+ for (i = 0; i < chip->num_pecs; i++) {
PnvPhb4PecState *pec = &chip9->pecs[i];
PnvPhb4PecClass *pecc = PNV_PHB4_PEC_GET_CLASS(pec);
uint32_t pec_nest_base;
uint32_t pec_pci_base;
object_property_set_int(OBJECT(pec), "index", i, &error_fatal);
- /*
- * PEC0 -> 1 stack
- * PEC1 -> 2 stacks
- * PEC2 -> 3 stacks
- */
- object_property_set_int(OBJECT(pec), "num-stacks", i + 1,
- &error_fatal);
object_property_set_int(OBJECT(pec), "chip-id", chip->chip_id,
&error_fatal);
- object_property_set_link(OBJECT(pec), "system-memory",
- OBJECT(get_system_memory()), &error_abort);
+ object_property_set_link(OBJECT(pec), "chip", OBJECT(chip),
+ &error_fatal);
if (!qdev_realize(DEVICE(pec), NULL, errp)) {
return;
}
@@ -1411,37 +1411,6 @@ static void pnv_chip_power9_phb_realize(PnvChip *chip, Error **errp)
pnv_xscom_add_subregion(chip, pec_nest_base, &pec->nest_regs_mr);
pnv_xscom_add_subregion(chip, pec_pci_base, &pec->pci_regs_mr);
-
- for (j = 0; j < pec->num_stacks && phb_id < chip->num_phbs;
- j++, phb_id++) {
- PnvPhb4PecStack *stack = &pec->stacks[j];
- Object *obj = OBJECT(&stack->phb);
-
- object_property_set_int(obj, "index", phb_id, &error_fatal);
- object_property_set_int(obj, "chip-id", chip->chip_id,
- &error_fatal);
- object_property_set_int(obj, "version", PNV_PHB4_VERSION,
- &error_fatal);
- object_property_set_int(obj, "device-id", PNV_PHB4_DEVICE_ID,
- &error_fatal);
- object_property_set_link(obj, "stack", OBJECT(stack),
- &error_abort);
- if (!sysbus_realize(SYS_BUS_DEVICE(obj), errp)) {
- return;
- }
-
- /* Populate the XSCOM address space. */
- pnv_xscom_add_subregion(chip,
- pec_nest_base + 0x40 * (stack->stack_no + 1),
- &stack->nest_regs_mr);
- pnv_xscom_add_subregion(chip,
- pec_pci_base + 0x40 * (stack->stack_no + 1),
- &stack->pci_regs_mr);
- pnv_xscom_add_subregion(chip,
- pec_pci_base + PNV9_XSCOM_PEC_PCI_STK0 +
- 0x40 * stack->stack_no,
- &stack->phb_regs_mr);
- }
}
}
@@ -1537,8 +1506,8 @@ static void pnv_chip_power9_realize(DeviceState *dev, Error **errp)
memory_region_add_subregion(get_system_memory(), PNV9_HOMER_BASE(chip),
&chip9->homer.regs);
- /* PHBs */
- pnv_chip_power9_phb_realize(chip, &local_err);
+ /* PEC PHBs */
+ pnv_chip_power9_pec_realize(chip, &local_err);
if (local_err) {
error_propagate(errp, local_err);
return;
@@ -1569,7 +1538,7 @@ static void pnv_chip_power9_class_init(ObjectClass *klass, void *data)
k->xscom_core_base = pnv_chip_power9_xscom_core_base;
k->xscom_pcba = pnv_chip_power9_xscom_pcba;
dc->desc = "PowerNV Chip POWER9";
- k->num_phbs = 6;
+ k->num_pecs = PNV9_CHIP_MAX_PEC;
device_class_set_parent_realize(dc, pnv_chip_power9_realize,
&k->parent_realize);
@@ -1764,7 +1733,6 @@ static Property pnv_chip_properties[] = {
DEFINE_PROP_UINT32("nr-cores", PnvChip, nr_cores, 1),
DEFINE_PROP_UINT64("cores-mask", PnvChip, cores_mask, 0x0),
DEFINE_PROP_UINT32("nr-threads", PnvChip, nr_threads, 1),
- DEFINE_PROP_UINT32("num-phbs", PnvChip, num_phbs, 0),
DEFINE_PROP_END_OF_LIST(),
};
@@ -1795,10 +1763,32 @@ PowerPCCPU *pnv_chip_find_cpu(PnvChip *chip, uint32_t pir)
return NULL;
}
+typedef struct ForeachPhb3Args {
+ int irq;
+ ICSState *ics;
+} ForeachPhb3Args;
+
+static int pnv_ics_get_child(Object *child, void *opaque)
+{
+ ForeachPhb3Args *args = opaque;
+ PnvPHB3 *phb3 = (PnvPHB3 *) object_dynamic_cast(child, TYPE_PNV_PHB3);
+
+ if (phb3) {
+ if (ics_valid_irq(&phb3->lsis, args->irq)) {
+ args->ics = &phb3->lsis;
+ }
+ if (ics_valid_irq(ICS(&phb3->msis), args->irq)) {
+ args->ics = ICS(&phb3->msis);
+ }
+ }
+ return args->ics ? 1 : 0;
+}
+
static ICSState *pnv_ics_get(XICSFabric *xi, int irq)
{
PnvMachineState *pnv = PNV_MACHINE(xi);
- int i, j;
+ ForeachPhb3Args args = { irq, NULL };
+ int i;
for (i = 0; i < pnv->num_chips; i++) {
PnvChip *chip = pnv->chips[i];
@@ -1807,32 +1797,37 @@ static ICSState *pnv_ics_get(XICSFabric *xi, int irq)
if (ics_valid_irq(&chip8->psi.ics, irq)) {
return &chip8->psi.ics;
}
- for (j = 0; j < chip->num_phbs; j++) {
- if (ics_valid_irq(&chip8->phbs[j].lsis, irq)) {
- return &chip8->phbs[j].lsis;
- }
- if (ics_valid_irq(ICS(&chip8->phbs[j].msis), irq)) {
- return ICS(&chip8->phbs[j].msis);
- }
+
+ object_child_foreach(OBJECT(chip), pnv_ics_get_child, &args);
+ if (args.ics) {
+ return args.ics;
}
}
return NULL;
}
+static int pnv_ics_resend_child(Object *child, void *opaque)
+{
+ PnvPHB3 *phb3 = (PnvPHB3 *) object_dynamic_cast(child, TYPE_PNV_PHB3);
+
+ if (phb3) {
+ ics_resend(&phb3->lsis);
+ ics_resend(ICS(&phb3->msis));
+ }
+ return 0;
+}
+
static void pnv_ics_resend(XICSFabric *xi)
{
PnvMachineState *pnv = PNV_MACHINE(xi);
- int i, j;
+ int i;
for (i = 0; i < pnv->num_chips; i++) {
PnvChip *chip = pnv->chips[i];
Pnv8Chip *chip8 = PNV8_CHIP(pnv->chips[i]);
ics_resend(&chip8->psi.ics);
- for (j = 0; j < chip->num_phbs; j++) {
- ics_resend(&chip8->phbs[j].lsis);
- ics_resend(ICS(&chip8->phbs[j].msis));
- }
+ object_child_foreach(OBJECT(chip), pnv_ics_resend_child, NULL);
}
}
diff --git a/hw/ppc/ppc.c b/hw/ppc/ppc.c
index e8127599c9..818d757985 100644
--- a/hw/ppc/ppc.c
+++ b/hw/ppc/ppc.c
@@ -1367,6 +1367,7 @@ int ppc_dcr_read (ppc_dcr_t *dcr_env, int dcrn, uint32_t *valp)
if (dcr->dcr_read == NULL)
goto error;
*valp = (*dcr->dcr_read)(dcr->opaque, dcrn);
+ trace_ppc_dcr_read(dcrn, *valp);
return 0;
@@ -1386,6 +1387,7 @@ int ppc_dcr_write (ppc_dcr_t *dcr_env, int dcrn, uint32_t val)
dcr = &dcr_env->dcrn[dcrn];
if (dcr->dcr_write == NULL)
goto error;
+ trace_ppc_dcr_write(dcrn, val);
(*dcr->dcr_write)(dcr->opaque, dcrn, val);
return 0;
diff --git a/hw/ppc/ppc405.h b/hw/ppc/ppc405.h
index c58f739886..83f156f585 100644
--- a/hw/ppc/ppc405.h
+++ b/hw/ppc/ppc405.h
@@ -27,6 +27,13 @@
#include "hw/ppc/ppc4xx.h"
+#define PPC405EP_SDRAM_BASE 0x00000000
+#define PPC405EP_NVRAM_BASE 0xF0000000
+#define PPC405EP_FPGA_BASE 0xF0300000
+#define PPC405EP_SRAM_BASE 0xFFF00000
+#define PPC405EP_SRAM_SIZE (512 * KiB)
+#define PPC405EP_FLASH_BASE 0xFFF80000
+
/* Bootinfo as set-up by u-boot */
typedef struct ppc4xx_bd_info_t ppc4xx_bd_info_t;
struct ppc4xx_bd_info_t {
@@ -50,19 +57,18 @@ struct ppc4xx_bd_info_t {
uint32_t bi_plb_busfreq;
uint32_t bi_pci_busfreq;
uint8_t bi_pci_enetaddr[6];
- uint32_t bi_pci_enetaddr2[6];
+ uint8_t bi_pci_enetaddr2[6]; /* PPC405EP specific */
uint32_t bi_opbfreq;
uint32_t bi_iic_fast[2];
};
/* PowerPC 405 core */
-ram_addr_t ppc405_set_bootinfo (CPUPPCState *env, ppc4xx_bd_info_t *bd,
- uint32_t flags);
+ram_addr_t ppc405_set_bootinfo(CPUPPCState *env, ram_addr_t ram_size);
void ppc4xx_plb_init(CPUPPCState *env);
void ppc405_ebc_init(CPUPPCState *env);
-CPUPPCState *ppc405ep_init(MemoryRegion *address_space_mem,
+PowerPCCPU *ppc405ep_init(MemoryRegion *address_space_mem,
MemoryRegion ram_memories[2],
hwaddr ram_bases[2],
hwaddr ram_sizes[2],
diff --git a/hw/ppc/ppc405_boards.c b/hw/ppc/ppc405_boards.c
index 972a7a4a3e..3ae2b36373 100644
--- a/hw/ppc/ppc405_boards.c
+++ b/hw/ppc/ppc405_boards.c
@@ -41,11 +41,12 @@
#include "qemu/error-report.h"
#include "hw/loader.h"
#include "qemu/cutils.h"
+#include "elf.h"
#define BIOS_FILENAME "ppc405_rom.bin"
#define BIOS_SIZE (2 * MiB)
-#define KERNEL_LOAD_ADDR 0x00000000
+#define KERNEL_LOAD_ADDR 0x01000000
#define INITRD_LOAD_ADDR 0x01800000
#define USE_FLASH_BIOS
@@ -136,32 +137,101 @@ static void ref405ep_fpga_init(MemoryRegion *sysmem, uint32_t base)
qemu_register_reset(&ref405ep_fpga_reset, fpga);
}
+/*
+ * CPU reset handler when booting directly from a loaded kernel
+ */
+static struct boot_info {
+ uint32_t entry;
+ uint32_t bdloc;
+ uint32_t initrd_base;
+ uint32_t initrd_size;
+ uint32_t cmdline_base;
+ uint32_t cmdline_size;
+} boot_info;
+
+static void main_cpu_reset(void *opaque)
+{
+ PowerPCCPU *cpu = opaque;
+ CPUPPCState *env = &cpu->env;
+ struct boot_info *bi = env->load_info;
+
+ cpu_reset(CPU(cpu));
+
+ /* stack: top of sram */
+ env->gpr[1] = PPC405EP_SRAM_BASE + PPC405EP_SRAM_SIZE - 8;
+
+ /* Tune our boot state */
+ env->gpr[3] = bi->bdloc;
+ env->gpr[4] = bi->initrd_base;
+ env->gpr[5] = bi->initrd_base + bi->initrd_size;
+ env->gpr[6] = bi->cmdline_base;
+ env->gpr[7] = bi->cmdline_size;
+
+ env->nip = bi->entry;
+}
+
+static void boot_from_kernel(MachineState *machine, PowerPCCPU *cpu)
+{
+ CPUPPCState *env = &cpu->env;
+ hwaddr boot_entry;
+ hwaddr kernel_base;
+ int kernel_size;
+ hwaddr initrd_base;
+ int initrd_size;
+ ram_addr_t bdloc;
+ int len;
+
+ bdloc = ppc405_set_bootinfo(env, machine->ram_size);
+ boot_info.bdloc = bdloc;
+
+ kernel_size = load_elf(machine->kernel_filename, NULL, NULL, NULL,
+ &boot_entry, &kernel_base, NULL, NULL,
+ 1, PPC_ELF_MACHINE, 0, 0);
+ if (kernel_size < 0) {
+ error_report("Could not load kernel '%s' : %s",
+ machine->kernel_filename, load_elf_strerror(kernel_size));
+ exit(1);
+ }
+ boot_info.entry = boot_entry;
+
+ /* load initrd */
+ if (machine->initrd_filename) {
+ initrd_base = INITRD_LOAD_ADDR;
+ initrd_size = load_image_targphys(machine->initrd_filename, initrd_base,
+ machine->ram_size - initrd_base);
+ if (initrd_size < 0) {
+ error_report("could not load initial ram disk '%s'",
+ machine->initrd_filename);
+ exit(1);
+ }
+
+ boot_info.initrd_base = initrd_base;
+ boot_info.initrd_size = initrd_size;
+ }
+
+ if (machine->kernel_cmdline) {
+ len = strlen(machine->kernel_cmdline);
+ bdloc -= ((len + 255) & ~255);
+ cpu_physical_memory_write(bdloc, machine->kernel_cmdline, len + 1);
+ boot_info.cmdline_base = bdloc;
+ boot_info.cmdline_size = bdloc + len;
+ }
+
+ /* Install our custom reset handler to start from Linux */
+ qemu_register_reset(main_cpu_reset, cpu);
+ env->load_info = &boot_info;
+}
+
static void ref405ep_init(MachineState *machine)
{
MachineClass *mc = MACHINE_GET_CLASS(machine);
- const char *bios_name = machine->firmware ?: BIOS_FILENAME;
const char *kernel_filename = machine->kernel_filename;
- const char *kernel_cmdline = machine->kernel_cmdline;
- const char *initrd_filename = machine->initrd_filename;
- char *filename;
- ppc4xx_bd_info_t bd;
- CPUPPCState *env;
+ PowerPCCPU *cpu;
DeviceState *dev;
SysBusDevice *s;
- MemoryRegion *bios;
MemoryRegion *sram = g_new(MemoryRegion, 1);
- ram_addr_t bdloc;
MemoryRegion *ram_memories = g_new(MemoryRegion, 2);
hwaddr ram_bases[2], ram_sizes[2];
- target_ulong sram_size;
- long bios_size;
- //int phy_addr = 0;
- //static int phy_addr = 1;
- target_ulong kernel_base, initrd_base;
- long kernel_size, initrd_size;
- int linux_boot;
- int len;
- DriveInfo *dinfo;
MemoryRegion *sysmem = get_system_memory();
DeviceState *uicdev;
@@ -180,132 +250,80 @@ static void ref405ep_init(MachineState *machine)
memory_region_init(&ram_memories[1], NULL, "ef405ep.ram1", 0);
ram_bases[1] = 0x00000000;
ram_sizes[1] = 0x00000000;
- env = ppc405ep_init(sysmem, ram_memories, ram_bases, ram_sizes,
+
+ cpu = ppc405ep_init(sysmem, ram_memories, ram_bases, ram_sizes,
33333333, &uicdev, kernel_filename == NULL ? 0 : 1);
+
/* allocate SRAM */
- sram_size = 512 * KiB;
- memory_region_init_ram(sram, NULL, "ef405ep.sram", sram_size,
+ memory_region_init_ram(sram, NULL, "ef405ep.sram", PPC405EP_SRAM_SIZE,
&error_fatal);
- memory_region_add_subregion(sysmem, 0xFFF00000, sram);
+ memory_region_add_subregion(sysmem, PPC405EP_SRAM_BASE, sram);
+
/* allocate and load BIOS */
-#ifdef USE_FLASH_BIOS
- dinfo = drive_get(IF_PFLASH, 0, 0);
- if (dinfo) {
- bios_size = 8 * MiB;
- pflash_cfi02_register((uint32_t)(-bios_size),
- "ef405ep.bios", bios_size,
- blk_by_legacy_dinfo(dinfo),
- 64 * KiB, 1,
- 2, 0x0001, 0x22DA, 0x0000, 0x0000, 0x555, 0x2AA,
- 1);
- } else
-#endif
- {
- bios = g_new(MemoryRegion, 1);
+ if (machine->firmware) {
+ MemoryRegion *bios = g_new(MemoryRegion, 1);
+ g_autofree char *filename;
+ long bios_size;
+
memory_region_init_rom(bios, NULL, "ef405ep.bios", BIOS_SIZE,
&error_fatal);
- filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
- if (filename) {
- bios_size = load_image_size(filename,
- memory_region_get_ram_ptr(bios),
- BIOS_SIZE);
- g_free(filename);
- if (bios_size < 0) {
- error_report("Could not load PowerPC BIOS '%s'", bios_name);
- exit(1);
- }
- bios_size = (bios_size + 0xfff) & ~0xfff;
- memory_region_add_subregion(sysmem, (uint32_t)(-bios_size), bios);
- } else if (!qtest_enabled() || kernel_filename != NULL) {
- error_report("Could not load PowerPC BIOS '%s'", bios_name);
+ filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, machine->firmware);
+ if (!filename) {
+ error_report("Could not find firmware '%s'", machine->firmware);
exit(1);
- } else {
- /* Avoid an uninitialized variable warning */
- bios_size = -1;
}
+
+ bios_size = load_image_size(filename,
+ memory_region_get_ram_ptr(bios),
+ BIOS_SIZE);
+ if (bios_size < 0) {
+ error_report("Could not load PowerPC BIOS '%s'", machine->firmware);
+ exit(1);
+ }
+
+ bios_size = (bios_size + 0xfff) & ~0xfff;
+ memory_region_add_subregion(sysmem, (uint32_t)(-bios_size), bios);
}
+
/* Register FPGA */
- ref405ep_fpga_init(sysmem, 0xF0300000);
+ ref405ep_fpga_init(sysmem, PPC405EP_FPGA_BASE);
/* Register NVRAM */
dev = qdev_new("sysbus-m48t08");
qdev_prop_set_int32(dev, "base-year", 1968);
s = SYS_BUS_DEVICE(dev);
sysbus_realize_and_unref(s, &error_fatal);
- sysbus_mmio_map(s, 0, 0xF0000000);
- /* Load kernel */
- linux_boot = (kernel_filename != NULL);
- if (linux_boot) {
- memset(&bd, 0, sizeof(bd));
- bd.bi_memstart = 0x00000000;
- bd.bi_memsize = machine->ram_size;
- bd.bi_flashstart = -bios_size;
- bd.bi_flashsize = -bios_size;
- bd.bi_flashoffset = 0;
- bd.bi_sramstart = 0xFFF00000;
- bd.bi_sramsize = sram_size;
- bd.bi_bootflags = 0;
- bd.bi_intfreq = 133333333;
- bd.bi_busfreq = 33333333;
- bd.bi_baudrate = 115200;
- bd.bi_s_version[0] = 'Q';
- bd.bi_s_version[1] = 'M';
- bd.bi_s_version[2] = 'U';
- bd.bi_s_version[3] = '\0';
- bd.bi_r_version[0] = 'Q';
- bd.bi_r_version[1] = 'E';
- bd.bi_r_version[2] = 'M';
- bd.bi_r_version[3] = 'U';
- bd.bi_r_version[4] = '\0';
- bd.bi_procfreq = 133333333;
- bd.bi_plb_busfreq = 33333333;
- bd.bi_pci_busfreq = 33333333;
- bd.bi_opbfreq = 33333333;
- bdloc = ppc405_set_bootinfo(env, &bd, 0x00000001);
- env->gpr[3] = bdloc;
+ sysbus_mmio_map(s, 0, PPC405EP_NVRAM_BASE);
+
+ /* Load kernel and initrd using U-Boot images */
+ if (kernel_filename && machine->firmware) {
+ target_ulong kernel_base, initrd_base;
+ long kernel_size, initrd_size;
+
kernel_base = KERNEL_LOAD_ADDR;
- /* now we can load the kernel */
kernel_size = load_image_targphys(kernel_filename, kernel_base,
machine->ram_size - kernel_base);
if (kernel_size < 0) {
error_report("could not load kernel '%s'", kernel_filename);
exit(1);
}
- printf("Load kernel size %ld at " TARGET_FMT_lx,
- kernel_size, kernel_base);
+
/* load initrd */
- if (initrd_filename) {
+ if (machine->initrd_filename) {
initrd_base = INITRD_LOAD_ADDR;
- initrd_size = load_image_targphys(initrd_filename, initrd_base,
+ initrd_size = load_image_targphys(machine->initrd_filename,
+ initrd_base,
machine->ram_size - initrd_base);
if (initrd_size < 0) {
error_report("could not load initial ram disk '%s'",
- initrd_filename);
+ machine->initrd_filename);
exit(1);
}
- } else {
- initrd_base = 0;
- initrd_size = 0;
}
- env->gpr[4] = initrd_base;
- env->gpr[5] = initrd_size;
- if (kernel_cmdline != NULL) {
- len = strlen(kernel_cmdline);
- bdloc -= ((len + 255) & ~255);
- cpu_physical_memory_write(bdloc, kernel_cmdline, len + 1);
- env->gpr[6] = bdloc;
- env->gpr[7] = bdloc + len;
- } else {
- env->gpr[6] = 0;
- env->gpr[7] = 0;
- }
- env->nip = KERNEL_LOAD_ADDR;
- } else {
- kernel_base = 0;
- kernel_size = 0;
- initrd_base = 0;
- initrd_size = 0;
- bdloc = 0;
+
+ /* Load ELF kernel and rootfs.cpio */
+ } else if (kernel_filename && !machine->firmware) {
+ boot_from_kernel(machine, cpu);
}
}
@@ -547,6 +565,7 @@ static void taihu_class_init(ObjectClass *oc, void *data)
mc->init = taihu_405ep_init;
mc->default_ram_size = 0x08000000;
mc->default_ram_id = "taihu_405ep.ram";
+ mc->deprecation_reason = "incomplete, use 'ref405ep' instead";
}
static const TypeInfo taihu_type = {
diff --git a/hw/ppc/ppc405_uc.c b/hw/ppc/ppc405_uc.c
index e632c408bd..ec97b22bd0 100644
--- a/hw/ppc/ppc405_uc.c
+++ b/hw/ppc/ppc405_uc.c
@@ -25,6 +25,7 @@
#include "qemu/osdep.h"
#include "qemu/units.h"
#include "qapi/error.h"
+#include "qemu/log.h"
#include "cpu.h"
#include "hw/ppc/ppc.h"
#include "hw/i2c/ppc4xx_i2c.h"
@@ -38,18 +39,37 @@
#include "hw/intc/ppc-uic.h"
#include "hw/qdev-properties.h"
#include "qapi/error.h"
+#include "trace.h"
-//#define DEBUG_OPBA
-//#define DEBUG_SDRAM
-//#define DEBUG_GPIO
-//#define DEBUG_SERIAL
-//#define DEBUG_OCM
-//#define DEBUG_GPT
-//#define DEBUG_CLOCKS
-//#define DEBUG_CLOCKS_LL
-
-ram_addr_t ppc405_set_bootinfo (CPUPPCState *env, ppc4xx_bd_info_t *bd,
- uint32_t flags)
+static void ppc405_set_default_bootinfo(ppc4xx_bd_info_t *bd,
+ ram_addr_t ram_size)
+{
+ memset(bd, 0, sizeof(*bd));
+
+ bd->bi_memstart = PPC405EP_SDRAM_BASE;
+ bd->bi_memsize = ram_size;
+ bd->bi_sramstart = PPC405EP_SRAM_BASE;
+ bd->bi_sramsize = PPC405EP_SRAM_SIZE;
+ bd->bi_bootflags = 0;
+ bd->bi_intfreq = 133333333;
+ bd->bi_busfreq = 33333333;
+ bd->bi_baudrate = 115200;
+ bd->bi_s_version[0] = 'Q';
+ bd->bi_s_version[1] = 'M';
+ bd->bi_s_version[2] = 'U';
+ bd->bi_s_version[3] = '\0';
+ bd->bi_r_version[0] = 'Q';
+ bd->bi_r_version[1] = 'E';
+ bd->bi_r_version[2] = 'M';
+ bd->bi_r_version[3] = 'U';
+ bd->bi_r_version[4] = '\0';
+ bd->bi_procfreq = 133333333;
+ bd->bi_plb_busfreq = 33333333;
+ bd->bi_pci_busfreq = 33333333;
+ bd->bi_opbfreq = 33333333;
+}
+
+static ram_addr_t __ppc405_set_bootinfo(CPUPPCState *env, ppc4xx_bd_info_t *bd)
{
CPUState *cs = env_cpu(env);
ram_addr_t bdloc;
@@ -82,15 +102,15 @@ ram_addr_t ppc405_set_bootinfo (CPUPPCState *env, ppc4xx_bd_info_t *bd,
for (i = 0; i < 32; i++) {
stb_phys(cs->as, bdloc + 0x3C + i, bd->bi_r_version[i]);
}
- stl_be_phys(cs->as, bdloc + 0x5C, bd->bi_plb_busfreq);
- stl_be_phys(cs->as, bdloc + 0x60, bd->bi_pci_busfreq);
+ stl_be_phys(cs->as, bdloc + 0x5C, bd->bi_procfreq);
+ stl_be_phys(cs->as, bdloc + 0x60, bd->bi_plb_busfreq);
+ stl_be_phys(cs->as, bdloc + 0x64, bd->bi_pci_busfreq);
for (i = 0; i < 6; i++) {
- stb_phys(cs->as, bdloc + 0x64 + i, bd->bi_pci_enetaddr[i]);
+ stb_phys(cs->as, bdloc + 0x68 + i, bd->bi_pci_enetaddr[i]);
}
- n = 0x6A;
- if (flags & 0x00000001) {
- for (i = 0; i < 6; i++)
- stb_phys(cs->as, bdloc + n++, bd->bi_pci_enetaddr2[i]);
+ n = 0x70; /* includes 2 bytes hole */
+ for (i = 0; i < 6; i++) {
+ stb_phys(cs->as, bdloc + n++, bd->bi_pci_enetaddr2[i]);
}
stl_be_phys(cs->as, bdloc + n, bd->bi_opbfreq);
n += 4;
@@ -102,6 +122,17 @@ ram_addr_t ppc405_set_bootinfo (CPUPPCState *env, ppc4xx_bd_info_t *bd,
return bdloc;
}
+ram_addr_t ppc405_set_bootinfo(CPUPPCState *env, ram_addr_t ram_size)
+{
+ ppc4xx_bd_info_t bd;
+
+ memset(&bd, 0, sizeof(bd));
+
+ ppc405_set_default_bootinfo(&bd, ram_size);
+
+ return __ppc405_set_bootinfo(env, &bd);
+}
+
/*****************************************************************************/
/* Shared peripherals */
@@ -287,13 +318,9 @@ struct ppc4xx_opba_t {
static uint64_t opba_readb(void *opaque, hwaddr addr, unsigned size)
{
- ppc4xx_opba_t *opba;
+ ppc4xx_opba_t *opba = opaque;
uint32_t ret;
-#ifdef DEBUG_OPBA
- printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
-#endif
- opba = opaque;
switch (addr) {
case 0x00:
ret = opba->cr;
@@ -306,19 +333,17 @@ static uint64_t opba_readb(void *opaque, hwaddr addr, unsigned size)
break;
}
+ trace_opba_readb(addr, ret);
return ret;
}
static void opba_writeb(void *opaque, hwaddr addr, uint64_t value,
unsigned size)
{
- ppc4xx_opba_t *opba;
+ ppc4xx_opba_t *opba = opaque;
+
+ trace_opba_writeb(addr, value);
-#ifdef DEBUG_OPBA
- printf("%s: addr " TARGET_FMT_plx " val %08" PRIx32 "\n", __func__, addr,
- value);
-#endif
- opba = opaque;
switch (addr) {
case 0x00:
opba->cr = value & 0xF8;
@@ -353,10 +378,9 @@ static void ppc4xx_opba_init(hwaddr base)
{
ppc4xx_opba_t *opba;
+ trace_opba_init(base);
+
opba = g_malloc0(sizeof(ppc4xx_opba_t));
-#ifdef DEBUG_OPBA
- printf("%s: offset " TARGET_FMT_plx "\n", __func__, base);
-#endif
memory_region_init_io(&opba->io, NULL, &opba_ops, opba, "opba", 0x002);
memory_region_add_subregion(get_system_memory(), base, &opba->io);
qemu_register_reset(ppc4xx_opba_reset, opba);
@@ -707,20 +731,14 @@ struct ppc405_gpio_t {
static uint64_t ppc405_gpio_read(void *opaque, hwaddr addr, unsigned size)
{
-#ifdef DEBUG_GPIO
- printf("%s: addr " TARGET_FMT_plx " size %d\n", __func__, addr, size);
-#endif
-
+ trace_ppc405_gpio_read(addr, size);
return 0;
}
static void ppc405_gpio_write(void *opaque, hwaddr addr, uint64_t value,
unsigned size)
{
-#ifdef DEBUG_GPIO
- printf("%s: addr " TARGET_FMT_plx " size %d val %08" PRIx32 "\n",
- __func__, addr, size, value);
-#endif
+ trace_ppc405_gpio_write(addr, size, value);
}
static const MemoryRegionOps ppc405_gpio_ops = {
@@ -737,10 +755,9 @@ static void ppc405_gpio_init(hwaddr base)
{
ppc405_gpio_t *gpio;
+ trace_ppc405_gpio_init(base);
+
gpio = g_malloc0(sizeof(ppc405_gpio_t));
-#ifdef DEBUG_GPIO
- printf("%s: offset " TARGET_FMT_plx "\n", __func__, base);
-#endif
memory_region_init_io(&gpio->io, NULL, &ppc405_gpio_ops, gpio, "pgio", 0x038);
memory_region_add_subregion(get_system_memory(), base, &gpio->io);
qemu_register_reset(&ppc405_gpio_reset, gpio);
@@ -770,25 +787,19 @@ static void ocm_update_mappings (ppc405_ocm_t *ocm,
uint32_t isarc, uint32_t isacntl,
uint32_t dsarc, uint32_t dsacntl)
{
-#ifdef DEBUG_OCM
- printf("OCM update ISA %08" PRIx32 " %08" PRIx32 " (%08" PRIx32
- " %08" PRIx32 ") DSA %08" PRIx32 " %08" PRIx32
- " (%08" PRIx32 " %08" PRIx32 ")\n",
- isarc, isacntl, dsarc, dsacntl,
- ocm->isarc, ocm->isacntl, ocm->dsarc, ocm->dsacntl);
-#endif
+ trace_ocm_update_mappings(isarc, isacntl, dsarc, dsacntl, ocm->isarc,
+ ocm->isacntl, ocm->dsarc, ocm->dsacntl);
+
if (ocm->isarc != isarc ||
(ocm->isacntl & 0x80000000) != (isacntl & 0x80000000)) {
if (ocm->isacntl & 0x80000000) {
/* Unmap previously assigned memory region */
- printf("OCM unmap ISA %08" PRIx32 "\n", ocm->isarc);
+ trace_ocm_unmap("ISA", ocm->isarc);
memory_region_del_subregion(get_system_memory(), &ocm->isarc_ram);
}
if (isacntl & 0x80000000) {
/* Map new instruction memory region */
-#ifdef DEBUG_OCM
- printf("OCM map ISA %08" PRIx32 "\n", isarc);
-#endif
+ trace_ocm_map("ISA", isarc);
memory_region_add_subregion(get_system_memory(), isarc,
&ocm->isarc_ram);
}
@@ -799,9 +810,7 @@ static void ocm_update_mappings (ppc405_ocm_t *ocm,
/* Beware not to unmap the region we just mapped */
if (!(isacntl & 0x80000000) || ocm->dsarc != isarc) {
/* Unmap previously assigned memory region */
-#ifdef DEBUG_OCM
- printf("OCM unmap DSA %08" PRIx32 "\n", ocm->dsarc);
-#endif
+ trace_ocm_unmap("DSA", ocm->dsarc);
memory_region_del_subregion(get_system_memory(),
&ocm->dsarc_ram);
}
@@ -810,9 +819,7 @@ static void ocm_update_mappings (ppc405_ocm_t *ocm,
/* Beware not to remap the region we just mapped */
if (!(isacntl & 0x80000000) || dsarc != isarc) {
/* Map new data memory region */
-#ifdef DEBUG_OCM
- printf("OCM map DSA %08" PRIx32 "\n", dsarc);
-#endif
+ trace_ocm_map("DSA", dsarc);
memory_region_add_subregion(get_system_memory(), dsarc,
&ocm->dsarc_ram);
}
@@ -988,14 +995,12 @@ static void ppc4xx_gpt_compute_timer (ppc4xx_gpt_t *gpt)
static uint64_t ppc4xx_gpt_read(void *opaque, hwaddr addr, unsigned size)
{
- ppc4xx_gpt_t *gpt;
+ ppc4xx_gpt_t *gpt = opaque;
uint32_t ret;
int idx;
-#ifdef DEBUG_GPT
- printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
-#endif
- gpt = opaque;
+ trace_ppc4xx_gpt_read(addr, size);
+
switch (addr) {
case 0x00:
/* Time base counter */
@@ -1044,14 +1049,11 @@ static uint64_t ppc4xx_gpt_read(void *opaque, hwaddr addr, unsigned size)
static void ppc4xx_gpt_write(void *opaque, hwaddr addr, uint64_t value,
unsigned size)
{
- ppc4xx_gpt_t *gpt;
+ ppc4xx_gpt_t *gpt = opaque;
int idx;
-#ifdef DEBUG_I2C
- printf("%s: addr " TARGET_FMT_plx " val %08" PRIx32 "\n", __func__, addr,
- value);
-#endif
- gpt = opaque;
+ trace_ppc4xx_gpt_write(addr, size, value);
+
switch (addr) {
case 0x00:
/* Time base counter */
@@ -1144,14 +1146,13 @@ static void ppc4xx_gpt_init(hwaddr base, qemu_irq irqs[5])
ppc4xx_gpt_t *gpt;
int i;
+ trace_ppc4xx_gpt_init(base);
+
gpt = g_malloc0(sizeof(ppc4xx_gpt_t));
for (i = 0; i < 5; i++) {
gpt->irqs[i] = irqs[i];
}
gpt->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, &ppc4xx_gpt_cb, gpt);
-#ifdef DEBUG_GPT
- printf("%s: offset " TARGET_FMT_plx "\n", __func__, base);
-#endif
memory_region_init_io(&gpt->iomem, NULL, &gpt_ops, gpt, "gpt", 0x0d4);
memory_region_add_subregion(get_system_memory(), base, &gpt->iomem);
qemu_register_reset(ppc4xx_gpt_reset, gpt);
@@ -1215,17 +1216,14 @@ static void ppc405ep_compute_clocks (ppc405ep_cpc_t *cpc)
VCO_out = 0;
if ((cpc->pllmr[1] & 0x80000000) && !(cpc->pllmr[1] & 0x40000000)) {
M = (((cpc->pllmr[1] >> 20) - 1) & 0xF) + 1; /* FBMUL */
-#ifdef DEBUG_CLOCKS_LL
- printf("FBMUL %01" PRIx32 " %d\n", (cpc->pllmr[1] >> 20) & 0xF, M);
-#endif
+ trace_ppc405ep_clocks_compute("FBMUL", (cpc->pllmr[1] >> 20) & 0xF, M);
D = 8 - ((cpc->pllmr[1] >> 16) & 0x7); /* FWDA */
-#ifdef DEBUG_CLOCKS_LL
- printf("FWDA %01" PRIx32 " %d\n", (cpc->pllmr[1] >> 16) & 0x7, D);
-#endif
+ trace_ppc405ep_clocks_compute("FWDA", (cpc->pllmr[1] >> 16) & 0x7, D);
VCO_out = (uint64_t)cpc->sysclk * M * D;
if (VCO_out < 500000000UL || VCO_out > 1000000000UL) {
/* Error - unlock the PLL */
- printf("VCO out of range %" PRIu64 "\n", VCO_out);
+ qemu_log_mask(LOG_GUEST_ERROR, "VCO out of range %" PRIu64 "\n",
+ VCO_out);
#if 0
cpc->pllmr[1] &= ~0x80000000;
goto pll_bypass;
@@ -1246,54 +1244,43 @@ static void ppc405ep_compute_clocks (ppc405ep_cpc_t *cpc)
}
/* Now, compute all other clocks */
D = ((cpc->pllmr[0] >> 20) & 0x3) + 1; /* CCDV */
-#ifdef DEBUG_CLOCKS_LL
- printf("CCDV %01" PRIx32 " %d\n", (cpc->pllmr[0] >> 20) & 0x3, D);
-#endif
+ trace_ppc405ep_clocks_compute("CCDV", (cpc->pllmr[0] >> 20) & 0x3, D);
CPU_clk = PLL_out / D;
D = ((cpc->pllmr[0] >> 16) & 0x3) + 1; /* CBDV */
-#ifdef DEBUG_CLOCKS_LL
- printf("CBDV %01" PRIx32 " %d\n", (cpc->pllmr[0] >> 16) & 0x3, D);
-#endif
+ trace_ppc405ep_clocks_compute("CBDV", (cpc->pllmr[0] >> 16) & 0x3, D);
PLB_clk = CPU_clk / D;
D = ((cpc->pllmr[0] >> 12) & 0x3) + 1; /* OPDV */
-#ifdef DEBUG_CLOCKS_LL
- printf("OPDV %01" PRIx32 " %d\n", (cpc->pllmr[0] >> 12) & 0x3, D);
-#endif
+ trace_ppc405ep_clocks_compute("OPDV", (cpc->pllmr[0] >> 12) & 0x3, D);
OPB_clk = PLB_clk / D;
D = ((cpc->pllmr[0] >> 8) & 0x3) + 2; /* EPDV */
-#ifdef DEBUG_CLOCKS_LL
- printf("EPDV %01" PRIx32 " %d\n", (cpc->pllmr[0] >> 8) & 0x3, D);
-#endif
+ trace_ppc405ep_clocks_compute("EPDV", (cpc->pllmr[0] >> 8) & 0x3, D);
EBC_clk = PLB_clk / D;
D = ((cpc->pllmr[0] >> 4) & 0x3) + 1; /* MPDV */
-#ifdef DEBUG_CLOCKS_LL
- printf("MPDV %01" PRIx32 " %d\n", (cpc->pllmr[0] >> 4) & 0x3, D);
-#endif
+ trace_ppc405ep_clocks_compute("MPDV", (cpc->pllmr[0] >> 4) & 0x3, D);
MAL_clk = PLB_clk / D;
D = (cpc->pllmr[0] & 0x3) + 1; /* PPDV */
-#ifdef DEBUG_CLOCKS_LL
- printf("PPDV %01" PRIx32 " %d\n", cpc->pllmr[0] & 0x3, D);
-#endif
+ trace_ppc405ep_clocks_compute("PPDV", cpc->pllmr[0] & 0x3, D);
PCI_clk = PLB_clk / D;
D = ((cpc->ucr - 1) & 0x7F) + 1; /* U0DIV */
-#ifdef DEBUG_CLOCKS_LL
- printf("U0DIV %01" PRIx32 " %d\n", cpc->ucr & 0x7F, D);
-#endif
+ trace_ppc405ep_clocks_compute("U0DIV", cpc->ucr & 0x7F, D);
UART0_clk = PLL_out / D;
D = (((cpc->ucr >> 8) - 1) & 0x7F) + 1; /* U1DIV */
-#ifdef DEBUG_CLOCKS_LL
- printf("U1DIV %01" PRIx32 " %d\n", (cpc->ucr >> 8) & 0x7F, D);
-#endif
+ trace_ppc405ep_clocks_compute("U1DIV", (cpc->ucr >> 8) & 0x7F, D);
UART1_clk = PLL_out / D;
-#ifdef DEBUG_CLOCKS
- printf("Setup PPC405EP clocks - sysclk %" PRIu32 " VCO %" PRIu64
- " PLL out %" PRIu64 " Hz\n", cpc->sysclk, VCO_out, PLL_out);
- printf("CPU %" PRIu32 " PLB %" PRIu32 " OPB %" PRIu32 " EBC %" PRIu32
- " MAL %" PRIu32 " PCI %" PRIu32 " UART0 %" PRIu32
- " UART1 %" PRIu32 "\n",
- CPU_clk, PLB_clk, OPB_clk, EBC_clk, MAL_clk, PCI_clk,
- UART0_clk, UART1_clk);
-#endif
+
+ if (trace_event_get_state_backends(TRACE_PPC405EP_CLOCKS_SETUP)) {
+ g_autofree char *trace = g_strdup_printf(
+ "Setup PPC405EP clocks - sysclk %" PRIu32 " VCO %" PRIu64
+ " PLL out %" PRIu64 " Hz\n"
+ "CPU %" PRIu32 " PLB %" PRIu32 " OPB %" PRIu32 " EBC %" PRIu32
+ " MAL %" PRIu32 " PCI %" PRIu32 " UART0 %" PRIu32
+ " UART1 %" PRIu32 "\n",
+ cpc->sysclk, VCO_out, PLL_out,
+ CPU_clk, PLB_clk, OPB_clk, EBC_clk, MAL_clk, PCI_clk,
+ UART0_clk, UART1_clk);
+ trace_ppc405ep_clocks_setup(trace);
+ }
+
/* Setup CPU clocks */
clk_setup(&cpc->clk_setup[PPC405EP_CPU_CLK], CPU_clk);
/* Setup PLB clock */
@@ -1395,9 +1382,9 @@ static void ppc405ep_cpc_reset (void *opaque)
cpc->boot = 0x00000010; /* Boot from PCI - IIC EEPROM disabled */
cpc->epctl = 0x00000000;
- cpc->pllmr[0] = 0x00011010;
- cpc->pllmr[1] = 0x40000000;
- cpc->ucr = 0x00000000;
+ cpc->pllmr[0] = 0x00021002;
+ cpc->pllmr[1] = 0x80a552be;
+ cpc->ucr = 0x00004646;
cpc->srr = 0x00040000;
cpc->pci = 0x00000000;
cpc->er = 0x00000000;
@@ -1444,7 +1431,7 @@ static void ppc405ep_cpc_init (CPUPPCState *env, clk_setup_t clk_setup[8],
#endif
}
-CPUPPCState *ppc405ep_init(MemoryRegion *address_space_mem,
+PowerPCCPU *ppc405ep_init(MemoryRegion *address_space_mem,
MemoryRegion ram_memories[2],
hwaddr ram_bases[2],
hwaddr ram_sizes[2],
@@ -1543,5 +1530,5 @@ CPUPPCState *ppc405ep_init(MemoryRegion *address_space_mem,
/* CPU control */
ppc405ep_cpc_init(env, clk_setup, sysclk);
- return env;
+ return cpu;
}
diff --git a/hw/ppc/spapr_cpu_core.c b/hw/ppc/spapr_cpu_core.c
index 58e7341cb7..a57ba70a87 100644
--- a/hw/ppc/spapr_cpu_core.c
+++ b/hw/ppc/spapr_cpu_core.c
@@ -20,6 +20,7 @@
#include "target/ppc/kvm_ppc.h"
#include "hw/ppc/ppc.h"
#include "target/ppc/mmu-hash64.h"
+#include "target/ppc/power8-pmu.h"
#include "sysemu/numa.h"
#include "sysemu/reset.h"
#include "sysemu/hw_accel.h"
diff --git a/hw/ppc/trace-events b/hw/ppc/trace-events
index 3bf43fa340..ada644652d 100644
--- a/hw/ppc/trace-events
+++ b/hw/ppc/trace-events
@@ -119,6 +119,9 @@ ppc_irq_set_state(const char *name, uint32_t level) "\"%s\" level %d"
ppc_irq_reset(const char *name) "%s"
ppc_irq_cpu(const char *action) "%s"
+ppc_dcr_read(uint32_t addr, uint32_t val) "DRCN[0x%x] -> 0x%x"
+ppc_dcr_write(uint32_t addr, uint32_t val) "DRCN[0x%x] <- 0x%x"
+
# prep_systemio.c
prep_systemio_read(uint32_t addr, uint32_t val) "read addr=0x%x val=0x%x"
prep_systemio_write(uint32_t addr, uint32_t val) "write addr=0x%x val=0x%x"
@@ -141,3 +144,23 @@ ppc440_pcix_update_pim(int idx, uint64_t size, uint64_t la) "Added window %d of
ppc440_pcix_update_pom(int idx, uint32_t size, uint64_t la, uint64_t pcia) "Added window %d of size=0x%x from CPU=0x%" PRIx64 " to PCI=0x%" PRIx64
ppc440_pcix_reg_read(uint64_t addr, uint32_t val) "addr 0x%" PRIx64 " = 0x%" PRIx32
ppc440_pcix_reg_write(uint64_t addr, uint32_t val, uint32_t size) "addr 0x%" PRIx64 " = 0x%" PRIx32 " size 0x%" PRIx32
+
+# ppc405_boards.c
+opba_readb(uint64_t addr, uint32_t val) "addr 0x%" PRIx64 " = 0x%" PRIx32
+opba_writeb(uint64_t addr, uint64_t val) "addr 0x%" PRIx64 " = 0x%" PRIx64
+opba_init(uint64_t addr) "offet 0x%" PRIx64
+
+ppc405_gpio_read(uint64_t addr, uint32_t size) "addr 0x%" PRIx64 " size %d"
+ppc405_gpio_write(uint64_t addr, uint32_t size, uint64_t val) "addr 0x%" PRIx64 " size %d = 0x%" PRIx64
+ppc405_gpio_init(uint64_t addr) "offet 0x%" PRIx64
+
+ocm_update_mappings(uint32_t isarc, uint32_t isacntl, uint32_t dsarc, uint32_t dsacntl, uint32_t ocm_isarc, uint32_t ocm_isacntl, uint32_t ocm_dsarc, uint32_t ocm_dsacntl) "OCM update ISA 0x%08" PRIx32 " 0x%08" PRIx32 " (0x%08" PRIx32" 0x%08" PRIx32 ") DSA 0x%08" PRIx32 " 0x%08" PRIx32" (0x%08" PRIx32 " 0x%08" PRIx32 ")"
+ocm_map(const char* prefix, uint32_t isarc) "OCM map %s 0x%08" PRIx32
+ocm_unmap(const char* prefix, uint32_t isarc) "OCM unmap %s 0x%08" PRIx32
+
+ppc4xx_gpt_read(uint64_t addr, uint32_t size) "addr 0x%" PRIx64 " size %d"
+ppc4xx_gpt_write(uint64_t addr, uint32_t size, uint64_t val) "addr 0x%" PRIx64 " size %d = 0x%" PRIx64
+ppc4xx_gpt_init(uint64_t addr) "offet 0x%" PRIx64
+
+ppc405ep_clocks_compute(const char *param, uint32_t param2, uint32_t val) "%s 0x%1" PRIx32 " %d"
+ppc405ep_clocks_setup(const char *trace) "%s"