:p
atchew
Login
The following changes since commit b5a3d8bc9146ba22a25116cb748c97341bf99737: Merge tag 'pull-misc-20220103' of https://gitlab.com/rth7680/qemu into staging (2022-01-03 09:34:41 -0800) are available in the Git repository at: https://github.com/legoater/qemu/ tags/pull-ppc-20220104 for you to fetch changes up to 0625c7760d5451d7436ef0738f763c6bb5141919: target/ppc: do not call hreg_compute_hflags() in helper_store_mmcr0() (2022-01-04 07:55:35 +0100) ---------------------------------------------------------------- ppc 7.0 queue: * Cleanup of PowerNV PHBs (Daniel and Cedric) * Cleanup and fixes for PPC405 machine (Cedric) * Fix for xscvspdpn (Matheus) * Rework of powerpc exception handling 1/n (Fabiano) * Optimisation for PMU (Richard and Daniel) ---------------------------------------------------------------- Cédric Le Goater (14): ppc/pnv: Change the maximum of PHB3 devices for Power8NVL ppc/pnv: Remove PHB4 reset handler ppc/pnv: Remove the PHB4 "device-id" property target/ppc: Improve logging in Radix MMU target/ppc: Check effective address validity target/ppc: Remove static inline target/ppc: Print out literal exception names in logs ppc/ppc4xx: Convert printfs() ppc/ppc405: Activate MMU logs ppc/ppc405: Restore TCR and STR write handlers ppc/ppc405: Rework ppc_40x_timers_init() to use a PowerPCCPU ppc/ppc405: Fix timer initialization ppc/ppc405: Introduce a store helper for SPR_40x_PID ppc/ppc405: Dump specific registers Daniel Henrique Barboza (3): pnv_phb3.c: do not set 'root-bus' as bus name pnv_phb4.c: do not set 'root-bus' as bus name target/ppc: do not call hreg_compute_hflags() in helper_store_mmcr0() Fabiano Rosas (5): target/ppc: powerpc_excp: Set alternate SRRs directly target/ppc: powerpc_excp: Add excp_vectors bounds check target/ppc: powerpc_excp: Set vector earlier target/ppc: powerpc_excp: Move system call vectored code together target/ppc: powerpc_excp: Stop passing excp_model around Matheus Ferst (1): target/ppc: do not silence snan in xscvspdpn Richard Henderson (3): target/ppc: Cache per-pmc insn and cycle count settings target/ppc: Rewrite pmu_increment_insns target/ppc: Use env->pnc_cyc_cnt include/hw/pci-host/pnv_phb4.h | 2 - target/ppc/cpu.h | 5 + target/ppc/helper.h | 2 + target/ppc/mmu-radix64.h | 1 + target/ppc/power8-pmu.h | 14 +- target/ppc/spr_tcg.h | 3 + hw/pci-host/pnv_phb3.c | 3 +- hw/pci-host/pnv_phb4.c | 16 +-- hw/pci-host/pnv_phb4_pec.c | 3 - hw/ppc/mpc8544_guts.c | 9 +- hw/ppc/pnv.c | 2 +- hw/ppc/ppc.c | 67 ++++++--- hw/ppc/ppc405_uc.c | 2 - hw/ppc/ppc4xx_devs.c | 39 ++---- hw/ppc/ppc4xx_pci.c | 11 +- target/ppc/cpu_init.c | 34 +++-- target/ppc/excp_helper.c | 187 ++++++++++++++++--------- target/ppc/fpu_helper.c | 5 +- target/ppc/helper_regs.c | 2 +- target/ppc/machine.c | 2 + target/ppc/mmu-radix64.c | 60 +++++++- target/ppc/mmu_common.c | 164 +++++++++++----------- target/ppc/mmu_helper.c | 97 ++++++------- target/ppc/power8-pmu.c | 238 ++++++++++++++------------------ target/ppc/timebase_helper.c | 10 ++ target/ppc/translate.c | 20 +++ tests/tcg/ppc64le/non_signalling_xscv.c | 37 +++++ hw/ppc/trace-events | 7 + tests/tcg/ppc64/Makefile.target | 4 +- tests/tcg/ppc64le/Makefile.target | 4 +- 30 files changed, 604 insertions(+), 446 deletions(-) create mode 100644 tests/tcg/ppc64le/non_signalling_xscv.c
The POWER8 processors with a NVLink logic unit have 4 PHB3 devices per chip. Signed-off-by: Cédric Le Goater <clg@kaod.org> Reviewed-by: Daniel Henrique Barboza <danielhb413@gmail.com> Message-Id: <20211222063817.1541058-2-clg@kaod.org> Signed-off-by: Cédric Le Goater <clg@kaod.org> --- hw/ppc/pnv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c index XXXXXXX..XXXXXXX 100644 --- a/hw/ppc/pnv.c +++ b/hw/ppc/pnv.c @@ -XXX,XX +XXX,XX @@ static void pnv_chip_power8nvl_class_init(ObjectClass *klass, void *data) k->chip_cfam_id = 0x120d304980000000ull; /* P8 Naples DD1.0 */ k->cores_mask = POWER8_CORE_MASK; - k->num_phbs = 3; + k->num_phbs = 4; k->core_pir = pnv_chip_core_pir_p8; k->intc_create = pnv_chip_power8_intc_create; k->intc_reset = pnv_chip_power8_intc_reset; -- 2.31.1
The PHB4 reset handler was preparing ground for PHB5 to set appropriately the device id. We don't need it for the PHB4 since the device id is already set in the root port complex. PH5 will introduce its own. "device-id" property is now useless. It should be removed. Signed-off-by: Cédric Le Goater <clg@kaod.org> Reviewed-by: Daniel Henrique Barboza <danielhb413@gmail.com> Message-Id: <20211222063817.1541058-3-clg@kaod.org> Signed-off-by: Cédric Le Goater <clg@kaod.org> --- hw/pci-host/pnv_phb4.c | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/hw/pci-host/pnv_phb4.c b/hw/pci-host/pnv_phb4.c index XXXXXXX..XXXXXXX 100644 --- a/hw/pci-host/pnv_phb4.c +++ b/hw/pci-host/pnv_phb4.c @@ -XXX,XX +XXX,XX @@ static void pnv_phb4_realize(DeviceState *dev, Error **errp) phb->qirqs = qemu_allocate_irqs(xive_source_set_irq, xsrc, xsrc->nr_irqs); } -static void pnv_phb4_reset(DeviceState *dev) -{ - PnvPHB4 *phb = PNV_PHB4(dev); - PCIDevice *root_dev = PCI_DEVICE(&phb->root); - - /* - * Configure PCI device id at reset using a property. - */ - pci_config_set_vendor_id(root_dev->config, PCI_VENDOR_ID_IBM); - pci_config_set_device_id(root_dev->config, phb->device_id); -} - static const char *pnv_phb4_root_bus_path(PCIHostState *host_bridge, PCIBus *rootbus) { @@ -XXX,XX +XXX,XX @@ static void pnv_phb4_class_init(ObjectClass *klass, void *data) device_class_set_props(dc, pnv_phb4_properties); set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); dc->user_creatable = false; - dc->reset = pnv_phb4_reset; xfc->notify = pnv_phb4_xive_notify; } -- 2.31.1
It's unused. Signed-off-by: Cédric Le Goater <clg@kaod.org> Reviewed-by: Daniel Henrique Barboza <danielhb413@gmail.com> Message-Id: <20211222063817.1541058-4-clg@kaod.org> Signed-off-by: Cédric Le Goater <clg@kaod.org> --- include/hw/pci-host/pnv_phb4.h | 2 -- hw/pci-host/pnv_phb4.c | 1 - hw/pci-host/pnv_phb4_pec.c | 3 --- 3 files changed, 6 deletions(-) diff --git a/include/hw/pci-host/pnv_phb4.h b/include/hw/pci-host/pnv_phb4.h index XXXXXXX..XXXXXXX 100644 --- a/include/hw/pci-host/pnv_phb4.h +++ b/include/hw/pci-host/pnv_phb4.h @@ -XXX,XX +XXX,XX @@ struct PnvPHB4 { uint32_t phb_id; uint64_t version; - uint16_t device_id; char bus_path[8]; @@ -XXX,XX +XXX,XX @@ struct PnvPhb4PecClass { const char *stk_compat; int stk_compat_size; uint64_t version; - uint64_t device_id; const uint32_t *num_stacks; }; diff --git a/hw/pci-host/pnv_phb4.c b/hw/pci-host/pnv_phb4.c index XXXXXXX..XXXXXXX 100644 --- a/hw/pci-host/pnv_phb4.c +++ b/hw/pci-host/pnv_phb4.c @@ -XXX,XX +XXX,XX @@ static Property pnv_phb4_properties[] = { DEFINE_PROP_UINT32("index", PnvPHB4, phb_id, 0), DEFINE_PROP_UINT32("chip-id", PnvPHB4, chip_id, 0), DEFINE_PROP_UINT64("version", PnvPHB4, version, 0), - DEFINE_PROP_UINT16("device-id", PnvPHB4, device_id, 0), DEFINE_PROP_LINK("stack", PnvPHB4, stack, TYPE_PNV_PHB4_PEC_STACK, PnvPhb4PecStack *), DEFINE_PROP_END_OF_LIST(), diff --git a/hw/pci-host/pnv_phb4_pec.c b/hw/pci-host/pnv_phb4_pec.c index XXXXXXX..XXXXXXX 100644 --- a/hw/pci-host/pnv_phb4_pec.c +++ b/hw/pci-host/pnv_phb4_pec.c @@ -XXX,XX +XXX,XX @@ static void pnv_pec_class_init(ObjectClass *klass, void *data) 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; } @@ -XXX,XX +XXX,XX @@ static void pnv_pec_stk_realize(DeviceState *dev, Error **errp) &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)) { -- 2.31.1
From: Daniel Henrique Barboza <danielhb413@gmail.com> All pnv-phb3-root-bus buses are being created as 'root-bus'. This makes it impossible to, for example, add a pnv-phb3-root-port in a specific root bus, since they all have the same name. By default the device will be parented by the pnv-phb3 device that precedeced it in the QEMU command line. Moreover, this doesn't all for custom bus naming. Libvirt, for instance, likes to name these buses as 'pcie.N', where 'N' is the index value of the controller in the domain XML, by using the 'id' command line attribute. At this moment this is also being ignored - the created root bus will always be named 'root-bus'. This patch fixes both scenarios by removing the 'root-bus' name from the pci_register_root_bus() call. If an "id" is provided, use that. Otherwise use 'NULL' as bus name. The 'NULL' value will be handled in qbus_init_internal() and it will defaulted as lowercase bus type + the global bus_id value. After this path we can define the bus name by using the 'id' attribute: qemu-system-ppc64 -m 4G -machine powernv8,accel=tcg \ -device pnv-phb3,chip-id=0,index=1,id=pcie.0 dev: pnv-phb3, id "pcie.0" index = 1 (0x1) chip-id = 0 (0x0) x-config-reg-migration-enabled = true bypass-iommu = false bus: pcie.0 type pnv-phb3-root-bus And without an 'id' we will have the following default: qemu-system-ppc64 -m 4G -machine powernv8,accel=tcg \ -device pnv-phb3,chip-id=0,index=1 dev: pnv-phb3, id "" index = 1 (0x1) chip-id = 0 (0x0) x-config-reg-migration-enabled = true bypass-iommu = false bus: pnv-phb3-root-bus.0 type pnv-phb3-root-bus Signed-off-by: Daniel Henrique Barboza <danielhb413@gmail.com> Reviewed-by: Cédric Le Goater <clg@kaod.org> Message-Id: <20211228193806.1198496-3-danielhb413@gmail.com> Signed-off-by: Cédric Le Goater <clg@kaod.org> --- hw/pci-host/pnv_phb3.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/hw/pci-host/pnv_phb3.c b/hw/pci-host/pnv_phb3.c index XXXXXXX..XXXXXXX 100644 --- a/hw/pci-host/pnv_phb3.c +++ b/hw/pci-host/pnv_phb3.c @@ -XXX,XX +XXX,XX @@ static void pnv_phb3_realize(DeviceState *dev, Error **errp) memory_region_init(&phb->pci_mmio, OBJECT(phb), "pci-mmio", PCI_MMIO_TOTAL_SIZE); - pci->bus = pci_register_root_bus(dev, "root-bus", + pci->bus = pci_register_root_bus(dev, + dev->id ? dev->id : NULL, pnv_phb3_set_irq, pnv_phb3_map_irq, phb, &phb->pci_mmio, &phb->pci_io, 0, 4, TYPE_PNV_PHB3_ROOT_BUS); -- 2.31.1
From: Daniel Henrique Barboza <danielhb413@gmail.com> This change has the same motivation as the one done for pnv-phb3-root-bus buses previously. Defaulting every bus to 'root-bus' makes it impossible to attach root ports to specific buses and it doesn't allow for custom bus naming because we're ignoring the 'id' value when registering the root bus. After this patch, creating pnv-phb4 devices with 'id' being set will result in the following qtree: qemu-system-ppc64 -m 4G -machine powernv9,accel=tcg \ -device pnv-phb4,chip-id=0,index=0,id=pcie.0 \ -device pnv-phb4,chip-id=1,index=4,id=pcie.1 bus: main-system-bus type System dev: pnv-phb4, id "pcie.1" index = 4 (0x4) chip-id = 1 (0x1) version = 704374636546 (0xa400000002) device-id = 1217 (0x4c1) x-config-reg-migration-enabled = true bypass-iommu = false bus: pcie.1 type pnv-phb4-root-bus dev: pnv-phb4, id "pcie.0" index = 0 (0x0) chip-id = 0 (0x0) version = 704374636546 (0xa400000002) device-id = 1217 (0x4c1) x-config-reg-migration-enabled = true bypass-iommu = false bus: pcie.0 type pnv-phb4-root-bus And without setting any ids: qemu-system-ppc64 -m 4G -machine powernv9,accel=tcg \ -device pnv-phb4,chip-id=0,index=0,id=pcie.0 \ -device pnv-phb4,chip-id=1,index=4,id=pcie.1 bus: main-system-bus type System dev: pnv-phb4, id "" index = 4 (0x4) chip-id = 1 (0x1) version = 704374636546 (0xa400000002) device-id = 1217 (0x4c1) x-config-reg-migration-enabled = true bypass-iommu = false bus: pnv-phb4-root-bus.1 type pnv-phb4-root-bus dev: pnv-phb4, id "" index = 0 (0x0) chip-id = 0 (0x0) version = 704374636546 (0xa400000002) device-id = 1217 (0x4c1) x-config-reg-migration-enabled = true bypass-iommu = false bus: pnv-phb4-root-bus.0 type pnv-phb4-root-bus Signed-off-by: Daniel Henrique Barboza <danielhb413@gmail.com> Reviewed-by: Cédric Le Goater <clg@kaod.org> Message-Id: <20211228193806.1198496-17-danielhb413@gmail.com> Signed-off-by: Cédric Le Goater <clg@kaod.org> --- hw/pci-host/pnv_phb4.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/pci-host/pnv_phb4.c b/hw/pci-host/pnv_phb4.c index XXXXXXX..XXXXXXX 100644 --- a/hw/pci-host/pnv_phb4.c +++ b/hw/pci-host/pnv_phb4.c @@ -XXX,XX +XXX,XX @@ static void pnv_phb4_realize(DeviceState *dev, Error **errp) memory_region_init(&phb->pci_mmio, OBJECT(phb), name, PCI_MMIO_TOTAL_SIZE); - pci->bus = pci_register_root_bus(dev, "root-bus", + pci->bus = pci_register_root_bus(dev, dev->id, pnv_phb4_set_irq, pnv_phb4_map_irq, phb, &phb->pci_mmio, &phb->pci_io, 0, 4, TYPE_PNV_PHB4_ROOT_BUS); -- 2.31.1
Signed-off-by: Cédric Le Goater <clg@kaod.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-Id: <20211222071002.1568894-1-clg@kaod.org> Signed-off-by: Cédric Le Goater <clg@kaod.org> --- target/ppc/mmu-radix64.c | 55 +++++++++++++++++++++++++++++++++++++--- 1 file changed, 52 insertions(+), 3 deletions(-) diff --git a/target/ppc/mmu-radix64.c b/target/ppc/mmu-radix64.c index XXXXXXX..XXXXXXX 100644 --- a/target/ppc/mmu-radix64.c +++ b/target/ppc/mmu-radix64.c @@ -XXX,XX +XXX,XX @@ static void ppc_radix64_raise_segi(PowerPCCPU *cpu, MMUAccessType access_type, env->error_code = 0; } +static inline const char *access_str(MMUAccessType access_type) +{ + return access_type == MMU_DATA_LOAD ? "reading" : + (access_type == MMU_DATA_STORE ? "writing" : "execute"); +} + static void ppc_radix64_raise_si(PowerPCCPU *cpu, MMUAccessType access_type, vaddr eaddr, uint32_t cause) { CPUState *cs = CPU(cpu); CPUPPCState *env = &cpu->env; + qemu_log_mask(CPU_LOG_MMU, "%s for %s @0x%"VADDR_PRIx" cause %08x\n", + __func__, access_str(access_type), + eaddr, cause); + switch (access_type) { case MMU_INST_FETCH: /* Instruction Storage Interrupt */ @@ -XXX,XX +XXX,XX @@ static void ppc_radix64_raise_hsi(PowerPCCPU *cpu, MMUAccessType access_type, CPUState *cs = CPU(cpu); CPUPPCState *env = &cpu->env; + qemu_log_mask(CPU_LOG_MMU, "%s for %s @0x%"VADDR_PRIx" 0x%" + HWADDR_PRIx" cause %08x\n", + __func__, access_str(access_type), + eaddr, g_raddr, cause); + switch (access_type) { case MMU_INST_FETCH: /* H Instruction Storage Interrupt */ @@ -XXX,XX +XXX,XX @@ static int ppc_radix64_partition_scoped_xlate(PowerPCCPU *cpu, hwaddr pte_addr; uint64_t pte; + qemu_log_mask(CPU_LOG_MMU, "%s for %s @0x%"VADDR_PRIx + " mmu_idx %u (prot %c%c%c) 0x%"HWADDR_PRIx"\n", + __func__, access_str(access_type), + eaddr, mmu_idx, + *h_prot & PAGE_READ ? 'r' : '-', + *h_prot & PAGE_WRITE ? 'w' : '-', + *h_prot & PAGE_EXEC ? 'x' : '-', + g_raddr); + *h_page_size = PRTBE_R_GET_RTS(pate.dw0); /* No valid pte or access denied due to protection */ if (ppc_radix64_walk_tree(CPU(cpu)->as, g_raddr, pate.dw0 & PRTBE_R_RPDB, @@ -XXX,XX +XXX,XX @@ static int ppc_radix64_process_scoped_xlate(PowerPCCPU *cpu, hwaddr h_raddr, pte_addr; int ret; + qemu_log_mask(CPU_LOG_MMU, "%s for %s @0x%"VADDR_PRIx + " mmu_idx %u pid %"PRIu64"\n", + __func__, access_str(access_type), + eaddr, mmu_idx, pid); + /* Index Process Table by PID to Find Corresponding Process Table Entry */ offset = pid * sizeof(struct prtb_entry); size = 1ULL << ((pate.dw1 & PATE1_R_PRTS) + 12); @@ -XXX,XX +XXX,XX @@ static int ppc_radix64_process_scoped_xlate(PowerPCCPU *cpu, * | = On | Process Scoped | Scoped | * +-------------+----------------+---------------+ */ -bool ppc_radix64_xlate(PowerPCCPU *cpu, vaddr eaddr, MMUAccessType access_type, - hwaddr *raddr, int *psizep, int *protp, int mmu_idx, - bool guest_visible) +static bool ppc_radix64_xlate_impl(PowerPCCPU *cpu, vaddr eaddr, + MMUAccessType access_type, hwaddr *raddr, + int *psizep, int *protp, int mmu_idx, + bool guest_visible) { CPUPPCState *env = &cpu->env; uint64_t lpid, pid; @@ -XXX,XX +XXX,XX @@ bool ppc_radix64_xlate(PowerPCCPU *cpu, vaddr eaddr, MMUAccessType access_type, return true; } + +bool ppc_radix64_xlate(PowerPCCPU *cpu, vaddr eaddr, MMUAccessType access_type, + hwaddr *raddrp, int *psizep, int *protp, int mmu_idx, + bool guest_visible) +{ + bool ret = ppc_radix64_xlate_impl(cpu, eaddr, access_type, raddrp, + psizep, protp, mmu_idx, guest_visible); + + qemu_log_mask(CPU_LOG_MMU, "%s for %s @0x%"VADDR_PRIx + " mmu_idx %u (prot %c%c%c) -> 0x%"HWADDR_PRIx"\n", + __func__, access_str(access_type), + eaddr, mmu_idx, + *protp & PAGE_READ ? 'r' : '-', + *protp & PAGE_WRITE ? 'w' : '-', + *protp & PAGE_EXEC ? 'x' : '-', + *raddrp); + + return ret; +} -- 2.31.1
For Radix translation, the EA range is 64-bits. when EA(2:11) are nonzero, a segment interrupt should occur. Signed-off-by: Cédric Le Goater <clg@kaod.org> Reviewed-by: Frederic Barrat <fbarrat@linux.ibm.com> Message-Id: <20211231073122.3183583-1-clg@kaod.org> Signed-off-by: Cédric Le Goater <clg@kaod.org> --- target/ppc/mmu-radix64.h | 1 + target/ppc/mmu-radix64.c | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/target/ppc/mmu-radix64.h b/target/ppc/mmu-radix64.h index XXXXXXX..XXXXXXX 100644 --- a/target/ppc/mmu-radix64.h +++ b/target/ppc/mmu-radix64.h @@ -XXX,XX +XXX,XX @@ /* Radix Quadrants */ #define R_EADDR_MASK 0x3FFFFFFFFFFFFFFF +#define R_EADDR_VALID_MASK 0xC00FFFFFFFFFFFFF #define R_EADDR_QUADRANT 0xC000000000000000 #define R_EADDR_QUADRANT0 0x0000000000000000 #define R_EADDR_QUADRANT1 0x4000000000000000 diff --git a/target/ppc/mmu-radix64.c b/target/ppc/mmu-radix64.c index XXXXXXX..XXXXXXX 100644 --- a/target/ppc/mmu-radix64.c +++ b/target/ppc/mmu-radix64.c @@ -XXX,XX +XXX,XX @@ static bool ppc_radix64_get_fully_qualified_addr(const CPUPPCState *env, vaddr eaddr, uint64_t *lpid, uint64_t *pid) { + /* When EA(2:11) are nonzero, raise a segment interrupt */ + if (eaddr & ~R_EADDR_VALID_MASK) { + return false; + } + if (msr_hv) { /* MSR[HV] -> Hypervisor/bare metal */ switch (eaddr & R_EADDR_QUADRANT) { case R_EADDR_QUADRANT0: -- 2.31.1
The compiler should know better how to inline code if necessary. Suggested-by: Richard Henderson <richard.henderson@linaro.org> Signed-off-by: Cédric Le Goater <clg@kaod.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-Id: <20220103063441.3424853-2-clg@kaod.org> Signed-off-by: Cédric Le Goater <clg@kaod.org> --- target/ppc/excp_helper.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c index XXXXXXX..XXXXXXX 100644 --- a/target/ppc/excp_helper.c +++ b/target/ppc/excp_helper.c @@ -XXX,XX +XXX,XX @@ /* Exception processing */ #if !defined(CONFIG_USER_ONLY) -static inline void dump_syscall(CPUPPCState *env) +static void dump_syscall(CPUPPCState *env) { qemu_log_mask(CPU_LOG_INT, "syscall r0=%016" PRIx64 " r3=%016" PRIx64 " r4=%016" PRIx64 " r5=%016" PRIx64 @@ -XXX,XX +XXX,XX @@ static inline void dump_syscall(CPUPPCState *env) ppc_dump_gpr(env, 8), env->nip); } -static inline void dump_hcall(CPUPPCState *env) +static void dump_hcall(CPUPPCState *env) { qemu_log_mask(CPU_LOG_INT, "hypercall r3=%016" PRIx64 " r4=%016" PRIx64 " r5=%016" PRIx64 " r6=%016" PRIx64 @@ -XXX,XX +XXX,XX @@ static int powerpc_reset_wakeup(CPUState *cs, CPUPPCState *env, int excp, * | a | h | 11 | 1 | 1 | h | * +--------------------------------------------------------------------+ */ -static inline void ppc_excp_apply_ail(PowerPCCPU *cpu, int excp_model, int excp, +static void ppc_excp_apply_ail(PowerPCCPU *cpu, int excp_model, int excp, target_ulong msr, target_ulong *new_msr, target_ulong *vector) @@ -XXX,XX +XXX,XX @@ static inline void ppc_excp_apply_ail(PowerPCCPU *cpu, int excp_model, int excp, #endif } -static inline void powerpc_set_excp_state(PowerPCCPU *cpu, +static void powerpc_set_excp_state(PowerPCCPU *cpu, target_ulong vector, target_ulong msr) { CPUState *cs = CPU(cpu); @@ -XXX,XX +XXX,XX @@ static inline void powerpc_set_excp_state(PowerPCCPU *cpu, * Note that this function should be greatly optimized when called * with a constant excp, from ppc_hw_interrupt */ -static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp) +static void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp) { CPUState *cs = CPU(cpu); CPUPPCState *env = &cpu->env; @@ -XXX,XX +XXX,XX @@ void helper_pminsn(CPUPPCState *env, powerpc_pm_insn_t insn) #endif /* defined(TARGET_PPC64) */ #endif /* CONFIG_TCG */ -static inline void do_rfi(CPUPPCState *env, target_ulong nip, target_ulong msr) +static void do_rfi(CPUPPCState *env, target_ulong nip, target_ulong msr) { CPUState *cs = env_cpu(env); -- 2.31.1
It facilitates reading the logs when mask CPU_LOG_INT is activated. We should do the same for error codes. Cc: Fabiano Rosas <farosas@linux.ibm.com> Signed-off-by: Cédric Le Goater <clg@kaod.org> Reviewed-by: Fabiano Rosas <farosas@linux.ibm.com> Reviewed-by: David Gibson <david@gibson.dropbear.id.au> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-Id: <20211222064025.1541490-2-clg@kaod.org> Signed-off-by: Cédric Le Goater <clg@kaod.org> Message-Id: <20220103063441.3424853-3-clg@kaod.org> Signed-off-by: Cédric Le Goater <clg@kaod.org> --- target/ppc/excp_helper.c | 75 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 74 insertions(+), 1 deletion(-) diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c index XXXXXXX..XXXXXXX 100644 --- a/target/ppc/excp_helper.c +++ b/target/ppc/excp_helper.c @@ -XXX,XX +XXX,XX @@ /* Exception processing */ #if !defined(CONFIG_USER_ONLY) +static const char *powerpc_excp_name(int excp) +{ + switch (excp) { + case POWERPC_EXCP_CRITICAL: return "CRITICAL"; + case POWERPC_EXCP_MCHECK: return "MCHECK"; + case POWERPC_EXCP_DSI: return "DSI"; + case POWERPC_EXCP_ISI: return "ISI"; + case POWERPC_EXCP_EXTERNAL: return "EXTERNAL"; + case POWERPC_EXCP_ALIGN: return "ALIGN"; + case POWERPC_EXCP_PROGRAM: return "PROGRAM"; + case POWERPC_EXCP_FPU: return "FPU"; + case POWERPC_EXCP_SYSCALL: return "SYSCALL"; + case POWERPC_EXCP_APU: return "APU"; + case POWERPC_EXCP_DECR: return "DECR"; + case POWERPC_EXCP_FIT: return "FIT"; + case POWERPC_EXCP_WDT: return "WDT"; + case POWERPC_EXCP_DTLB: return "DTLB"; + case POWERPC_EXCP_ITLB: return "ITLB"; + case POWERPC_EXCP_DEBUG: return "DEBUG"; + case POWERPC_EXCP_SPEU: return "SPEU"; + case POWERPC_EXCP_EFPDI: return "EFPDI"; + case POWERPC_EXCP_EFPRI: return "EFPRI"; + case POWERPC_EXCP_EPERFM: return "EPERFM"; + case POWERPC_EXCP_DOORI: return "DOORI"; + case POWERPC_EXCP_DOORCI: return "DOORCI"; + case POWERPC_EXCP_GDOORI: return "GDOORI"; + case POWERPC_EXCP_GDOORCI: return "GDOORCI"; + case POWERPC_EXCP_HYPPRIV: return "HYPPRIV"; + case POWERPC_EXCP_RESET: return "RESET"; + case POWERPC_EXCP_DSEG: return "DSEG"; + case POWERPC_EXCP_ISEG: return "ISEG"; + case POWERPC_EXCP_HDECR: return "HDECR"; + case POWERPC_EXCP_TRACE: return "TRACE"; + case POWERPC_EXCP_HDSI: return "HDSI"; + case POWERPC_EXCP_HISI: return "HISI"; + case POWERPC_EXCP_HDSEG: return "HDSEG"; + case POWERPC_EXCP_HISEG: return "HISEG"; + case POWERPC_EXCP_VPU: return "VPU"; + case POWERPC_EXCP_PIT: return "PIT"; + case POWERPC_EXCP_IO: return "IO"; + case POWERPC_EXCP_RUNM: return "RUNM"; + case POWERPC_EXCP_EMUL: return "EMUL"; + case POWERPC_EXCP_IFTLB: return "IFTLB"; + case POWERPC_EXCP_DLTLB: return "DLTLB"; + case POWERPC_EXCP_DSTLB: return "DSTLB"; + case POWERPC_EXCP_FPA: return "FPA"; + case POWERPC_EXCP_DABR: return "DABR"; + case POWERPC_EXCP_IABR: return "IABR"; + case POWERPC_EXCP_SMI: return "SMI"; + case POWERPC_EXCP_PERFM: return "PERFM"; + case POWERPC_EXCP_THERM: return "THERM"; + case POWERPC_EXCP_VPUA: return "VPUA"; + case POWERPC_EXCP_SOFTP: return "SOFTP"; + case POWERPC_EXCP_MAINT: return "MAINT"; + case POWERPC_EXCP_MEXTBR: return "MEXTBR"; + case POWERPC_EXCP_NMEXTBR: return "NMEXTBR"; + case POWERPC_EXCP_ITLBE: return "ITLBE"; + case POWERPC_EXCP_DTLBE: return "DTLBE"; + case POWERPC_EXCP_VSXU: return "VSXU"; + case POWERPC_EXCP_FU: return "FU"; + case POWERPC_EXCP_HV_EMU: return "HV_EMU"; + case POWERPC_EXCP_HV_MAINT: return "HV_MAINT"; + case POWERPC_EXCP_HV_FU: return "HV_FU"; + case POWERPC_EXCP_SDOOR: return "SDOOR"; + case POWERPC_EXCP_SDOOR_HV: return "SDOOR_HV"; + case POWERPC_EXCP_HVIRT: return "HVIRT"; + case POWERPC_EXCP_SYSCALL_VECTORED: return "SYSCALL_VECTORED"; + default: + g_assert_not_reached(); + } +} + static void dump_syscall(CPUPPCState *env) { qemu_log_mask(CPU_LOG_INT, "syscall r0=%016" PRIx64 @@ -XXX,XX +XXX,XX @@ static void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp) int srr0, srr1, asrr0, asrr1, lev = -1; qemu_log_mask(CPU_LOG_INT, "Raise exception at " TARGET_FMT_lx - " => %08x (%02x)\n", env->nip, excp, env->error_code); + " => %s (%d) error=%02x\n", env->nip, powerpc_excp_name(excp), + excp, env->error_code); /* new srr1 value excluding must-be-zero bits */ if (excp_model == POWERPC_EXCP_BOOKE) { -- 2.31.1
Use a QEMU log primitive for errors and trace events for debug. Signed-off-by: Cédric Le Goater <clg@kaod.org> Reviewed-by: David Gibson <david@gibson.drobear.id.au> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-Id: <20211222064025.1541490-3-clg@kaod.org> Signed-off-by: Cédric Le Goater <clg@kaod.org> Message-Id: <20220103063441.3424853-4-clg@kaod.org> Signed-off-by: Cédric Le Goater <clg@kaod.org> --- hw/ppc/mpc8544_guts.c | 9 ++++++--- hw/ppc/ppc4xx_devs.c | 39 +++++++++++---------------------------- hw/ppc/ppc4xx_pci.c | 11 +++++++---- hw/ppc/trace-events | 5 +++++ 4 files changed, 29 insertions(+), 35 deletions(-) diff --git a/hw/ppc/mpc8544_guts.c b/hw/ppc/mpc8544_guts.c index XXXXXXX..XXXXXXX 100644 --- a/hw/ppc/mpc8544_guts.c +++ b/hw/ppc/mpc8544_guts.c @@ -XXX,XX +XXX,XX @@ #include "qemu/osdep.h" #include "qemu/module.h" +#include "qemu/log.h" #include "sysemu/runstate.h" #include "cpu.h" #include "hw/sysbus.h" @@ -XXX,XX +XXX,XX @@ static uint64_t mpc8544_guts_read(void *opaque, hwaddr addr, value = env->spr[SPR_E500_SVR]; break; default: - fprintf(stderr, "guts: Unknown register read: %x\n", (int)addr); + qemu_log_mask(LOG_GUEST_ERROR, + "%s: Unknown register 0x%" HWADDR_PRIx "\n", + __func__, addr); break; } @@ -XXX,XX +XXX,XX @@ static void mpc8544_guts_write(void *opaque, hwaddr addr, } break; default: - fprintf(stderr, "guts: Unknown register write: %x = %x\n", - (int)addr, (unsigned)value); + qemu_log_mask(LOG_GUEST_ERROR, "%s: Unknown register 0x%" HWADDR_PRIx + " = 0x%" PRIx64 "\n", __func__, addr, value); break; } } diff --git a/hw/ppc/ppc4xx_devs.c b/hw/ppc/ppc4xx_devs.c index XXXXXXX..XXXXXXX 100644 --- a/hw/ppc/ppc4xx_devs.c +++ b/hw/ppc/ppc4xx_devs.c @@ -XXX,XX +XXX,XX @@ #include "exec/address-spaces.h" #include "qemu/error-report.h" #include "qapi/error.h" - -/*#define DEBUG_UIC*/ - -#ifdef DEBUG_UIC -# define LOG_UIC(...) qemu_log_mask(CPU_LOG_INT, ## __VA_ARGS__) -#else -# define LOG_UIC(...) do { } while (0) -#endif +#include "trace.h" static void ppc4xx_reset(void *opaque) { @@ -XXX,XX +XXX,XX @@ static uint32_t sdram_bcr (hwaddr ram_base, bcr = 0x000C0000; break; default: - printf("%s: invalid RAM size " TARGET_FMT_plx "\n", __func__, - ram_size); + qemu_log_mask(LOG_GUEST_ERROR, + "%s: invalid RAM size 0x%" HWADDR_PRIx "\n", __func__, + ram_size); return 0x00000000; } bcr |= ram_base & 0xFF800000; @@ -XXX,XX +XXX,XX @@ static void sdram_set_bcr(ppc4xx_sdram_t *sdram, int i, { if (sdram->bcr[i] & 0x00000001) { /* Unmap RAM */ -#ifdef DEBUG_SDRAM - printf("%s: unmap RAM area " TARGET_FMT_plx " " TARGET_FMT_lx "\n", - __func__, sdram_base(sdram->bcr[i]), sdram_size(sdram->bcr[i])); -#endif + trace_ppc4xx_sdram_unmap(sdram_base(sdram->bcr[i]), + sdram_size(sdram->bcr[i])); memory_region_del_subregion(get_system_memory(), &sdram->containers[i]); memory_region_del_subregion(&sdram->containers[i], @@ -XXX,XX +XXX,XX @@ static void sdram_set_bcr(ppc4xx_sdram_t *sdram, int i, } sdram->bcr[i] = bcr & 0xFFDEE001; if (enabled && (bcr & 0x00000001)) { -#ifdef DEBUG_SDRAM - printf("%s: Map RAM area " TARGET_FMT_plx " " TARGET_FMT_lx "\n", - __func__, sdram_base(bcr), sdram_size(bcr)); -#endif + trace_ppc4xx_sdram_unmap(sdram_base(bcr), sdram_size(bcr)); memory_region_init(&sdram->containers[i], NULL, "sdram-containers", sdram_size(bcr)); memory_region_add_subregion(&sdram->containers[i], 0, @@ -XXX,XX +XXX,XX @@ static void sdram_unmap_bcr (ppc4xx_sdram_t *sdram) int i; for (i = 0; i < sdram->nbanks; i++) { -#ifdef DEBUG_SDRAM - printf("%s: Unmap RAM area " TARGET_FMT_plx " " TARGET_FMT_lx "\n", - __func__, sdram_base(sdram->bcr[i]), sdram_size(sdram->bcr[i])); -#endif + trace_ppc4xx_sdram_unmap(sdram_base(sdram->bcr[i]), + sdram_size(sdram->bcr[i])); memory_region_del_subregion(get_system_memory(), &sdram->ram_memories[i]); } @@ -XXX,XX +XXX,XX @@ static void dcr_write_sdram (void *opaque, int dcrn, uint32_t val) case 0x20: /* SDRAM_CFG */ val &= 0xFFE00000; if (!(sdram->cfg & 0x80000000) && (val & 0x80000000)) { -#ifdef DEBUG_SDRAM - printf("%s: enable SDRAM controller\n", __func__); -#endif + trace_ppc4xx_sdram_enable("enable"); /* validate all RAM mappings */ sdram_map_bcr(sdram); sdram->status &= ~0x80000000; } else if ((sdram->cfg & 0x80000000) && !(val & 0x80000000)) { -#ifdef DEBUG_SDRAM - printf("%s: disable SDRAM controller\n", __func__); -#endif + trace_ppc4xx_sdram_enable("disable"); /* invalidate all RAM mappings */ sdram_unmap_bcr(sdram); sdram->status |= 0x80000000; diff --git a/hw/ppc/ppc4xx_pci.c b/hw/ppc/ppc4xx_pci.c index XXXXXXX..XXXXXXX 100644 --- a/hw/ppc/ppc4xx_pci.c +++ b/hw/ppc/ppc4xx_pci.c @@ -XXX,XX +XXX,XX @@ * 4xx SoCs, such as the 440EP. */ #include "qemu/osdep.h" +#include "qemu/log.h" #include "hw/irq.h" #include "hw/ppc/ppc.h" #include "hw/ppc/ppc4xx.h" @@ -XXX,XX +XXX,XX @@ static void ppc4xx_pci_reg_write4(void *opaque, hwaddr offset, break; default: - printf("%s: unhandled PCI internal register 0x%lx\n", __func__, - (unsigned long)offset); + qemu_log_mask(LOG_GUEST_ERROR, + "%s: unhandled PCI internal register 0x%" HWADDR_PRIx "\n", + __func__, offset); break; } } @@ -XXX,XX +XXX,XX @@ static uint64_t ppc4xx_pci_reg_read4(void *opaque, hwaddr offset, break; default: - printf("%s: invalid PCI internal register 0x%lx\n", __func__, - (unsigned long)offset); + qemu_log_mask(LOG_GUEST_ERROR, + "%s: invalid PCI internal register 0x%" HWADDR_PRIx "\n", + __func__, offset); value = 0; } diff --git a/hw/ppc/trace-events b/hw/ppc/trace-events index XXXXXXX..XXXXXXX 100644 --- a/hw/ppc/trace-events +++ b/hw/ppc/trace-events @@ -XXX,XX +XXX,XX @@ 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" + +# ppc4xx_devs.c +ppc4xx_sdram_enable(const char *trace) "%s SDRAM controller" +ppc4xx_sdram_unmap(uint64_t addr, uint64_t size) "Unmap RAM area 0x%" PRIx64 " size 0x%" PRIx64 +ppc4xx_sdram_map(uint64_t addr, uint64_t size) "Map RAM area 0x%" PRIx64 " size 0x%" PRIx64 -- 2.31.1
There is no need to deactivate MMU logging at compile time. Remove all use of defines. Only keep DUMP_PAGE_TABLES for another series since page tables could be dumped from the monitor. Signed-off-by: Cédric Le Goater <clg@kaod.org> Message-Id: <20211222064025.1541490-4-clg@kaod.org> Signed-off-by: Cédric Le Goater <clg@kaod.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-Id: <20220103063441.3424853-5-clg@kaod.org> Signed-off-by: Cédric Le Goater <clg@kaod.org> --- target/ppc/mmu_common.c | 164 +++++++++++++++++++--------------------- target/ppc/mmu_helper.c | 97 +++++++++++------------- 2 files changed, 122 insertions(+), 139 deletions(-) diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c index XXXXXXX..XXXXXXX 100644 --- a/target/ppc/mmu_common.c +++ b/target/ppc/mmu_common.c @@ -XXX,XX +XXX,XX @@ #include "mmu-book3s-v3.h" #include "mmu-radix64.h" -/* #define DEBUG_MMU */ -/* #define DEBUG_BATS */ -/* #define DEBUG_SOFTWARE_TLB */ /* #define DUMP_PAGE_TABLES */ -/* #define FLUSH_ALL_TLBS */ - -#ifdef DEBUG_MMU -# define LOG_MMU_STATE(cpu) log_cpu_state_mask(CPU_LOG_MMU, (cpu), 0) -#else -# define LOG_MMU_STATE(cpu) do { } while (0) -#endif - -#ifdef DEBUG_SOFTWARE_TLB -# define LOG_SWTLB(...) qemu_log_mask(CPU_LOG_MMU, __VA_ARGS__) -#else -# define LOG_SWTLB(...) do { } while (0) -#endif - -#ifdef DEBUG_BATS -# define LOG_BATS(...) qemu_log_mask(CPU_LOG_MMU, __VA_ARGS__) -#else -# define LOG_BATS(...) do { } while (0) -#endif void ppc_store_sdr1(CPUPPCState *env, target_ulong value) { @@ -XXX,XX +XXX,XX @@ static int ppc6xx_tlb_check(CPUPPCState *env, mmu_ctx_t *ctx, tlb = &env->tlb.tlb6[nr]; /* This test "emulates" the PTE index match for hardware TLBs */ if ((eaddr & TARGET_PAGE_MASK) != tlb->EPN) { - LOG_SWTLB("TLB %d/%d %s [" TARGET_FMT_lx " " TARGET_FMT_lx - "] <> " TARGET_FMT_lx "\n", nr, env->nb_tlb, - pte_is_valid(tlb->pte0) ? "valid" : "inval", - tlb->EPN, tlb->EPN + TARGET_PAGE_SIZE, eaddr); + qemu_log_mask(CPU_LOG_MMU, "TLB %d/%d %s [" TARGET_FMT_lx + " " TARGET_FMT_lx "] <> " TARGET_FMT_lx "\n", + nr, env->nb_tlb, + pte_is_valid(tlb->pte0) ? "valid" : "inval", + tlb->EPN, tlb->EPN + TARGET_PAGE_SIZE, eaddr); continue; } - LOG_SWTLB("TLB %d/%d %s " TARGET_FMT_lx " <> " TARGET_FMT_lx " " - TARGET_FMT_lx " %c %c\n", nr, env->nb_tlb, - pte_is_valid(tlb->pte0) ? "valid" : "inval", - tlb->EPN, eaddr, tlb->pte1, - access_type == MMU_DATA_STORE ? 'S' : 'L', - access_type == MMU_INST_FETCH ? 'I' : 'D'); + qemu_log_mask(CPU_LOG_MMU, "TLB %d/%d %s " TARGET_FMT_lx " <> " + TARGET_FMT_lx " " TARGET_FMT_lx " %c %c\n", + nr, env->nb_tlb, + pte_is_valid(tlb->pte0) ? "valid" : "inval", + tlb->EPN, eaddr, tlb->pte1, + access_type == MMU_DATA_STORE ? 'S' : 'L', + access_type == MMU_INST_FETCH ? 'I' : 'D'); switch (ppc6xx_tlb_pte_check(ctx, tlb->pte0, tlb->pte1, 0, access_type)) { case -3: @@ -XXX,XX +XXX,XX @@ static int ppc6xx_tlb_check(CPUPPCState *env, mmu_ctx_t *ctx, } if (best != -1) { done: - LOG_SWTLB("found TLB at addr " TARGET_FMT_plx " prot=%01x ret=%d\n", - ctx->raddr & TARGET_PAGE_MASK, ctx->prot, ret); + qemu_log_mask(CPU_LOG_MMU, "found TLB at addr " TARGET_FMT_plx + " prot=%01x ret=%d\n", + ctx->raddr & TARGET_PAGE_MASK, ctx->prot, ret); /* Update page flags */ pte_update_flags(ctx, &env->tlb.tlb6[best].pte1, ret, access_type); } @@ -XXX,XX +XXX,XX @@ static int get_bat_6xx_tlb(CPUPPCState *env, mmu_ctx_t *ctx, int ret = -1; bool ifetch = access_type == MMU_INST_FETCH; - LOG_BATS("%s: %cBAT v " TARGET_FMT_lx "\n", __func__, + qemu_log_mask(CPU_LOG_MMU, "%s: %cBAT v " TARGET_FMT_lx "\n", __func__, ifetch ? 'I' : 'D', virtual); if (ifetch) { BATlt = env->IBAT[1]; @@ -XXX,XX +XXX,XX @@ static int get_bat_6xx_tlb(CPUPPCState *env, mmu_ctx_t *ctx, BEPIu = *BATu & 0xF0000000; BEPIl = *BATu & 0x0FFE0000; bat_size_prot(env, &bl, &valid, &prot, BATu, BATl); - LOG_BATS("%s: %cBAT%d v " TARGET_FMT_lx " BATu " TARGET_FMT_lx - " BATl " TARGET_FMT_lx "\n", __func__, - ifetch ? 'I' : 'D', i, virtual, *BATu, *BATl); + qemu_log_mask(CPU_LOG_MMU, "%s: %cBAT%d v " TARGET_FMT_lx " BATu " + TARGET_FMT_lx " BATl " TARGET_FMT_lx "\n", __func__, + ifetch ? 'I' : 'D', i, virtual, *BATu, *BATl); if ((virtual & 0xF0000000) == BEPIu && ((virtual & 0x0FFE0000) & ~bl) == BEPIl) { /* BAT matches */ @@ -XXX,XX +XXX,XX @@ static int get_bat_6xx_tlb(CPUPPCState *env, mmu_ctx_t *ctx, ctx->prot = prot; ret = check_prot(ctx->prot, access_type); if (ret == 0) { - LOG_BATS("BAT %d match: r " TARGET_FMT_plx " prot=%c%c\n", - i, ctx->raddr, ctx->prot & PAGE_READ ? 'R' : '-', - ctx->prot & PAGE_WRITE ? 'W' : '-'); + qemu_log_mask(CPU_LOG_MMU, "BAT %d match: r " TARGET_FMT_plx + " prot=%c%c\n", i, ctx->raddr, + ctx->prot & PAGE_READ ? 'R' : '-', + ctx->prot & PAGE_WRITE ? 'W' : '-'); } break; } } } if (ret < 0) { -#if defined(DEBUG_BATS) if (qemu_log_enabled()) { - LOG_BATS("no BAT match for " TARGET_FMT_lx ":\n", virtual); + qemu_log_mask(CPU_LOG_MMU, "no BAT match for " + TARGET_FMT_lx ":\n", virtual); for (i = 0; i < 4; i++) { BATu = &BATut[i]; BATl = &BATlt[i]; BEPIu = *BATu & 0xF0000000; BEPIl = *BATu & 0x0FFE0000; bl = (*BATu & 0x00001FFC) << 15; - LOG_BATS("%s: %cBAT%d v " TARGET_FMT_lx " BATu " TARGET_FMT_lx - " BATl " TARGET_FMT_lx "\n\t" TARGET_FMT_lx " " - TARGET_FMT_lx " " TARGET_FMT_lx "\n", - __func__, ifetch ? 'I' : 'D', i, virtual, - *BATu, *BATl, BEPIu, BEPIl, bl); + qemu_log_mask(CPU_LOG_MMU, "%s: %cBAT%d v " + TARGET_FMT_lx " BATu " TARGET_FMT_lx + " BATl " TARGET_FMT_lx "\n\t" TARGET_FMT_lx " " + TARGET_FMT_lx " " TARGET_FMT_lx "\n", + __func__, ifetch ? 'I' : 'D', i, virtual, + *BATu, *BATl, BEPIu, BEPIl, bl); } } -#endif } /* No hit */ return ret; @@ -XXX,XX +XXX,XX @@ static int get_segment_6xx_tlb(CPUPPCState *env, mmu_ctx_t *ctx, vsid = sr & 0x00FFFFFF; target_page_bits = TARGET_PAGE_BITS; qemu_log_mask(CPU_LOG_MMU, - "Check segment v=" TARGET_FMT_lx " %d " TARGET_FMT_lx - " nip=" TARGET_FMT_lx " lr=" TARGET_FMT_lx - " ir=%d dr=%d pr=%d %d t=%d\n", - eaddr, (int)(eaddr >> 28), sr, env->nip, env->lr, (int)msr_ir, - (int)msr_dr, pr != 0 ? 1 : 0, access_type == MMU_DATA_STORE, type); + "Check segment v=" TARGET_FMT_lx " %d " TARGET_FMT_lx + " nip=" TARGET_FMT_lx " lr=" TARGET_FMT_lx + " ir=%d dr=%d pr=%d %d t=%d\n", + eaddr, (int)(eaddr >> 28), sr, env->nip, env->lr, (int)msr_ir, + (int)msr_dr, pr != 0 ? 1 : 0, + access_type == MMU_DATA_STORE, type); pgidx = (eaddr & ~SEGMENT_MASK_256M) >> target_page_bits; hash = vsid ^ pgidx; ctx->ptem = (vsid << 7) | (pgidx >> 10); @@ -XXX,XX +XXX,XX @@ int ppcemb_tlb_check(CPUPPCState *env, ppcemb_tlb_t *tlb, return -1; } mask = ~(tlb->size - 1); - LOG_SWTLB("%s: TLB %d address " TARGET_FMT_lx " PID %u <=> " TARGET_FMT_lx - " " TARGET_FMT_lx " %u %x\n", __func__, i, address, pid, tlb->EPN, - mask, (uint32_t)tlb->PID, tlb->prot); + qemu_log_mask(CPU_LOG_MMU, "%s: TLB %d address " TARGET_FMT_lx + " PID %u <=> " TARGET_FMT_lx " " TARGET_FMT_lx " %u %x\n", + __func__, i, address, pid, tlb->EPN, + mask, (uint32_t)tlb->PID, tlb->prot); /* Check PID */ if (tlb->PID != 0 && tlb->PID != pid) { return -1; @@ -XXX,XX +XXX,XX @@ static int mmu40x_get_physical_address(CPUPPCState *env, mmu_ctx_t *ctx, } zsel = (tlb->attr >> 4) & 0xF; zpr = (env->spr[SPR_40x_ZPR] >> (30 - (2 * zsel))) & 0x3; - LOG_SWTLB("%s: TLB %d zsel %d zpr %d ty %d attr %08x\n", - __func__, i, zsel, zpr, access_type, tlb->attr); + qemu_log_mask(CPU_LOG_MMU, + "%s: TLB %d zsel %d zpr %d ty %d attr %08x\n", + __func__, i, zsel, zpr, access_type, tlb->attr); /* Check execute enable bit */ switch (zpr) { case 0x2: @@ -XXX,XX +XXX,XX @@ static int mmu40x_get_physical_address(CPUPPCState *env, mmu_ctx_t *ctx, } if (ret >= 0) { ctx->raddr = raddr; - LOG_SWTLB("%s: access granted " TARGET_FMT_lx " => " TARGET_FMT_plx - " %d %d\n", __func__, address, ctx->raddr, ctx->prot, - ret); + qemu_log_mask(CPU_LOG_MMU, "%s: access granted " TARGET_FMT_lx + " => " TARGET_FMT_plx + " %d %d\n", __func__, address, ctx->raddr, ctx->prot, + ret); return 0; } } - LOG_SWTLB("%s: access refused " TARGET_FMT_lx " => " TARGET_FMT_plx - " %d %d\n", __func__, address, raddr, ctx->prot, ret); + qemu_log_mask(CPU_LOG_MMU, "%s: access refused " TARGET_FMT_lx + " => " TARGET_FMT_plx + " %d %d\n", __func__, address, raddr, ctx->prot, ret); return ret; } @@ -XXX,XX +XXX,XX @@ static int mmubooke_check_tlb(CPUPPCState *env, ppcemb_tlb_t *tlb, goto found_tlb; } - LOG_SWTLB("%s: TLB entry not found\n", __func__); + qemu_log_mask(CPU_LOG_MMU, "%s: TLB entry not found\n", __func__); return -1; found_tlb: @@ -XXX,XX +XXX,XX @@ found_tlb: /* Check the address space */ if ((access_type == MMU_INST_FETCH ? msr_ir : msr_dr) != (tlb->attr & 1)) { - LOG_SWTLB("%s: AS doesn't match\n", __func__); + qemu_log_mask(CPU_LOG_MMU, "%s: AS doesn't match\n", __func__); return -1; } *prot = prot2; if (prot2 & prot_for_access_type(access_type)) { - LOG_SWTLB("%s: good TLB!\n", __func__); + qemu_log_mask(CPU_LOG_MMU, "%s: good TLB!\n", __func__); return 0; } - LOG_SWTLB("%s: no prot match: %x\n", __func__, prot2); + qemu_log_mask(CPU_LOG_MMU, "%s: no prot match: %x\n", __func__, prot2); return access_type == MMU_INST_FETCH ? -3 : -2; } @@ -XXX,XX +XXX,XX @@ static int mmubooke_get_physical_address(CPUPPCState *env, mmu_ctx_t *ctx, if (ret >= 0) { ctx->raddr = raddr; - LOG_SWTLB("%s: access granted " TARGET_FMT_lx " => " TARGET_FMT_plx - " %d %d\n", __func__, address, ctx->raddr, ctx->prot, - ret); + qemu_log_mask(CPU_LOG_MMU, "%s: access granted " TARGET_FMT_lx + " => " TARGET_FMT_plx " %d %d\n", __func__, + address, ctx->raddr, ctx->prot, ret); } else { - LOG_SWTLB("%s: access refused " TARGET_FMT_lx " => " TARGET_FMT_plx - " %d %d\n", __func__, address, raddr, ctx->prot, ret); + qemu_log_mask(CPU_LOG_MMU, "%s: access refused " TARGET_FMT_lx + " => " TARGET_FMT_plx " %d %d\n", __func__, + address, raddr, ctx->prot, ret); } return ret; @@ -XXX,XX +XXX,XX @@ int ppcmas_tlb_check(CPUPPCState *env, ppcmas_tlb_t *tlb, } mask = ~(booke206_tlb_to_page_size(env, tlb) - 1); - LOG_SWTLB("%s: TLB ADDR=0x" TARGET_FMT_lx " PID=0x%x MAS1=0x%x MAS2=0x%" - PRIx64 " mask=0x%" HWADDR_PRIx " MAS7_3=0x%" PRIx64 " MAS8=0x%" - PRIx32 "\n", __func__, address, pid, tlb->mas1, tlb->mas2, mask, - tlb->mas7_3, tlb->mas8); + qemu_log_mask(CPU_LOG_MMU, "%s: TLB ADDR=0x" TARGET_FMT_lx + " PID=0x%x MAS1=0x%x MAS2=0x%" PRIx64 " mask=0x%" + HWADDR_PRIx " MAS7_3=0x%" PRIx64 " MAS8=0x%" PRIx32 "\n", + __func__, address, pid, tlb->mas1, tlb->mas2, mask, + tlb->mas7_3, tlb->mas8); /* Check PID */ tlb_pid = (tlb->mas1 & MAS1_TID_MASK) >> MAS1_TID_SHIFT; @@ -XXX,XX +XXX,XX @@ static int mmubooke206_check_tlb(CPUPPCState *env, ppcmas_tlb_t *tlb, } } - LOG_SWTLB("%s: TLB entry not found\n", __func__); + qemu_log_mask(CPU_LOG_MMU, "%s: TLB entry not found\n", __func__); return -1; found_tlb: @@ -XXX,XX +XXX,XX @@ found_tlb: } if (as != ((tlb->mas1 & MAS1_TS) >> MAS1_TS_SHIFT)) { - LOG_SWTLB("%s: AS doesn't match\n", __func__); + qemu_log_mask(CPU_LOG_MMU, "%s: AS doesn't match\n", __func__); return -1; } *prot = prot2; if (prot2 & prot_for_access_type(access_type)) { - LOG_SWTLB("%s: good TLB!\n", __func__); + qemu_log_mask(CPU_LOG_MMU, "%s: good TLB!\n", __func__); return 0; } - LOG_SWTLB("%s: no prot match: %x\n", __func__, prot2); + qemu_log_mask(CPU_LOG_MMU, "%s: no prot match: %x\n", __func__, prot2); return access_type == MMU_INST_FETCH ? -3 : -2; } @@ -XXX,XX +XXX,XX @@ found_tlb: if (ret >= 0) { ctx->raddr = raddr; - LOG_SWTLB("%s: access granted " TARGET_FMT_lx " => " TARGET_FMT_plx - " %d %d\n", __func__, address, ctx->raddr, ctx->prot, - ret); + qemu_log_mask(CPU_LOG_MMU, "%s: access granted " TARGET_FMT_lx + " => " TARGET_FMT_plx " %d %d\n", __func__, address, + ctx->raddr, ctx->prot, ret); } else { - LOG_SWTLB("%s: access refused " TARGET_FMT_lx " => " TARGET_FMT_plx - " %d %d\n", __func__, address, raddr, ctx->prot, ret); + qemu_log_mask(CPU_LOG_MMU, "%s: access refused " TARGET_FMT_lx + " => " TARGET_FMT_plx " %d %d\n", __func__, address, + raddr, ctx->prot, ret); } return ret; @@ -XXX,XX +XXX,XX @@ static bool ppc_jumbo_xlate(PowerPCCPU *cpu, vaddr eaddr, } if (guest_visible) { - LOG_MMU_STATE(cs); + log_cpu_state_mask(CPU_LOG_MMU, cs, 0); if (type == ACCESS_CODE) { switch (ret) { case -1: diff --git a/target/ppc/mmu_helper.c b/target/ppc/mmu_helper.c index XXXXXXX..XXXXXXX 100644 --- a/target/ppc/mmu_helper.c +++ b/target/ppc/mmu_helper.c @@ -XXX,XX +XXX,XX @@ #include "exec/helper-proto.h" #include "exec/cpu_ldst.h" -/* #define DEBUG_BATS */ -/* #define DEBUG_SOFTWARE_TLB */ -/* #define DUMP_PAGE_TABLES */ /* #define FLUSH_ALL_TLBS */ -#ifdef DEBUG_SOFTWARE_TLB -# define LOG_SWTLB(...) qemu_log_mask(CPU_LOG_MMU, __VA_ARGS__) -#else -# define LOG_SWTLB(...) do { } while (0) -#endif - -#ifdef DEBUG_BATS -# define LOG_BATS(...) qemu_log_mask(CPU_LOG_MMU, __VA_ARGS__) -#else -# define LOG_BATS(...) do { } while (0) -#endif - /*****************************************************************************/ /* PowerPC MMU emulation */ @@ -XXX,XX +XXX,XX @@ static inline void ppc6xx_tlb_invalidate_virt2(CPUPPCState *env, nr = ppc6xx_tlb_getnum(env, eaddr, way, is_code); tlb = &env->tlb.tlb6[nr]; if (pte_is_valid(tlb->pte0) && (match_epn == 0 || eaddr == tlb->EPN)) { - LOG_SWTLB("TLB invalidate %d/%d " TARGET_FMT_lx "\n", nr, - env->nb_tlb, eaddr); + qemu_log_mask(CPU_LOG_MMU, "TLB invalidate %d/%d " + TARGET_FMT_lx "\n", nr, env->nb_tlb, eaddr); pte_invalidate(&tlb->pte0); tlb_flush_page(cs, tlb->EPN); } @@ -XXX,XX +XXX,XX @@ static void ppc6xx_tlb_store(CPUPPCState *env, target_ulong EPN, int way, nr = ppc6xx_tlb_getnum(env, EPN, way, is_code); tlb = &env->tlb.tlb6[nr]; - LOG_SWTLB("Set TLB %d/%d EPN " TARGET_FMT_lx " PTE0 " TARGET_FMT_lx - " PTE1 " TARGET_FMT_lx "\n", nr, env->nb_tlb, EPN, pte0, pte1); + qemu_log_mask(CPU_LOG_MMU, "Set TLB %d/%d EPN " TARGET_FMT_lx " PTE0 " + TARGET_FMT_lx " PTE1 " TARGET_FMT_lx "\n", nr, env->nb_tlb, + EPN, pte0, pte1); /* Invalidate any pending reference in QEMU for this virtual address */ ppc6xx_tlb_invalidate_virt2(env, EPN, is_code, 1); tlb->pte0 = pte0; @@ -XXX,XX +XXX,XX @@ static inline void do_invalidate_BAT(CPUPPCState *env, target_ulong BATu, end = base + mask + 0x00020000; if (((end - base) >> TARGET_PAGE_BITS) > 1024) { /* Flushing 1024 4K pages is slower than a complete flush */ - LOG_BATS("Flush all BATs\n"); + qemu_log_mask(CPU_LOG_MMU, "Flush all BATs\n"); tlb_flush(cs); - LOG_BATS("Flush done\n"); + qemu_log_mask(CPU_LOG_MMU, "Flush done\n"); return; } - LOG_BATS("Flush BAT from " TARGET_FMT_lx " to " TARGET_FMT_lx " (" - TARGET_FMT_lx ")\n", base, end, mask); + qemu_log_mask(CPU_LOG_MMU, "Flush BAT from " TARGET_FMT_lx + " to " TARGET_FMT_lx " (" TARGET_FMT_lx ")\n", + base, end, mask); for (page = base; page != end; page += TARGET_PAGE_SIZE) { tlb_flush_page(cs, page); } - LOG_BATS("Flush done\n"); + qemu_log_mask(CPU_LOG_MMU, "Flush done\n"); } #endif static inline void dump_store_bat(CPUPPCState *env, char ID, int ul, int nr, target_ulong value) { - LOG_BATS("Set %cBAT%d%c to " TARGET_FMT_lx " (" TARGET_FMT_lx ")\n", ID, - nr, ul == 0 ? 'u' : 'l', value, env->nip); + qemu_log_mask(CPU_LOG_MMU, "Set %cBAT%d%c to " TARGET_FMT_lx " (" + TARGET_FMT_lx ")\n", ID, nr, ul == 0 ? 'u' : 'l', + value, env->nip); } void helper_store_ibatu(CPUPPCState *env, uint32_t nr, target_ulong value) @@ -XXX,XX +XXX,XX @@ static void do_6xx_tlb(CPUPPCState *env, target_ulong new_EPN, int is_code) } way = (env->spr[SPR_SRR1] >> 17) & 1; (void)EPN; /* avoid a compiler warning */ - LOG_SWTLB("%s: EPN " TARGET_FMT_lx " " TARGET_FMT_lx " PTE0 " TARGET_FMT_lx - " PTE1 " TARGET_FMT_lx " way %d\n", __func__, new_EPN, EPN, CMP, - RPN, way); + qemu_log_mask(CPU_LOG_MMU, "%s: EPN " TARGET_FMT_lx " " TARGET_FMT_lx + " PTE0 " TARGET_FMT_lx " PTE1 " TARGET_FMT_lx " way %d\n", + __func__, new_EPN, EPN, CMP, RPN, way); /* Store this TLB */ ppc6xx_tlb_store(env, (uint32_t)(new_EPN & TARGET_PAGE_MASK), way, is_code, CMP, RPN); @@ -XXX,XX +XXX,XX @@ void helper_4xx_tlbwe_hi(CPUPPCState *env, target_ulong entry, ppcemb_tlb_t *tlb; target_ulong page, end; - LOG_SWTLB("%s entry %d val " TARGET_FMT_lx "\n", __func__, (int)entry, + qemu_log_mask(CPU_LOG_MMU, "%s entry %d val " TARGET_FMT_lx "\n", + __func__, (int)entry, val); entry &= PPC4XX_TLB_ENTRY_MASK; tlb = &env->tlb.tlbe[entry]; /* Invalidate previous TLB (if it's valid) */ if (tlb->prot & PAGE_VALID) { end = tlb->EPN + tlb->size; - LOG_SWTLB("%s: invalidate old TLB %d start " TARGET_FMT_lx " end " - TARGET_FMT_lx "\n", __func__, (int)entry, tlb->EPN, end); + qemu_log_mask(CPU_LOG_MMU, "%s: invalidate old TLB %d start " + TARGET_FMT_lx " end " TARGET_FMT_lx "\n", __func__, + (int)entry, tlb->EPN, end); for (page = tlb->EPN; page < end; page += TARGET_PAGE_SIZE) { tlb_flush_page(cs, page); } @@ -XXX,XX +XXX,XX @@ void helper_4xx_tlbwe_hi(CPUPPCState *env, target_ulong entry, tlb->prot &= ~PAGE_VALID; } tlb->PID = env->spr[SPR_40x_PID]; /* PID */ - LOG_SWTLB("%s: set up TLB %d RPN " TARGET_FMT_plx " EPN " TARGET_FMT_lx - " size " TARGET_FMT_lx " prot %c%c%c%c PID %d\n", __func__, - (int)entry, tlb->RPN, tlb->EPN, tlb->size, - tlb->prot & PAGE_READ ? 'r' : '-', - tlb->prot & PAGE_WRITE ? 'w' : '-', - tlb->prot & PAGE_EXEC ? 'x' : '-', - tlb->prot & PAGE_VALID ? 'v' : '-', (int)tlb->PID); + qemu_log_mask(CPU_LOG_MMU, "%s: set up TLB %d RPN " TARGET_FMT_plx + " EPN " TARGET_FMT_lx " size " TARGET_FMT_lx + " prot %c%c%c%c PID %d\n", __func__, + (int)entry, tlb->RPN, tlb->EPN, tlb->size, + tlb->prot & PAGE_READ ? 'r' : '-', + tlb->prot & PAGE_WRITE ? 'w' : '-', + tlb->prot & PAGE_EXEC ? 'x' : '-', + tlb->prot & PAGE_VALID ? 'v' : '-', (int)tlb->PID); /* Invalidate new TLB (if valid) */ if (tlb->prot & PAGE_VALID) { end = tlb->EPN + tlb->size; - LOG_SWTLB("%s: invalidate TLB %d start " TARGET_FMT_lx " end " - TARGET_FMT_lx "\n", __func__, (int)entry, tlb->EPN, end); + qemu_log_mask(CPU_LOG_MMU, "%s: invalidate TLB %d start " + TARGET_FMT_lx " end " TARGET_FMT_lx "\n", __func__, + (int)entry, tlb->EPN, end); for (page = tlb->EPN; page < end; page += TARGET_PAGE_SIZE) { tlb_flush_page(cs, page); } @@ -XXX,XX +XXX,XX @@ void helper_4xx_tlbwe_lo(CPUPPCState *env, target_ulong entry, { ppcemb_tlb_t *tlb; - LOG_SWTLB("%s entry %i val " TARGET_FMT_lx "\n", __func__, (int)entry, - val); + qemu_log_mask(CPU_LOG_MMU, "%s entry %i val " TARGET_FMT_lx "\n", + __func__, (int)entry, val); entry &= PPC4XX_TLB_ENTRY_MASK; tlb = &env->tlb.tlbe[entry]; tlb->attr = val & PPC4XX_TLBLO_ATTR_MASK; @@ -XXX,XX +XXX,XX @@ void helper_4xx_tlbwe_lo(CPUPPCState *env, target_ulong entry, if (val & PPC4XX_TLBLO_WR) { tlb->prot |= PAGE_WRITE; } - LOG_SWTLB("%s: set up TLB %d RPN " TARGET_FMT_plx " EPN " TARGET_FMT_lx - " size " TARGET_FMT_lx " prot %c%c%c%c PID %d\n", __func__, - (int)entry, tlb->RPN, tlb->EPN, tlb->size, - tlb->prot & PAGE_READ ? 'r' : '-', - tlb->prot & PAGE_WRITE ? 'w' : '-', - tlb->prot & PAGE_EXEC ? 'x' : '-', - tlb->prot & PAGE_VALID ? 'v' : '-', (int)tlb->PID); + qemu_log_mask(CPU_LOG_MMU, "%s: set up TLB %d RPN " TARGET_FMT_plx + " EPN " TARGET_FMT_lx + " size " TARGET_FMT_lx " prot %c%c%c%c PID %d\n", __func__, + (int)entry, tlb->RPN, tlb->EPN, tlb->size, + tlb->prot & PAGE_READ ? 'r' : '-', + tlb->prot & PAGE_WRITE ? 'w' : '-', + tlb->prot & PAGE_EXEC ? 'x' : '-', + tlb->prot & PAGE_VALID ? 'v' : '-', (int)tlb->PID); } target_ulong helper_4xx_tlbsx(CPUPPCState *env, target_ulong address) @@ -XXX,XX +XXX,XX @@ void helper_440_tlbwe(CPUPPCState *env, uint32_t word, target_ulong entry, target_ulong EPN, RPN, size; int do_flush_tlbs; - LOG_SWTLB("%s word %d entry %d value " TARGET_FMT_lx "\n", - __func__, word, (int)entry, value); + qemu_log_mask(CPU_LOG_MMU, "%s word %d entry %d value " TARGET_FMT_lx "\n", + __func__, word, (int)entry, value); do_flush_tlbs = 0; entry &= 0x3F; tlb = &env->tlb.tlbe[entry]; -- 2.31.1
The 405 timers were broken when booke support was added. Assumption was made that the register numbers were the same but it's not : SPR_BOOKE_TSR (0x150) SPR_BOOKE_TCR (0x154) SPR_40x_TSR (0x3D8) SPR_40x_TCR (0x3DA) Cc: Christophe Leroy <christophe.leroy@c-s.fr> Fixes: ddd1055b07fd ("PPC: booke timers") Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Signed-off-by: Cédric Le Goater <clg@kaod.org> Message-Id: <20211222064025.1541490-5-clg@kaod.org> Signed-off-by: Cédric Le Goater <clg@kaod.org> Message-Id: <20220103063441.3424853-6-clg@kaod.org> Signed-off-by: Cédric Le Goater <clg@kaod.org> --- target/ppc/cpu.h | 2 ++ target/ppc/helper.h | 2 ++ target/ppc/spr_tcg.h | 2 ++ hw/ppc/ppc.c | 25 +++++++++++++++++++++++++ target/ppc/cpu_init.c | 4 ++-- target/ppc/timebase_helper.c | 10 ++++++++++ target/ppc/translate.c | 12 ++++++++++++ hw/ppc/trace-events | 2 ++ 8 files changed, 57 insertions(+), 2 deletions(-) diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h index XXXXXXX..XXXXXXX 100644 --- a/target/ppc/cpu.h +++ b/target/ppc/cpu.h @@ -XXX,XX +XXX,XX @@ target_ulong load_40x_pit(CPUPPCState *env); void store_40x_pit(CPUPPCState *env, target_ulong val); void store_40x_dbcr0(CPUPPCState *env, uint32_t val); void store_40x_sler(CPUPPCState *env, uint32_t val); +void store_40x_tcr(CPUPPCState *env, target_ulong val); +void store_40x_tsr(CPUPPCState *env, target_ulong val); void store_booke_tcr(CPUPPCState *env, target_ulong val); void store_booke_tsr(CPUPPCState *env, target_ulong val); void ppc_tlb_invalidate_all(CPUPPCState *env); diff --git a/target/ppc/helper.h b/target/ppc/helper.h index XXXXXXX..XXXXXXX 100644 --- a/target/ppc/helper.h +++ b/target/ppc/helper.h @@ -XXX,XX +XXX,XX @@ DEF_HELPER_2(store_hid0_601, void, env, tl) DEF_HELPER_3(store_403_pbr, void, env, i32, tl) DEF_HELPER_FLAGS_1(load_40x_pit, TCG_CALL_NO_RWG, tl, env) DEF_HELPER_FLAGS_2(store_40x_pit, TCG_CALL_NO_RWG, void, env, tl) +DEF_HELPER_FLAGS_2(store_40x_tcr, TCG_CALL_NO_RWG, void, env, tl) +DEF_HELPER_FLAGS_2(store_40x_tsr, TCG_CALL_NO_RWG, void, env, tl) DEF_HELPER_2(store_40x_dbcr0, void, env, tl) DEF_HELPER_2(store_40x_sler, void, env, tl) DEF_HELPER_FLAGS_2(store_booke_tcr, TCG_CALL_NO_RWG, void, env, tl) diff --git a/target/ppc/spr_tcg.h b/target/ppc/spr_tcg.h index XXXXXXX..XXXXXXX 100644 --- a/target/ppc/spr_tcg.h +++ b/target/ppc/spr_tcg.h @@ -XXX,XX +XXX,XX @@ void spr_read_40x_pit(DisasContext *ctx, int gprn, int sprn); void spr_write_40x_pit(DisasContext *ctx, int sprn, int gprn); void spr_write_40x_dbcr0(DisasContext *ctx, int sprn, int gprn); void spr_write_40x_sler(DisasContext *ctx, int sprn, int gprn); +void spr_write_40x_tcr(DisasContext *ctx, int sprn, int gprn); +void spr_write_40x_tsr(DisasContext *ctx, int sprn, int gprn); void spr_write_booke_tcr(DisasContext *ctx, int sprn, int gprn); void spr_write_booke_tsr(DisasContext *ctx, int sprn, int gprn); void spr_read_403_pbr(DisasContext *ctx, int gprn, int sprn); diff --git a/hw/ppc/ppc.c b/hw/ppc/ppc.c index XXXXXXX..XXXXXXX 100644 --- a/hw/ppc/ppc.c +++ b/hw/ppc/ppc.c @@ -XXX,XX +XXX,XX @@ target_ulong load_40x_pit (CPUPPCState *env) return cpu_ppc_load_decr(env); } +void store_40x_tsr(CPUPPCState *env, target_ulong val) +{ + PowerPCCPU *cpu = env_archcpu(env); + + trace_ppc40x_store_tcr(val); + + env->spr[SPR_40x_TSR] &= ~(val & 0xFC000000); + if (val & 0x80000000) { + ppc_set_irq(cpu, PPC_INTERRUPT_PIT, 0); + } +} + +void store_40x_tcr(CPUPPCState *env, target_ulong val) +{ + PowerPCCPU *cpu = env_archcpu(env); + ppc_tb_t *tb_env; + + trace_ppc40x_store_tsr(val); + + tb_env = env->tb_env; + env->spr[SPR_40x_TCR] = val & 0xFFC00000; + start_stop_pit(env, tb_env, 1); + cpu_4xx_wdt_cb(cpu); +} + static void ppc_40x_set_tb_clk (void *opaque, uint32_t freq) { CPUPPCState *env = opaque; diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c index XXXXXXX..XXXXXXX 100644 --- a/target/ppc/cpu_init.c +++ b/target/ppc/cpu_init.c @@ -XXX,XX +XXX,XX @@ static void register_40x_sprs(CPUPPCState *env) 0x00000000); spr_register(env, SPR_40x_TCR, "TCR", SPR_NOACCESS, SPR_NOACCESS, - &spr_read_generic, &spr_write_booke_tcr, + &spr_read_generic, &spr_write_40x_tcr, 0x00000000); spr_register(env, SPR_40x_TSR, "TSR", SPR_NOACCESS, SPR_NOACCESS, - &spr_read_generic, &spr_write_booke_tsr, + &spr_read_generic, &spr_write_40x_tsr, 0x00000000); } diff --git a/target/ppc/timebase_helper.c b/target/ppc/timebase_helper.c index XXXXXXX..XXXXXXX 100644 --- a/target/ppc/timebase_helper.c +++ b/target/ppc/timebase_helper.c @@ -XXX,XX +XXX,XX @@ void helper_store_40x_pit(CPUPPCState *env, target_ulong val) store_40x_pit(env, val); } +void helper_store_40x_tcr(CPUPPCState *env, target_ulong val) +{ + store_40x_tcr(env, val); +} + +void helper_store_40x_tsr(CPUPPCState *env, target_ulong val) +{ + store_40x_tsr(env, val); +} + void helper_store_booke_tcr(CPUPPCState *env, target_ulong val) { store_booke_tcr(env, val); diff --git a/target/ppc/translate.c b/target/ppc/translate.c index XXXXXXX..XXXXXXX 100644 --- a/target/ppc/translate.c +++ b/target/ppc/translate.c @@ -XXX,XX +XXX,XX @@ void spr_write_40x_sler(DisasContext *ctx, int sprn, int gprn) gen_helper_store_40x_sler(cpu_env, cpu_gpr[gprn]); } +void spr_write_40x_tcr(DisasContext *ctx, int sprn, int gprn) +{ + gen_icount_io_start(ctx); + gen_helper_store_40x_tcr(cpu_env, cpu_gpr[gprn]); +} + +void spr_write_40x_tsr(DisasContext *ctx, int sprn, int gprn) +{ + gen_icount_io_start(ctx); + gen_helper_store_40x_tsr(cpu_env, cpu_gpr[gprn]); +} + void spr_write_booke_tcr(DisasContext *ctx, int sprn, int gprn) { gen_icount_io_start(ctx); diff --git a/hw/ppc/trace-events b/hw/ppc/trace-events index XXXXXXX..XXXXXXX 100644 --- a/hw/ppc/trace-events +++ b/hw/ppc/trace-events @@ -XXX,XX +XXX,XX @@ ppc4xx_pit_start(uint64_t reload) "PIT 0x%016" PRIx64 ppc4xx_pit(uint32_t ar, uint32_t ir, uint64_t tcr, uint64_t tsr, uint64_t reload) "ar %d ir %d TCR 0x%" PRIx64 " TSR 0x%" PRIx64 " PIT 0x%016" PRIx64 ppc4xx_wdt(uint64_t tcr, uint64_t tsr) "TCR 0x%" PRIx64 " TSR 0x%" PRIx64 ppc40x_store_pit(uint64_t value) "val 0x%" PRIx64 +ppc40x_store_tcr(uint64_t value) "val 0x%" PRIx64 +ppc40x_store_tsr(uint64_t value) "val 0x%" PRIx64 ppc40x_set_tb_clk(uint32_t value) "new frequency %" PRIu32 ppc40x_timers_init(uint32_t value) "frequency %" PRIu32 -- 2.31.1
This is a small cleanup to ease reading. It includes the removal of a check done on the returned value of g_malloc0(), which can not fail. Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Signed-off-by: Cédric Le Goater <clg@kaod.org> Message-Id: <20211222064025.1541490-6-clg@kaod.org> Signed-off-by: Cédric Le Goater <clg@kaod.org> Message-Id: <20220103063441.3424853-7-clg@kaod.org> Signed-off-by: Cédric Le Goater <clg@kaod.org> --- hw/ppc/ppc.c | 42 +++++++++++++++++++----------------------- 1 file changed, 19 insertions(+), 23 deletions(-) diff --git a/hw/ppc/ppc.c b/hw/ppc/ppc.c index XXXXXXX..XXXXXXX 100644 --- a/hw/ppc/ppc.c +++ b/hw/ppc/ppc.c @@ -XXX,XX +XXX,XX @@ struct ppc40x_timer_t { /* Fixed interval timer */ static void cpu_4xx_fit_cb (void *opaque) { - PowerPCCPU *cpu; - CPUPPCState *env; + PowerPCCPU *cpu = opaque; + CPUPPCState *env = &cpu->env; ppc_tb_t *tb_env; ppc40x_timer_t *ppc40x_timer; uint64_t now, next; - env = opaque; - cpu = env_archcpu(env); tb_env = env->tb_env; ppc40x_timer = tb_env->opaque; now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); @@ -XXX,XX +XXX,XX @@ static void start_stop_pit (CPUPPCState *env, ppc_tb_t *tb_env, int is_excp) static void cpu_4xx_pit_cb (void *opaque) { - PowerPCCPU *cpu; - CPUPPCState *env; + PowerPCCPU *cpu = opaque; + CPUPPCState *env = &cpu->env; ppc_tb_t *tb_env; ppc40x_timer_t *ppc40x_timer; - env = opaque; - cpu = env_archcpu(env); tb_env = env->tb_env; ppc40x_timer = tb_env->opaque; env->spr[SPR_40x_TSR] |= 1 << 27; @@ -XXX,XX +XXX,XX @@ static void cpu_4xx_pit_cb (void *opaque) /* Watchdog timer */ static void cpu_4xx_wdt_cb (void *opaque) { - PowerPCCPU *cpu; - CPUPPCState *env; + PowerPCCPU *cpu = opaque; + CPUPPCState *env = &cpu->env; ppc_tb_t *tb_env; ppc40x_timer_t *ppc40x_timer; uint64_t now, next; - env = opaque; - cpu = env_archcpu(env); tb_env = env->tb_env; ppc40x_timer = tb_env->opaque; now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); @@ -XXX,XX +XXX,XX @@ clk_setup_cb ppc_40x_timers_init (CPUPPCState *env, uint32_t freq, { ppc_tb_t *tb_env; ppc40x_timer_t *ppc40x_timer; + PowerPCCPU *cpu = env_archcpu(env); + + trace_ppc40x_timers_init(freq); tb_env = g_malloc0(sizeof(ppc_tb_t)); + ppc40x_timer = g_malloc0(sizeof(ppc40x_timer_t)); + env->tb_env = tb_env; tb_env->flags = PPC_DECR_UNDERFLOW_TRIGGERED; - ppc40x_timer = g_malloc0(sizeof(ppc40x_timer_t)); tb_env->tb_freq = freq; tb_env->decr_freq = freq; tb_env->opaque = ppc40x_timer; - trace_ppc40x_timers_init(freq); - if (ppc40x_timer != NULL) { - /* We use decr timer for PIT */ - tb_env->decr_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, &cpu_4xx_pit_cb, env); - ppc40x_timer->fit_timer = - timer_new_ns(QEMU_CLOCK_VIRTUAL, &cpu_4xx_fit_cb, env); - ppc40x_timer->wdt_timer = - timer_new_ns(QEMU_CLOCK_VIRTUAL, &cpu_4xx_wdt_cb, env); - ppc40x_timer->decr_excp = decr_excp; - } + + /* We use decr timer for PIT */ + tb_env->decr_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, &cpu_4xx_pit_cb, cpu); + ppc40x_timer->fit_timer = + timer_new_ns(QEMU_CLOCK_VIRTUAL, &cpu_4xx_fit_cb, cpu); + ppc40x_timer->wdt_timer = + timer_new_ns(QEMU_CLOCK_VIRTUAL, &cpu_4xx_wdt_cb, cpu); + ppc40x_timer->decr_excp = decr_excp; return &ppc_40x_set_tb_clk; } -- 2.31.1
Timers are already initialized in ppc4xx_init(). No need to do it a second time with a wrong set. Fixes: d715ea961254 ("PPC: 405: Fix ppc405ep initialization") Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Signed-off-by: Cédric Le Goater <clg@kaod.org> Message-Id: <20211222064025.1541490-7-clg@kaod.org> Signed-off-by: Cédric Le Goater <clg@kaod.org> Message-Id: <20220103063441.3424853-8-clg@kaod.org> Signed-off-by: Cédric Le Goater <clg@kaod.org> --- hw/ppc/ppc405_uc.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/hw/ppc/ppc405_uc.c b/hw/ppc/ppc405_uc.c index XXXXXXX..XXXXXXX 100644 --- a/hw/ppc/ppc405_uc.c +++ b/hw/ppc/ppc405_uc.c @@ -XXX,XX +XXX,XX @@ PowerPCCPU *ppc405ep_init(MemoryRegion *address_space_mem, ppc4xx_pob_init(env); /* OBP arbitrer */ ppc4xx_opba_init(0xef600600); - /* Initialize timers */ - ppc_booke_timers_init(cpu, sysclk, 0); /* Universal interrupt controller */ uicdev = qdev_new(TYPE_PPC_UIC); uicsbd = SYS_BUS_DEVICE(uicdev); -- 2.31.1
The PID SPR of the 405 CPU contains the translation ID of the TLB which is a 8-bit field. Enforce the mask with a store helper. Cc: Christophe Leroy <christophe.leroy@c-s.fr> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Signed-off-by: Cédric Le Goater <clg@kaod.org> Message-Id: <20211222064025.1541490-8-clg@kaod.org> Signed-off-by: Cédric Le Goater <clg@kaod.org> Message-Id: <20220103063441.3424853-9-clg@kaod.org> Signed-off-by: Cédric Le Goater <clg@kaod.org> --- target/ppc/spr_tcg.h | 1 + target/ppc/cpu_init.c | 2 +- target/ppc/translate.c | 8 ++++++++ 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/target/ppc/spr_tcg.h b/target/ppc/spr_tcg.h index XXXXXXX..XXXXXXX 100644 --- a/target/ppc/spr_tcg.h +++ b/target/ppc/spr_tcg.h @@ -XXX,XX +XXX,XX @@ void spr_write_40x_dbcr0(DisasContext *ctx, int sprn, int gprn); void spr_write_40x_sler(DisasContext *ctx, int sprn, int gprn); void spr_write_40x_tcr(DisasContext *ctx, int sprn, int gprn); void spr_write_40x_tsr(DisasContext *ctx, int sprn, int gprn); +void spr_write_40x_pid(DisasContext *ctx, int sprn, int gprn); void spr_write_booke_tcr(DisasContext *ctx, int sprn, int gprn); void spr_write_booke_tsr(DisasContext *ctx, int sprn, int gprn); void spr_read_403_pbr(DisasContext *ctx, int gprn, int sprn); diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c index XXXXXXX..XXXXXXX 100644 --- a/target/ppc/cpu_init.c +++ b/target/ppc/cpu_init.c @@ -XXX,XX +XXX,XX @@ static void register_405_sprs(CPUPPCState *env) /* MMU */ spr_register(env, SPR_40x_PID, "PID", SPR_NOACCESS, SPR_NOACCESS, - &spr_read_generic, &spr_write_generic, + &spr_read_generic, &spr_write_40x_pid, 0x00000000); spr_register(env, SPR_4xx_CCR0, "CCR0", SPR_NOACCESS, SPR_NOACCESS, diff --git a/target/ppc/translate.c b/target/ppc/translate.c index XXXXXXX..XXXXXXX 100644 --- a/target/ppc/translate.c +++ b/target/ppc/translate.c @@ -XXX,XX +XXX,XX @@ void spr_write_40x_tsr(DisasContext *ctx, int sprn, int gprn) gen_helper_store_40x_tsr(cpu_env, cpu_gpr[gprn]); } +void spr_write_40x_pid(DisasContext *ctx, int sprn, int gprn) +{ + TCGv t0 = tcg_temp_new(); + tcg_gen_andi_tl(t0, cpu_gpr[gprn], 0xFF); + gen_store_spr(SPR_40x_PID, t0); + tcg_temp_free(t0); +} + void spr_write_booke_tcr(DisasContext *ctx, int sprn, int gprn) { gen_icount_io_start(ctx); -- 2.31.1
Rework slightly ppc_cpu_dump_state() to replace the various 'if' statements with a 'switch'. Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Signed-off-by: Cédric Le Goater <clg@kaod.org> Message-Id: <20211222064025.1541490-9-clg@kaod.org> Signed-off-by: Cédric Le Goater <clg@kaod.org> Message-Id: <20220103063441.3424853-10-clg@kaod.org> Signed-off-by: Cédric Le Goater <clg@kaod.org> --- target/ppc/cpu_init.c | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c index XXXXXXX..XXXXXXX 100644 --- a/target/ppc/cpu_init.c +++ b/target/ppc/cpu_init.c @@ -XXX,XX +XXX,XX @@ void ppc_cpu_dump_state(CPUState *cs, FILE *f, int flags) env->spr[SPR_SPRG4], env->spr[SPR_SPRG5], env->spr[SPR_SPRG6], env->spr[SPR_SPRG7]); + switch (env->excp_model) { #if defined(TARGET_PPC64) - if (env->excp_model == POWERPC_EXCP_POWER7 || - env->excp_model == POWERPC_EXCP_POWER8 || - env->excp_model == POWERPC_EXCP_POWER9 || - env->excp_model == POWERPC_EXCP_POWER10) { + case POWERPC_EXCP_POWER7: + case POWERPC_EXCP_POWER8: + case POWERPC_EXCP_POWER9: + case POWERPC_EXCP_POWER10: qemu_fprintf(f, "HSRR0 " TARGET_FMT_lx " HSRR1 " TARGET_FMT_lx "\n", env->spr[SPR_HSRR0], env->spr[SPR_HSRR1]); - } + break; #endif - if (env->excp_model == POWERPC_EXCP_BOOKE) { + case POWERPC_EXCP_BOOKE: qemu_fprintf(f, "CSRR0 " TARGET_FMT_lx " CSRR1 " TARGET_FMT_lx " MCSRR0 " TARGET_FMT_lx " MCSRR1 " TARGET_FMT_lx "\n", env->spr[SPR_BOOKE_CSRR0], env->spr[SPR_BOOKE_CSRR1], @@ -XXX,XX +XXX,XX @@ void ppc_cpu_dump_state(CPUState *cs, FILE *f, int flags) * IVORs are left out as they are large and do not change often -- * they can be read with "p $ivor0", "p $ivor1", etc. */ + break; + case POWERPC_EXCP_40x: + qemu_fprintf(f, " TCR " TARGET_FMT_lx " TSR " TARGET_FMT_lx + " ESR " TARGET_FMT_lx " DEAR " TARGET_FMT_lx "\n", + env->spr[SPR_40x_TCR], env->spr[SPR_40x_TSR], + env->spr[SPR_40x_ESR], env->spr[SPR_40x_DEAR]); + + qemu_fprintf(f, " EVPR " TARGET_FMT_lx " SRR2 " TARGET_FMT_lx + " SRR3 " TARGET_FMT_lx " PID " TARGET_FMT_lx "\n", + env->spr[SPR_40x_EVPR], env->spr[SPR_40x_SRR2], + env->spr[SPR_40x_SRR3], env->spr[SPR_40x_PID]); + break; + default: + break; } #if defined(TARGET_PPC64) -- 2.31.1
From: Matheus Ferst <matheus.ferst@eldorado.org.br> The non-signalling versions of VSX scalar convert to shorter/longer precision insns doesn't silence SNaNs in the hardware. To better match this behavior, use the non-arithmatic conversion of helper_todouble instead of float32_to_float64. A test is added to prevent future regressions. Signed-off-by: Matheus Ferst <matheus.ferst@eldorado.org.br> Message-Id: <20211228120310.1957990-1-matheus.ferst@eldorado.org.br> Signed-off-by: Cédric Le Goater <clg@kaod.org> --- target/ppc/fpu_helper.c | 5 +--- tests/tcg/ppc64le/non_signalling_xscv.c | 37 +++++++++++++++++++++++++ tests/tcg/ppc64/Makefile.target | 4 +-- tests/tcg/ppc64le/Makefile.target | 4 +-- 4 files changed, 42 insertions(+), 8 deletions(-) create mode 100644 tests/tcg/ppc64le/non_signalling_xscv.c diff --git a/target/ppc/fpu_helper.c b/target/ppc/fpu_helper.c index XXXXXXX..XXXXXXX 100644 --- a/target/ppc/fpu_helper.c +++ b/target/ppc/fpu_helper.c @@ -XXX,XX +XXX,XX @@ uint64_t helper_xscvdpspn(CPUPPCState *env, uint64_t xb) uint64_t helper_xscvspdpn(CPUPPCState *env, uint64_t xb) { - float_status tstat = env->fp_status; - set_float_exception_flags(0, &tstat); - - return float32_to_float64(xb >> 32, &tstat); + return helper_todouble(xb >> 32); } /* diff --git a/tests/tcg/ppc64le/non_signalling_xscv.c b/tests/tcg/ppc64le/non_signalling_xscv.c new file mode 100644 index XXXXXXX..XXXXXXX --- /dev/null +++ b/tests/tcg/ppc64le/non_signalling_xscv.c @@ -XXX,XX +XXX,XX @@ +#include <stdio.h> +#include <stdint.h> +#include <inttypes.h> +#include <assert.h> + +#define TEST(INSN, B_HI, B_LO, T_HI, T_LO) \ + do { \ + uint64_t th, tl, bh = B_HI, bl = B_LO; \ + asm("mtvsrd 0, %2\n\t" \ + "mtvsrd 1, %3\n\t" \ + "xxmrghd 0, 0, 1\n\t" \ + INSN " 0, 0\n\t" \ + "mfvsrd %0, 0\n\t" \ + "xxswapd 0, 0\n\t" \ + "mfvsrd %1, 0\n\t" \ + : "=r" (th), "=r" (tl) \ + : "r" (bh), "r" (bl) \ + : "vs0", "vs1"); \ + printf(INSN "(0x%016" PRIx64 "%016" PRIx64 ") = 0x%016" PRIx64 \ + "%016" PRIx64 "\n", bh, bl, th, tl); \ + assert(th == T_HI && tl == T_LO); \ + } while (0) + +int main(void) +{ + /* SNaN shouldn't be silenced */ + TEST("xscvspdpn", 0x7fbfffff00000000ULL, 0x0, 0x7ff7ffffe0000000ULL, 0x0); + TEST("xscvdpspn", 0x7ff7ffffffffffffULL, 0x0, 0x7fbfffff7fbfffffULL, 0x0); + + /* + * SNaN inputs having no significant bits in the upper 23 bits of the + * signifcand will return Infinity as the result. + */ + TEST("xscvdpspn", 0x7ff000001fffffffULL, 0x0, 0x7f8000007f800000ULL, 0x0); + + return 0; +} diff --git a/tests/tcg/ppc64/Makefile.target b/tests/tcg/ppc64/Makefile.target index XXXXXXX..XXXXXXX 100644 --- a/tests/tcg/ppc64/Makefile.target +++ b/tests/tcg/ppc64/Makefile.target @@ -XXX,XX +XXX,XX @@ VPATH += $(SRC_PATH)/tests/tcg/ppc64 VPATH += $(SRC_PATH)/tests/tcg/ppc64le ifneq ($(DOCKER_IMAGE)$(CROSS_CC_HAS_POWER8_VECTOR),) -PPC64_TESTS=bcdsub +PPC64_TESTS=bcdsub non_signalling_xscv endif -bcdsub: CFLAGS += -mpower8-vector +$(PPC64_TESTS): CFLAGS += -mpower8-vector PPC64_TESTS += byte_reverse PPC64_TESTS += mtfsf diff --git a/tests/tcg/ppc64le/Makefile.target b/tests/tcg/ppc64le/Makefile.target index XXXXXXX..XXXXXXX 100644 --- a/tests/tcg/ppc64le/Makefile.target +++ b/tests/tcg/ppc64le/Makefile.target @@ -XXX,XX +XXX,XX @@ VPATH += $(SRC_PATH)/tests/tcg/ppc64le ifneq ($(DOCKER_IMAGE)$(CROSS_CC_HAS_POWER8_VECTOR),) -PPC64LE_TESTS=bcdsub +PPC64LE_TESTS=bcdsub non_signalling_xscv endif -bcdsub: CFLAGS += -mpower8-vector +$(PPC64LE_TESTS): CFLAGS += -mpower8-vector ifneq ($(DOCKER_IMAGE)$(CROSS_CC_HAS_POWER10),) PPC64LE_TESTS += byte_reverse -- 2.31.1
From: Fabiano Rosas <farosas@linux.ibm.com> There are currently only two interrupts that use alternate SRRs, so let them write to them directly during the setup code. No functional change intended. Signed-off-by: Fabiano Rosas <farosas@linux.ibm.com> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Reviewed-by: Cédric Le Goater <clg@kaod.org> Reviewed-by: David Gibson <david@gibson.dropbear.id.au> Message-Id: <20211229165751.3774248-2-farosas@linux.ibm.com> Signed-off-by: Cédric Le Goater <clg@kaod.org> --- target/ppc/excp_helper.c | 23 ++++++++--------------- 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c index XXXXXXX..XXXXXXX 100644 --- a/target/ppc/excp_helper.c +++ b/target/ppc/excp_helper.c @@ -XXX,XX +XXX,XX @@ static void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp) CPUState *cs = CPU(cpu); CPUPPCState *env = &cpu->env; target_ulong msr, new_msr, vector; - int srr0, srr1, asrr0, asrr1, lev = -1; + int srr0, srr1, lev = -1; qemu_log_mask(CPU_LOG_INT, "Raise exception at " TARGET_FMT_lx " => %s (%d) error=%02x\n", env->nip, powerpc_excp_name(excp), @@ -XXX,XX +XXX,XX @@ static void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp) /* target registers */ srr0 = SPR_SRR0; srr1 = SPR_SRR1; - asrr0 = -1; - asrr1 = -1; /* * check for special resume at 0x100 from doze/nap/sleep/winkle on @@ -XXX,XX +XXX,XX @@ static void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp) /* FIXME: choose one or the other based on CPU type */ srr0 = SPR_BOOKE_MCSRR0; srr1 = SPR_BOOKE_MCSRR1; - asrr0 = SPR_BOOKE_CSRR0; - asrr1 = SPR_BOOKE_CSRR1; + + env->spr[SPR_BOOKE_CSRR0] = env->nip; + env->spr[SPR_BOOKE_CSRR1] = msr; break; default: break; @@ -XXX,XX +XXX,XX @@ static void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp) /* FIXME: choose one or the other based on CPU type */ srr0 = SPR_BOOKE_DSRR0; srr1 = SPR_BOOKE_DSRR1; - asrr0 = SPR_BOOKE_CSRR0; - asrr1 = SPR_BOOKE_CSRR1; + + env->spr[SPR_BOOKE_CSRR0] = env->nip; + env->spr[SPR_BOOKE_CSRR1] = msr; + /* DBSR already modified by caller */ } else { cpu_abort(cs, "Debug exception triggered on unsupported model\n"); @@ -XXX,XX +XXX,XX @@ static void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp) vector |= env->excp_prefix; - /* If any alternate SRR register are defined, duplicate saved values */ - if (asrr0 != -1) { - env->spr[asrr0] = env->nip; - } - if (asrr1 != -1) { - env->spr[asrr1] = msr; - } - #if defined(TARGET_PPC64) if (excp_model == POWERPC_EXCP_BOOKE) { if (env->spr[SPR_BOOKE_EPCR] & EPCR_ICM) { -- 2.31.1
From: Fabiano Rosas <farosas@linux.ibm.com> The next patch will start accessing the excp_vectors array earlier in the function, so add a bounds check as first thing here. This converts the empty return on POWERPC_EXCP_NONE to an error. This exception number never reaches this function and if it does it probably means something else went wrong up the line. Signed-off-by: Fabiano Rosas <farosas@linux.ibm.com> Reviewed-by: Cédric Le Goater <clg@kaod.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Reviewed-by: David Gibson <david@gibson.dropbear.id.au> Message-Id: <20211229165751.3774248-3-farosas@linux.ibm.com> Signed-off-by: Cédric Le Goater <clg@kaod.org> --- target/ppc/excp_helper.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c index XXXXXXX..XXXXXXX 100644 --- a/target/ppc/excp_helper.c +++ b/target/ppc/excp_helper.c @@ -XXX,XX +XXX,XX @@ static void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp) target_ulong msr, new_msr, vector; int srr0, srr1, lev = -1; + if (excp <= POWERPC_EXCP_NONE || excp >= POWERPC_EXCP_NB) { + cpu_abort(cs, "Invalid PowerPC exception %d. Aborting\n", excp); + } + qemu_log_mask(CPU_LOG_INT, "Raise exception at " TARGET_FMT_lx " => %s (%d) error=%02x\n", env->nip, powerpc_excp_name(excp), excp, env->error_code); @@ -XXX,XX +XXX,XX @@ static void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp) #endif switch (excp) { - case POWERPC_EXCP_NONE: - /* Should never happen */ - return; case POWERPC_EXCP_CRITICAL: /* Critical input */ switch (excp_model) { case POWERPC_EXCP_40x: -- 2.31.1
From: Fabiano Rosas <farosas@linux.ibm.com> None of the interrupt setup code touches 'vector', so we can move it earlier in the function. This will allow us to later move the System Call Vectored setup that is on the top level into the POWERPC_EXCP_SYSCALL_VECTORED code block. This patch also moves the verification for when 'excp' does not have an address associated with it. We now bail a little earlier when that is the case. This should not cause any visible effects. Signed-off-by: Fabiano Rosas <farosas@linux.ibm.com> Reviewed-by: Cédric Le Goater <clg@kaod.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Reviewed-by: David Gibson <david@gibson.dropbear.id.au> Message-Id: <20211229165751.3774248-4-farosas@linux.ibm.com> Signed-off-by: Cédric Le Goater <clg@kaod.org> --- target/ppc/excp_helper.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c index XXXXXXX..XXXXXXX 100644 --- a/target/ppc/excp_helper.c +++ b/target/ppc/excp_helper.c @@ -XXX,XX +XXX,XX @@ static void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp) } #endif + vector = env->excp_vectors[excp]; + if (vector == (target_ulong)-1ULL) { + cpu_abort(cs, "Raised an exception without defined vector %d\n", + excp); + } + + vector |= env->excp_prefix; + switch (excp) { case POWERPC_EXCP_CRITICAL: /* Critical input */ switch (excp_model) { @@ -XXX,XX +XXX,XX @@ static void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp) } #endif - vector = env->excp_vectors[excp]; - if (vector == (target_ulong)-1ULL) { - cpu_abort(cs, "Raised an exception without defined vector %d\n", - excp); - } - - vector |= env->excp_prefix; - #if defined(TARGET_PPC64) if (excp_model == POWERPC_EXCP_BOOKE) { if (env->spr[SPR_BOOKE_EPCR] & EPCR_ICM) { -- 2.31.1
From: Fabiano Rosas <farosas@linux.ibm.com> Now that 'vector' is known before calling the interrupt-specific setup code, we can move all of the scv setup into one place. No functional change intended. Signed-off-by: Fabiano Rosas <farosas@linux.ibm.com> Reviewed-by: Cédric Le Goater <clg@kaod.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-Id: <20211229165751.3774248-5-farosas@linux.ibm.com> Signed-off-by: Cédric Le Goater <clg@kaod.org> --- target/ppc/excp_helper.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c index XXXXXXX..XXXXXXX 100644 --- a/target/ppc/excp_helper.c +++ b/target/ppc/excp_helper.c @@ -XXX,XX +XXX,XX @@ static void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp) env->nip += 4; new_msr |= env->msr & ((target_ulong)1 << MSR_EE); new_msr |= env->msr & ((target_ulong)1 << MSR_RI); + + vector += lev * 0x20; + + env->lr = env->nip; + env->ctr = msr; break; case POWERPC_EXCP_FPU: /* Floating-point unavailable exception */ case POWERPC_EXCP_APU: /* Auxiliary processor unavailable */ @@ -XXX,XX +XXX,XX @@ static void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp) /* Save MSR */ env->spr[srr1] = msr; - -#if defined(TARGET_PPC64) - } else { - vector += lev * 0x20; - - env->lr = env->nip; - env->ctr = msr; -#endif } /* This can update new_msr and vector if AIL applies */ -- 2.31.1
From: Fabiano Rosas <farosas@linux.ibm.com> We can just access it directly in powerpc_excp. Signed-off-by: Fabiano Rosas <farosas@linux.ibm.com> Reviewed-by: Cédric Le Goater <clg@kaod.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Reviewed-by: David Gibson <david@gibson.dropbear.id.au> [ clg: Took into account removal of inline ] Message-Id: <20211229165751.3774248-6-farosas@linux.ibm.com> Signed-off-by: Cédric Le Goater <clg@kaod.org> --- target/ppc/excp_helper.c | 43 ++++++++++++++++++++-------------------- 1 file changed, 21 insertions(+), 22 deletions(-) diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c index XXXXXXX..XXXXXXX 100644 --- a/target/ppc/excp_helper.c +++ b/target/ppc/excp_helper.c @@ -XXX,XX +XXX,XX @@ static void powerpc_set_excp_state(PowerPCCPU *cpu, * Note that this function should be greatly optimized when called * with a constant excp, from ppc_hw_interrupt */ -static void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp) +static void powerpc_excp(PowerPCCPU *cpu, int excp) { CPUState *cs = CPU(cpu); CPUPPCState *env = &cpu->env; + int excp_model = env->excp_model; target_ulong msr, new_msr, vector; int srr0, srr1, lev = -1; @@ -XXX,XX +XXX,XX @@ static void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp) void ppc_cpu_do_interrupt(CPUState *cs) { PowerPCCPU *cpu = POWERPC_CPU(cs); - CPUPPCState *env = &cpu->env; - powerpc_excp(cpu, env->excp_model, cs->exception_index); + powerpc_excp(cpu, cs->exception_index); } static void ppc_hw_interrupt(CPUPPCState *env) @@ -XXX,XX +XXX,XX @@ static void ppc_hw_interrupt(CPUPPCState *env) /* External reset */ if (env->pending_interrupts & (1 << PPC_INTERRUPT_RESET)) { env->pending_interrupts &= ~(1 << PPC_INTERRUPT_RESET); - powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_RESET); + powerpc_excp(cpu, POWERPC_EXCP_RESET); return; } /* Machine check exception */ if (env->pending_interrupts & (1 << PPC_INTERRUPT_MCK)) { env->pending_interrupts &= ~(1 << PPC_INTERRUPT_MCK); - powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_MCHECK); + powerpc_excp(cpu, POWERPC_EXCP_MCHECK); return; } #if 0 /* TODO */ /* External debug exception */ if (env->pending_interrupts & (1 << PPC_INTERRUPT_DEBUG)) { env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DEBUG); - powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_DEBUG); + powerpc_excp(cpu, POWERPC_EXCP_DEBUG); return; } #endif @@ -XXX,XX +XXX,XX @@ static void ppc_hw_interrupt(CPUPPCState *env) if ((async_deliver || msr_hv == 0) && hdice) { /* HDEC clears on delivery */ env->pending_interrupts &= ~(1 << PPC_INTERRUPT_HDECR); - powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_HDECR); + powerpc_excp(cpu, POWERPC_EXCP_HDECR); return; } } @@ -XXX,XX +XXX,XX @@ static void ppc_hw_interrupt(CPUPPCState *env) /* LPCR will be clear when not supported so this will work */ bool hvice = !!(env->spr[SPR_LPCR] & LPCR_HVICE); if ((async_deliver || msr_hv == 0) && hvice) { - powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_HVIRT); + powerpc_excp(cpu, POWERPC_EXCP_HVIRT); return; } } @@ -XXX,XX +XXX,XX @@ static void ppc_hw_interrupt(CPUPPCState *env) /* HEIC blocks delivery to the hypervisor */ if ((async_deliver && !(heic && msr_hv && !msr_pr)) || (env->has_hv_mode && msr_hv == 0 && !lpes0)) { - powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_EXTERNAL); + powerpc_excp(cpu, POWERPC_EXCP_EXTERNAL); return; } } if (msr_ce != 0) { /* External critical interrupt */ if (env->pending_interrupts & (1 << PPC_INTERRUPT_CEXT)) { - powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_CRITICAL); + powerpc_excp(cpu, POWERPC_EXCP_CRITICAL); return; } } @@ -XXX,XX +XXX,XX @@ static void ppc_hw_interrupt(CPUPPCState *env) /* Watchdog timer on embedded PowerPC */ if (env->pending_interrupts & (1 << PPC_INTERRUPT_WDT)) { env->pending_interrupts &= ~(1 << PPC_INTERRUPT_WDT); - powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_WDT); + powerpc_excp(cpu, POWERPC_EXCP_WDT); return; } if (env->pending_interrupts & (1 << PPC_INTERRUPT_CDOORBELL)) { env->pending_interrupts &= ~(1 << PPC_INTERRUPT_CDOORBELL); - powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_DOORCI); + powerpc_excp(cpu, POWERPC_EXCP_DOORCI); return; } /* Fixed interval timer on embedded PowerPC */ if (env->pending_interrupts & (1 << PPC_INTERRUPT_FIT)) { env->pending_interrupts &= ~(1 << PPC_INTERRUPT_FIT); - powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_FIT); + powerpc_excp(cpu, POWERPC_EXCP_FIT); return; } /* Programmable interval timer on embedded PowerPC */ if (env->pending_interrupts & (1 << PPC_INTERRUPT_PIT)) { env->pending_interrupts &= ~(1 << PPC_INTERRUPT_PIT); - powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_PIT); + powerpc_excp(cpu, POWERPC_EXCP_PIT); return; } /* Decrementer exception */ @@ -XXX,XX +XXX,XX @@ static void ppc_hw_interrupt(CPUPPCState *env) if (ppc_decr_clear_on_delivery(env)) { env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DECR); } - powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_DECR); + powerpc_excp(cpu, POWERPC_EXCP_DECR); return; } if (env->pending_interrupts & (1 << PPC_INTERRUPT_DOORBELL)) { env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DOORBELL); if (is_book3s_arch2x(env)) { - powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_SDOOR); + powerpc_excp(cpu, POWERPC_EXCP_SDOOR); } else { - powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_DOORI); + powerpc_excp(cpu, POWERPC_EXCP_DOORI); } return; } if (env->pending_interrupts & (1 << PPC_INTERRUPT_HDOORBELL)) { env->pending_interrupts &= ~(1 << PPC_INTERRUPT_HDOORBELL); - powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_SDOOR_HV); + powerpc_excp(cpu, POWERPC_EXCP_SDOOR_HV); return; } if (env->pending_interrupts & (1 << PPC_INTERRUPT_PERFM)) { env->pending_interrupts &= ~(1 << PPC_INTERRUPT_PERFM); - powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_PERFM); + powerpc_excp(cpu, POWERPC_EXCP_PERFM); return; } /* Thermal interrupt */ if (env->pending_interrupts & (1 << PPC_INTERRUPT_THERM)) { env->pending_interrupts &= ~(1 << PPC_INTERRUPT_THERM); - powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_THERM); + powerpc_excp(cpu, POWERPC_EXCP_THERM); return; } } @@ -XXX,XX +XXX,XX @@ static void ppc_hw_interrupt(CPUPPCState *env) void ppc_cpu_do_system_reset(CPUState *cs) { PowerPCCPU *cpu = POWERPC_CPU(cs); - CPUPPCState *env = &cpu->env; - powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_RESET); + powerpc_excp(cpu, POWERPC_EXCP_RESET); } void ppc_cpu_do_fwnmi_machine_check(CPUState *cs, target_ulong vector) -- 2.31.1
From: Richard Henderson <richard.henderson@linaro.org> This is the combination of frozen bit and counter type, on a per counter basis. So far this is only used by HFLAGS_INSN_CNT, but will be used more later. Signed-off-by: Richard Henderson <richard.henderson@linaro.org> [danielhb: fixed PMC4 cyc_cnt shift, insn run latch code, MMCR0_FC handling, "PMC[1-6]" comment] Signed-off-by: Daniel Henrique Barboza <danielhb413@gmail.com> Message-Id: <20220103224746.167831-2-danielhb413@gmail.com> Signed-off-by: Cédric Le Goater <clg@kaod.org> --- target/ppc/cpu.h | 3 +++ target/ppc/power8-pmu.h | 14 +++++----- target/ppc/cpu_init.c | 1 + target/ppc/helper_regs.c | 2 +- target/ppc/machine.c | 2 ++ target/ppc/power8-pmu.c | 56 ++++++++++++++++++++++++++++++++-------- 6 files changed, 58 insertions(+), 20 deletions(-) diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h index XXXXXXX..XXXXXXX 100644 --- a/target/ppc/cpu.h +++ b/target/ppc/cpu.h @@ -XXX,XX +XXX,XX @@ struct CPUPPCState { /* Other registers */ target_ulong spr[1024]; /* special purpose registers */ ppc_spr_t spr_cb[1024]; + /* Composite status for PMC[1-6] enabled and counting insns or cycles. */ + uint8_t pmc_ins_cnt; + uint8_t pmc_cyc_cnt; /* Vector status and control register, minus VSCR_SAT */ uint32_t vscr; /* VSX registers (including FP and AVR) */ diff --git a/target/ppc/power8-pmu.h b/target/ppc/power8-pmu.h index XXXXXXX..XXXXXXX 100644 --- a/target/ppc/power8-pmu.h +++ b/target/ppc/power8-pmu.h @@ -XXX,XX +XXX,XX @@ #ifndef POWER8_PMU #define POWER8_PMU -#include "qemu/osdep.h" -#include "cpu.h" -#include "exec/exec-all.h" -#include "exec/helper-proto.h" -#include "qemu/error-report.h" -#include "qemu/main-loop.h" - void cpu_ppc_pmu_init(CPUPPCState *env); -bool pmu_insn_cnt_enabled(CPUPPCState *env); + +#if defined(TARGET_PPC64) && !defined(CONFIG_USER_ONLY) +void pmu_update_summaries(CPUPPCState *env); +#else +static inline void pmu_update_summaries(CPUPPCState *env) { } +#endif #endif diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c index XXXXXXX..XXXXXXX 100644 --- a/target/ppc/cpu_init.c +++ b/target/ppc/cpu_init.c @@ -XXX,XX +XXX,XX @@ static void ppc_cpu_reset(DeviceState *dev) #endif /* CONFIG_TCG */ #endif + pmu_update_summaries(env); hreg_compute_hflags(env); env->reserve_addr = (target_ulong)-1ULL; /* Be sure no exception or interrupt is pending */ diff --git a/target/ppc/helper_regs.c b/target/ppc/helper_regs.c index XXXXXXX..XXXXXXX 100644 --- a/target/ppc/helper_regs.c +++ b/target/ppc/helper_regs.c @@ -XXX,XX +XXX,XX @@ static uint32_t hreg_compute_hflags_value(CPUPPCState *env) } #if defined(TARGET_PPC64) - if (pmu_insn_cnt_enabled(env)) { + if (env->pmc_ins_cnt) { hflags |= 1 << HFLAGS_INSN_CNT; } #endif diff --git a/target/ppc/machine.c b/target/ppc/machine.c index XXXXXXX..XXXXXXX 100644 --- a/target/ppc/machine.c +++ b/target/ppc/machine.c @@ -XXX,XX +XXX,XX @@ #include "qapi/error.h" #include "qemu/main-loop.h" #include "kvm_ppc.h" +#include "power8-pmu.h" static void post_load_update_msr(CPUPPCState *env) { @@ -XXX,XX +XXX,XX @@ static void post_load_update_msr(CPUPPCState *env) */ env->msr ^= env->msr_mask & ~((1ULL << MSR_TGPR) | MSR_HVB); ppc_store_msr(env, msr); + pmu_update_summaries(env); } static int cpu_load_old(QEMUFile *f, void *opaque, int version_id) diff --git a/target/ppc/power8-pmu.c b/target/ppc/power8-pmu.c index XXXXXXX..XXXXXXX 100644 --- a/target/ppc/power8-pmu.c +++ b/target/ppc/power8-pmu.c @@ -XXX,XX +XXX,XX @@ */ #include "qemu/osdep.h" - -#include "power8-pmu.h" #include "cpu.h" #include "helper_regs.h" #include "exec/exec-all.h" @@ -XXX,XX +XXX,XX @@ #include "qemu/error-report.h" #include "qemu/main-loop.h" #include "hw/ppc/ppc.h" +#include "power8-pmu.h" #if defined(TARGET_PPC64) && !defined(CONFIG_USER_ONLY) @@ -XXX,XX +XXX,XX @@ static PMUEventType pmc_get_event(CPUPPCState *env, int sprn) return evt_type; } -bool pmu_insn_cnt_enabled(CPUPPCState *env) +void pmu_update_summaries(CPUPPCState *env) { - int sprn; + target_ulong mmcr0 = env->spr[SPR_POWER_MMCR0]; + target_ulong mmcr1 = env->spr[SPR_POWER_MMCR1]; + int ins_cnt = 0; + int cyc_cnt = 0; - for (sprn = SPR_POWER_PMC1; sprn <= SPR_POWER_PMC5; sprn++) { - if (pmc_get_event(env, sprn) == PMU_EVENT_INSTRUCTIONS || - pmc_get_event(env, sprn) == PMU_EVENT_INSN_RUN_LATCH) { - return true; + if (mmcr0 & MMCR0_FC) { + goto hflags_calc; + } + + if (!(mmcr0 & MMCR0_FC14) && mmcr1 != 0) { + target_ulong sel; + + sel = extract64(mmcr1, MMCR1_PMC1EVT_EXTR, MMCR1_EVT_SIZE); + switch (sel) { + case 0x02: + case 0xfe: + ins_cnt |= 1 << 1; + break; + case 0x1e: + case 0xf0: + cyc_cnt |= 1 << 1; + break; } + + sel = extract64(mmcr1, MMCR1_PMC2EVT_EXTR, MMCR1_EVT_SIZE); + ins_cnt |= (sel == 0x02) << 2; + cyc_cnt |= (sel == 0x1e) << 2; + + sel = extract64(mmcr1, MMCR1_PMC3EVT_EXTR, MMCR1_EVT_SIZE); + ins_cnt |= (sel == 0x02) << 3; + cyc_cnt |= (sel == 0x1e) << 3; + + sel = extract64(mmcr1, MMCR1_PMC4EVT_EXTR, MMCR1_EVT_SIZE); + ins_cnt |= ((sel == 0xfa) || (sel == 0x2)) << 4; + cyc_cnt |= (sel == 0x1e) << 4; } - return false; + ins_cnt |= !(mmcr0 & MMCR0_FC56) << 5; + cyc_cnt |= !(mmcr0 & MMCR0_FC56) << 6; + + hflags_calc: + env->pmc_ins_cnt = ins_cnt; + env->pmc_cyc_cnt = cyc_cnt; + env->hflags = deposit32(env->hflags, HFLAGS_INSN_CNT, 1, ins_cnt != 0); } static bool pmu_increment_insns(CPUPPCState *env, uint32_t num_insns) @@ -XXX,XX +XXX,XX @@ void helper_store_mmcr0(CPUPPCState *env, target_ulong value) env->spr[SPR_POWER_MMCR0] = value; - /* MMCR0 writes can change HFLAGS_PMCCCLEAR and HFLAGS_INSN_CNT */ + /* MMCR0 writes can change HFLAGS_PMCC[01] and HFLAGS_INSN_CNT */ hreg_compute_hflags(env); + pmu_update_summaries(env); /* Update cycle overflow timers with the current MMCR0 state */ pmu_update_overflow_timers(env); @@ -XXX,XX +XXX,XX @@ void helper_store_mmcr1(CPUPPCState *env, uint64_t value) env->spr[SPR_POWER_MMCR1] = value; /* MMCR1 writes can change HFLAGS_INSN_CNT */ - hreg_compute_hflags(env); + pmu_update_summaries(env); } target_ulong helper_read_pmc(CPUPPCState *env, uint32_t sprn) -- 2.31.1
From: Richard Henderson <richard.henderson@linaro.org> Use the cached pmc_ins_cnt value. Unroll the loop over the different PMC counters. Treat the PMC4 run-latch specially. Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Message-Id: <20220103224746.167831-3-danielhb413@gmail.com> Signed-off-by: Cédric Le Goater <clg@kaod.org> --- target/ppc/power8-pmu.c | 78 ++++++++++++++++++++++++++--------------- 1 file changed, 49 insertions(+), 29 deletions(-) diff --git a/target/ppc/power8-pmu.c b/target/ppc/power8-pmu.c index XXXXXXX..XXXXXXX 100644 --- a/target/ppc/power8-pmu.c +++ b/target/ppc/power8-pmu.c @@ -XXX,XX +XXX,XX @@ void pmu_update_summaries(CPUPPCState *env) static bool pmu_increment_insns(CPUPPCState *env, uint32_t num_insns) { + target_ulong mmcr0 = env->spr[SPR_POWER_MMCR0]; + unsigned ins_cnt = env->pmc_ins_cnt; bool overflow_triggered = false; - int sprn; - - /* PMC6 never counts instructions */ - for (sprn = SPR_POWER_PMC1; sprn <= SPR_POWER_PMC5; sprn++) { - PMUEventType evt_type = pmc_get_event(env, sprn); - bool insn_event = evt_type == PMU_EVENT_INSTRUCTIONS || - evt_type == PMU_EVENT_INSN_RUN_LATCH; - - if (pmc_is_inactive(env, sprn) || !insn_event) { - continue; + target_ulong tmp; + + if (unlikely(ins_cnt & 0x1e)) { + if (ins_cnt & (1 << 1)) { + tmp = env->spr[SPR_POWER_PMC1]; + tmp += num_insns; + if (tmp >= PMC_COUNTER_NEGATIVE_VAL && (mmcr0 & MMCR0_PMC1CE)) { + tmp = PMC_COUNTER_NEGATIVE_VAL; + overflow_triggered = true; + } + env->spr[SPR_POWER_PMC1] = tmp; } - if (evt_type == PMU_EVENT_INSTRUCTIONS) { - env->spr[sprn] += num_insns; + if (ins_cnt & (1 << 2)) { + tmp = env->spr[SPR_POWER_PMC2]; + tmp += num_insns; + if (tmp >= PMC_COUNTER_NEGATIVE_VAL && (mmcr0 & MMCR0_PMCjCE)) { + tmp = PMC_COUNTER_NEGATIVE_VAL; + overflow_triggered = true; + } + env->spr[SPR_POWER_PMC2] = tmp; } - if (evt_type == PMU_EVENT_INSN_RUN_LATCH && - env->spr[SPR_CTRL] & CTRL_RUN) { - env->spr[sprn] += num_insns; + if (ins_cnt & (1 << 3)) { + tmp = env->spr[SPR_POWER_PMC3]; + tmp += num_insns; + if (tmp >= PMC_COUNTER_NEGATIVE_VAL && (mmcr0 & MMCR0_PMCjCE)) { + tmp = PMC_COUNTER_NEGATIVE_VAL; + overflow_triggered = true; + } + env->spr[SPR_POWER_PMC3] = tmp; } - if (env->spr[sprn] >= PMC_COUNTER_NEGATIVE_VAL && - pmc_has_overflow_enabled(env, sprn)) { + if (ins_cnt & (1 << 4)) { + target_ulong mmcr1 = env->spr[SPR_POWER_MMCR1]; + int sel = extract64(mmcr1, MMCR1_PMC4EVT_EXTR, MMCR1_EVT_SIZE); + if (sel == 0x02 || (env->spr[SPR_CTRL] & CTRL_RUN)) { + tmp = env->spr[SPR_POWER_PMC4]; + tmp += num_insns; + if (tmp >= PMC_COUNTER_NEGATIVE_VAL && (mmcr0 & MMCR0_PMCjCE)) { + tmp = PMC_COUNTER_NEGATIVE_VAL; + overflow_triggered = true; + } + env->spr[SPR_POWER_PMC4] = tmp; + } + } + } + if (ins_cnt & (1 << 5)) { + tmp = env->spr[SPR_POWER_PMC5]; + tmp += num_insns; + if (tmp >= PMC_COUNTER_NEGATIVE_VAL && (mmcr0 & MMCR0_PMCjCE)) { + tmp = PMC_COUNTER_NEGATIVE_VAL; overflow_triggered = true; - - /* - * The real PMU will always trigger a counter overflow with - * PMC_COUNTER_NEGATIVE_VAL. We don't have an easy way to - * do that since we're counting block of instructions at - * the end of each translation block, and we're probably - * passing this value at this point. - * - * Let's write PMC_COUNTER_NEGATIVE_VAL to the overflowed - * counter to simulate what the real hardware would do. - */ - env->spr[sprn] = PMC_COUNTER_NEGATIVE_VAL; } + env->spr[SPR_POWER_PMC5] = tmp; } return overflow_triggered; -- 2.31.1
From: Richard Henderson <richard.henderson@linaro.org> Use the cached pmc_cyc_cnt value in pmu_update_cycles and pmc_update_overflow_timer. This leaves pmc_get_event and pmc_is_inactive unused, so remove them. Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Message-Id: <20220103224746.167831-4-danielhb413@gmail.com> Signed-off-by: Cédric Le Goater <clg@kaod.org> --- target/ppc/power8-pmu.c | 107 ++++------------------------------------ 1 file changed, 9 insertions(+), 98 deletions(-) diff --git a/target/ppc/power8-pmu.c b/target/ppc/power8-pmu.c index XXXXXXX..XXXXXXX 100644 --- a/target/ppc/power8-pmu.c +++ b/target/ppc/power8-pmu.c @@ -XXX,XX +XXX,XX @@ #define PMC_COUNTER_NEGATIVE_VAL 0x80000000UL -static bool pmc_is_inactive(CPUPPCState *env, int sprn) -{ - if (env->spr[SPR_POWER_MMCR0] & MMCR0_FC) { - return true; - } - - if (sprn < SPR_POWER_PMC5) { - return env->spr[SPR_POWER_MMCR0] & MMCR0_FC14; - } - - return env->spr[SPR_POWER_MMCR0] & MMCR0_FC56; -} - static bool pmc_has_overflow_enabled(CPUPPCState *env, int sprn) { if (sprn == SPR_POWER_PMC1) { @@ -XXX,XX +XXX,XX @@ static bool pmc_has_overflow_enabled(CPUPPCState *env, int sprn) return env->spr[SPR_POWER_MMCR0] & MMCR0_PMCjCE; } -/* - * For PMCs 1-4, IBM POWER chips has support for an implementation - * dependent event, 0x1E, that enables cycle counting. The Linux kernel - * makes extensive use of 0x1E, so let's also support it. - * - * Likewise, event 0x2 is an implementation-dependent event that IBM - * POWER chips implement (at least since POWER8) that is equivalent to - * PM_INST_CMPL. Let's support this event on PMCs 1-4 as well. - */ -static PMUEventType pmc_get_event(CPUPPCState *env, int sprn) -{ - uint8_t mmcr1_evt_extr[] = { MMCR1_PMC1EVT_EXTR, MMCR1_PMC2EVT_EXTR, - MMCR1_PMC3EVT_EXTR, MMCR1_PMC4EVT_EXTR }; - PMUEventType evt_type = PMU_EVENT_INVALID; - uint8_t pmcsel; - int i; - - if (pmc_is_inactive(env, sprn)) { - return PMU_EVENT_INACTIVE; - } - - if (sprn == SPR_POWER_PMC5) { - return PMU_EVENT_INSTRUCTIONS; - } - - if (sprn == SPR_POWER_PMC6) { - return PMU_EVENT_CYCLES; - } - - i = sprn - SPR_POWER_PMC1; - pmcsel = extract64(env->spr[SPR_POWER_MMCR1], mmcr1_evt_extr[i], - MMCR1_EVT_SIZE); - - switch (pmcsel) { - case 0x2: - evt_type = PMU_EVENT_INSTRUCTIONS; - break; - case 0x1E: - evt_type = PMU_EVENT_CYCLES; - break; - case 0xF0: - /* - * PMC1SEL = 0xF0 is the architected PowerISA v3.1 - * event that counts cycles using PMC1. - */ - if (sprn == SPR_POWER_PMC1) { - evt_type = PMU_EVENT_CYCLES; - } - break; - case 0xFA: - /* - * PMC4SEL = 0xFA is the "instructions completed - * with run latch set" event. - */ - if (sprn == SPR_POWER_PMC4) { - evt_type = PMU_EVENT_INSN_RUN_LATCH; - } - break; - case 0xFE: - /* - * PMC1SEL = 0xFE is the architected PowerISA v3.1 - * event to sample instructions using PMC1. - */ - if (sprn == SPR_POWER_PMC1) { - evt_type = PMU_EVENT_INSTRUCTIONS; - } - break; - default: - break; - } - - return evt_type; -} - void pmu_update_summaries(CPUPPCState *env) { target_ulong mmcr0 = env->spr[SPR_POWER_MMCR0]; @@ -XXX,XX +XXX,XX @@ static void pmu_update_cycles(CPUPPCState *env) { uint64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); uint64_t time_delta = now - env->pmu_base_time; - int sprn; + int sprn, cyc_cnt = env->pmc_cyc_cnt; for (sprn = SPR_POWER_PMC1; sprn <= SPR_POWER_PMC6; sprn++) { - if (pmc_get_event(env, sprn) != PMU_EVENT_CYCLES) { - continue; + if (cyc_cnt & (1 << (sprn - SPR_POWER_PMC1 + 1))) { + /* + * The pseries and powernv clock runs at 1Ghz, meaning + * that 1 nanosec equals 1 cycle. + */ + env->spr[sprn] += time_delta; } - - /* - * The pseries and powernv clock runs at 1Ghz, meaning - * that 1 nanosec equals 1 cycle. - */ - env->spr[sprn] += time_delta; } /* Update base_time for future calculations */ @@ -XXX,XX +XXX,XX @@ static void pmc_update_overflow_timer(CPUPPCState *env, int sprn) return; } - if (pmc_get_event(env, sprn) != PMU_EVENT_CYCLES || + if (!(env->pmc_cyc_cnt & (1 << (sprn - SPR_POWER_PMC1 + 1))) || !pmc_has_overflow_enabled(env, sprn)) { /* Overflow timer is not needed for this counter */ timer_del(pmc_overflow_timer); @@ -XXX,XX +XXX,XX @@ static void pmc_update_overflow_timer(CPUPPCState *env, int sprn) } if (env->spr[sprn] >= PMC_COUNTER_NEGATIVE_VAL) { - timeout = 0; + timeout = 0; } else { timeout = PMC_COUNTER_NEGATIVE_VAL - env->spr[sprn]; } -- 2.31.1
From: Daniel Henrique Barboza <danielhb413@gmail.com> MMCR0 writes will change only MMCR0 bits which are used to calculate HFLAGS_PMCC0, HFLAGS_PMCC1 and HFLAGS_INSN_CNT hflags. No other machine register will be changed during this operation. This means that hreg_compute_hflags() is overkill for what we need to do. pmu_update_summaries() is already updating HFLAGS_INSN_CNT without calling hreg_compure_hflags(). Let's do the same for the other 2 MMCR0 hflags. Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Signed-off-by: Daniel Henrique Barboza <danielhb413@gmail.com> Message-Id: <20220103224746.167831-5-danielhb413@gmail.com> Signed-off-by: Cédric Le Goater <clg@kaod.org> --- target/ppc/power8-pmu.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/target/ppc/power8-pmu.c b/target/ppc/power8-pmu.c index XXXXXXX..XXXXXXX 100644 --- a/target/ppc/power8-pmu.c +++ b/target/ppc/power8-pmu.c @@ -XXX,XX +XXX,XX @@ static void pmu_update_overflow_timers(CPUPPCState *env) void helper_store_mmcr0(CPUPPCState *env, target_ulong value) { + bool hflags_pmcc0 = (value & MMCR0_PMCC0) != 0; + bool hflags_pmcc1 = (value & MMCR0_PMCC1) != 0; + pmu_update_cycles(env); env->spr[SPR_POWER_MMCR0] = value; /* MMCR0 writes can change HFLAGS_PMCC[01] and HFLAGS_INSN_CNT */ - hreg_compute_hflags(env); + env->hflags = deposit32(env->hflags, HFLAGS_PMCC0, 1, hflags_pmcc0); + env->hflags = deposit32(env->hflags, HFLAGS_PMCC1, 1, hflags_pmcc1); + pmu_update_summaries(env); /* Update cycle overflow timers with the current MMCR0 state */ -- 2.31.1
The following changes since commit 76b56fdfc9fa43ec6e5986aee33f108c6c6a511e: Merge tag 'block-pull-request' of https://gitlab.com/stefanha/qemu into staging (2021-12-14 12:46:18 -0800) are available in the Git repository at: https://github.com/legoater/qemu/ tags/pull-ppc-20211217 for you to fetch changes up to 0e6232bc3cb96bdf6fac1b5d7659aa9887afe657: ppc/pnv: Use QOM hierarchy to scan PEC PHB4 devices (2021-12-17 17:57:19 +0100) Changes in v3: - Fixed patch "docs: Introducing pseries documentation" with a newline and checked documentation generation with : make docker-test-build@ubuntu1804 TARGET_LIST=i386-softmmu Changes in v2: - Fixed patch "docs: rSTify ppc-spapr-hcalls.txt" with a newline - dropped patch "target/ppc: do not silence SNaN in xscvspdpn" which still had some comments pending. ---------------------------------------------------------------- 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) ---------------------------------------------------------------- Alexey Kardashevskiy (1): pseries: Update SLOF firmware image Christophe Lombard (1): pci-host: Allow extended config space access for PowerNV PHB4 model Cédric Le Goater (28): Merge tag 'qemu-slof-20211112' of github.com:aik/qemu into ppc-next target/ppc: remove 401/403 CPUs ppc/ppc405: Change kernel load address ppc: Add trace-events for DCR accesses ppc/ppc405: Convert printfs to trace-events ppc/ppc405: Drop flag parameter in ppc405_set_bootinfo() ppc/ppc405: Change ppc405ep_init() return value ppc/ppc405: Add some address space definitions ppc/ppc405: Remove flash support ppc/ppc405: Rework FW load ppc/ppc405: Introduce ppc405_set_default_bootinfo() ppc/ppc405: Fix boot from kernel ppc/ppc405: Change default PLL values at reset ppc/ppc405: Fix bi_pci_enetaddr2 field in U-Boot board information ppc/ppc405: Add update of bi_procfreq field ppc/pnv: Introduce a "chip" property under PHB3 ppc/pnv: Use the chip class to check the index of PHB3 devices ppc/pnv: Drop the "num-phbs" property ppc/pnv: Move mapping of the PHB3 CQ regions under pnv_pbcq_realize() ppc/pnv: Use QOM hierarchy to scan PHB3 devices ppc/pnv: Introduce a num_pecs class attribute for PHB4 PEC devices ppc/pnv: Introduce version and device_id class atributes for PHB4 devices ppc/pnv: Introduce a "chip" property under the PHB4 model ppc/pnv: Introduce a num_stack class attribute ppc/pnv: Compute the PHB index from the PHB4 PEC model ppc/pnv: Remove "system-memory" property from PHB4 PEC ppc/pnv: Move realize of PEC stacks under the PEC model ppc/pnv: Use QOM hierarchy to scan PEC PHB4 devices Daniel Henrique Barboza (13): ivshmem.c: change endianness to LITTLE_ENDIAN ivshmem-test.c: enable test_ivshmem_server for ppc64 arch ppc/pnv.c: add a friendly warning when accel=kvm is used docs/system/ppc/powernv.rst: document KVM support status ppc/pnv.c: fix "system-id" FDT when -uuid is set target/ppc: introduce PMUEventType and PMU overflow timers target/ppc: PMU basic cycle count for pseries TCG target/ppc: PMU: update counters on PMCs r/w target/ppc: PMU: update counters on MMCR1 write target/ppc: enable PMU counter overflow with cycle events target/ppc: enable PMU instruction count target/ppc/power8-pmu.c: add PM_RUN_INST_CMPL (0xFA) event PPC64/TCG: Implement 'rfebb' instruction Fabiano Rosas (8): target/ppc: Disable software TLB for the 7450 family target/ppc: Disable unused facilities in the e600 CPU target/ppc: Remove the software TLB model of 7450 CPUs target/ppc: Fix MPCxxx FPU interrupt address target/ppc: Remove 603e exception model target/ppc: Set 601v exception model id target/ppc: Fix e6500 boot Revert "target/ppc: Move SPR_DSISR setting to powerpc_excp" Leonardo Garcia (5): docs: Minor updates on the powernv documentation. docs: Introducing pseries documentation. docs: rSTify ppc-spapr-hcalls.txt docs: Rename ppc-spapr-hcalls.txt to ppc-spapr-hcalls.rst. Link new ppc-spapr-hcalls.rst file to pseries.rst. Lucas Mateus Castro (alqotel) (3): target/ppc: Fixed call to deferred exception test/tcg/ppc64le: test mtfsf target/ppc: ppc_store_fpscr doesn't update bits 0 to 28 and 52 Matheus Ferst (5): target/ppc: Implement Vector Expand Mask target/ppc: Implement Vector Extract Mask target/ppc: Implement Vector Mask Move insns target/ppc: fix xscvqpdp register access target/ppc: move xscvqpdp to decodetree Peter Maydell (1): hw/ppc/mac.h: Remove MAX_CPUS macro Richard Henderson (34): softfloat: Extend float_exception_flags to 16 bits softfloat: Add flag specific to Inf - Inf softfloat: Add flag specific to Inf * 0 softfloat: Add flags specific to Inf / Inf and 0 / 0 softfloat: Add flag specific to sqrt(-x) softfloat: Add flag specific to convert non-nan to int softfloat: Add flag specific to signaling nans target/ppc: Update float_invalid_op_addsub for new flags target/ppc: Update float_invalid_op_mul for new flags target/ppc: Update float_invalid_op_div for new flags target/ppc: Move float_check_status from FPU_FCTI to translate target/ppc: Update float_invalid_cvt for new flags target/ppc: Fix VXCVI return value target/ppc: Remove inline from do_fri target/ppc: Use FloatRoundMode in do_fri target/ppc: Tidy inexact handling in do_fri target/ppc: Clean up do_fri target/ppc: Update fmadd for new flags target/ppc: Split out do_fmadd target/ppc: Do not call do_float_check_status from do_fmadd target/ppc: Split out do_frsp target/ppc: Update do_frsp for new flags target/ppc: Use helper_todouble in do_frsp target/ppc: Update sqrt for new flags target/ppc: Update xsrqpi and xsrqpxp to new flags target/ppc: Update fre to new flags softfloat: Add float64r32 arithmetic routines target/ppc: Add helpers for fmadds et al target/ppc: Add helper for fsqrts target/ppc: Add helpers for fadds, fsubs, fdivs target/ppc: Add helper for fmuls target/ppc: Add helper for frsqrtes target/ppc: Update fres to new flags and float64r32 target/ppc: Use helper_todouble/tosingle in helper_xststdcsp Thomas Huth (1): ppc: Mark the 'taihu' machine as deprecated Victor Colombo (2): target/ppc: Fix xs{max, min}[cj]dp to use VSX registers target/ppc: Move xs{max,min}[cj]dp to decodetree docs/about/deprecated.rst | 9 + docs/specs/ppc-spapr-hcalls.rst | 100 +++++ docs/specs/ppc-spapr-hcalls.txt | 78 ---- docs/system/ppc/powernv.rst | 68 ++-- docs/system/ppc/pseries.rst | 226 +++++++++++ hw/ppc/mac.h | 3 - hw/ppc/ppc405.h | 14 +- include/fpu/softfloat-types.h | 23 +- include/fpu/softfloat.h | 14 +- include/hw/pci-host/pnv_phb3.h | 3 + include/hw/pci-host/pnv_phb4.h | 5 + include/hw/ppc/pnv.h | 2 + target/ppc/cpu-models.h | 19 - target/ppc/cpu-qom.h | 12 +- target/ppc/cpu.h | 63 +++- target/ppc/helper.h | 29 +- target/ppc/power8-pmu.h | 26 ++ target/ppc/spr_tcg.h | 5 + target/ppc/insn32.decode | 54 ++- fpu/softfloat.c | 114 +++++- hw/misc/ivshmem.c | 2 +- hw/pci-host/pnv_phb3.c | 3 +- hw/pci-host/pnv_phb3_pbcq.c | 11 + hw/pci-host/pnv_phb4.c | 1 + hw/pci-host/pnv_phb4_pec.c | 75 +++- hw/ppc/mac_newworld.c | 3 +- hw/ppc/mac_oldworld.c | 3 +- hw/ppc/pnv.c | 177 +++++---- hw/ppc/ppc.c | 2 + hw/ppc/ppc405_boards.c | 245 ++++++------ hw/ppc/ppc405_uc.c | 225 ++++++----- hw/ppc/spapr_cpu_core.c | 1 + target/ppc/cpu-models.c | 34 -- target/ppc/cpu.c | 2 +- target/ppc/cpu_init.c | 658 +++------------------------------ target/ppc/excp_helper.c | 95 +++-- target/ppc/fpu_helper.c | 593 +++++++++++++++-------------- target/ppc/helper_regs.c | 7 + target/ppc/mmu_common.c | 60 +-- target/ppc/mmu_helper.c | 32 -- target/ppc/power8-pmu.c | 350 ++++++++++++++++++ target/ppc/translate.c | 104 ++++-- tests/qtest/ivshmem-test.c | 5 +- tests/tcg/ppc64le/mtfsf.c | 61 +++ fpu/softfloat-parts.c.inc | 57 +-- fpu/softfloat-specialize.c.inc | 12 +- target/ppc/power8-pmu-regs.c.inc | 69 +++- target/ppc/translate/branch-impl.c.inc | 33 ++ target/ppc/translate/fp-impl.c.inc | 53 +-- target/ppc/translate/vmx-impl.c.inc | 231 ++++++++++++ target/ppc/translate/vsx-impl.c.inc | 55 ++- target/ppc/translate/vsx-ops.c.inc | 5 - hw/ppc/trace-events | 23 ++ pc-bios/README | 2 +- pc-bios/slof.bin | Bin 991744 -> 991920 bytes roms/SLOF | 2 +- target/ppc/meson.build | 1 + tests/tcg/ppc64/Makefile.target | 1 + tests/tcg/ppc64le/Makefile.target | 1 + 59 files changed, 2514 insertions(+), 1647 deletions(-) create mode 100644 docs/specs/ppc-spapr-hcalls.rst delete mode 100644 docs/specs/ppc-spapr-hcalls.txt create mode 100644 target/ppc/power8-pmu.h create mode 100644 target/ppc/power8-pmu.c create mode 100644 tests/tcg/ppc64le/mtfsf.c create mode 100644 target/ppc/translate/branch-impl.c.inc