diff options
author | Richard Henderson <richard.henderson@linaro.org> | 2021-12-17 09:55:14 -0800 |
---|---|---|
committer | Richard Henderson <richard.henderson@linaro.org> | 2021-12-17 09:55:14 -0800 |
commit | 93dc314c9225e103487ae22b62da1ac59ac86325 (patch) | |
tree | 275f2baa8247550f15991852ff3d662c307f252c /hw | |
parent | 48c03a0e13f49e8dff9a8ac37fff43e00a0a9bb3 (diff) | |
parent | 0e6232bc3cb96bdf6fac1b5d7659aa9887afe657 (diff) |
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.c | 2 | ||||
-rw-r--r-- | hw/pci-host/pnv_phb3.c | 3 | ||||
-rw-r--r-- | hw/pci-host/pnv_phb3_pbcq.c | 11 | ||||
-rw-r--r-- | hw/pci-host/pnv_phb4.c | 1 | ||||
-rw-r--r-- | hw/pci-host/pnv_phb4_pec.c | 75 | ||||
-rw-r--r-- | hw/ppc/mac.h | 3 | ||||
-rw-r--r-- | hw/ppc/mac_newworld.c | 3 | ||||
-rw-r--r-- | hw/ppc/mac_oldworld.c | 3 | ||||
-rw-r--r-- | hw/ppc/pnv.c | 177 | ||||
-rw-r--r-- | hw/ppc/ppc.c | 2 | ||||
-rw-r--r-- | hw/ppc/ppc405.h | 14 | ||||
-rw-r--r-- | hw/ppc/ppc405_boards.c | 245 | ||||
-rw-r--r-- | hw/ppc/ppc405_uc.c | 225 | ||||
-rw-r--r-- | hw/ppc/spapr_cpu_core.c | 1 | ||||
-rw-r--r-- | hw/ppc/trace-events | 23 |
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" |