From 6e3f09c28a2e1767dddaf08b2f1414cd57c6c909 Mon Sep 17 00:00:00 2001 From: Alexey Kardashevskiy Date: Fri, 28 Jan 2022 13:15:01 +0100 Subject: [PATCH 01/41] spapr: Force 32bit when resetting a core MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit "PowerPC Processor binding to IEEE 1275" says in "8.2.1. Initial Register Values" that the initial state is defined as 32bit so do it for both SLOF and VOF. This should not cause behavioral change as SLOF switches to 64bit very early anyway. As nothing enforces LE anywhere, this drops it for VOF. The goal is to make VOF work with TCG as otherwise it barfs with qemu: fatal: TCG hflags mismatch (current:0x6c000004 rebuilt:0x6c000000) Signed-off-by: Alexey Kardashevskiy Reviewed-by: Cédric Le Goater Message-Id: <20220107072423.2278113-1-aik@ozlabs.ru> Signed-off-by: Cédric Le Goater --- hw/ppc/spapr_cpu_core.c | 5 +++++ hw/ppc/spapr_vof.c | 2 -- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/hw/ppc/spapr_cpu_core.c b/hw/ppc/spapr_cpu_core.c index a57ba70a87..a781e97f8d 100644 --- a/hw/ppc/spapr_cpu_core.c +++ b/hw/ppc/spapr_cpu_core.c @@ -37,6 +37,11 @@ static void spapr_reset_vcpu(PowerPCCPU *cpu) cpu_reset(cs); + /* + * "PowerPC Processor binding to IEEE 1275" defines the initial MSR state + * as 32bit (MSR_SF=0) in "8.2.1. Initial Register Values". + */ + env->msr &= ~(1ULL << MSR_SF); env->spr[SPR_HIOR] = 0; lpcr = env->spr[SPR_LPCR]; diff --git a/hw/ppc/spapr_vof.c b/hw/ppc/spapr_vof.c index 40ce8fe003..a33f940c32 100644 --- a/hw/ppc/spapr_vof.c +++ b/hw/ppc/spapr_vof.c @@ -88,8 +88,6 @@ void spapr_vof_reset(SpaprMachineState *spapr, void *fdt, Error **errp) spapr_cpu_set_entry_state(first_ppc_cpu, SPAPR_ENTRY_POINT, stack_ptr, spapr->initrd_base, spapr->initrd_size); - /* VOF is 32bit BE so enforce MSR here */ - first_ppc_cpu->env.msr &= ~((1ULL << MSR_SF) | (1ULL << MSR_LE)); /* * At this point the expected allocation map is: From 5aad0457eceec0085a289dde72e73f15db556b99 Mon Sep 17 00:00:00 2001 From: Christophe Leroy Date: Fri, 28 Jan 2022 13:15:01 +0100 Subject: [PATCH 02/41] target/ppc: 603: fix restore of GPRs 0-3 on rfi MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit After a TLB miss exception, GPRs 0-3 must be restored on rfi. This is managed by hreg_store_msr() which is called by do_rfi() However, hreg_store_msr() does it if MSR[TGPR] is unset in the passed MSR value. The problem is that do_rfi() is given the content of SRR1 as the value to be set in MSR, but TGPR bit is not part of SRR1 and that bit is used for something else and is sometimes set to 1, leading to hreg_store_msr() not restoring GPRs. So, do the same way as for POW bit, force clearing it. Signed-off-by: Christophe Leroy Cc: Cedric Le Goater Cc: Fabiano Rosas Reviewed-by: Cédric Le Goater Message-Id: <20220120103824.239573-1-christophe.leroy@csgroup.eu> Signed-off-by: Cédric Le Goater --- target/ppc/excp_helper.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c index bc646c67a0..980f62fd79 100644 --- a/target/ppc/excp_helper.c +++ b/target/ppc/excp_helper.c @@ -1164,6 +1164,10 @@ static void do_rfi(CPUPPCState *env, target_ulong nip, target_ulong msr) /* MSR:POW cannot be set by any form of rfi */ msr &= ~(1ULL << MSR_POW); + /* MSR:TGPR cannot be set by any form of rfi */ + if (env->flags & POWERPC_FLAG_TGPR) + msr &= ~(1ULL << MSR_TGPR); + #if defined(TARGET_PPC64) /* Switching to 32-bit ? Crop the nip */ if (!msr_is_64bit(env, msr)) { From e31ea5d89b613072e64b83f67e9763e9b149b87e Mon Sep 17 00:00:00 2001 From: Vitaly Cheptsov Date: Fri, 28 Jan 2022 13:15:02 +0100 Subject: [PATCH 03/41] target/ppc/mmu_common: Fix SRR1/MSR error code on Book-E MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Book-E architecture does not set the error code in 31:27 bits of SRR1, but instead uses these bits for custom fields such as GS (Guest Supervisor). Wrongly setting these fields will result in QEMU crashes when attempting to execute not executable code due to the attempts to use Guest Supervisor mode. Cc: "Cédric Le Goater" Cc: Daniel Henrique Barboza Cc: David Gibson Cc: Greg Kurz Cc: qemu-ppc@nongnu.org Cc: qemu-devel@nongnu.org Cc: qemu-stable@nongnu.org Signed-off-by: Vitaly Cheptsov Reviewed-by: Cédric Le Goater Message-Id: <20220121093107.15478-1-cheptsov@ispras.ru> Signed-off-by: Cédric Le Goater --- target/ppc/mmu_common.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c index 91270c1f17..6512ee031c 100644 --- a/target/ppc/mmu_common.c +++ b/target/ppc/mmu_common.c @@ -1367,22 +1367,34 @@ static bool ppc_jumbo_xlate(PowerPCCPU *cpu, vaddr eaddr, case -2: /* Access rights violation */ cs->exception_index = POWERPC_EXCP_ISI; - env->error_code = 0x08000000; + if ((env->mmu_model == POWERPC_MMU_BOOKE) || + (env->mmu_model == POWERPC_MMU_BOOKE206)) { + env->error_code = 0; + } else { + env->error_code = 0x08000000; + } break; case -3: /* No execute protection violation */ if ((env->mmu_model == POWERPC_MMU_BOOKE) || (env->mmu_model == POWERPC_MMU_BOOKE206)) { env->spr[SPR_BOOKE_ESR] = 0x00000000; + env->error_code = 0; + } else { + env->error_code = 0x10000000; } cs->exception_index = POWERPC_EXCP_ISI; - env->error_code = 0x10000000; break; case -4: /* Direct store exception */ /* No code fetch is allowed in direct-store areas */ cs->exception_index = POWERPC_EXCP_ISI; - env->error_code = 0x10000000; + if ((env->mmu_model == POWERPC_MMU_BOOKE) || + (env->mmu_model == POWERPC_MMU_BOOKE206)) { + env->error_code = 0; + } else { + env->error_code = 0x10000000; + } break; } } else { From 50c8e11ac0672b726a2b3e2217cb32dc8416299f Mon Sep 17 00:00:00 2001 From: Frederic Barrat Date: Fri, 28 Jan 2022 13:15:02 +0100 Subject: [PATCH 04/41] ppc/pnv: Fail DMA access if page permissions are not correct MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If an iommu page has wrong permissions, an error message is displayed, but the access is allowed, which is odd. This patch fixes it. Signed-off-by: Frederic Barrat Reviewed-by: Daniel Henrique Barboza Message-Id: <20220121152350.381685-1-fbarrat@linux.ibm.com> Signed-off-by: Cédric Le Goater --- hw/pci-host/pnv_phb3.c | 11 ++++++----- hw/pci-host/pnv_phb4.c | 11 ++++++----- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/hw/pci-host/pnv_phb3.c b/hw/pci-host/pnv_phb3.c index 7fb35dc031..a757f1a58e 100644 --- a/hw/pci-host/pnv_phb3.c +++ b/hw/pci-host/pnv_phb3.c @@ -816,18 +816,19 @@ static void pnv_phb3_translate_tve(PnvPhb3DMASpace *ds, hwaddr addr, } /* We exit the loop with TCE being the final TCE */ - tce_mask = ~((1ull << tce_shift) - 1); - tlb->iova = addr & tce_mask; - tlb->translated_addr = tce & tce_mask; - tlb->addr_mask = ~tce_mask; - tlb->perm = tce & 3; if ((is_write & !(tce & 2)) || ((!is_write) && !(tce & 1))) { phb3_error(phb, "TCE access fault at 0x%"PRIx64, taddr); phb3_error(phb, " xlate %"PRIx64":%c TVE=%"PRIx64, addr, is_write ? 'W' : 'R', tve); phb3_error(phb, " tta=%"PRIx64" lev=%d tts=%d tps=%d", tta, lev, tts, tps); + return; } + tce_mask = ~((1ull << tce_shift) - 1); + tlb->iova = addr & tce_mask; + tlb->translated_addr = tce & tce_mask; + tlb->addr_mask = ~tce_mask; + tlb->perm = tce & 3; } } diff --git a/hw/pci-host/pnv_phb4.c b/hw/pci-host/pnv_phb4.c index a78add75b0..ee56377c02 100644 --- a/hw/pci-host/pnv_phb4.c +++ b/hw/pci-host/pnv_phb4.c @@ -1291,18 +1291,19 @@ static void pnv_phb4_translate_tve(PnvPhb4DMASpace *ds, hwaddr addr, } /* We exit the loop with TCE being the final TCE */ - tce_mask = ~((1ull << tce_shift) - 1); - tlb->iova = addr & tce_mask; - tlb->translated_addr = tce & tce_mask; - tlb->addr_mask = ~tce_mask; - tlb->perm = tce & 3; if ((is_write & !(tce & 2)) || ((!is_write) && !(tce & 1))) { phb_error(ds->phb, "TCE access fault at 0x%"PRIx64, taddr); phb_error(ds->phb, " xlate %"PRIx64":%c TVE=%"PRIx64, addr, is_write ? 'W' : 'R', tve); phb_error(ds->phb, " tta=%"PRIx64" lev=%d tts=%d tps=%d", tta, lev, tts, tps); + return; } + tce_mask = ~((1ull << tce_shift) - 1); + tlb->iova = addr & tce_mask; + tlb->translated_addr = tce & tce_mask; + tlb->addr_mask = ~tce_mask; + tlb->perm = tce & 3; } } From 83d2bea68a778b98ecbf9472be6f1ed8031719ac Mon Sep 17 00:00:00 2001 From: Daniel Henrique Barboza Date: Fri, 28 Jan 2022 13:15:02 +0100 Subject: [PATCH 05/41] ppc/pnv: use a do-while() loop in pnv_phb3_translate_tve() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The 'taddr' variable is left unintialized, being set only inside the "while ((lev--) >= 0)" loop where we get the TCE address. The 'lev' var is an int32_t that is being initiliazed by the GETFIELD() macro, which returns an uint64_t. For a human reader this means that 'lev' will always be positive or zero. But some compilers may beg to differ. 'lev' being an int32_t can in theory be set as negative, and the "while ((lev--) >= 0)" loop might never be reached, and 'taddr' will be left unitialized. This can cause phb3_error() to use 'taddr' uninitialized down below: if ((is_write & !(tce & 2)) || ((!is_write) && !(tce & 1))) { phb3_error(phb, "TCE access fault at 0x%"PRIx64, taddr); A quick way of fixing it is to use a do/while() loop. This will keep the same semanting as the existing while() loop does and the compiler will understand that 'taddr' will be initialized at least once. Suggested-by: Matheus K. Ferst Resolves: https://gitlab.com/qemu-project/qemu/-/issues/573 Signed-off-by: Daniel Henrique Barboza Message-Id: <20220127122234.842145-2-danielhb413@gmail.com> Signed-off-by: Cédric Le Goater --- hw/pci-host/pnv_phb3.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/hw/pci-host/pnv_phb3.c b/hw/pci-host/pnv_phb3.c index a757f1a58e..aafd46b635 100644 --- a/hw/pci-host/pnv_phb3.c +++ b/hw/pci-host/pnv_phb3.c @@ -792,7 +792,9 @@ static void pnv_phb3_translate_tve(PnvPhb3DMASpace *ds, hwaddr addr, sh = tbl_shift * lev + tce_shift; /* TODO: Multi-level untested */ - while ((lev--) >= 0) { + do { + lev--; + /* Grab the TCE address */ taddr = base | (((addr >> sh) & ((1ul << tbl_shift) - 1)) << 3); if (dma_memory_read(&address_space_memory, taddr, &tce, @@ -813,7 +815,7 @@ static void pnv_phb3_translate_tve(PnvPhb3DMASpace *ds, hwaddr addr, } sh -= tbl_shift; base = tce & ~0xfffull; - } + } while (lev >= 0); /* We exit the loop with TCE being the final TCE */ if ((is_write & !(tce & 2)) || ((!is_write) && !(tce & 1))) { From 799c179ed844b01542e729405c0bf5ef4cd294dc Mon Sep 17 00:00:00 2001 From: Daniel Henrique Barboza Date: Fri, 28 Jan 2022 13:15:02 +0100 Subject: [PATCH 06/41] ppc/pnv: use a do-while() loop in pnv_phb4_translate_tve() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit pnv_phb4_translate_tve() is quite similar to pnv_phb3_translate_tve(), and that includes the fact that 'taddr' can be considered uninitialized when throwing the "TCE access fault" error because, in theory, the loop that sets 'taddr' can be skippable due to 'lev' being an signed int. No one complained about this specific case yet, but since we took the time to handle the same situtation in pnv_phb3_translate_tve(), let's replicate it here as well. Signed-off-by: Daniel Henrique Barboza Reviewed-by: Matheus Ferst Message-Id: <20220127122234.842145-3-danielhb413@gmail.com> Signed-off-by: Cédric Le Goater --- hw/pci-host/pnv_phb4.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/hw/pci-host/pnv_phb4.c b/hw/pci-host/pnv_phb4.c index ee56377c02..e91249ef64 100644 --- a/hw/pci-host/pnv_phb4.c +++ b/hw/pci-host/pnv_phb4.c @@ -1267,7 +1267,9 @@ static void pnv_phb4_translate_tve(PnvPhb4DMASpace *ds, hwaddr addr, /* TODO: Limit to support IO page sizes */ /* TODO: Multi-level untested */ - while ((lev--) >= 0) { + do { + lev--; + /* Grab the TCE address */ taddr = base | (((addr >> sh) & ((1ul << tbl_shift) - 1)) << 3); if (dma_memory_read(&address_space_memory, taddr, &tce, @@ -1288,7 +1290,7 @@ static void pnv_phb4_translate_tve(PnvPhb4DMASpace *ds, hwaddr addr, } sh -= tbl_shift; base = tce & ~0xfffull; - } + } while (lev >= 0); /* We exit the loop with TCE being the final TCE */ if ((is_write & !(tce & 2)) || ((!is_write) && !(tce & 1))) { From e9711c6149fc087f5cadd6f60e9ffa5541e421af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= Date: Fri, 28 Jan 2022 13:15:02 +0100 Subject: [PATCH 07/41] ppc/xive: check return value of ldq_be_dma() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The ldq_be_dma() routine was recently changed to return a result of the transaction. Use it when loading the virtual structure descriptors in the XIVE PowerNV model. Cc: Philippe Mathieu-Daudé Signed-off-by: Cédric Le Goater Message-Id: <20220124081635.3672439-1-clg@kaod.org> Signed-off-by: Cédric Le Goater --- hw/intc/pnv_xive.c | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/hw/intc/pnv_xive.c b/hw/intc/pnv_xive.c index bb207514f2..621b20a03f 100644 --- a/hw/intc/pnv_xive.c +++ b/hw/intc/pnv_xive.c @@ -172,7 +172,12 @@ static uint64_t pnv_xive_vst_addr_indirect(PnvXive *xive, uint32_t type, /* Get the page size of the indirect table. */ vsd_addr = vsd & VSD_ADDRESS_MASK; - ldq_be_dma(&address_space_memory, vsd_addr, &vsd, MEMTXATTRS_UNSPECIFIED); + if (ldq_be_dma(&address_space_memory, vsd_addr, &vsd, + MEMTXATTRS_UNSPECIFIED)) { + xive_error(xive, "VST: failed to access %s entry %x @0x%" PRIx64, + info->name, idx, vsd_addr); + return 0; + } if (!(vsd & VSD_ADDRESS_MASK)) { #ifdef XIVE_DEBUG @@ -195,8 +200,12 @@ static uint64_t pnv_xive_vst_addr_indirect(PnvXive *xive, uint32_t type, /* Load the VSD we are looking for, if not already done */ if (vsd_idx) { vsd_addr = vsd_addr + vsd_idx * XIVE_VSD_SIZE; - ldq_be_dma(&address_space_memory, vsd_addr, &vsd, - MEMTXATTRS_UNSPECIFIED); + if (ldq_be_dma(&address_space_memory, vsd_addr, &vsd, + MEMTXATTRS_UNSPECIFIED)) { + xive_error(xive, "VST: failed to access %s entry %x @0x%" + PRIx64, info->name, vsd_idx, vsd_addr); + return 0; + } if (!(vsd & VSD_ADDRESS_MASK)) { #ifdef XIVE_DEBUG @@ -543,7 +552,12 @@ static uint64_t pnv_xive_vst_per_subpage(PnvXive *xive, uint32_t type) /* Get the page size of the indirect table. */ vsd_addr = vsd & VSD_ADDRESS_MASK; - ldq_be_dma(&address_space_memory, vsd_addr, &vsd, MEMTXATTRS_UNSPECIFIED); + if (ldq_be_dma(&address_space_memory, vsd_addr, &vsd, + MEMTXATTRS_UNSPECIFIED)) { + xive_error(xive, "VST: failed to access %s entry @0x%" PRIx64, + info->name, vsd_addr); + return 0; + } if (!(vsd & VSD_ADDRESS_MASK)) { #ifdef XIVE_DEBUG From 0c0aac01c49cc159a37841b1954b1938f0582fb4 Mon Sep 17 00:00:00 2001 From: Daniel Henrique Barboza Date: Fri, 28 Jan 2022 13:15:02 +0100 Subject: [PATCH 08/41] target/ppc: fix 'skip KVM' cond in cpu_interrupt_exittb() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit cpu_interrupt_exittb() was introduced by commit 044897ef4a22 ("target/ppc: Fix system lockups caused by interrupt_request state corruption") as a way to wrap cpu_interrupt() helper in BQL. After that, commit 6d38666a8931 ("ppc: Ignore the CPU_INTERRUPT_EXITTB interrupt with KVM") added a condition to skip this interrupt if we're running with KVM. Problem is that the change made by the above commit, testing for !kvm_enabled() at the start of cpu_interrupt_exittb(): static inline void cpu_interrupt_exittb(CPUState *cs) { if (!kvm_enabled()) { return; } (... do cpu_interrupt(cs, CPU_INTERRUPT_EXITTB) ...) is doing the opposite of what it intended to do. This will return immediately if not kvm_enabled(), i.e. it's a emulated CPU, and if kvm_enabled() it will proceed to fire CPU_INTERRUPT_EXITTB. Fix the 'skip KVM' condition so the function is a no-op when kvm_enabled(). CC: Greg Kurz Resolves: https://gitlab.com/qemu-project/qemu/-/issues/809 Fixes: 6d38666a8931 ("ppc: Ignore the CPU_INTERRUPT_EXITTB interrupt with KVM") Signed-off-by: Daniel Henrique Barboza Reviewed-by: Fabiano Rosas Reviewed-by: Greg Kurz Message-Id: <20220121160841.9102-1-danielhb413@gmail.com> Signed-off-by: Cédric Le Goater --- target/ppc/helper_regs.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/target/ppc/helper_regs.c b/target/ppc/helper_regs.c index 8671b7bb69..7dca585ddd 100644 --- a/target/ppc/helper_regs.c +++ b/target/ppc/helper_regs.c @@ -201,7 +201,11 @@ void cpu_get_tb_cpu_state(CPUPPCState *env, target_ulong *pc, void cpu_interrupt_exittb(CPUState *cs) { - if (!kvm_enabled()) { + /* + * We don't need to worry about translation blocks + * when running with KVM. + */ + if (kvm_enabled()) { return; } From 1977434bbfbdd97d28c2fea071ea00bf4ecd0079 Mon Sep 17 00:00:00 2001 From: Daniel Henrique Barboza Date: Fri, 28 Jan 2022 13:15:02 +0100 Subject: [PATCH 09/41] spapr.c: check bus != NULL in spapr_get_fw_dev_path() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit spapr_get_fw_dev_path() is an impl of FWPathProviderClass::get_dev_path(). This interface is used by hw/core/qdev-fw.c via fw_path_provider_try_get_dev_path() in two functions: - static char *qdev_get_fw_dev_path_from_handler(), which is used only in qdev_get_fw_dev_path_helper() and it's guarded by "if (dev && dev->parent_bus)"; - char *qdev_get_own_fw_dev_path_from_handler(), which is used in softmmu/bootdevice.c in get_boot_device_path() like this: if (dev) { d = qdev_get_own_fw_dev_path_from_handler(dev->parent_bus, dev); This means that, when called via softmmu/bootdevice.c, there's no check of 'dev->parent_bus' being not NULL. The result is that the "BusState *bus" arg of spapr_get_fw_dev_path() can potentially be NULL and if, at the same time, "SCSIDevice *d" is not NULL, we'll hit this line: void *spapr = CAST(void, bus->parent, "spapr-vscsi"); And we'll SIGINT because 'bus' is NULL and we're accessing bus->parent. Adding a simple 'bus != NULL' check to guard the instances where we access 'bus->parent' can avoid this altogether. Signed-off-by: Daniel Henrique Barboza Reviewed-by: Cédric Le Goater Message-Id: <20220121213852.30243-1-danielhb413@gmail.com> Signed-off-by: Cédric Le Goater --- hw/ppc/spapr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index 72f5dce751..3d6ec309dd 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -3053,7 +3053,7 @@ static char *spapr_get_fw_dev_path(FWPathProvider *p, BusState *bus, VHostSCSICommon *vsc = CAST(VHostSCSICommon, dev, TYPE_VHOST_SCSI_COMMON); PCIDevice *pcidev = CAST(PCIDevice, dev, TYPE_PCI_DEVICE); - if (d) { + if (d && bus) { void *spapr = CAST(void, bus->parent, "spapr-vscsi"); VirtIOSCSI *virtio = CAST(VirtIOSCSI, bus->parent, TYPE_VIRTIO_SCSI); USBDevice *usb = CAST(USBDevice, bus->parent, TYPE_USB_DEVICE); From 63f38cc3d228a0886b544e9a069b922b4416d29d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= Date: Fri, 28 Jan 2022 13:15:03 +0100 Subject: [PATCH 10/41] target/ppc: Fix test on mmu_model in hreg_compute_hflags_value() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit POWERPC_MMU_BOOKE is not a mask and should not be tested with a bitwise AND operator. It went unnoticed because it only impacts the 601 CPU implementation for which we don't have a known firmware image. Signed-off-by: Cédric Le Goater Reviewed-by: David Gibson Message-Id: <20220124081609.3672341-1-clg@kaod.org> Signed-off-by: Cédric Le Goater --- target/ppc/helper_regs.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/target/ppc/helper_regs.c b/target/ppc/helper_regs.c index 7dca585ddd..5b12cb03c9 100644 --- a/target/ppc/helper_regs.c +++ b/target/ppc/helper_regs.c @@ -156,7 +156,8 @@ static uint32_t hreg_compute_hflags_value(CPUPPCState *env) */ unsigned immu_idx, dmmu_idx; dmmu_idx = msr & (1 << MSR_PR) ? 0 : 1; - if (env->mmu_model & POWERPC_MMU_BOOKE) { + if (env->mmu_model == POWERPC_MMU_BOOKE || + env->mmu_model == POWERPC_MMU_BOOKE206) { dmmu_idx |= msr & (1 << MSR_GS) ? 4 : 0; immu_idx = dmmu_idx; immu_idx |= msr & (1 << MSR_IS) ? 2 : 0; @@ -237,7 +238,8 @@ int hreg_store_msr(CPUPPCState *env, target_ulong value, int alter_hv) ((value >> MSR_DR) & 1) != msr_dr) { cpu_interrupt_exittb(cs); } - if ((env->mmu_model & POWERPC_MMU_BOOKE) && + if ((env->mmu_model == POWERPC_MMU_BOOKE || + env->mmu_model == POWERPC_MMU_BOOKE206) && ((value >> MSR_GS) & 1) != msr_gs) { cpu_interrupt_exittb(cs); } From a01b64cee77061118b8cdaefeacd5440ec26107c Mon Sep 17 00:00:00 2001 From: Fabiano Rosas Date: Fri, 28 Jan 2022 13:15:03 +0100 Subject: [PATCH 11/41] target/ppc: Put do_rfi under a TCG-only block MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The --disable-tcg build broke when do_rfi stopped being inlined. Fixes: 62e79ef914 ("target/ppc: Remove static inline") Signed-off-by: Fabiano Rosas Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Daniel Henrique Barboza Message-Id: <20220124191547.1008391-1-farosas@linux.ibm.com> Signed-off-by: Cédric Le Goater --- target/ppc/excp_helper.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c index 980f62fd79..883fb13cfe 100644 --- a/target/ppc/excp_helper.c +++ b/target/ppc/excp_helper.c @@ -1155,7 +1155,6 @@ void helper_pminsn(CPUPPCState *env, powerpc_pm_insn_t insn) (env->spr[SPR_PSSCR] & PSSCR_EC); } #endif /* defined(TARGET_PPC64) */ -#endif /* CONFIG_TCG */ static void do_rfi(CPUPPCState *env, target_ulong nip, target_ulong msr) { @@ -1192,7 +1191,6 @@ static void do_rfi(CPUPPCState *env, target_ulong nip, target_ulong msr) check_tlb_flush(env, false); } -#ifdef CONFIG_TCG void helper_rfi(CPUPPCState *env) { do_rfi(env, env->spr[SPR_SRR0], env->spr[SPR_SRR1] & 0xfffffffful); From dc10da64e1f704bec8ed66f6a402d22589a3c4f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Fri, 28 Jan 2022 13:15:03 +0100 Subject: [PATCH 12/41] hw/ppc/vof: Add missing includes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit vof.h requires "qom/object.h" for DECLARE_CLASS_CHECKERS(), "exec/memory.h" for address_space_read/write(), "exec/address-spaces.h" for address_space_memory and more importantly "cpu.h" for target_ulong. vof.c doesn't need "exec/ram_addr.h". Signed-off-by: Philippe Mathieu-Daudé Message-Id: <20220122003104.84391-1-f4bug@amsat.org> Signed-off-by: Cédric Le Goater --- hw/ppc/vof.c | 1 - include/hw/ppc/vof.h | 5 +++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/hw/ppc/vof.c b/hw/ppc/vof.c index 73adc44ec2..2b63a62875 100644 --- a/hw/ppc/vof.c +++ b/hw/ppc/vof.c @@ -16,7 +16,6 @@ #include "qemu/units.h" #include "qemu/log.h" #include "qapi/error.h" -#include "exec/ram_addr.h" #include "exec/address-spaces.h" #include "hw/ppc/vof.h" #include "hw/ppc/fdt.h" diff --git a/include/hw/ppc/vof.h b/include/hw/ppc/vof.h index 97fdef758b..f8c0effcaf 100644 --- a/include/hw/ppc/vof.h +++ b/include/hw/ppc/vof.h @@ -6,6 +6,11 @@ #ifndef HW_VOF_H #define HW_VOF_H +#include "qom/object.h" +#include "exec/address-spaces.h" +#include "exec/memory.h" +#include "cpu.h" + typedef struct Vof { uint64_t top_addr; /* copied from rma_size */ GArray *claimed; /* array of SpaprOfClaimed */ From 47822486f5e7d6dad8d9a2381d127a831a3c5c11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= Date: Fri, 28 Jan 2022 13:15:03 +0100 Subject: [PATCH 13/41] ppc/ppc405: Fix TLB flushing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit cd0c6f473532 did not take into account 405 CPUs when adding support to batching of TCG tlb flushes. Set the TLB_NEED_LOCAL_FLUSH flag when the SPR_40x_PID is set or a TLB updated. Cc: Thomas Huth Cc: Christophe Leroy Cc: Fabiano Rosas Reviewed-by: Fabiano Rosas Fixes: cd0c6f473532 ("ppc: Do some batching of TCG tlb flushes") Signed-off-by: Cédric Le Goater Message-Id: <20220113180352.1234512-1-clg@kaod.org> Signed-off-by: Cédric Le Goater --- target/ppc/helper.h | 1 + target/ppc/mmu_helper.c | 12 +++++++++++- target/ppc/translate.c | 2 +- 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/target/ppc/helper.h b/target/ppc/helper.h index d318837ea5..bdbbd5e1d9 100644 --- a/target/ppc/helper.h +++ b/target/ppc/helper.h @@ -707,6 +707,7 @@ 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_pid, 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/mmu_helper.c b/target/ppc/mmu_helper.c index 59df6952ae..a2a52a12c3 100644 --- a/target/ppc/mmu_helper.c +++ b/target/ppc/mmu_helper.c @@ -664,6 +664,14 @@ static inline int booke_page_size_to_tlb(target_ulong page_size) #define PPC4XX_TLBLO_ATTR_MASK 0x000000FF #define PPC4XX_TLBLO_RPN_MASK 0xFFFFFC00 +void helper_store_40x_pid(CPUPPCState *env, target_ulong val) +{ + if (env->spr[SPR_40x_PID] != val) { + env->spr[SPR_40x_PID] = val; + env->tlb_need_flush |= TLB_NEED_LOCAL_FLUSH; + } +} + target_ulong helper_4xx_tlbre_hi(CPUPPCState *env, target_ulong entry) { ppcemb_tlb_t *tlb; @@ -681,7 +689,7 @@ target_ulong helper_4xx_tlbre_hi(CPUPPCState *env, target_ulong entry) size = PPC4XX_TLBHI_SIZE_DEFAULT; } ret |= size << PPC4XX_TLBHI_SIZE_SHIFT; - env->spr[SPR_40x_PID] = tlb->PID; + helper_store_40x_pid(env, tlb->PID); return ret; } @@ -794,6 +802,8 @@ void helper_4xx_tlbwe_lo(CPUPPCState *env, target_ulong entry, tlb->prot & PAGE_WRITE ? 'w' : '-', tlb->prot & PAGE_EXEC ? 'x' : '-', tlb->prot & PAGE_VALID ? 'v' : '-', (int)tlb->PID); + + env->tlb_need_flush |= TLB_NEED_LOCAL_FLUSH; } target_ulong helper_4xx_tlbsx(CPUPPCState *env, target_ulong address) diff --git a/target/ppc/translate.c b/target/ppc/translate.c index 9d2adc0cae..d61c6f0e8f 100644 --- a/target/ppc/translate.c +++ b/target/ppc/translate.c @@ -894,7 +894,7 @@ 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); + gen_helper_store_40x_pid(cpu_env, t0); tcg_temp_free(t0); } From 645d843ca55f0a7aa9be3ef19694d5a44b002f6e Mon Sep 17 00:00:00 2001 From: Fabiano Rosas Date: Fri, 28 Jan 2022 13:15:03 +0100 Subject: [PATCH 14/41] target/ppc: 405: Rename MSR_POW to MSR_WE MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bit 13 is the Wait State Enable bit. Give it its proper name. As far as I can see we don't do anything with MSR_POW for the 405, so this change has no effect. Suggested-by: David Gibson Signed-off-by: Fabiano Rosas Reviewed-by: Cédric Le Goater Message-Id: <20220118184448.852996-2-farosas@linux.ibm.com> Signed-off-by: Cédric Le Goater --- target/ppc/cpu.h | 1 + target/ppc/cpu_init.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h index 2560b70c5f..66e13075c3 100644 --- a/target/ppc/cpu.h +++ b/target/ppc/cpu.h @@ -327,6 +327,7 @@ typedef enum { #define MSR_S 22 /* Secure state */ #define MSR_KEY 19 /* key bit on 603e */ #define MSR_POW 18 /* Power management */ +#define MSR_WE 18 /* Wait State Enable on 405 */ #define MSR_TGPR 17 /* TGPR usage on 602/603 x */ #define MSR_CE 17 /* Critical interrupt enable on embedded PowerPC x */ #define MSR_ILE 16 /* Interrupt little-endian mode */ diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c index e30e86fe9d..e63705b1c6 100644 --- a/target/ppc/cpu_init.c +++ b/target/ppc/cpu_init.c @@ -2535,7 +2535,7 @@ POWERPC_FAMILY(405)(ObjectClass *oc, void *data) PPC_MEM_SYNC | PPC_MEM_EIEIO | PPC_40x_TLB | PPC_MEM_TLBIA | PPC_MEM_TLBSYNC | PPC_4xx_COMMON | PPC_405_MAC | PPC_40x_EXCP; - pcc->msr_mask = (1ull << MSR_POW) | + pcc->msr_mask = (1ull << MSR_WE) | (1ull << MSR_CE) | (1ull << MSR_EE) | (1ull << MSR_PR) | From 301e5d48b15d2846cabe0f5c7600860b35c58c12 Mon Sep 17 00:00:00 2001 From: Fabiano Rosas Date: Fri, 28 Jan 2022 13:15:03 +0100 Subject: [PATCH 15/41] target/ppc: 405: Add missing MSR_ME bit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The 405 MSR has the Machine Check Enable bit. We're making use of it when dispatching Machine Check, so add the bit to the msr_mask. Signed-off-by: Fabiano Rosas Reviewed-by: Cédric Le Goater Message-Id: <20220118184448.852996-3-farosas@linux.ibm.com> Signed-off-by: Cédric Le Goater --- target/ppc/cpu_init.c | 1 + 1 file changed, 1 insertion(+) diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c index e63705b1c6..23a13036b2 100644 --- a/target/ppc/cpu_init.c +++ b/target/ppc/cpu_init.c @@ -2540,6 +2540,7 @@ POWERPC_FAMILY(405)(ObjectClass *oc, void *data) (1ull << MSR_EE) | (1ull << MSR_PR) | (1ull << MSR_FP) | + (1ull << MSR_ME) | (1ull << MSR_DWE) | (1ull << MSR_DE) | (1ull << MSR_IR) | From e808c2ed07f25b93ed796dfe266a30f2236ad69a Mon Sep 17 00:00:00 2001 From: Fabiano Rosas Date: Fri, 28 Jan 2022 13:15:04 +0100 Subject: [PATCH 16/41] target/ppc: Introduce powerpc_excp_40x MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Introduce a new powerpc_excp function specific for 40x CPUs. This commit copies powerpc_excp_legacy verbatim so the next one has a clean diff. Signed-off-by: Fabiano Rosas Reviewed-by: Cédric Le Goater Reviewed-by: Richard Henderson Message-Id: <20220118184448.852996-4-farosas@linux.ibm.com> Signed-off-by: Cédric Le Goater --- target/ppc/excp_helper.c | 474 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 474 insertions(+) diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c index 883fb13cfe..5dc948aec2 100644 --- a/target/ppc/excp_helper.c +++ b/target/ppc/excp_helper.c @@ -392,6 +392,477 @@ static void powerpc_set_excp_state(PowerPCCPU *cpu, check_tlb_flush(env, false); } +static void powerpc_excp_40x(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; + + 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); + + /* new srr1 value excluding must-be-zero bits */ + if (excp_model == POWERPC_EXCP_BOOKE) { + msr = env->msr; + } else { + msr = env->msr & ~0x783f0000ULL; + } + + /* + * new interrupt handler msr preserves existing HV and ME unless + * explicitly overriden + */ + new_msr = env->msr & (((target_ulong)1 << MSR_ME) | MSR_HVB); + + /* target registers */ + srr0 = SPR_SRR0; + srr1 = SPR_SRR1; + + /* + * check for special resume at 0x100 from doze/nap/sleep/winkle on + * P7/P8/P9 + */ + if (env->resume_as_sreset) { + excp = powerpc_reset_wakeup(cs, env, excp, &msr); + } + + /* + * Hypervisor emulation assistance interrupt only exists on server + * arch 2.05 server or later. We also don't want to generate it if + * we don't have HVB in msr_mask (PAPR mode). + */ + if (excp == POWERPC_EXCP_HV_EMU +#if defined(TARGET_PPC64) + && !(mmu_is_64bit(env->mmu_model) && (env->msr_mask & MSR_HVB)) +#endif /* defined(TARGET_PPC64) */ + + ) { + excp = POWERPC_EXCP_PROGRAM; + } + +#ifdef TARGET_PPC64 + /* + * SPEU and VPU share the same IVOR but they exist in different + * processors. SPEU is e500v1/2 only and VPU is e6500 only. + */ + if (excp_model == POWERPC_EXCP_BOOKE && excp == POWERPC_EXCP_VPU) { + excp = POWERPC_EXCP_SPEU; + } +#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) { + case POWERPC_EXCP_40x: + srr0 = SPR_40x_SRR2; + srr1 = SPR_40x_SRR3; + break; + case POWERPC_EXCP_BOOKE: + srr0 = SPR_BOOKE_CSRR0; + srr1 = SPR_BOOKE_CSRR1; + break; + case POWERPC_EXCP_G2: + break; + default: + goto excp_invalid; + } + break; + case POWERPC_EXCP_MCHECK: /* Machine check exception */ + if (msr_me == 0) { + /* + * Machine check exception is not enabled. Enter + * checkstop state. + */ + fprintf(stderr, "Machine check while not allowed. " + "Entering checkstop state\n"); + if (qemu_log_separate()) { + qemu_log("Machine check while not allowed. " + "Entering checkstop state\n"); + } + cs->halted = 1; + cpu_interrupt_exittb(cs); + } + if (env->msr_mask & MSR_HVB) { + /* + * ISA specifies HV, but can be delivered to guest with HV + * clear (e.g., see FWNMI in PAPR). + */ + new_msr |= (target_ulong)MSR_HVB; + } + + /* machine check exceptions don't have ME set */ + new_msr &= ~((target_ulong)1 << MSR_ME); + + /* XXX: should also have something loaded in DAR / DSISR */ + switch (excp_model) { + case POWERPC_EXCP_40x: + srr0 = SPR_40x_SRR2; + srr1 = SPR_40x_SRR3; + break; + case POWERPC_EXCP_BOOKE: + /* FIXME: choose one or the other based on CPU type */ + srr0 = SPR_BOOKE_MCSRR0; + srr1 = SPR_BOOKE_MCSRR1; + + env->spr[SPR_BOOKE_CSRR0] = env->nip; + env->spr[SPR_BOOKE_CSRR1] = msr; + break; + default: + break; + } + break; + case POWERPC_EXCP_DSI: /* Data storage exception */ + trace_ppc_excp_dsi(env->spr[SPR_DSISR], env->spr[SPR_DAR]); + break; + case POWERPC_EXCP_ISI: /* Instruction storage exception */ + trace_ppc_excp_isi(msr, env->nip); + msr |= env->error_code; + break; + case POWERPC_EXCP_EXTERNAL: /* External input */ + { + bool lpes0; + + cs = CPU(cpu); + + /* + * Exception targeting modifiers + * + * LPES0 is supported on POWER7/8/9 + * LPES1 is not supported (old iSeries mode) + * + * On anything else, we behave as if LPES0 is 1 + * (externals don't alter MSR:HV) + */ +#if defined(TARGET_PPC64) + if (excp_model == POWERPC_EXCP_POWER7 || + excp_model == POWERPC_EXCP_POWER8 || + excp_model == POWERPC_EXCP_POWER9 || + excp_model == POWERPC_EXCP_POWER10) { + lpes0 = !!(env->spr[SPR_LPCR] & LPCR_LPES0); + } else +#endif /* defined(TARGET_PPC64) */ + { + lpes0 = true; + } + + if (!lpes0) { + new_msr |= (target_ulong)MSR_HVB; + new_msr |= env->msr & ((target_ulong)1 << MSR_RI); + srr0 = SPR_HSRR0; + srr1 = SPR_HSRR1; + } + if (env->mpic_proxy) { + /* IACK the IRQ on delivery */ + env->spr[SPR_BOOKE_EPR] = ldl_phys(cs->as, env->mpic_iack); + } + break; + } + case POWERPC_EXCP_ALIGN: /* Alignment exception */ + /* Get rS/rD and rA from faulting opcode */ + /* + * Note: the opcode fields will not be set properly for a + * direct store load/store, but nobody cares as nobody + * actually uses direct store segments. + */ + env->spr[SPR_DSISR] |= (env->error_code & 0x03FF0000) >> 16; + break; + case POWERPC_EXCP_PROGRAM: /* Program exception */ + switch (env->error_code & ~0xF) { + case POWERPC_EXCP_FP: + if ((msr_fe0 == 0 && msr_fe1 == 0) || msr_fp == 0) { + trace_ppc_excp_fp_ignore(); + cs->exception_index = POWERPC_EXCP_NONE; + env->error_code = 0; + return; + } + + /* + * FP exceptions always have NIP pointing to the faulting + * instruction, so always use store_next and claim we are + * precise in the MSR. + */ + msr |= 0x00100000; + env->spr[SPR_BOOKE_ESR] = ESR_FP; + break; + case POWERPC_EXCP_INVAL: + trace_ppc_excp_inval(env->nip); + msr |= 0x00080000; + env->spr[SPR_BOOKE_ESR] = ESR_PIL; + break; + case POWERPC_EXCP_PRIV: + msr |= 0x00040000; + env->spr[SPR_BOOKE_ESR] = ESR_PPR; + break; + case POWERPC_EXCP_TRAP: + msr |= 0x00020000; + env->spr[SPR_BOOKE_ESR] = ESR_PTR; + break; + default: + /* Should never occur */ + cpu_abort(cs, "Invalid program exception %d. Aborting\n", + env->error_code); + break; + } + break; + case POWERPC_EXCP_SYSCALL: /* System call exception */ + lev = env->error_code; + + if ((lev == 1) && cpu->vhyp) { + dump_hcall(env); + } else { + dump_syscall(env); + } + + /* + * We need to correct the NIP which in this case is supposed + * to point to the next instruction + */ + env->nip += 4; + + /* "PAPR mode" built-in hypercall emulation */ + if ((lev == 1) && cpu->vhyp) { + PPCVirtualHypervisorClass *vhc = + PPC_VIRTUAL_HYPERVISOR_GET_CLASS(cpu->vhyp); + vhc->hypercall(cpu->vhyp, cpu); + return; + } + if (lev == 1) { + new_msr |= (target_ulong)MSR_HVB; + } + break; + case POWERPC_EXCP_SYSCALL_VECTORED: /* scv exception */ + lev = env->error_code; + dump_syscall(env); + 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 */ + case POWERPC_EXCP_DECR: /* Decrementer exception */ + break; + case POWERPC_EXCP_FIT: /* Fixed-interval timer interrupt */ + /* FIT on 4xx */ + trace_ppc_excp_print("FIT"); + break; + case POWERPC_EXCP_WDT: /* Watchdog timer interrupt */ + trace_ppc_excp_print("WDT"); + switch (excp_model) { + case POWERPC_EXCP_BOOKE: + srr0 = SPR_BOOKE_CSRR0; + srr1 = SPR_BOOKE_CSRR1; + break; + default: + break; + } + break; + case POWERPC_EXCP_DTLB: /* Data TLB error */ + case POWERPC_EXCP_ITLB: /* Instruction TLB error */ + break; + case POWERPC_EXCP_DEBUG: /* Debug interrupt */ + if (env->flags & POWERPC_FLAG_DE) { + /* FIXME: choose one or the other based on CPU type */ + srr0 = SPR_BOOKE_DSRR0; + srr1 = SPR_BOOKE_DSRR1; + + 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"); + } + break; + case POWERPC_EXCP_SPEU: /* SPE/embedded floating-point unavailable/VPU */ + env->spr[SPR_BOOKE_ESR] = ESR_SPV; + break; + case POWERPC_EXCP_DOORI: /* Embedded doorbell interrupt */ + break; + case POWERPC_EXCP_DOORCI: /* Embedded doorbell critical interrupt */ + srr0 = SPR_BOOKE_CSRR0; + srr1 = SPR_BOOKE_CSRR1; + break; + case POWERPC_EXCP_RESET: /* System reset exception */ + /* A power-saving exception sets ME, otherwise it is unchanged */ + if (msr_pow) { + /* indicate that we resumed from power save mode */ + msr |= 0x10000; + new_msr |= ((target_ulong)1 << MSR_ME); + } + if (env->msr_mask & MSR_HVB) { + /* + * ISA specifies HV, but can be delivered to guest with HV + * clear (e.g., see FWNMI in PAPR, NMI injection in QEMU). + */ + new_msr |= (target_ulong)MSR_HVB; + } else { + if (msr_pow) { + cpu_abort(cs, "Trying to deliver power-saving system reset " + "exception %d with no HV support\n", excp); + } + } + break; + case POWERPC_EXCP_DSEG: /* Data segment exception */ + case POWERPC_EXCP_ISEG: /* Instruction segment exception */ + case POWERPC_EXCP_TRACE: /* Trace exception */ + break; + case POWERPC_EXCP_HISI: /* Hypervisor instruction storage exception */ + msr |= env->error_code; + /* fall through */ + case POWERPC_EXCP_HDECR: /* Hypervisor decrementer exception */ + case POWERPC_EXCP_HDSI: /* Hypervisor data storage exception */ + case POWERPC_EXCP_HDSEG: /* Hypervisor data segment exception */ + case POWERPC_EXCP_HISEG: /* Hypervisor instruction segment exception */ + case POWERPC_EXCP_SDOOR_HV: /* Hypervisor Doorbell interrupt */ + case POWERPC_EXCP_HV_EMU: + case POWERPC_EXCP_HVIRT: /* Hypervisor virtualization */ + srr0 = SPR_HSRR0; + srr1 = SPR_HSRR1; + new_msr |= (target_ulong)MSR_HVB; + new_msr |= env->msr & ((target_ulong)1 << MSR_RI); + break; + case POWERPC_EXCP_VPU: /* Vector unavailable exception */ + case POWERPC_EXCP_VSXU: /* VSX unavailable exception */ + case POWERPC_EXCP_FU: /* Facility unavailable exception */ +#ifdef TARGET_PPC64 + env->spr[SPR_FSCR] |= ((target_ulong)env->error_code << 56); +#endif + break; + case POWERPC_EXCP_HV_FU: /* Hypervisor Facility Unavailable Exception */ +#ifdef TARGET_PPC64 + env->spr[SPR_HFSCR] |= ((target_ulong)env->error_code << FSCR_IC_POS); + srr0 = SPR_HSRR0; + srr1 = SPR_HSRR1; + new_msr |= (target_ulong)MSR_HVB; + new_msr |= env->msr & ((target_ulong)1 << MSR_RI); +#endif + break; + case POWERPC_EXCP_PIT: /* Programmable interval timer interrupt */ + trace_ppc_excp_print("PIT"); + break; + case POWERPC_EXCP_IFTLB: /* Instruction fetch TLB error */ + case POWERPC_EXCP_DLTLB: /* Data load TLB miss */ + case POWERPC_EXCP_DSTLB: /* Data store TLB miss */ + switch (excp_model) { + case POWERPC_EXCP_602: + case POWERPC_EXCP_603: + case POWERPC_EXCP_G2: + /* Swap temporary saved registers with GPRs */ + if (!(new_msr & ((target_ulong)1 << MSR_TGPR))) { + new_msr |= (target_ulong)1 << MSR_TGPR; + hreg_swap_gpr_tgpr(env); + } + /* fall through */ + case POWERPC_EXCP_7x5: + ppc_excp_debug_sw_tlb(env, excp); + + msr |= env->crf[0] << 28; + msr |= env->error_code; /* key, D/I, S/L bits */ + /* Set way using a LRU mechanism */ + msr |= ((env->last_way + 1) & (env->nb_ways - 1)) << 17; + break; + default: + cpu_abort(cs, "Invalid TLB miss exception\n"); + break; + } + break; + case POWERPC_EXCP_EFPDI: /* Embedded floating-point data interrupt */ + case POWERPC_EXCP_EFPRI: /* Embedded floating-point round interrupt */ + case POWERPC_EXCP_EPERFM: /* Embedded performance monitor interrupt */ + case POWERPC_EXCP_IO: /* IO error exception */ + case POWERPC_EXCP_RUNM: /* Run mode exception */ + case POWERPC_EXCP_EMUL: /* Emulation trap exception */ + case POWERPC_EXCP_FPA: /* Floating-point assist exception */ + case POWERPC_EXCP_DABR: /* Data address breakpoint */ + case POWERPC_EXCP_IABR: /* Instruction address breakpoint */ + case POWERPC_EXCP_SMI: /* System management interrupt */ + case POWERPC_EXCP_THERM: /* Thermal interrupt */ + case POWERPC_EXCP_PERFM: /* Embedded performance monitor interrupt */ + case POWERPC_EXCP_VPUA: /* Vector assist exception */ + case POWERPC_EXCP_SOFTP: /* Soft patch exception */ + case POWERPC_EXCP_MAINT: /* Maintenance exception */ + case POWERPC_EXCP_MEXTBR: /* Maskable external breakpoint */ + case POWERPC_EXCP_NMEXTBR: /* Non maskable external breakpoint */ + cpu_abort(cs, "%s exception not implemented\n", + powerpc_excp_name(excp)); + break; + default: + excp_invalid: + cpu_abort(cs, "Invalid PowerPC exception %d. Aborting\n", excp); + break; + } + + /* Sanity check */ + if (!(env->msr_mask & MSR_HVB)) { + if (new_msr & MSR_HVB) { + cpu_abort(cs, "Trying to deliver HV exception (MSR) %d with " + "no HV support\n", excp); + } + if (srr0 == SPR_HSRR0) { + cpu_abort(cs, "Trying to deliver HV exception (HSRR) %d with " + "no HV support\n", excp); + } + } + + /* + * Sort out endianness of interrupt, this differs depending on the + * CPU, the HV mode, etc... + */ + if (ppc_interrupts_little_endian(cpu, !!(new_msr & MSR_HVB))) { + new_msr |= (target_ulong)1 << MSR_LE; + } + +#if defined(TARGET_PPC64) + if (excp_model == POWERPC_EXCP_BOOKE) { + if (env->spr[SPR_BOOKE_EPCR] & EPCR_ICM) { + /* Cat.64-bit: EPCR.ICM is copied to MSR.CM */ + new_msr |= (target_ulong)1 << MSR_CM; + } else { + vector = (uint32_t)vector; + } + } else { + if (!msr_isf && !mmu_is_64bit(env->mmu_model)) { + vector = (uint32_t)vector; + } else { + new_msr |= (target_ulong)1 << MSR_SF; + } + } +#endif + + if (excp != POWERPC_EXCP_SYSCALL_VECTORED) { + /* Save PC */ + env->spr[srr0] = env->nip; + + /* Save MSR */ + env->spr[srr1] = msr; + } + + /* This can update new_msr and vector if AIL applies */ + ppc_excp_apply_ail(cpu, excp_model, excp, msr, &new_msr, &vector); + + powerpc_set_excp_state(cpu, vector, new_msr); +} + /* * Note that this function should be greatly optimized when called * with a constant excp, from ppc_hw_interrupt @@ -872,6 +1343,9 @@ static void powerpc_excp(PowerPCCPU *cpu, int excp) CPUPPCState *env = &cpu->env; switch (env->excp_model) { + case POWERPC_EXCP_40x: + powerpc_excp_40x(cpu, excp); + break; default: powerpc_excp_legacy(cpu, excp); } From 495fc7ff9677edc31b97084fb17db91737ce4ea4 Mon Sep 17 00:00:00 2001 From: Fabiano Rosas Date: Fri, 28 Jan 2022 13:15:04 +0100 Subject: [PATCH 17/41] target/ppc: Simplify powerpc_excp_40x MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Differences from the generic powerpc_excp code: - Not BookE, so some MSR bits are cleared at interrupt dispatch; - No MSR_HV or MSR_LE; - No power saving states; - No Hypervisor Emulation Assistance; - Not 64 bits; - No System call vectored; - No Interrupts Little Endian; - No Alternate Interrupt Location. Exceptions used: POWERPC_EXCP_ALIGN POWERPC_EXCP_CRITICAL POWERPC_EXCP_DEBUG POWERPC_EXCP_DSI POWERPC_EXCP_DTLB POWERPC_EXCP_EXTERNAL POWERPC_EXCP_FIT POWERPC_EXCP_ISI POWERPC_EXCP_ITLB POWERPC_EXCP_MCHECK POWERPC_EXCP_PIT POWERPC_EXCP_PROGRAM POWERPC_EXCP_SYSCALL POWERPC_EXCP_WDT Signed-off-by: Fabiano Rosas Reviewed-by: David Gibson Message-Id: <20220118184448.852996-5-farosas@linux.ibm.com> Signed-off-by: Cédric Le Goater --- target/ppc/excp_helper.c | 205 ++------------------------------------- 1 file changed, 10 insertions(+), 195 deletions(-) diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c index 5dc948aec2..341a765bd4 100644 --- a/target/ppc/excp_helper.c +++ b/target/ppc/excp_helper.c @@ -409,54 +409,26 @@ static void powerpc_excp_40x(PowerPCCPU *cpu, int excp) excp, env->error_code); /* new srr1 value excluding must-be-zero bits */ - if (excp_model == POWERPC_EXCP_BOOKE) { - msr = env->msr; - } else { - msr = env->msr & ~0x783f0000ULL; - } + msr = env->msr & ~0x783f0000ULL; /* - * new interrupt handler msr preserves existing HV and ME unless - * explicitly overriden + * new interrupt handler msr preserves existing ME unless + * explicitly overriden. */ - new_msr = env->msr & (((target_ulong)1 << MSR_ME) | MSR_HVB); + new_msr = env->msr & (((target_ulong)1 << MSR_ME)); /* target registers */ srr0 = SPR_SRR0; srr1 = SPR_SRR1; - /* - * check for special resume at 0x100 from doze/nap/sleep/winkle on - * P7/P8/P9 - */ - if (env->resume_as_sreset) { - excp = powerpc_reset_wakeup(cs, env, excp, &msr); - } - /* * Hypervisor emulation assistance interrupt only exists on server - * arch 2.05 server or later. We also don't want to generate it if - * we don't have HVB in msr_mask (PAPR mode). + * arch 2.05 server or later. */ - if (excp == POWERPC_EXCP_HV_EMU -#if defined(TARGET_PPC64) - && !(mmu_is_64bit(env->mmu_model) && (env->msr_mask & MSR_HVB)) -#endif /* defined(TARGET_PPC64) */ - - ) { + if (excp == POWERPC_EXCP_HV_EMU) { excp = POWERPC_EXCP_PROGRAM; } -#ifdef TARGET_PPC64 - /* - * SPEU and VPU share the same IVOR but they exist in different - * processors. SPEU is e500v1/2 only and VPU is e6500 only. - */ - if (excp_model == POWERPC_EXCP_BOOKE && excp == POWERPC_EXCP_VPU) { - excp = POWERPC_EXCP_SPEU; - } -#endif - vector = env->excp_vectors[excp]; if (vector == (target_ulong)-1ULL) { cpu_abort(cs, "Raised an exception without defined vector %d\n", @@ -645,24 +617,7 @@ static void powerpc_excp_40x(PowerPCCPU *cpu, int excp) new_msr |= (target_ulong)MSR_HVB; } break; - case POWERPC_EXCP_SYSCALL_VECTORED: /* scv exception */ - lev = env->error_code; - dump_syscall(env); - 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 */ - case POWERPC_EXCP_DECR: /* Decrementer exception */ - break; case POWERPC_EXCP_FIT: /* Fixed-interval timer interrupt */ - /* FIT on 4xx */ trace_ppc_excp_print("FIT"); break; case POWERPC_EXCP_WDT: /* Watchdog timer interrupt */ @@ -693,119 +648,9 @@ static void powerpc_excp_40x(PowerPCCPU *cpu, int excp) cpu_abort(cs, "Debug exception triggered on unsupported model\n"); } break; - case POWERPC_EXCP_SPEU: /* SPE/embedded floating-point unavailable/VPU */ - env->spr[SPR_BOOKE_ESR] = ESR_SPV; - break; - case POWERPC_EXCP_DOORI: /* Embedded doorbell interrupt */ - break; - case POWERPC_EXCP_DOORCI: /* Embedded doorbell critical interrupt */ - srr0 = SPR_BOOKE_CSRR0; - srr1 = SPR_BOOKE_CSRR1; - break; - case POWERPC_EXCP_RESET: /* System reset exception */ - /* A power-saving exception sets ME, otherwise it is unchanged */ - if (msr_pow) { - /* indicate that we resumed from power save mode */ - msr |= 0x10000; - new_msr |= ((target_ulong)1 << MSR_ME); - } - if (env->msr_mask & MSR_HVB) { - /* - * ISA specifies HV, but can be delivered to guest with HV - * clear (e.g., see FWNMI in PAPR, NMI injection in QEMU). - */ - new_msr |= (target_ulong)MSR_HVB; - } else { - if (msr_pow) { - cpu_abort(cs, "Trying to deliver power-saving system reset " - "exception %d with no HV support\n", excp); - } - } - break; - case POWERPC_EXCP_DSEG: /* Data segment exception */ - case POWERPC_EXCP_ISEG: /* Instruction segment exception */ - case POWERPC_EXCP_TRACE: /* Trace exception */ - break; - case POWERPC_EXCP_HISI: /* Hypervisor instruction storage exception */ - msr |= env->error_code; - /* fall through */ - case POWERPC_EXCP_HDECR: /* Hypervisor decrementer exception */ - case POWERPC_EXCP_HDSI: /* Hypervisor data storage exception */ - case POWERPC_EXCP_HDSEG: /* Hypervisor data segment exception */ - case POWERPC_EXCP_HISEG: /* Hypervisor instruction segment exception */ - case POWERPC_EXCP_SDOOR_HV: /* Hypervisor Doorbell interrupt */ - case POWERPC_EXCP_HV_EMU: - case POWERPC_EXCP_HVIRT: /* Hypervisor virtualization */ - srr0 = SPR_HSRR0; - srr1 = SPR_HSRR1; - new_msr |= (target_ulong)MSR_HVB; - new_msr |= env->msr & ((target_ulong)1 << MSR_RI); - break; - case POWERPC_EXCP_VPU: /* Vector unavailable exception */ - case POWERPC_EXCP_VSXU: /* VSX unavailable exception */ - case POWERPC_EXCP_FU: /* Facility unavailable exception */ -#ifdef TARGET_PPC64 - env->spr[SPR_FSCR] |= ((target_ulong)env->error_code << 56); -#endif - break; - case POWERPC_EXCP_HV_FU: /* Hypervisor Facility Unavailable Exception */ -#ifdef TARGET_PPC64 - env->spr[SPR_HFSCR] |= ((target_ulong)env->error_code << FSCR_IC_POS); - srr0 = SPR_HSRR0; - srr1 = SPR_HSRR1; - new_msr |= (target_ulong)MSR_HVB; - new_msr |= env->msr & ((target_ulong)1 << MSR_RI); -#endif - break; case POWERPC_EXCP_PIT: /* Programmable interval timer interrupt */ trace_ppc_excp_print("PIT"); break; - case POWERPC_EXCP_IFTLB: /* Instruction fetch TLB error */ - case POWERPC_EXCP_DLTLB: /* Data load TLB miss */ - case POWERPC_EXCP_DSTLB: /* Data store TLB miss */ - switch (excp_model) { - case POWERPC_EXCP_602: - case POWERPC_EXCP_603: - case POWERPC_EXCP_G2: - /* Swap temporary saved registers with GPRs */ - if (!(new_msr & ((target_ulong)1 << MSR_TGPR))) { - new_msr |= (target_ulong)1 << MSR_TGPR; - hreg_swap_gpr_tgpr(env); - } - /* fall through */ - case POWERPC_EXCP_7x5: - ppc_excp_debug_sw_tlb(env, excp); - - msr |= env->crf[0] << 28; - msr |= env->error_code; /* key, D/I, S/L bits */ - /* Set way using a LRU mechanism */ - msr |= ((env->last_way + 1) & (env->nb_ways - 1)) << 17; - break; - default: - cpu_abort(cs, "Invalid TLB miss exception\n"); - break; - } - break; - case POWERPC_EXCP_EFPDI: /* Embedded floating-point data interrupt */ - case POWERPC_EXCP_EFPRI: /* Embedded floating-point round interrupt */ - case POWERPC_EXCP_EPERFM: /* Embedded performance monitor interrupt */ - case POWERPC_EXCP_IO: /* IO error exception */ - case POWERPC_EXCP_RUNM: /* Run mode exception */ - case POWERPC_EXCP_EMUL: /* Emulation trap exception */ - case POWERPC_EXCP_FPA: /* Floating-point assist exception */ - case POWERPC_EXCP_DABR: /* Data address breakpoint */ - case POWERPC_EXCP_IABR: /* Instruction address breakpoint */ - case POWERPC_EXCP_SMI: /* System management interrupt */ - case POWERPC_EXCP_THERM: /* Thermal interrupt */ - case POWERPC_EXCP_PERFM: /* Embedded performance monitor interrupt */ - case POWERPC_EXCP_VPUA: /* Vector assist exception */ - case POWERPC_EXCP_SOFTP: /* Soft patch exception */ - case POWERPC_EXCP_MAINT: /* Maintenance exception */ - case POWERPC_EXCP_MEXTBR: /* Maskable external breakpoint */ - case POWERPC_EXCP_NMEXTBR: /* Non maskable external breakpoint */ - cpu_abort(cs, "%s exception not implemented\n", - powerpc_excp_name(excp)); - break; default: excp_invalid: cpu_abort(cs, "Invalid PowerPC exception %d. Aborting\n", excp); @@ -824,41 +669,11 @@ static void powerpc_excp_40x(PowerPCCPU *cpu, int excp) } } - /* - * Sort out endianness of interrupt, this differs depending on the - * CPU, the HV mode, etc... - */ - if (ppc_interrupts_little_endian(cpu, !!(new_msr & MSR_HVB))) { - new_msr |= (target_ulong)1 << MSR_LE; - } + /* Save PC */ + env->spr[srr0] = env->nip; -#if defined(TARGET_PPC64) - if (excp_model == POWERPC_EXCP_BOOKE) { - if (env->spr[SPR_BOOKE_EPCR] & EPCR_ICM) { - /* Cat.64-bit: EPCR.ICM is copied to MSR.CM */ - new_msr |= (target_ulong)1 << MSR_CM; - } else { - vector = (uint32_t)vector; - } - } else { - if (!msr_isf && !mmu_is_64bit(env->mmu_model)) { - vector = (uint32_t)vector; - } else { - new_msr |= (target_ulong)1 << MSR_SF; - } - } -#endif - - if (excp != POWERPC_EXCP_SYSCALL_VECTORED) { - /* Save PC */ - env->spr[srr0] = env->nip; - - /* Save MSR */ - env->spr[srr1] = msr; - } - - /* This can update new_msr and vector if AIL applies */ - ppc_excp_apply_ail(cpu, excp_model, excp, msr, &new_msr, &vector); + /* Save MSR */ + env->spr[srr1] = msr; powerpc_set_excp_state(cpu, vector, new_msr); } From ba96828ec25f04fd6b0b93076be506fe5adc6f6d Mon Sep 17 00:00:00 2001 From: Fabiano Rosas Date: Fri, 28 Jan 2022 13:15:04 +0100 Subject: [PATCH 18/41] target/ppc: 405: Critical exceptions cleanup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In powerpc_excp_40x the Critical exception is now for 405 only, so we can remove the BookE and G2 blocks. Signed-off-by: Fabiano Rosas Reviewed-by: David Gibson Reviewed-by: Richard Henderson Message-Id: <20220118184448.852996-6-farosas@linux.ibm.com> Signed-off-by: Cédric Le Goater --- target/ppc/excp_helper.c | 17 ++--------------- 1 file changed, 2 insertions(+), 15 deletions(-) diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c index 341a765bd4..aafc381eb0 100644 --- a/target/ppc/excp_helper.c +++ b/target/ppc/excp_helper.c @@ -439,20 +439,8 @@ static void powerpc_excp_40x(PowerPCCPU *cpu, int excp) switch (excp) { case POWERPC_EXCP_CRITICAL: /* Critical input */ - switch (excp_model) { - case POWERPC_EXCP_40x: - srr0 = SPR_40x_SRR2; - srr1 = SPR_40x_SRR3; - break; - case POWERPC_EXCP_BOOKE: - srr0 = SPR_BOOKE_CSRR0; - srr1 = SPR_BOOKE_CSRR1; - break; - case POWERPC_EXCP_G2: - break; - default: - goto excp_invalid; - } + srr0 = SPR_40x_SRR2; + srr1 = SPR_40x_SRR3; break; case POWERPC_EXCP_MCHECK: /* Machine check exception */ if (msr_me == 0) { @@ -652,7 +640,6 @@ static void powerpc_excp_40x(PowerPCCPU *cpu, int excp) trace_ppc_excp_print("PIT"); break; default: - excp_invalid: cpu_abort(cs, "Invalid PowerPC exception %d. Aborting\n", excp); break; } From 2149e6518032e2209c7520bda6aa38b98850def6 Mon Sep 17 00:00:00 2001 From: Fabiano Rosas Date: Fri, 28 Jan 2022 13:15:04 +0100 Subject: [PATCH 19/41] target/ppc: 405: Machine check exception cleanup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit powerpc_excp_40x applies only to the 405, so remove HV code and references to BookE. Signed-off-by: Fabiano Rosas Reviewed-by: David Gibson Message-Id: <20220118184448.852996-7-farosas@linux.ibm.com> Signed-off-by: Cédric Le Goater --- target/ppc/excp_helper.c | 26 ++------------------------ 1 file changed, 2 insertions(+), 24 deletions(-) diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c index aafc381eb0..3894d36685 100644 --- a/target/ppc/excp_helper.c +++ b/target/ppc/excp_helper.c @@ -457,34 +457,12 @@ static void powerpc_excp_40x(PowerPCCPU *cpu, int excp) cs->halted = 1; cpu_interrupt_exittb(cs); } - if (env->msr_mask & MSR_HVB) { - /* - * ISA specifies HV, but can be delivered to guest with HV - * clear (e.g., see FWNMI in PAPR). - */ - new_msr |= (target_ulong)MSR_HVB; - } /* machine check exceptions don't have ME set */ new_msr &= ~((target_ulong)1 << MSR_ME); - /* XXX: should also have something loaded in DAR / DSISR */ - switch (excp_model) { - case POWERPC_EXCP_40x: - srr0 = SPR_40x_SRR2; - srr1 = SPR_40x_SRR3; - break; - case POWERPC_EXCP_BOOKE: - /* FIXME: choose one or the other based on CPU type */ - srr0 = SPR_BOOKE_MCSRR0; - srr1 = SPR_BOOKE_MCSRR1; - - env->spr[SPR_BOOKE_CSRR0] = env->nip; - env->spr[SPR_BOOKE_CSRR1] = msr; - break; - default: - break; - } + srr0 = SPR_40x_SRR2; + srr1 = SPR_40x_SRR3; break; case POWERPC_EXCP_DSI: /* Data storage exception */ trace_ppc_excp_dsi(env->spr[SPR_DSISR], env->spr[SPR_DAR]); From 9026e99c894a85774b8fdf4bd32a2233863fc2f8 Mon Sep 17 00:00:00 2001 From: Fabiano Rosas Date: Fri, 28 Jan 2022 13:15:04 +0100 Subject: [PATCH 20/41] target/ppc: 405: External exception cleanup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 405 has no MSR_HV and EPR is BookE only so we can remove it all. Signed-off-by: Fabiano Rosas Reviewed-by: David Gibson Message-Id: <20220118184448.852996-8-farosas@linux.ibm.com> Signed-off-by: Cédric Le Goater --- target/ppc/excp_helper.c | 37 ------------------------------------- 1 file changed, 37 deletions(-) diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c index 3894d36685..069288a5c8 100644 --- a/target/ppc/excp_helper.c +++ b/target/ppc/excp_helper.c @@ -472,44 +472,7 @@ static void powerpc_excp_40x(PowerPCCPU *cpu, int excp) msr |= env->error_code; break; case POWERPC_EXCP_EXTERNAL: /* External input */ - { - bool lpes0; - - cs = CPU(cpu); - - /* - * Exception targeting modifiers - * - * LPES0 is supported on POWER7/8/9 - * LPES1 is not supported (old iSeries mode) - * - * On anything else, we behave as if LPES0 is 1 - * (externals don't alter MSR:HV) - */ -#if defined(TARGET_PPC64) - if (excp_model == POWERPC_EXCP_POWER7 || - excp_model == POWERPC_EXCP_POWER8 || - excp_model == POWERPC_EXCP_POWER9 || - excp_model == POWERPC_EXCP_POWER10) { - lpes0 = !!(env->spr[SPR_LPCR] & LPCR_LPES0); - } else -#endif /* defined(TARGET_PPC64) */ - { - lpes0 = true; - } - - if (!lpes0) { - new_msr |= (target_ulong)MSR_HVB; - new_msr |= env->msr & ((target_ulong)1 << MSR_RI); - srr0 = SPR_HSRR0; - srr1 = SPR_HSRR1; - } - if (env->mpic_proxy) { - /* IACK the IRQ on delivery */ - env->spr[SPR_BOOKE_EPR] = ldl_phys(cs->as, env->mpic_iack); - } break; - } case POWERPC_EXCP_ALIGN: /* Alignment exception */ /* Get rS/rD and rA from faulting opcode */ /* From 8428cdb245099dcf03c32e1b66f530ada65a6e83 Mon Sep 17 00:00:00 2001 From: Fabiano Rosas Date: Fri, 28 Jan 2022 13:15:04 +0100 Subject: [PATCH 21/41] target/ppc: 405: System call exception cleanup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There's no sc 1. Signed-off-by: Fabiano Rosas Reviewed-by: Cédric Le Goater Reviewed-by: Richard Henderson Message-Id: <20220118184448.852996-9-farosas@linux.ibm.com> Signed-off-by: Cédric Le Goater --- target/ppc/excp_helper.c | 21 ++------------------- 1 file changed, 2 insertions(+), 19 deletions(-) diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c index 069288a5c8..1f915f607d 100644 --- a/target/ppc/excp_helper.c +++ b/target/ppc/excp_helper.c @@ -398,7 +398,7 @@ static void powerpc_excp_40x(PowerPCCPU *cpu, int excp) CPUPPCState *env = &cpu->env; int excp_model = env->excp_model; target_ulong msr, new_msr, vector; - int srr0, srr1, lev = -1; + int srr0, srr1; if (excp <= POWERPC_EXCP_NONE || excp >= POWERPC_EXCP_NB) { cpu_abort(cs, "Invalid PowerPC exception %d. Aborting\n", excp); @@ -521,30 +521,13 @@ static void powerpc_excp_40x(PowerPCCPU *cpu, int excp) } break; case POWERPC_EXCP_SYSCALL: /* System call exception */ - lev = env->error_code; - - if ((lev == 1) && cpu->vhyp) { - dump_hcall(env); - } else { - dump_syscall(env); - } + dump_syscall(env); /* * We need to correct the NIP which in this case is supposed * to point to the next instruction */ env->nip += 4; - - /* "PAPR mode" built-in hypercall emulation */ - if ((lev == 1) && cpu->vhyp) { - PPCVirtualHypervisorClass *vhc = - PPC_VIRTUAL_HYPERVISOR_GET_CLASS(cpu->vhyp); - vhc->hypercall(cpu->vhyp, cpu); - return; - } - if (lev == 1) { - new_msr |= (target_ulong)MSR_HVB; - } break; case POWERPC_EXCP_FIT: /* Fixed-interval timer interrupt */ trace_ppc_excp_print("FIT"); From 66b5ad561552c5c77058502ea3c7f04316937b64 Mon Sep 17 00:00:00 2001 From: Fabiano Rosas Date: Fri, 28 Jan 2022 13:15:04 +0100 Subject: [PATCH 22/41] target/ppc: 405: Alignment exception cleanup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There is no DSISR in the 405. It uses DEAR which we already set earlier at ppc_cpu_do_unaligned_access. Signed-off-by: Fabiano Rosas Reviewed-by: David Gibson Signed-off-by: Cédric Le Goater --- target/ppc/excp_helper.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c index 1f915f607d..55f6b0e981 100644 --- a/target/ppc/excp_helper.c +++ b/target/ppc/excp_helper.c @@ -474,13 +474,6 @@ static void powerpc_excp_40x(PowerPCCPU *cpu, int excp) case POWERPC_EXCP_EXTERNAL: /* External input */ break; case POWERPC_EXCP_ALIGN: /* Alignment exception */ - /* Get rS/rD and rA from faulting opcode */ - /* - * Note: the opcode fields will not be set properly for a - * direct store load/store, but nobody cares as nobody - * actually uses direct store segments. - */ - env->spr[SPR_DSISR] |= (env->error_code & 0x03FF0000) >> 16; break; case POWERPC_EXCP_PROGRAM: /* Program exception */ switch (env->error_code & ~0xF) { From 4d8ac1d15ec34d0967c7e51e375e72c522c1e6b5 Mon Sep 17 00:00:00 2001 From: Fabiano Rosas Date: Fri, 28 Jan 2022 13:15:04 +0100 Subject: [PATCH 23/41] target/ppc: 405: Debug exception cleanup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The current Debug exception dispatch is the BookE one, so it is different from the 405. We effectively don't support the 405 Debug exception. This patch removes the BookE code and moves the DEBUG into the "not implemented" block. Note that there is in theory a functional change here since we now abort when a Debug exception happens. However, given how it was never implemented, I don't believe this to have ever been dispatched for the 405. Signed-off-by: Fabiano Rosas Reviewed-by: David Gibson Message-Id: <20220118184448.852996-11-farosas@linux.ibm.com> Signed-off-by: Cédric Le Goater --- target/ppc/excp_helper.c | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c index 55f6b0e981..89fc40bb73 100644 --- a/target/ppc/excp_helper.c +++ b/target/ppc/excp_helper.c @@ -539,23 +539,13 @@ static void powerpc_excp_40x(PowerPCCPU *cpu, int excp) case POWERPC_EXCP_DTLB: /* Data TLB error */ case POWERPC_EXCP_ITLB: /* Instruction TLB error */ break; - case POWERPC_EXCP_DEBUG: /* Debug interrupt */ - if (env->flags & POWERPC_FLAG_DE) { - /* FIXME: choose one or the other based on CPU type */ - srr0 = SPR_BOOKE_DSRR0; - srr1 = SPR_BOOKE_DSRR1; - - 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"); - } - break; case POWERPC_EXCP_PIT: /* Programmable interval timer interrupt */ trace_ppc_excp_print("PIT"); break; + case POWERPC_EXCP_DEBUG: /* Debug interrupt */ + cpu_abort(cs, "%s exception not implemented\n", + powerpc_excp_name(excp)); + break; default: cpu_abort(cs, "Invalid PowerPC exception %d. Aborting\n", excp); break; From f9911e1e5513ebf661ae871ae31269a9a1cfabdc Mon Sep 17 00:00:00 2001 From: Fabiano Rosas Date: Fri, 28 Jan 2022 13:15:05 +0100 Subject: [PATCH 24/41] target/ppc: 405: Data Storage exception cleanup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The 405 has no DSISR or DAR, so convert the trace entry to use ESR and DEAR instead. Signed-off-by: Fabiano Rosas Reviewed-by: Cédric Le Goater [ clg : - changed registers to ESR and DEAR. - updated commit log ] Message-Id: <20220118184448.852996-12-farosas@linux.ibm.com> Signed-off-by: Cédric Le Goater --- target/ppc/excp_helper.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c index 89fc40bb73..deba12f4f3 100644 --- a/target/ppc/excp_helper.c +++ b/target/ppc/excp_helper.c @@ -465,7 +465,7 @@ static void powerpc_excp_40x(PowerPCCPU *cpu, int excp) srr1 = SPR_40x_SRR3; break; case POWERPC_EXCP_DSI: /* Data storage exception */ - trace_ppc_excp_dsi(env->spr[SPR_DSISR], env->spr[SPR_DAR]); + trace_ppc_excp_dsi(env->spr[SPR_40x_ESR], env->spr[SPR_40x_DEAR]); break; case POWERPC_EXCP_ISI: /* Instruction storage exception */ trace_ppc_excp_isi(msr, env->nip); From 35f579f5c21682311039f84e2e81254937e6ff78 Mon Sep 17 00:00:00 2001 From: Fabiano Rosas Date: Fri, 28 Jan 2022 13:15:05 +0100 Subject: [PATCH 25/41] target/ppc: 405: Instruction storage interrupt cleanup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The 405 ISI does not set SRR1 with any exception syndrome bits, only a clean copy of the MSR. Signed-off-by: Fabiano Rosas Reviewed-by: Cédric Le Goater [ clg : Fixed removal which was done in the wrong routine ] Message-Id: <20220118184448.852996-13-farosas@linux.ibm.com> Signed-off-by: Cédric Le Goater --- target/ppc/excp_helper.c | 1 - 1 file changed, 1 deletion(-) diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c index deba12f4f3..7d89bd0651 100644 --- a/target/ppc/excp_helper.c +++ b/target/ppc/excp_helper.c @@ -469,7 +469,6 @@ static void powerpc_excp_40x(PowerPCCPU *cpu, int excp) break; case POWERPC_EXCP_ISI: /* Instruction storage exception */ trace_ppc_excp_isi(msr, env->nip); - msr |= env->error_code; break; case POWERPC_EXCP_EXTERNAL: /* External input */ break; From 64e62cfbec19ed22d097645219bdddb55df6f562 Mon Sep 17 00:00:00 2001 From: Fabiano Rosas Date: Fri, 28 Jan 2022 13:15:05 +0100 Subject: [PATCH 26/41] target/ppc: 405: Program exception cleanup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The 405 Program Interrupt does not set SRR1 with any diagnostic bits, just a clean copy of the MSR. We're using the BookE Exception Syndrome Register which is different from the 405. Signed-off-by: Fabiano Rosas Reviewed-by: Cédric Le Goater [ clg: restored SPR_40x_ESR settings ] Message-Id: <20220118184448.852996-14-farosas@linux.ibm.com> Signed-off-by: Cédric Le Goater --- target/ppc/excp_helper.c | 19 ++++--------------- 1 file changed, 4 insertions(+), 15 deletions(-) diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c index 7d89bd0651..b528457d92 100644 --- a/target/ppc/excp_helper.c +++ b/target/ppc/excp_helper.c @@ -483,30 +483,19 @@ static void powerpc_excp_40x(PowerPCCPU *cpu, int excp) env->error_code = 0; return; } - - /* - * FP exceptions always have NIP pointing to the faulting - * instruction, so always use store_next and claim we are - * precise in the MSR. - */ - msr |= 0x00100000; - env->spr[SPR_BOOKE_ESR] = ESR_FP; + env->spr[SPR_40x_ESR] = ESR_FP; break; case POWERPC_EXCP_INVAL: trace_ppc_excp_inval(env->nip); - msr |= 0x00080000; - env->spr[SPR_BOOKE_ESR] = ESR_PIL; + env->spr[SPR_40x_ESR] = ESR_PIL; break; case POWERPC_EXCP_PRIV: - msr |= 0x00040000; - env->spr[SPR_BOOKE_ESR] = ESR_PPR; + env->spr[SPR_40x_ESR] = ESR_PPR; break; case POWERPC_EXCP_TRAP: - msr |= 0x00020000; - env->spr[SPR_BOOKE_ESR] = ESR_PTR; + env->spr[SPR_40x_ESR] = ESR_PTR; break; default: - /* Should never occur */ cpu_abort(cs, "Invalid program exception %d. Aborting\n", env->error_code); break; From 1afe57802ab0127b31b323be171ba9c943a04133 Mon Sep 17 00:00:00 2001 From: Fabiano Rosas Date: Fri, 28 Jan 2022 13:15:05 +0100 Subject: [PATCH 27/41] target/ppc: 405: Watchdog timer exception cleanup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove references to BookE. Signed-off-by: Fabiano Rosas Reviewed-by: Cédric Le Goater Message-Id: <20220118184448.852996-15-farosas@linux.ibm.com> Signed-off-by: Cédric Le Goater --- target/ppc/excp_helper.c | 9 --------- 1 file changed, 9 deletions(-) diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c index b528457d92..c3ff798d9d 100644 --- a/target/ppc/excp_helper.c +++ b/target/ppc/excp_helper.c @@ -396,7 +396,6 @@ static void powerpc_excp_40x(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; @@ -515,14 +514,6 @@ static void powerpc_excp_40x(PowerPCCPU *cpu, int excp) break; case POWERPC_EXCP_WDT: /* Watchdog timer interrupt */ trace_ppc_excp_print("WDT"); - switch (excp_model) { - case POWERPC_EXCP_BOOKE: - srr0 = SPR_BOOKE_CSRR0; - srr1 = SPR_BOOKE_CSRR1; - break; - default: - break; - } break; case POWERPC_EXCP_DTLB: /* Data TLB error */ case POWERPC_EXCP_ITLB: /* Instruction TLB error */ From 9f338e4da17a73cd1b78bbef02f797d7edfd133a Mon Sep 17 00:00:00 2001 From: Fabiano Rosas Date: Fri, 28 Jan 2022 13:15:05 +0100 Subject: [PATCH 28/41] target/ppc: Introduce powerpc_excp_books MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Introduce a new powerpc_excp function specific for BookS CPUs. This commit copies powerpc_excp_legacy verbatim so the next one has a clean diff. Signed-off-by: Fabiano Rosas Reviewed-by: Cédric Le Goater Message-Id: <20220124184605.999353-2-farosas@linux.ibm.com> Signed-off-by: Cédric Le Goater --- target/ppc/excp_helper.c | 478 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 478 insertions(+) diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c index c3ff798d9d..a2a605f8f5 100644 --- a/target/ppc/excp_helper.c +++ b/target/ppc/excp_helper.c @@ -551,6 +551,477 @@ static void powerpc_excp_40x(PowerPCCPU *cpu, int excp) powerpc_set_excp_state(cpu, vector, new_msr); } +static void powerpc_excp_books(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; + + 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); + + /* new srr1 value excluding must-be-zero bits */ + if (excp_model == POWERPC_EXCP_BOOKE) { + msr = env->msr; + } else { + msr = env->msr & ~0x783f0000ULL; + } + + /* + * new interrupt handler msr preserves existing HV and ME unless + * explicitly overriden + */ + new_msr = env->msr & (((target_ulong)1 << MSR_ME) | MSR_HVB); + + /* target registers */ + srr0 = SPR_SRR0; + srr1 = SPR_SRR1; + + /* + * check for special resume at 0x100 from doze/nap/sleep/winkle on + * P7/P8/P9 + */ + if (env->resume_as_sreset) { + excp = powerpc_reset_wakeup(cs, env, excp, &msr); + } + + /* + * Hypervisor emulation assistance interrupt only exists on server + * arch 2.05 server or later. We also don't want to generate it if + * we don't have HVB in msr_mask (PAPR mode). + */ + if (excp == POWERPC_EXCP_HV_EMU +#if defined(TARGET_PPC64) + && !(mmu_is_64bit(env->mmu_model) && (env->msr_mask & MSR_HVB)) +#endif /* defined(TARGET_PPC64) */ + + ) { + excp = POWERPC_EXCP_PROGRAM; + } + +#ifdef TARGET_PPC64 + /* + * SPEU and VPU share the same IVOR but they exist in different + * processors. SPEU is e500v1/2 only and VPU is e6500 only. + */ + if (excp_model == POWERPC_EXCP_BOOKE && excp == POWERPC_EXCP_VPU) { + excp = POWERPC_EXCP_SPEU; + } +#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) { + case POWERPC_EXCP_40x: + srr0 = SPR_40x_SRR2; + srr1 = SPR_40x_SRR3; + break; + case POWERPC_EXCP_BOOKE: + srr0 = SPR_BOOKE_CSRR0; + srr1 = SPR_BOOKE_CSRR1; + break; + case POWERPC_EXCP_G2: + break; + default: + goto excp_invalid; + } + break; + case POWERPC_EXCP_MCHECK: /* Machine check exception */ + if (msr_me == 0) { + /* + * Machine check exception is not enabled. Enter + * checkstop state. + */ + fprintf(stderr, "Machine check while not allowed. " + "Entering checkstop state\n"); + if (qemu_log_separate()) { + qemu_log("Machine check while not allowed. " + "Entering checkstop state\n"); + } + cs->halted = 1; + cpu_interrupt_exittb(cs); + } + if (env->msr_mask & MSR_HVB) { + /* + * ISA specifies HV, but can be delivered to guest with HV + * clear (e.g., see FWNMI in PAPR). + */ + new_msr |= (target_ulong)MSR_HVB; + } + + /* machine check exceptions don't have ME set */ + new_msr &= ~((target_ulong)1 << MSR_ME); + + /* XXX: should also have something loaded in DAR / DSISR */ + switch (excp_model) { + case POWERPC_EXCP_40x: + srr0 = SPR_40x_SRR2; + srr1 = SPR_40x_SRR3; + break; + case POWERPC_EXCP_BOOKE: + /* FIXME: choose one or the other based on CPU type */ + srr0 = SPR_BOOKE_MCSRR0; + srr1 = SPR_BOOKE_MCSRR1; + + env->spr[SPR_BOOKE_CSRR0] = env->nip; + env->spr[SPR_BOOKE_CSRR1] = msr; + break; + default: + break; + } + break; + case POWERPC_EXCP_DSI: /* Data storage exception */ + trace_ppc_excp_dsi(env->spr[SPR_DSISR], env->spr[SPR_DAR]); + break; + case POWERPC_EXCP_ISI: /* Instruction storage exception */ + trace_ppc_excp_isi(msr, env->nip); + msr |= env->error_code; + break; + case POWERPC_EXCP_EXTERNAL: /* External input */ + { + bool lpes0; + + cs = CPU(cpu); + + /* + * Exception targeting modifiers + * + * LPES0 is supported on POWER7/8/9 + * LPES1 is not supported (old iSeries mode) + * + * On anything else, we behave as if LPES0 is 1 + * (externals don't alter MSR:HV) + */ +#if defined(TARGET_PPC64) + if (excp_model == POWERPC_EXCP_POWER7 || + excp_model == POWERPC_EXCP_POWER8 || + excp_model == POWERPC_EXCP_POWER9 || + excp_model == POWERPC_EXCP_POWER10) { + lpes0 = !!(env->spr[SPR_LPCR] & LPCR_LPES0); + } else +#endif /* defined(TARGET_PPC64) */ + { + lpes0 = true; + } + + if (!lpes0) { + new_msr |= (target_ulong)MSR_HVB; + new_msr |= env->msr & ((target_ulong)1 << MSR_RI); + srr0 = SPR_HSRR0; + srr1 = SPR_HSRR1; + } + if (env->mpic_proxy) { + /* IACK the IRQ on delivery */ + env->spr[SPR_BOOKE_EPR] = ldl_phys(cs->as, env->mpic_iack); + } + break; + } + case POWERPC_EXCP_ALIGN: /* Alignment exception */ + /* Get rS/rD and rA from faulting opcode */ + /* + * Note: the opcode fields will not be set properly for a + * direct store load/store, but nobody cares as nobody + * actually uses direct store segments. + */ + env->spr[SPR_DSISR] |= (env->error_code & 0x03FF0000) >> 16; + break; + case POWERPC_EXCP_PROGRAM: /* Program exception */ + switch (env->error_code & ~0xF) { + case POWERPC_EXCP_FP: + if ((msr_fe0 == 0 && msr_fe1 == 0) || msr_fp == 0) { + trace_ppc_excp_fp_ignore(); + cs->exception_index = POWERPC_EXCP_NONE; + env->error_code = 0; + return; + } + + /* + * FP exceptions always have NIP pointing to the faulting + * instruction, so always use store_next and claim we are + * precise in the MSR. + */ + msr |= 0x00100000; + env->spr[SPR_BOOKE_ESR] = ESR_FP; + break; + case POWERPC_EXCP_INVAL: + trace_ppc_excp_inval(env->nip); + msr |= 0x00080000; + env->spr[SPR_BOOKE_ESR] = ESR_PIL; + break; + case POWERPC_EXCP_PRIV: + msr |= 0x00040000; + env->spr[SPR_BOOKE_ESR] = ESR_PPR; + break; + case POWERPC_EXCP_TRAP: + msr |= 0x00020000; + env->spr[SPR_BOOKE_ESR] = ESR_PTR; + break; + default: + /* Should never occur */ + cpu_abort(cs, "Invalid program exception %d. Aborting\n", + env->error_code); + break; + } + break; + case POWERPC_EXCP_SYSCALL: /* System call exception */ + lev = env->error_code; + + if ((lev == 1) && cpu->vhyp) { + dump_hcall(env); + } else { + dump_syscall(env); + } + + /* + * We need to correct the NIP which in this case is supposed + * to point to the next instruction + */ + env->nip += 4; + + /* "PAPR mode" built-in hypercall emulation */ + if ((lev == 1) && cpu->vhyp) { + PPCVirtualHypervisorClass *vhc = + PPC_VIRTUAL_HYPERVISOR_GET_CLASS(cpu->vhyp); + vhc->hypercall(cpu->vhyp, cpu); + return; + } + if (lev == 1) { + new_msr |= (target_ulong)MSR_HVB; + } + break; + case POWERPC_EXCP_SYSCALL_VECTORED: /* scv exception */ + lev = env->error_code; + dump_syscall(env); + 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 */ + case POWERPC_EXCP_DECR: /* Decrementer exception */ + break; + case POWERPC_EXCP_FIT: /* Fixed-interval timer interrupt */ + /* FIT on 4xx */ + trace_ppc_excp_print("FIT"); + break; + case POWERPC_EXCP_WDT: /* Watchdog timer interrupt */ + trace_ppc_excp_print("WDT"); + switch (excp_model) { + case POWERPC_EXCP_BOOKE: + srr0 = SPR_BOOKE_CSRR0; + srr1 = SPR_BOOKE_CSRR1; + break; + default: + break; + } + break; + case POWERPC_EXCP_DTLB: /* Data TLB error */ + case POWERPC_EXCP_ITLB: /* Instruction TLB error */ + break; + case POWERPC_EXCP_DEBUG: /* Debug interrupt */ + if (env->flags & POWERPC_FLAG_DE) { + /* FIXME: choose one or the other based on CPU type */ + srr0 = SPR_BOOKE_DSRR0; + srr1 = SPR_BOOKE_DSRR1; + + 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"); + } + break; + case POWERPC_EXCP_SPEU: /* SPE/embedded floating-point unavailable/VPU */ + env->spr[SPR_BOOKE_ESR] = ESR_SPV; + break; + case POWERPC_EXCP_DOORI: /* Embedded doorbell interrupt */ + break; + case POWERPC_EXCP_DOORCI: /* Embedded doorbell critical interrupt */ + srr0 = SPR_BOOKE_CSRR0; + srr1 = SPR_BOOKE_CSRR1; + break; + case POWERPC_EXCP_RESET: /* System reset exception */ + /* A power-saving exception sets ME, otherwise it is unchanged */ + if (msr_pow) { + /* indicate that we resumed from power save mode */ + msr |= 0x10000; + new_msr |= ((target_ulong)1 << MSR_ME); + } + if (env->msr_mask & MSR_HVB) { + /* + * ISA specifies HV, but can be delivered to guest with HV + * clear (e.g., see FWNMI in PAPR, NMI injection in QEMU). + */ + new_msr |= (target_ulong)MSR_HVB; + } else { + if (msr_pow) { + cpu_abort(cs, "Trying to deliver power-saving system reset " + "exception %d with no HV support\n", excp); + } + } + break; + case POWERPC_EXCP_DSEG: /* Data segment exception */ + case POWERPC_EXCP_ISEG: /* Instruction segment exception */ + case POWERPC_EXCP_TRACE: /* Trace exception */ + break; + case POWERPC_EXCP_HISI: /* Hypervisor instruction storage exception */ + msr |= env->error_code; + /* fall through */ + case POWERPC_EXCP_HDECR: /* Hypervisor decrementer exception */ + case POWERPC_EXCP_HDSI: /* Hypervisor data storage exception */ + case POWERPC_EXCP_HDSEG: /* Hypervisor data segment exception */ + case POWERPC_EXCP_HISEG: /* Hypervisor instruction segment exception */ + case POWERPC_EXCP_SDOOR_HV: /* Hypervisor Doorbell interrupt */ + case POWERPC_EXCP_HV_EMU: + case POWERPC_EXCP_HVIRT: /* Hypervisor virtualization */ + srr0 = SPR_HSRR0; + srr1 = SPR_HSRR1; + new_msr |= (target_ulong)MSR_HVB; + new_msr |= env->msr & ((target_ulong)1 << MSR_RI); + break; + case POWERPC_EXCP_VPU: /* Vector unavailable exception */ + case POWERPC_EXCP_VSXU: /* VSX unavailable exception */ + case POWERPC_EXCP_FU: /* Facility unavailable exception */ +#ifdef TARGET_PPC64 + env->spr[SPR_FSCR] |= ((target_ulong)env->error_code << 56); +#endif + break; + case POWERPC_EXCP_HV_FU: /* Hypervisor Facility Unavailable Exception */ +#ifdef TARGET_PPC64 + env->spr[SPR_HFSCR] |= ((target_ulong)env->error_code << FSCR_IC_POS); + srr0 = SPR_HSRR0; + srr1 = SPR_HSRR1; + new_msr |= (target_ulong)MSR_HVB; + new_msr |= env->msr & ((target_ulong)1 << MSR_RI); +#endif + break; + case POWERPC_EXCP_PIT: /* Programmable interval timer interrupt */ + trace_ppc_excp_print("PIT"); + break; + case POWERPC_EXCP_IFTLB: /* Instruction fetch TLB error */ + case POWERPC_EXCP_DLTLB: /* Data load TLB miss */ + case POWERPC_EXCP_DSTLB: /* Data store TLB miss */ + switch (excp_model) { + case POWERPC_EXCP_602: + case POWERPC_EXCP_603: + case POWERPC_EXCP_G2: + /* Swap temporary saved registers with GPRs */ + if (!(new_msr & ((target_ulong)1 << MSR_TGPR))) { + new_msr |= (target_ulong)1 << MSR_TGPR; + hreg_swap_gpr_tgpr(env); + } + /* fall through */ + case POWERPC_EXCP_7x5: + ppc_excp_debug_sw_tlb(env, excp); + + msr |= env->crf[0] << 28; + msr |= env->error_code; /* key, D/I, S/L bits */ + /* Set way using a LRU mechanism */ + msr |= ((env->last_way + 1) & (env->nb_ways - 1)) << 17; + break; + default: + cpu_abort(cs, "Invalid TLB miss exception\n"); + break; + } + break; + case POWERPC_EXCP_EFPDI: /* Embedded floating-point data interrupt */ + case POWERPC_EXCP_EFPRI: /* Embedded floating-point round interrupt */ + case POWERPC_EXCP_EPERFM: /* Embedded performance monitor interrupt */ + case POWERPC_EXCP_IO: /* IO error exception */ + case POWERPC_EXCP_RUNM: /* Run mode exception */ + case POWERPC_EXCP_EMUL: /* Emulation trap exception */ + case POWERPC_EXCP_FPA: /* Floating-point assist exception */ + case POWERPC_EXCP_DABR: /* Data address breakpoint */ + case POWERPC_EXCP_IABR: /* Instruction address breakpoint */ + case POWERPC_EXCP_SMI: /* System management interrupt */ + case POWERPC_EXCP_THERM: /* Thermal interrupt */ + case POWERPC_EXCP_PERFM: /* Embedded performance monitor interrupt */ + case POWERPC_EXCP_VPUA: /* Vector assist exception */ + case POWERPC_EXCP_SOFTP: /* Soft patch exception */ + case POWERPC_EXCP_MAINT: /* Maintenance exception */ + case POWERPC_EXCP_MEXTBR: /* Maskable external breakpoint */ + case POWERPC_EXCP_NMEXTBR: /* Non maskable external breakpoint */ + cpu_abort(cs, "%s exception not implemented\n", + powerpc_excp_name(excp)); + break; + default: + excp_invalid: + cpu_abort(cs, "Invalid PowerPC exception %d. Aborting\n", excp); + break; + } + + /* Sanity check */ + if (!(env->msr_mask & MSR_HVB)) { + if (new_msr & MSR_HVB) { + cpu_abort(cs, "Trying to deliver HV exception (MSR) %d with " + "no HV support\n", excp); + } + if (srr0 == SPR_HSRR0) { + cpu_abort(cs, "Trying to deliver HV exception (HSRR) %d with " + "no HV support\n", excp); + } + } + + /* + * Sort out endianness of interrupt, this differs depending on the + * CPU, the HV mode, etc... + */ + if (ppc_interrupts_little_endian(cpu, !!(new_msr & MSR_HVB))) { + new_msr |= (target_ulong)1 << MSR_LE; + } + +#if defined(TARGET_PPC64) + if (excp_model == POWERPC_EXCP_BOOKE) { + if (env->spr[SPR_BOOKE_EPCR] & EPCR_ICM) { + /* Cat.64-bit: EPCR.ICM is copied to MSR.CM */ + new_msr |= (target_ulong)1 << MSR_CM; + } else { + vector = (uint32_t)vector; + } + } else { + if (!msr_isf && !mmu_is_64bit(env->mmu_model)) { + vector = (uint32_t)vector; + } else { + new_msr |= (target_ulong)1 << MSR_SF; + } + } +#endif + + if (excp != POWERPC_EXCP_SYSCALL_VECTORED) { + /* Save PC */ + env->spr[srr0] = env->nip; + + /* Save MSR */ + env->spr[srr1] = msr; + } + + /* This can update new_msr and vector if AIL applies */ + ppc_excp_apply_ail(cpu, excp_model, excp, msr, &new_msr, &vector); + + powerpc_set_excp_state(cpu, vector, new_msr); +} + /* * Note that this function should be greatly optimized when called * with a constant excp, from ppc_hw_interrupt @@ -1034,6 +1505,13 @@ static void powerpc_excp(PowerPCCPU *cpu, int excp) case POWERPC_EXCP_40x: powerpc_excp_40x(cpu, excp); break; + case POWERPC_EXCP_970: + case POWERPC_EXCP_POWER7: + case POWERPC_EXCP_POWER8: + case POWERPC_EXCP_POWER9: + case POWERPC_EXCP_POWER10: + powerpc_excp_books(cpu, excp); + break; default: powerpc_excp_legacy(cpu, excp); } From 30c4e4269c168187f4f681e7b87db5333fd0603e Mon Sep 17 00:00:00 2001 From: Fabiano Rosas Date: Fri, 28 Jan 2022 13:15:05 +0100 Subject: [PATCH 29/41] target/ppc: Simplify powerpc_excp_books MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Differences from the generic powerpc_excp code: - Not BookE, so some MSR bits are cleared at interrupt dispatch; - Always uses HV_EMU if the CPU has MSR_HV; - Exceptions always delivered in 64 bit. Exceptions used: POWERPC_EXCP_ALIGN POWERPC_EXCP_DECR POWERPC_EXCP_DSEG POWERPC_EXCP_DSI POWERPC_EXCP_EXTERNAL POWERPC_EXCP_FPU POWERPC_EXCP_FU POWERPC_EXCP_HDECR POWERPC_EXCP_HDSI POWERPC_EXCP_HISI POWERPC_EXCP_HVIRT POWERPC_EXCP_HV_EMU POWERPC_EXCP_HV_FU POWERPC_EXCP_ISEG POWERPC_EXCP_ISI POWERPC_EXCP_MAINT POWERPC_EXCP_MCHECK POWERPC_EXCP_PERFM POWERPC_EXCP_PROGRAM POWERPC_EXCP_RESET POWERPC_EXCP_SDOOR_HV POWERPC_EXCP_SYSCALL POWERPC_EXCP_SYSCALL_VECTORED POWERPC_EXCP_THERM POWERPC_EXCP_TRACE POWERPC_EXCP_VPU POWERPC_EXCP_VPUA POWERPC_EXCP_VSXU POWERPC_EXCP_HV_MAINT POWERPC_EXCP_SDOOR (I added the two above that were not being considered. They used to be "Invalid exception". Now they become "Unimplemented exception" which is more accurate.) Signed-off-by: Fabiano Rosas Reviewed-by: Cédric Le Goater Message-Id: <20220124184605.999353-3-farosas@linux.ibm.com> Signed-off-by: Cédric Le Goater --- target/ppc/excp_helper.c | 161 ++++----------------------------------- 1 file changed, 14 insertions(+), 147 deletions(-) diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c index a2a605f8f5..161b207bc7 100644 --- a/target/ppc/excp_helper.c +++ b/target/ppc/excp_helper.c @@ -551,6 +551,7 @@ static void powerpc_excp_40x(PowerPCCPU *cpu, int excp) powerpc_set_excp_state(cpu, vector, new_msr); } +#ifdef TARGET_PPC64 static void powerpc_excp_books(PowerPCCPU *cpu, int excp) { CPUState *cs = CPU(cpu); @@ -568,11 +569,7 @@ static void powerpc_excp_books(PowerPCCPU *cpu, int excp) excp, env->error_code); /* new srr1 value excluding must-be-zero bits */ - if (excp_model == POWERPC_EXCP_BOOKE) { - msr = env->msr; - } else { - msr = env->msr & ~0x783f0000ULL; - } + msr = env->msr & ~0x783f0000ULL; /* * new interrupt handler msr preserves existing HV and ME unless @@ -593,29 +590,13 @@ static void powerpc_excp_books(PowerPCCPU *cpu, int excp) } /* - * Hypervisor emulation assistance interrupt only exists on server - * arch 2.05 server or later. We also don't want to generate it if - * we don't have HVB in msr_mask (PAPR mode). + * We don't want to generate a Hypervisor Emulation Assistance + * Interrupt if we don't have HVB in msr_mask (PAPR mode). */ - if (excp == POWERPC_EXCP_HV_EMU -#if defined(TARGET_PPC64) - && !(mmu_is_64bit(env->mmu_model) && (env->msr_mask & MSR_HVB)) -#endif /* defined(TARGET_PPC64) */ - - ) { + if (excp == POWERPC_EXCP_HV_EMU && !(env->msr_mask & MSR_HVB)) { excp = POWERPC_EXCP_PROGRAM; } -#ifdef TARGET_PPC64 - /* - * SPEU and VPU share the same IVOR but they exist in different - * processors. SPEU is e500v1/2 only and VPU is e6500 only. - */ - if (excp_model == POWERPC_EXCP_BOOKE && excp == POWERPC_EXCP_VPU) { - excp = POWERPC_EXCP_SPEU; - } -#endif - vector = env->excp_vectors[excp]; if (vector == (target_ulong)-1ULL) { cpu_abort(cs, "Raised an exception without defined vector %d\n", @@ -625,22 +606,6 @@ static void powerpc_excp_books(PowerPCCPU *cpu, int excp) vector |= env->excp_prefix; switch (excp) { - case POWERPC_EXCP_CRITICAL: /* Critical input */ - switch (excp_model) { - case POWERPC_EXCP_40x: - srr0 = SPR_40x_SRR2; - srr1 = SPR_40x_SRR3; - break; - case POWERPC_EXCP_BOOKE: - srr0 = SPR_BOOKE_CSRR0; - srr1 = SPR_BOOKE_CSRR1; - break; - case POWERPC_EXCP_G2: - break; - default: - goto excp_invalid; - } - break; case POWERPC_EXCP_MCHECK: /* Machine check exception */ if (msr_me == 0) { /* @@ -817,50 +782,8 @@ static void powerpc_excp_books(PowerPCCPU *cpu, int excp) env->ctr = msr; break; case POWERPC_EXCP_FPU: /* Floating-point unavailable exception */ - case POWERPC_EXCP_APU: /* Auxiliary processor unavailable */ case POWERPC_EXCP_DECR: /* Decrementer exception */ break; - case POWERPC_EXCP_FIT: /* Fixed-interval timer interrupt */ - /* FIT on 4xx */ - trace_ppc_excp_print("FIT"); - break; - case POWERPC_EXCP_WDT: /* Watchdog timer interrupt */ - trace_ppc_excp_print("WDT"); - switch (excp_model) { - case POWERPC_EXCP_BOOKE: - srr0 = SPR_BOOKE_CSRR0; - srr1 = SPR_BOOKE_CSRR1; - break; - default: - break; - } - break; - case POWERPC_EXCP_DTLB: /* Data TLB error */ - case POWERPC_EXCP_ITLB: /* Instruction TLB error */ - break; - case POWERPC_EXCP_DEBUG: /* Debug interrupt */ - if (env->flags & POWERPC_FLAG_DE) { - /* FIXME: choose one or the other based on CPU type */ - srr0 = SPR_BOOKE_DSRR0; - srr1 = SPR_BOOKE_DSRR1; - - 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"); - } - break; - case POWERPC_EXCP_SPEU: /* SPE/embedded floating-point unavailable/VPU */ - env->spr[SPR_BOOKE_ESR] = ESR_SPV; - break; - case POWERPC_EXCP_DOORI: /* Embedded doorbell interrupt */ - break; - case POWERPC_EXCP_DOORCI: /* Embedded doorbell critical interrupt */ - srr0 = SPR_BOOKE_CSRR0; - srr1 = SPR_BOOKE_CSRR1; - break; case POWERPC_EXCP_RESET: /* System reset exception */ /* A power-saving exception sets ME, otherwise it is unchanged */ if (msr_pow) { @@ -890,8 +813,6 @@ static void powerpc_excp_books(PowerPCCPU *cpu, int excp) /* fall through */ case POWERPC_EXCP_HDECR: /* Hypervisor decrementer exception */ case POWERPC_EXCP_HDSI: /* Hypervisor data storage exception */ - case POWERPC_EXCP_HDSEG: /* Hypervisor data segment exception */ - case POWERPC_EXCP_HISEG: /* Hypervisor instruction segment exception */ case POWERPC_EXCP_SDOOR_HV: /* Hypervisor Doorbell interrupt */ case POWERPC_EXCP_HV_EMU: case POWERPC_EXCP_HVIRT: /* Hypervisor virtualization */ @@ -903,70 +824,25 @@ static void powerpc_excp_books(PowerPCCPU *cpu, int excp) case POWERPC_EXCP_VPU: /* Vector unavailable exception */ case POWERPC_EXCP_VSXU: /* VSX unavailable exception */ case POWERPC_EXCP_FU: /* Facility unavailable exception */ -#ifdef TARGET_PPC64 env->spr[SPR_FSCR] |= ((target_ulong)env->error_code << 56); -#endif break; case POWERPC_EXCP_HV_FU: /* Hypervisor Facility Unavailable Exception */ -#ifdef TARGET_PPC64 env->spr[SPR_HFSCR] |= ((target_ulong)env->error_code << FSCR_IC_POS); srr0 = SPR_HSRR0; srr1 = SPR_HSRR1; new_msr |= (target_ulong)MSR_HVB; new_msr |= env->msr & ((target_ulong)1 << MSR_RI); -#endif break; - case POWERPC_EXCP_PIT: /* Programmable interval timer interrupt */ - trace_ppc_excp_print("PIT"); - break; - case POWERPC_EXCP_IFTLB: /* Instruction fetch TLB error */ - case POWERPC_EXCP_DLTLB: /* Data load TLB miss */ - case POWERPC_EXCP_DSTLB: /* Data store TLB miss */ - switch (excp_model) { - case POWERPC_EXCP_602: - case POWERPC_EXCP_603: - case POWERPC_EXCP_G2: - /* Swap temporary saved registers with GPRs */ - if (!(new_msr & ((target_ulong)1 << MSR_TGPR))) { - new_msr |= (target_ulong)1 << MSR_TGPR; - hreg_swap_gpr_tgpr(env); - } - /* fall through */ - case POWERPC_EXCP_7x5: - ppc_excp_debug_sw_tlb(env, excp); - - msr |= env->crf[0] << 28; - msr |= env->error_code; /* key, D/I, S/L bits */ - /* Set way using a LRU mechanism */ - msr |= ((env->last_way + 1) & (env->nb_ways - 1)) << 17; - break; - default: - cpu_abort(cs, "Invalid TLB miss exception\n"); - break; - } - break; - case POWERPC_EXCP_EFPDI: /* Embedded floating-point data interrupt */ - case POWERPC_EXCP_EFPRI: /* Embedded floating-point round interrupt */ - case POWERPC_EXCP_EPERFM: /* Embedded performance monitor interrupt */ - case POWERPC_EXCP_IO: /* IO error exception */ - case POWERPC_EXCP_RUNM: /* Run mode exception */ - case POWERPC_EXCP_EMUL: /* Emulation trap exception */ - case POWERPC_EXCP_FPA: /* Floating-point assist exception */ - case POWERPC_EXCP_DABR: /* Data address breakpoint */ - case POWERPC_EXCP_IABR: /* Instruction address breakpoint */ - case POWERPC_EXCP_SMI: /* System management interrupt */ case POWERPC_EXCP_THERM: /* Thermal interrupt */ case POWERPC_EXCP_PERFM: /* Embedded performance monitor interrupt */ case POWERPC_EXCP_VPUA: /* Vector assist exception */ - case POWERPC_EXCP_SOFTP: /* Soft patch exception */ case POWERPC_EXCP_MAINT: /* Maintenance exception */ - case POWERPC_EXCP_MEXTBR: /* Maskable external breakpoint */ - case POWERPC_EXCP_NMEXTBR: /* Non maskable external breakpoint */ + case POWERPC_EXCP_SDOOR: /* Doorbell interrupt */ + case POWERPC_EXCP_HV_MAINT: /* Hypervisor Maintenance exception */ cpu_abort(cs, "%s exception not implemented\n", powerpc_excp_name(excp)); break; default: - excp_invalid: cpu_abort(cs, "Invalid PowerPC exception %d. Aborting\n", excp); break; } @@ -991,22 +867,7 @@ static void powerpc_excp_books(PowerPCCPU *cpu, int excp) new_msr |= (target_ulong)1 << MSR_LE; } -#if defined(TARGET_PPC64) - if (excp_model == POWERPC_EXCP_BOOKE) { - if (env->spr[SPR_BOOKE_EPCR] & EPCR_ICM) { - /* Cat.64-bit: EPCR.ICM is copied to MSR.CM */ - new_msr |= (target_ulong)1 << MSR_CM; - } else { - vector = (uint32_t)vector; - } - } else { - if (!msr_isf && !mmu_is_64bit(env->mmu_model)) { - vector = (uint32_t)vector; - } else { - new_msr |= (target_ulong)1 << MSR_SF; - } - } -#endif + new_msr |= (target_ulong)1 << MSR_SF; if (excp != POWERPC_EXCP_SYSCALL_VECTORED) { /* Save PC */ @@ -1021,6 +882,12 @@ static void powerpc_excp_books(PowerPCCPU *cpu, int excp) powerpc_set_excp_state(cpu, vector, new_msr); } +#else +static inline void powerpc_excp_books(PowerPCCPU *cpu, int excp) +{ + g_assert_not_reached(); +} +#endif /* * Note that this function should be greatly optimized when called From 58a02119f39581409444c31e04d6b8b2c15e6f8e Mon Sep 17 00:00:00 2001 From: Fabiano Rosas Date: Fri, 28 Jan 2022 13:15:05 +0100 Subject: [PATCH 30/41] target/ppc: books: Machine Check exception cleanup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit powerpc_excp_books is BookS only, so remove 40x and BookE code. Signed-off-by: Fabiano Rosas Reviewed-by: Cédric Le Goater Message-Id: <20220124184605.999353-4-farosas@linux.ibm.com> Signed-off-by: Cédric Le Goater --- target/ppc/excp_helper.c | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c index 161b207bc7..be8c64a0cd 100644 --- a/target/ppc/excp_helper.c +++ b/target/ppc/excp_helper.c @@ -632,23 +632,6 @@ static void powerpc_excp_books(PowerPCCPU *cpu, int excp) /* machine check exceptions don't have ME set */ new_msr &= ~((target_ulong)1 << MSR_ME); - /* XXX: should also have something loaded in DAR / DSISR */ - switch (excp_model) { - case POWERPC_EXCP_40x: - srr0 = SPR_40x_SRR2; - srr1 = SPR_40x_SRR3; - break; - case POWERPC_EXCP_BOOKE: - /* FIXME: choose one or the other based on CPU type */ - srr0 = SPR_BOOKE_MCSRR0; - srr1 = SPR_BOOKE_MCSRR1; - - env->spr[SPR_BOOKE_CSRR0] = env->nip; - env->spr[SPR_BOOKE_CSRR1] = msr; - break; - default: - break; - } break; case POWERPC_EXCP_DSI: /* Data storage exception */ trace_ppc_excp_dsi(env->spr[SPR_DSISR], env->spr[SPR_DAR]); From 67baff7715b3c1a2beb7df7af615eb3f132b9d13 Mon Sep 17 00:00:00 2001 From: Fabiano Rosas Date: Fri, 28 Jan 2022 13:15:06 +0100 Subject: [PATCH 31/41] target/ppc: books: External interrupt cleanup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since this is now BookS only, we can simplify the code a bit and check has_hv_mode instead of enumerating the exception models. LPES0 does not make sense if there is no MSR_HV. Note that QEMU does not support HV mode on 970 and POWER5+ so we don't set MSR_HV in msr_mask. Signed-off-by: Fabiano Rosas Reviewed-by: Cédric Le Goater Message-Id: <20220124184605.999353-5-farosas@linux.ibm.com> Signed-off-by: Cédric Le Goater --- target/ppc/excp_helper.c | 30 +++++++----------------------- 1 file changed, 7 insertions(+), 23 deletions(-) diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c index be8c64a0cd..e0d6287c4e 100644 --- a/target/ppc/excp_helper.c +++ b/target/ppc/excp_helper.c @@ -644,39 +644,23 @@ static void powerpc_excp_books(PowerPCCPU *cpu, int excp) { bool lpes0; - cs = CPU(cpu); - /* - * Exception targeting modifiers - * - * LPES0 is supported on POWER7/8/9 - * LPES1 is not supported (old iSeries mode) - * - * On anything else, we behave as if LPES0 is 1 - * (externals don't alter MSR:HV) + * LPES0 is only taken into consideration if we support HV + * mode for this CPU. */ -#if defined(TARGET_PPC64) - if (excp_model == POWERPC_EXCP_POWER7 || - excp_model == POWERPC_EXCP_POWER8 || - excp_model == POWERPC_EXCP_POWER9 || - excp_model == POWERPC_EXCP_POWER10) { - lpes0 = !!(env->spr[SPR_LPCR] & LPCR_LPES0); - } else -#endif /* defined(TARGET_PPC64) */ - { - lpes0 = true; + if (!env->has_hv_mode) { + break; } + lpes0 = !!(env->spr[SPR_LPCR] & LPCR_LPES0); + if (!lpes0) { new_msr |= (target_ulong)MSR_HVB; new_msr |= env->msr & ((target_ulong)1 << MSR_RI); srr0 = SPR_HSRR0; srr1 = SPR_HSRR1; } - if (env->mpic_proxy) { - /* IACK the IRQ on delivery */ - env->spr[SPR_BOOKE_EPR] = ldl_phys(cs->as, env->mpic_iack); - } + break; } case POWERPC_EXCP_ALIGN: /* Alignment exception */ From aca2b93fd7edd00d70bf51bf01428e8f2b6456e0 Mon Sep 17 00:00:00 2001 From: Fabiano Rosas Date: Fri, 28 Jan 2022 13:15:06 +0100 Subject: [PATCH 32/41] target/ppc: books: Program exception cleanup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove setting of BookE registers. Signed-off-by: Fabiano Rosas Reviewed-by: Cédric Le Goater Message-Id: <20220124184605.999353-6-farosas@linux.ibm.com> Signed-off-by: Cédric Le Goater --- target/ppc/excp_helper.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c index e0d6287c4e..0e84cecc68 100644 --- a/target/ppc/excp_helper.c +++ b/target/ppc/excp_helper.c @@ -688,20 +688,16 @@ static void powerpc_excp_books(PowerPCCPU *cpu, int excp) * precise in the MSR. */ msr |= 0x00100000; - env->spr[SPR_BOOKE_ESR] = ESR_FP; break; case POWERPC_EXCP_INVAL: trace_ppc_excp_inval(env->nip); msr |= 0x00080000; - env->spr[SPR_BOOKE_ESR] = ESR_PIL; break; case POWERPC_EXCP_PRIV: msr |= 0x00040000; - env->spr[SPR_BOOKE_ESR] = ESR_PPR; break; case POWERPC_EXCP_TRAP: msr |= 0x00020000; - env->spr[SPR_BOOKE_ESR] = ESR_PTR; break; default: /* Should never occur */ From 52926b0debd4aeced56c1560a4ff77b56547df22 Mon Sep 17 00:00:00 2001 From: Fabiano Rosas Date: Fri, 28 Jan 2022 13:15:06 +0100 Subject: [PATCH 33/41] target/ppc: Introduce powerpc_excp_74xx MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Introduce a new powerpc_excp function specific for PowerPC 74xx CPUs. This commit copies powerpc_excp_legacy verbatim so the next one has a clean diff. Signed-off-by: Fabiano Rosas Message-Id: <20220127201116.1154733-2-farosas@linux.ibm.com> Signed-off-by: Cédric Le Goater --- target/ppc/excp_helper.c | 474 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 474 insertions(+) diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c index 0e84cecc68..0e3d3ffcf4 100644 --- a/target/ppc/excp_helper.c +++ b/target/ppc/excp_helper.c @@ -551,6 +551,477 @@ static void powerpc_excp_40x(PowerPCCPU *cpu, int excp) powerpc_set_excp_state(cpu, vector, new_msr); } +static void powerpc_excp_74xx(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; + + 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); + + /* new srr1 value excluding must-be-zero bits */ + if (excp_model == POWERPC_EXCP_BOOKE) { + msr = env->msr; + } else { + msr = env->msr & ~0x783f0000ULL; + } + + /* + * new interrupt handler msr preserves existing HV and ME unless + * explicitly overriden + */ + new_msr = env->msr & (((target_ulong)1 << MSR_ME) | MSR_HVB); + + /* target registers */ + srr0 = SPR_SRR0; + srr1 = SPR_SRR1; + + /* + * check for special resume at 0x100 from doze/nap/sleep/winkle on + * P7/P8/P9 + */ + if (env->resume_as_sreset) { + excp = powerpc_reset_wakeup(cs, env, excp, &msr); + } + + /* + * Hypervisor emulation assistance interrupt only exists on server + * arch 2.05 server or later. We also don't want to generate it if + * we don't have HVB in msr_mask (PAPR mode). + */ + if (excp == POWERPC_EXCP_HV_EMU +#if defined(TARGET_PPC64) + && !(mmu_is_64bit(env->mmu_model) && (env->msr_mask & MSR_HVB)) +#endif /* defined(TARGET_PPC64) */ + + ) { + excp = POWERPC_EXCP_PROGRAM; + } + +#ifdef TARGET_PPC64 + /* + * SPEU and VPU share the same IVOR but they exist in different + * processors. SPEU is e500v1/2 only and VPU is e6500 only. + */ + if (excp_model == POWERPC_EXCP_BOOKE && excp == POWERPC_EXCP_VPU) { + excp = POWERPC_EXCP_SPEU; + } +#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) { + case POWERPC_EXCP_40x: + srr0 = SPR_40x_SRR2; + srr1 = SPR_40x_SRR3; + break; + case POWERPC_EXCP_BOOKE: + srr0 = SPR_BOOKE_CSRR0; + srr1 = SPR_BOOKE_CSRR1; + break; + case POWERPC_EXCP_G2: + break; + default: + goto excp_invalid; + } + break; + case POWERPC_EXCP_MCHECK: /* Machine check exception */ + if (msr_me == 0) { + /* + * Machine check exception is not enabled. Enter + * checkstop state. + */ + fprintf(stderr, "Machine check while not allowed. " + "Entering checkstop state\n"); + if (qemu_log_separate()) { + qemu_log("Machine check while not allowed. " + "Entering checkstop state\n"); + } + cs->halted = 1; + cpu_interrupt_exittb(cs); + } + if (env->msr_mask & MSR_HVB) { + /* + * ISA specifies HV, but can be delivered to guest with HV + * clear (e.g., see FWNMI in PAPR). + */ + new_msr |= (target_ulong)MSR_HVB; + } + + /* machine check exceptions don't have ME set */ + new_msr &= ~((target_ulong)1 << MSR_ME); + + /* XXX: should also have something loaded in DAR / DSISR */ + switch (excp_model) { + case POWERPC_EXCP_40x: + srr0 = SPR_40x_SRR2; + srr1 = SPR_40x_SRR3; + break; + case POWERPC_EXCP_BOOKE: + /* FIXME: choose one or the other based on CPU type */ + srr0 = SPR_BOOKE_MCSRR0; + srr1 = SPR_BOOKE_MCSRR1; + + env->spr[SPR_BOOKE_CSRR0] = env->nip; + env->spr[SPR_BOOKE_CSRR1] = msr; + break; + default: + break; + } + break; + case POWERPC_EXCP_DSI: /* Data storage exception */ + trace_ppc_excp_dsi(env->spr[SPR_DSISR], env->spr[SPR_DAR]); + break; + case POWERPC_EXCP_ISI: /* Instruction storage exception */ + trace_ppc_excp_isi(msr, env->nip); + msr |= env->error_code; + break; + case POWERPC_EXCP_EXTERNAL: /* External input */ + { + bool lpes0; + + cs = CPU(cpu); + + /* + * Exception targeting modifiers + * + * LPES0 is supported on POWER7/8/9 + * LPES1 is not supported (old iSeries mode) + * + * On anything else, we behave as if LPES0 is 1 + * (externals don't alter MSR:HV) + */ +#if defined(TARGET_PPC64) + if (excp_model == POWERPC_EXCP_POWER7 || + excp_model == POWERPC_EXCP_POWER8 || + excp_model == POWERPC_EXCP_POWER9 || + excp_model == POWERPC_EXCP_POWER10) { + lpes0 = !!(env->spr[SPR_LPCR] & LPCR_LPES0); + } else +#endif /* defined(TARGET_PPC64) */ + { + lpes0 = true; + } + + if (!lpes0) { + new_msr |= (target_ulong)MSR_HVB; + new_msr |= env->msr & ((target_ulong)1 << MSR_RI); + srr0 = SPR_HSRR0; + srr1 = SPR_HSRR1; + } + if (env->mpic_proxy) { + /* IACK the IRQ on delivery */ + env->spr[SPR_BOOKE_EPR] = ldl_phys(cs->as, env->mpic_iack); + } + break; + } + case POWERPC_EXCP_ALIGN: /* Alignment exception */ + /* Get rS/rD and rA from faulting opcode */ + /* + * Note: the opcode fields will not be set properly for a + * direct store load/store, but nobody cares as nobody + * actually uses direct store segments. + */ + env->spr[SPR_DSISR] |= (env->error_code & 0x03FF0000) >> 16; + break; + case POWERPC_EXCP_PROGRAM: /* Program exception */ + switch (env->error_code & ~0xF) { + case POWERPC_EXCP_FP: + if ((msr_fe0 == 0 && msr_fe1 == 0) || msr_fp == 0) { + trace_ppc_excp_fp_ignore(); + cs->exception_index = POWERPC_EXCP_NONE; + env->error_code = 0; + return; + } + + /* + * FP exceptions always have NIP pointing to the faulting + * instruction, so always use store_next and claim we are + * precise in the MSR. + */ + msr |= 0x00100000; + env->spr[SPR_BOOKE_ESR] = ESR_FP; + break; + case POWERPC_EXCP_INVAL: + trace_ppc_excp_inval(env->nip); + msr |= 0x00080000; + env->spr[SPR_BOOKE_ESR] = ESR_PIL; + break; + case POWERPC_EXCP_PRIV: + msr |= 0x00040000; + env->spr[SPR_BOOKE_ESR] = ESR_PPR; + break; + case POWERPC_EXCP_TRAP: + msr |= 0x00020000; + env->spr[SPR_BOOKE_ESR] = ESR_PTR; + break; + default: + /* Should never occur */ + cpu_abort(cs, "Invalid program exception %d. Aborting\n", + env->error_code); + break; + } + break; + case POWERPC_EXCP_SYSCALL: /* System call exception */ + lev = env->error_code; + + if ((lev == 1) && cpu->vhyp) { + dump_hcall(env); + } else { + dump_syscall(env); + } + + /* + * We need to correct the NIP which in this case is supposed + * to point to the next instruction + */ + env->nip += 4; + + /* "PAPR mode" built-in hypercall emulation */ + if ((lev == 1) && cpu->vhyp) { + PPCVirtualHypervisorClass *vhc = + PPC_VIRTUAL_HYPERVISOR_GET_CLASS(cpu->vhyp); + vhc->hypercall(cpu->vhyp, cpu); + return; + } + if (lev == 1) { + new_msr |= (target_ulong)MSR_HVB; + } + break; + case POWERPC_EXCP_SYSCALL_VECTORED: /* scv exception */ + lev = env->error_code; + dump_syscall(env); + 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 */ + case POWERPC_EXCP_DECR: /* Decrementer exception */ + break; + case POWERPC_EXCP_FIT: /* Fixed-interval timer interrupt */ + /* FIT on 4xx */ + trace_ppc_excp_print("FIT"); + break; + case POWERPC_EXCP_WDT: /* Watchdog timer interrupt */ + trace_ppc_excp_print("WDT"); + switch (excp_model) { + case POWERPC_EXCP_BOOKE: + srr0 = SPR_BOOKE_CSRR0; + srr1 = SPR_BOOKE_CSRR1; + break; + default: + break; + } + break; + case POWERPC_EXCP_DTLB: /* Data TLB error */ + case POWERPC_EXCP_ITLB: /* Instruction TLB error */ + break; + case POWERPC_EXCP_DEBUG: /* Debug interrupt */ + if (env->flags & POWERPC_FLAG_DE) { + /* FIXME: choose one or the other based on CPU type */ + srr0 = SPR_BOOKE_DSRR0; + srr1 = SPR_BOOKE_DSRR1; + + 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"); + } + break; + case POWERPC_EXCP_SPEU: /* SPE/embedded floating-point unavailable/VPU */ + env->spr[SPR_BOOKE_ESR] = ESR_SPV; + break; + case POWERPC_EXCP_DOORI: /* Embedded doorbell interrupt */ + break; + case POWERPC_EXCP_DOORCI: /* Embedded doorbell critical interrupt */ + srr0 = SPR_BOOKE_CSRR0; + srr1 = SPR_BOOKE_CSRR1; + break; + case POWERPC_EXCP_RESET: /* System reset exception */ + /* A power-saving exception sets ME, otherwise it is unchanged */ + if (msr_pow) { + /* indicate that we resumed from power save mode */ + msr |= 0x10000; + new_msr |= ((target_ulong)1 << MSR_ME); + } + if (env->msr_mask & MSR_HVB) { + /* + * ISA specifies HV, but can be delivered to guest with HV + * clear (e.g., see FWNMI in PAPR, NMI injection in QEMU). + */ + new_msr |= (target_ulong)MSR_HVB; + } else { + if (msr_pow) { + cpu_abort(cs, "Trying to deliver power-saving system reset " + "exception %d with no HV support\n", excp); + } + } + break; + case POWERPC_EXCP_DSEG: /* Data segment exception */ + case POWERPC_EXCP_ISEG: /* Instruction segment exception */ + case POWERPC_EXCP_TRACE: /* Trace exception */ + break; + case POWERPC_EXCP_HISI: /* Hypervisor instruction storage exception */ + msr |= env->error_code; + /* fall through */ + case POWERPC_EXCP_HDECR: /* Hypervisor decrementer exception */ + case POWERPC_EXCP_HDSI: /* Hypervisor data storage exception */ + case POWERPC_EXCP_HDSEG: /* Hypervisor data segment exception */ + case POWERPC_EXCP_HISEG: /* Hypervisor instruction segment exception */ + case POWERPC_EXCP_SDOOR_HV: /* Hypervisor Doorbell interrupt */ + case POWERPC_EXCP_HV_EMU: + case POWERPC_EXCP_HVIRT: /* Hypervisor virtualization */ + srr0 = SPR_HSRR0; + srr1 = SPR_HSRR1; + new_msr |= (target_ulong)MSR_HVB; + new_msr |= env->msr & ((target_ulong)1 << MSR_RI); + break; + case POWERPC_EXCP_VPU: /* Vector unavailable exception */ + case POWERPC_EXCP_VSXU: /* VSX unavailable exception */ + case POWERPC_EXCP_FU: /* Facility unavailable exception */ +#ifdef TARGET_PPC64 + env->spr[SPR_FSCR] |= ((target_ulong)env->error_code << 56); +#endif + break; + case POWERPC_EXCP_HV_FU: /* Hypervisor Facility Unavailable Exception */ +#ifdef TARGET_PPC64 + env->spr[SPR_HFSCR] |= ((target_ulong)env->error_code << FSCR_IC_POS); + srr0 = SPR_HSRR0; + srr1 = SPR_HSRR1; + new_msr |= (target_ulong)MSR_HVB; + new_msr |= env->msr & ((target_ulong)1 << MSR_RI); +#endif + break; + case POWERPC_EXCP_PIT: /* Programmable interval timer interrupt */ + trace_ppc_excp_print("PIT"); + break; + case POWERPC_EXCP_IFTLB: /* Instruction fetch TLB error */ + case POWERPC_EXCP_DLTLB: /* Data load TLB miss */ + case POWERPC_EXCP_DSTLB: /* Data store TLB miss */ + switch (excp_model) { + case POWERPC_EXCP_602: + case POWERPC_EXCP_603: + case POWERPC_EXCP_G2: + /* Swap temporary saved registers with GPRs */ + if (!(new_msr & ((target_ulong)1 << MSR_TGPR))) { + new_msr |= (target_ulong)1 << MSR_TGPR; + hreg_swap_gpr_tgpr(env); + } + /* fall through */ + case POWERPC_EXCP_7x5: + ppc_excp_debug_sw_tlb(env, excp); + + msr |= env->crf[0] << 28; + msr |= env->error_code; /* key, D/I, S/L bits */ + /* Set way using a LRU mechanism */ + msr |= ((env->last_way + 1) & (env->nb_ways - 1)) << 17; + break; + default: + cpu_abort(cs, "Invalid TLB miss exception\n"); + break; + } + break; + case POWERPC_EXCP_EFPDI: /* Embedded floating-point data interrupt */ + case POWERPC_EXCP_EFPRI: /* Embedded floating-point round interrupt */ + case POWERPC_EXCP_EPERFM: /* Embedded performance monitor interrupt */ + case POWERPC_EXCP_IO: /* IO error exception */ + case POWERPC_EXCP_RUNM: /* Run mode exception */ + case POWERPC_EXCP_EMUL: /* Emulation trap exception */ + case POWERPC_EXCP_FPA: /* Floating-point assist exception */ + case POWERPC_EXCP_DABR: /* Data address breakpoint */ + case POWERPC_EXCP_IABR: /* Instruction address breakpoint */ + case POWERPC_EXCP_SMI: /* System management interrupt */ + case POWERPC_EXCP_THERM: /* Thermal interrupt */ + case POWERPC_EXCP_PERFM: /* Embedded performance monitor interrupt */ + case POWERPC_EXCP_VPUA: /* Vector assist exception */ + case POWERPC_EXCP_SOFTP: /* Soft patch exception */ + case POWERPC_EXCP_MAINT: /* Maintenance exception */ + case POWERPC_EXCP_MEXTBR: /* Maskable external breakpoint */ + case POWERPC_EXCP_NMEXTBR: /* Non maskable external breakpoint */ + cpu_abort(cs, "%s exception not implemented\n", + powerpc_excp_name(excp)); + break; + default: + excp_invalid: + cpu_abort(cs, "Invalid PowerPC exception %d. Aborting\n", excp); + break; + } + + /* Sanity check */ + if (!(env->msr_mask & MSR_HVB)) { + if (new_msr & MSR_HVB) { + cpu_abort(cs, "Trying to deliver HV exception (MSR) %d with " + "no HV support\n", excp); + } + if (srr0 == SPR_HSRR0) { + cpu_abort(cs, "Trying to deliver HV exception (HSRR) %d with " + "no HV support\n", excp); + } + } + + /* + * Sort out endianness of interrupt, this differs depending on the + * CPU, the HV mode, etc... + */ + if (ppc_interrupts_little_endian(cpu, !!(new_msr & MSR_HVB))) { + new_msr |= (target_ulong)1 << MSR_LE; + } + +#if defined(TARGET_PPC64) + if (excp_model == POWERPC_EXCP_BOOKE) { + if (env->spr[SPR_BOOKE_EPCR] & EPCR_ICM) { + /* Cat.64-bit: EPCR.ICM is copied to MSR.CM */ + new_msr |= (target_ulong)1 << MSR_CM; + } else { + vector = (uint32_t)vector; + } + } else { + if (!msr_isf && !mmu_is_64bit(env->mmu_model)) { + vector = (uint32_t)vector; + } else { + new_msr |= (target_ulong)1 << MSR_SF; + } + } +#endif + + if (excp != POWERPC_EXCP_SYSCALL_VECTORED) { + /* Save PC */ + env->spr[srr0] = env->nip; + + /* Save MSR */ + env->spr[srr1] = msr; + } + + /* This can update new_msr and vector if AIL applies */ + ppc_excp_apply_ail(cpu, excp_model, excp, msr, &new_msr, &vector); + + powerpc_set_excp_state(cpu, vector, new_msr); +} + #ifdef TARGET_PPC64 static void powerpc_excp_books(PowerPCCPU *cpu, int excp) { @@ -1335,6 +1806,9 @@ static void powerpc_excp(PowerPCCPU *cpu, int excp) case POWERPC_EXCP_40x: powerpc_excp_40x(cpu, excp); break; + case POWERPC_EXCP_74xx: + powerpc_excp_74xx(cpu, excp); + break; case POWERPC_EXCP_970: case POWERPC_EXCP_POWER7: case POWERPC_EXCP_POWER8: From 1f6faf8b1451c41add592427c573ca76817aceec Mon Sep 17 00:00:00 2001 From: Fabiano Rosas Date: Fri, 28 Jan 2022 13:15:06 +0100 Subject: [PATCH 34/41] target/ppc: Simplify powerpc_excp_74xx MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Differences from the generic powerpc_excp code: - Not BookE, so some MSR bits are cleared at interrupt dispatch; - No MSR_HV; - No power saving states; - No Hypervisor Emulation Assistance; - Not 64 bits; - No System call vectored; - No Alternate Interrupt Location. Exceptions used: POWERPC_EXCP_ALIGN POWERPC_EXCP_DECR POWERPC_EXCP_DSI POWERPC_EXCP_EXTERNAL POWERPC_EXCP_FPU POWERPC_EXCP_IABR POWERPC_EXCP_ISI POWERPC_EXCP_MCHECK POWERPC_EXCP_PERFM POWERPC_EXCP_PROGRAM POWERPC_EXCP_RESET POWERPC_EXCP_SMI POWERPC_EXCP_SYSCALL POWERPC_EXCP_THERM POWERPC_EXCP_TRACE POWERPC_EXCP_VPU POWERPC_EXCP_VPUA Signed-off-by: Fabiano Rosas Message-Id: <20220127201116.1154733-3-farosas@linux.ibm.com> Signed-off-by: Cédric Le Goater --- target/ppc/excp_helper.c | 211 ++------------------------------------- 1 file changed, 9 insertions(+), 202 deletions(-) diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c index 0e3d3ffcf4..13e5cb3ddc 100644 --- a/target/ppc/excp_helper.c +++ b/target/ppc/excp_helper.c @@ -568,54 +568,26 @@ static void powerpc_excp_74xx(PowerPCCPU *cpu, int excp) excp, env->error_code); /* new srr1 value excluding must-be-zero bits */ - if (excp_model == POWERPC_EXCP_BOOKE) { - msr = env->msr; - } else { - msr = env->msr & ~0x783f0000ULL; - } + msr = env->msr & ~0x783f0000ULL; /* - * new interrupt handler msr preserves existing HV and ME unless + * new interrupt handler msr preserves existing ME unless * explicitly overriden */ - new_msr = env->msr & (((target_ulong)1 << MSR_ME) | MSR_HVB); + new_msr = env->msr & ((target_ulong)1 << MSR_ME); /* target registers */ srr0 = SPR_SRR0; srr1 = SPR_SRR1; - /* - * check for special resume at 0x100 from doze/nap/sleep/winkle on - * P7/P8/P9 - */ - if (env->resume_as_sreset) { - excp = powerpc_reset_wakeup(cs, env, excp, &msr); - } - /* * Hypervisor emulation assistance interrupt only exists on server - * arch 2.05 server or later. We also don't want to generate it if - * we don't have HVB in msr_mask (PAPR mode). + * arch 2.05 server or later. */ - if (excp == POWERPC_EXCP_HV_EMU -#if defined(TARGET_PPC64) - && !(mmu_is_64bit(env->mmu_model) && (env->msr_mask & MSR_HVB)) -#endif /* defined(TARGET_PPC64) */ - - ) { + if (excp == POWERPC_EXCP_HV_EMU) { excp = POWERPC_EXCP_PROGRAM; } -#ifdef TARGET_PPC64 - /* - * SPEU and VPU share the same IVOR but they exist in different - * processors. SPEU is e500v1/2 only and VPU is e6500 only. - */ - if (excp_model == POWERPC_EXCP_BOOKE && excp == POWERPC_EXCP_VPU) { - excp = POWERPC_EXCP_SPEU; - } -#endif - vector = env->excp_vectors[excp]; if (vector == (target_ulong)-1ULL) { cpu_abort(cs, "Raised an exception without defined vector %d\n", @@ -625,22 +597,6 @@ static void powerpc_excp_74xx(PowerPCCPU *cpu, int excp) vector |= env->excp_prefix; switch (excp) { - case POWERPC_EXCP_CRITICAL: /* Critical input */ - switch (excp_model) { - case POWERPC_EXCP_40x: - srr0 = SPR_40x_SRR2; - srr1 = SPR_40x_SRR3; - break; - case POWERPC_EXCP_BOOKE: - srr0 = SPR_BOOKE_CSRR0; - srr1 = SPR_BOOKE_CSRR1; - break; - case POWERPC_EXCP_G2: - break; - default: - goto excp_invalid; - } - break; case POWERPC_EXCP_MCHECK: /* Machine check exception */ if (msr_me == 0) { /* @@ -804,63 +760,9 @@ static void powerpc_excp_74xx(PowerPCCPU *cpu, int excp) new_msr |= (target_ulong)MSR_HVB; } break; - case POWERPC_EXCP_SYSCALL_VECTORED: /* scv exception */ - lev = env->error_code; - dump_syscall(env); - 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 */ case POWERPC_EXCP_DECR: /* Decrementer exception */ break; - case POWERPC_EXCP_FIT: /* Fixed-interval timer interrupt */ - /* FIT on 4xx */ - trace_ppc_excp_print("FIT"); - break; - case POWERPC_EXCP_WDT: /* Watchdog timer interrupt */ - trace_ppc_excp_print("WDT"); - switch (excp_model) { - case POWERPC_EXCP_BOOKE: - srr0 = SPR_BOOKE_CSRR0; - srr1 = SPR_BOOKE_CSRR1; - break; - default: - break; - } - break; - case POWERPC_EXCP_DTLB: /* Data TLB error */ - case POWERPC_EXCP_ITLB: /* Instruction TLB error */ - break; - case POWERPC_EXCP_DEBUG: /* Debug interrupt */ - if (env->flags & POWERPC_FLAG_DE) { - /* FIXME: choose one or the other based on CPU type */ - srr0 = SPR_BOOKE_DSRR0; - srr1 = SPR_BOOKE_DSRR1; - - 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"); - } - break; - case POWERPC_EXCP_SPEU: /* SPE/embedded floating-point unavailable/VPU */ - env->spr[SPR_BOOKE_ESR] = ESR_SPV; - break; - case POWERPC_EXCP_DOORI: /* Embedded doorbell interrupt */ - break; - case POWERPC_EXCP_DOORCI: /* Embedded doorbell critical interrupt */ - srr0 = SPR_BOOKE_CSRR0; - srr1 = SPR_BOOKE_CSRR1; - break; case POWERPC_EXCP_RESET: /* System reset exception */ /* A power-saving exception sets ME, otherwise it is unchanged */ if (msr_pow) { @@ -881,92 +783,19 @@ static void powerpc_excp_74xx(PowerPCCPU *cpu, int excp) } } break; - case POWERPC_EXCP_DSEG: /* Data segment exception */ - case POWERPC_EXCP_ISEG: /* Instruction segment exception */ case POWERPC_EXCP_TRACE: /* Trace exception */ break; - case POWERPC_EXCP_HISI: /* Hypervisor instruction storage exception */ - msr |= env->error_code; - /* fall through */ - case POWERPC_EXCP_HDECR: /* Hypervisor decrementer exception */ - case POWERPC_EXCP_HDSI: /* Hypervisor data storage exception */ - case POWERPC_EXCP_HDSEG: /* Hypervisor data segment exception */ - case POWERPC_EXCP_HISEG: /* Hypervisor instruction segment exception */ - case POWERPC_EXCP_SDOOR_HV: /* Hypervisor Doorbell interrupt */ - case POWERPC_EXCP_HV_EMU: - case POWERPC_EXCP_HVIRT: /* Hypervisor virtualization */ - srr0 = SPR_HSRR0; - srr1 = SPR_HSRR1; - new_msr |= (target_ulong)MSR_HVB; - new_msr |= env->msr & ((target_ulong)1 << MSR_RI); - break; case POWERPC_EXCP_VPU: /* Vector unavailable exception */ - case POWERPC_EXCP_VSXU: /* VSX unavailable exception */ - case POWERPC_EXCP_FU: /* Facility unavailable exception */ -#ifdef TARGET_PPC64 - env->spr[SPR_FSCR] |= ((target_ulong)env->error_code << 56); -#endif break; - case POWERPC_EXCP_HV_FU: /* Hypervisor Facility Unavailable Exception */ -#ifdef TARGET_PPC64 - env->spr[SPR_HFSCR] |= ((target_ulong)env->error_code << FSCR_IC_POS); - srr0 = SPR_HSRR0; - srr1 = SPR_HSRR1; - new_msr |= (target_ulong)MSR_HVB; - new_msr |= env->msr & ((target_ulong)1 << MSR_RI); -#endif - break; - case POWERPC_EXCP_PIT: /* Programmable interval timer interrupt */ - trace_ppc_excp_print("PIT"); - break; - case POWERPC_EXCP_IFTLB: /* Instruction fetch TLB error */ - case POWERPC_EXCP_DLTLB: /* Data load TLB miss */ - case POWERPC_EXCP_DSTLB: /* Data store TLB miss */ - switch (excp_model) { - case POWERPC_EXCP_602: - case POWERPC_EXCP_603: - case POWERPC_EXCP_G2: - /* Swap temporary saved registers with GPRs */ - if (!(new_msr & ((target_ulong)1 << MSR_TGPR))) { - new_msr |= (target_ulong)1 << MSR_TGPR; - hreg_swap_gpr_tgpr(env); - } - /* fall through */ - case POWERPC_EXCP_7x5: - ppc_excp_debug_sw_tlb(env, excp); - - msr |= env->crf[0] << 28; - msr |= env->error_code; /* key, D/I, S/L bits */ - /* Set way using a LRU mechanism */ - msr |= ((env->last_way + 1) & (env->nb_ways - 1)) << 17; - break; - default: - cpu_abort(cs, "Invalid TLB miss exception\n"); - break; - } - break; - case POWERPC_EXCP_EFPDI: /* Embedded floating-point data interrupt */ - case POWERPC_EXCP_EFPRI: /* Embedded floating-point round interrupt */ - case POWERPC_EXCP_EPERFM: /* Embedded performance monitor interrupt */ - case POWERPC_EXCP_IO: /* IO error exception */ - case POWERPC_EXCP_RUNM: /* Run mode exception */ - case POWERPC_EXCP_EMUL: /* Emulation trap exception */ - case POWERPC_EXCP_FPA: /* Floating-point assist exception */ - case POWERPC_EXCP_DABR: /* Data address breakpoint */ case POWERPC_EXCP_IABR: /* Instruction address breakpoint */ case POWERPC_EXCP_SMI: /* System management interrupt */ case POWERPC_EXCP_THERM: /* Thermal interrupt */ case POWERPC_EXCP_PERFM: /* Embedded performance monitor interrupt */ case POWERPC_EXCP_VPUA: /* Vector assist exception */ - case POWERPC_EXCP_SOFTP: /* Soft patch exception */ - case POWERPC_EXCP_MAINT: /* Maintenance exception */ - case POWERPC_EXCP_MEXTBR: /* Maskable external breakpoint */ - case POWERPC_EXCP_NMEXTBR: /* Non maskable external breakpoint */ cpu_abort(cs, "%s exception not implemented\n", powerpc_excp_name(excp)); break; default: - excp_invalid: cpu_abort(cs, "Invalid PowerPC exception %d. Aborting\n", excp); break; } @@ -991,33 +820,11 @@ static void powerpc_excp_74xx(PowerPCCPU *cpu, int excp) new_msr |= (target_ulong)1 << MSR_LE; } -#if defined(TARGET_PPC64) - if (excp_model == POWERPC_EXCP_BOOKE) { - if (env->spr[SPR_BOOKE_EPCR] & EPCR_ICM) { - /* Cat.64-bit: EPCR.ICM is copied to MSR.CM */ - new_msr |= (target_ulong)1 << MSR_CM; - } else { - vector = (uint32_t)vector; - } - } else { - if (!msr_isf && !mmu_is_64bit(env->mmu_model)) { - vector = (uint32_t)vector; - } else { - new_msr |= (target_ulong)1 << MSR_SF; - } - } -#endif + /* Save PC */ + env->spr[srr0] = env->nip; - if (excp != POWERPC_EXCP_SYSCALL_VECTORED) { - /* Save PC */ - env->spr[srr0] = env->nip; - - /* Save MSR */ - env->spr[srr1] = msr; - } - - /* This can update new_msr and vector if AIL applies */ - ppc_excp_apply_ail(cpu, excp_model, excp, msr, &new_msr, &vector); + /* Save MSR */ + env->spr[srr1] = msr; powerpc_set_excp_state(cpu, vector, new_msr); } From 3fbb46409f012aea9c1443ae4bd9f49d4fcabd75 Mon Sep 17 00:00:00 2001 From: Fabiano Rosas Date: Fri, 28 Jan 2022 13:15:06 +0100 Subject: [PATCH 35/41] target/ppc: 74xx: Machine Check exception cleanup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The 74xx don't have an MSR_HV. Also remove 40x and BookE code. Signed-off-by: Fabiano Rosas Message-Id: <20220127201116.1154733-4-farosas@linux.ibm.com> Signed-off-by: Cédric Le Goater --- target/ppc/excp_helper.c | 24 ------------------------ 1 file changed, 24 deletions(-) diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c index 13e5cb3ddc..0d8c66b98f 100644 --- a/target/ppc/excp_helper.c +++ b/target/ppc/excp_helper.c @@ -612,34 +612,10 @@ static void powerpc_excp_74xx(PowerPCCPU *cpu, int excp) cs->halted = 1; cpu_interrupt_exittb(cs); } - if (env->msr_mask & MSR_HVB) { - /* - * ISA specifies HV, but can be delivered to guest with HV - * clear (e.g., see FWNMI in PAPR). - */ - new_msr |= (target_ulong)MSR_HVB; - } /* machine check exceptions don't have ME set */ new_msr &= ~((target_ulong)1 << MSR_ME); - /* XXX: should also have something loaded in DAR / DSISR */ - switch (excp_model) { - case POWERPC_EXCP_40x: - srr0 = SPR_40x_SRR2; - srr1 = SPR_40x_SRR3; - break; - case POWERPC_EXCP_BOOKE: - /* FIXME: choose one or the other based on CPU type */ - srr0 = SPR_BOOKE_MCSRR0; - srr1 = SPR_BOOKE_MCSRR1; - - env->spr[SPR_BOOKE_CSRR0] = env->nip; - env->spr[SPR_BOOKE_CSRR1] = msr; - break; - default: - break; - } break; case POWERPC_EXCP_DSI: /* Data storage exception */ trace_ppc_excp_dsi(env->spr[SPR_DSISR], env->spr[SPR_DAR]); From 12e8042698a0682ff87909f513345b6d52c3de2e Mon Sep 17 00:00:00 2001 From: Fabiano Rosas Date: Fri, 28 Jan 2022 13:15:06 +0100 Subject: [PATCH 36/41] target/ppc: 74xx: External interrupt cleanup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The 74xx don't have MSR_HV so all the LPES0 logic can be removed. Also remove the BookE IRQ code. Signed-off-by: Fabiano Rosas Message-Id: <20220127201116.1154733-5-farosas@linux.ibm.com> Signed-off-by: Cédric Le Goater --- target/ppc/excp_helper.c | 38 -------------------------------------- 1 file changed, 38 deletions(-) diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c index 0d8c66b98f..b9a1d7ae7e 100644 --- a/target/ppc/excp_helper.c +++ b/target/ppc/excp_helper.c @@ -555,7 +555,6 @@ static void powerpc_excp_74xx(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; @@ -625,44 +624,7 @@ static void powerpc_excp_74xx(PowerPCCPU *cpu, int excp) msr |= env->error_code; break; case POWERPC_EXCP_EXTERNAL: /* External input */ - { - bool lpes0; - - cs = CPU(cpu); - - /* - * Exception targeting modifiers - * - * LPES0 is supported on POWER7/8/9 - * LPES1 is not supported (old iSeries mode) - * - * On anything else, we behave as if LPES0 is 1 - * (externals don't alter MSR:HV) - */ -#if defined(TARGET_PPC64) - if (excp_model == POWERPC_EXCP_POWER7 || - excp_model == POWERPC_EXCP_POWER8 || - excp_model == POWERPC_EXCP_POWER9 || - excp_model == POWERPC_EXCP_POWER10) { - lpes0 = !!(env->spr[SPR_LPCR] & LPCR_LPES0); - } else -#endif /* defined(TARGET_PPC64) */ - { - lpes0 = true; - } - - if (!lpes0) { - new_msr |= (target_ulong)MSR_HVB; - new_msr |= env->msr & ((target_ulong)1 << MSR_RI); - srr0 = SPR_HSRR0; - srr1 = SPR_HSRR1; - } - if (env->mpic_proxy) { - /* IACK the IRQ on delivery */ - env->spr[SPR_BOOKE_EPR] = ldl_phys(cs->as, env->mpic_iack); - } break; - } case POWERPC_EXCP_ALIGN: /* Alignment exception */ /* Get rS/rD and rA from faulting opcode */ /* From 0ea2a65fe811700d3be94150b5a83af2ee828c91 Mon Sep 17 00:00:00 2001 From: Fabiano Rosas Date: Fri, 28 Jan 2022 13:15:07 +0100 Subject: [PATCH 37/41] target/ppc: 74xx: Program exception cleanup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove the BookE ESR setting. Signed-off-by: Fabiano Rosas Message-Id: <20220127201116.1154733-6-farosas@linux.ibm.com> Signed-off-by: Cédric Le Goater --- target/ppc/excp_helper.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c index b9a1d7ae7e..bb17b65dc0 100644 --- a/target/ppc/excp_helper.c +++ b/target/ppc/excp_helper.c @@ -650,20 +650,16 @@ static void powerpc_excp_74xx(PowerPCCPU *cpu, int excp) * precise in the MSR. */ msr |= 0x00100000; - env->spr[SPR_BOOKE_ESR] = ESR_FP; break; case POWERPC_EXCP_INVAL: trace_ppc_excp_inval(env->nip); msr |= 0x00080000; - env->spr[SPR_BOOKE_ESR] = ESR_PIL; break; case POWERPC_EXCP_PRIV: msr |= 0x00040000; - env->spr[SPR_BOOKE_ESR] = ESR_PPR; break; case POWERPC_EXCP_TRAP: msr |= 0x00020000; - env->spr[SPR_BOOKE_ESR] = ESR_PTR; break; default: /* Should never occur */ From bca2c6d9e09177c5a6959c3c372dab8211f39404 Mon Sep 17 00:00:00 2001 From: Fabiano Rosas Date: Fri, 28 Jan 2022 13:15:07 +0100 Subject: [PATCH 38/41] target/ppc: 74xx: System Call exception cleanup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove the BookE code and add a comment explaining why we need to keep hypercall support even though this CPU does not have a hypervisor mode. Signed-off-by: Fabiano Rosas Message-Id: <20220127201116.1154733-7-farosas@linux.ibm.com> Signed-off-by: Cédric Le Goater --- target/ppc/excp_helper.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c index bb17b65dc0..396e25ed35 100644 --- a/target/ppc/excp_helper.c +++ b/target/ppc/excp_helper.c @@ -556,7 +556,7 @@ static void powerpc_excp_74xx(PowerPCCPU *cpu, int excp) CPUState *cs = CPU(cpu); CPUPPCState *env = &cpu->env; target_ulong msr, new_msr, vector; - int srr0, srr1, lev = -1; + int srr0, srr1; if (excp <= POWERPC_EXCP_NONE || excp >= POWERPC_EXCP_NB) { cpu_abort(cs, "Invalid PowerPC exception %d. Aborting\n", excp); @@ -669,7 +669,8 @@ static void powerpc_excp_74xx(PowerPCCPU *cpu, int excp) } break; case POWERPC_EXCP_SYSCALL: /* System call exception */ - lev = env->error_code; + { + int lev = env->error_code; if ((lev == 1) && cpu->vhyp) { dump_hcall(env); @@ -683,17 +684,21 @@ static void powerpc_excp_74xx(PowerPCCPU *cpu, int excp) */ env->nip += 4; - /* "PAPR mode" built-in hypercall emulation */ + /* + * The Virtual Open Firmware (VOF) relies on the 'sc 1' + * instruction to communicate with QEMU. The pegasos2 machine + * uses VOF and the 74xx CPUs, so although the 74xx don't have + * HV mode, we need to keep hypercall support. + */ if ((lev == 1) && cpu->vhyp) { PPCVirtualHypervisorClass *vhc = PPC_VIRTUAL_HYPERVISOR_GET_CLASS(cpu->vhyp); vhc->hypercall(cpu->vhyp, cpu); return; } - if (lev == 1) { - new_msr |= (target_ulong)MSR_HVB; - } + break; + } case POWERPC_EXCP_FPU: /* Floating-point unavailable exception */ case POWERPC_EXCP_DECR: /* Decrementer exception */ break; From 91a51fecef20ba4ee659a68a55b2b556f070908d Mon Sep 17 00:00:00 2001 From: Fabiano Rosas Date: Fri, 28 Jan 2022 13:15:07 +0100 Subject: [PATCH 39/41] target/ppc: 74xx: System Reset interrupt cleanup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The whole power saving states logic seems to be dependent on HV mode, which don't exist for 74xx so I'm removing it all and leaving the abort message. Signed-off-by: Fabiano Rosas Message-Id: <20220127201116.1154733-8-farosas@linux.ibm.com> Signed-off-by: Cédric Le Goater --- target/ppc/excp_helper.c | 18 ++---------------- 1 file changed, 2 insertions(+), 16 deletions(-) diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c index 396e25ed35..b7921c0956 100644 --- a/target/ppc/excp_helper.c +++ b/target/ppc/excp_helper.c @@ -703,23 +703,9 @@ static void powerpc_excp_74xx(PowerPCCPU *cpu, int excp) case POWERPC_EXCP_DECR: /* Decrementer exception */ break; case POWERPC_EXCP_RESET: /* System reset exception */ - /* A power-saving exception sets ME, otherwise it is unchanged */ if (msr_pow) { - /* indicate that we resumed from power save mode */ - msr |= 0x10000; - new_msr |= ((target_ulong)1 << MSR_ME); - } - if (env->msr_mask & MSR_HVB) { - /* - * ISA specifies HV, but can be delivered to guest with HV - * clear (e.g., see FWNMI in PAPR, NMI injection in QEMU). - */ - new_msr |= (target_ulong)MSR_HVB; - } else { - if (msr_pow) { - cpu_abort(cs, "Trying to deliver power-saving system reset " - "exception %d with no HV support\n", excp); - } + cpu_abort(cs, "Trying to deliver power-saving system reset " + "exception %d with no HV support\n", excp); } break; case POWERPC_EXCP_TRACE: /* Trace exception */ From f82db77761806613a62f622db9c1ca613ae1e6ed Mon Sep 17 00:00:00 2001 From: Fabiano Rosas Date: Fri, 28 Jan 2022 13:15:07 +0100 Subject: [PATCH 40/41] target/ppc: 74xx: Set SRRs directly in exception code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The 74xx does not have alternate/hypervisor Save and Restore Registers, so we can set SRR0 and SRR1 directly. Signed-off-by: Fabiano Rosas Message-Id: <20220127201116.1154733-9-farosas@linux.ibm.com> Signed-off-by: Cédric Le Goater --- target/ppc/excp_helper.c | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c index b7921c0956..4e6bb87b70 100644 --- a/target/ppc/excp_helper.c +++ b/target/ppc/excp_helper.c @@ -556,7 +556,6 @@ static void powerpc_excp_74xx(PowerPCCPU *cpu, int excp) CPUState *cs = CPU(cpu); CPUPPCState *env = &cpu->env; target_ulong msr, new_msr, vector; - int srr0, srr1; if (excp <= POWERPC_EXCP_NONE || excp >= POWERPC_EXCP_NB) { cpu_abort(cs, "Invalid PowerPC exception %d. Aborting\n", excp); @@ -575,10 +574,6 @@ static void powerpc_excp_74xx(PowerPCCPU *cpu, int excp) */ new_msr = env->msr & ((target_ulong)1 << MSR_ME); - /* target registers */ - srr0 = SPR_SRR0; - srr1 = SPR_SRR1; - /* * Hypervisor emulation assistance interrupt only exists on server * arch 2.05 server or later. @@ -731,10 +726,6 @@ static void powerpc_excp_74xx(PowerPCCPU *cpu, int excp) cpu_abort(cs, "Trying to deliver HV exception (MSR) %d with " "no HV support\n", excp); } - if (srr0 == SPR_HSRR0) { - cpu_abort(cs, "Trying to deliver HV exception (HSRR) %d with " - "no HV support\n", excp); - } } /* @@ -746,10 +737,10 @@ static void powerpc_excp_74xx(PowerPCCPU *cpu, int excp) } /* Save PC */ - env->spr[srr0] = env->nip; + env->spr[SPR_SRR0] = env->nip; /* Save MSR */ - env->spr[srr1] = msr; + env->spr[SPR_SRR1] = msr; powerpc_set_excp_state(cpu, vector, new_msr); } From 4537d62dcece45183632298272abfb4859418cc0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= Date: Mon, 24 Jan 2022 18:41:30 +0100 Subject: [PATCH 41/41] target/ppc: Remove support for the PowerPC 602 CPU MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The 602 was derived from the PowerPC 603, for the gaming market it seems. It was hardly used and no firmware supporting the CPU could be found. Drop support. Signed-off-by: Cédric Le Goater --- target/ppc/cpu-models.c | 2 - target/ppc/cpu-models.h | 1 - target/ppc/cpu.h | 8 +- target/ppc/cpu_init.c | 147 ----------------------------------- target/ppc/excp_helper.c | 1 - target/ppc/helper.h | 1 - target/ppc/int_helper.c | 21 ----- target/ppc/mfrom_table.c.inc | 78 ------------------- target/ppc/mfrom_table_gen.c | 34 -------- target/ppc/translate.c | 30 ------- 10 files changed, 1 insertion(+), 322 deletions(-) delete mode 100644 target/ppc/mfrom_table.c.inc delete mode 100644 target/ppc/mfrom_table_gen.c diff --git a/target/ppc/cpu-models.c b/target/ppc/cpu-models.c index 764afe5a2a..a2c720cc4d 100644 --- a/target/ppc/cpu-models.c +++ b/target/ppc/cpu-models.c @@ -428,8 +428,6 @@ "PowerPC 601v1") POWERPC_DEF("601_v2", CPU_POWERPC_601_v2, 601v, "PowerPC 601v2") - POWERPC_DEF("602", CPU_POWERPC_602, 602, - "PowerPC 602") POWERPC_DEF("603", CPU_POWERPC_603, 603, "PowerPC 603") POWERPC_DEF("603e_v1.1", CPU_POWERPC_603E_v11, 603E, diff --git a/target/ppc/cpu-models.h b/target/ppc/cpu-models.h index bf1dc7e5ca..612978a3fb 100644 --- a/target/ppc/cpu-models.h +++ b/target/ppc/cpu-models.h @@ -208,7 +208,6 @@ enum { CPU_POWERPC_601_v0 = 0x00010001, CPU_POWERPC_601_v1 = 0x00010001, CPU_POWERPC_601_v2 = 0x00010002, - CPU_POWERPC_602 = 0x00050100, CPU_POWERPC_603 = 0x00030100, CPU_POWERPC_603E_v11 = 0x00060101, CPU_POWERPC_603E_v12 = 0x00060102, diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h index 66e13075c3..dcd83b503c 100644 --- a/target/ppc/cpu.h +++ b/target/ppc/cpu.h @@ -321,9 +321,7 @@ typedef enum { #define MSR_UCLE 26 /* User-mode cache lock enable for BookE */ #define MSR_VR 25 /* altivec available x hflags */ #define MSR_SPE 25 /* SPE enable for BookE x hflags */ -#define MSR_AP 23 /* Access privilege state on 602 hflags */ #define MSR_VSX 23 /* Vector Scalar Extension (ISA 2.06 and later) x hflags */ -#define MSR_SA 22 /* Supervisor access mode on 602 hflags */ #define MSR_S 22 /* Secure state */ #define MSR_KEY 19 /* key bit on 603e */ #define MSR_POW 18 /* Power management */ @@ -477,9 +475,7 @@ typedef enum { #define msr_ucle ((env->msr >> MSR_UCLE) & 1) #define msr_vr ((env->msr >> MSR_VR) & 1) #define msr_spe ((env->msr >> MSR_SPE) & 1) -#define msr_ap ((env->msr >> MSR_AP) & 1) #define msr_vsx ((env->msr >> MSR_VSX) & 1) -#define msr_sa ((env->msr >> MSR_SA) & 1) #define msr_key ((env->msr >> MSR_KEY) & 1) #define msr_pow ((env->msr >> MSR_POW) & 1) #define msr_tgpr ((env->msr >> MSR_TGPR) & 1) @@ -2142,8 +2138,6 @@ enum { PPC_MFTB = 0x0000000000000200ULL, /* Fixed-point unit extensions */ - /* PowerPC 602 specific */ - PPC_602_SPEC = 0x0000000000000400ULL, /* isel instruction */ PPC_ISEL = 0x0000000000000800ULL, /* popcntb instruction */ @@ -2245,7 +2239,7 @@ enum { #define PPC_TCG_INSNS (PPC_INSNS_BASE | PPC_POWER | PPC_POWER2 \ | PPC_POWER_RTC | PPC_POWER_BR | PPC_64B \ | PPC_64BX | PPC_64H | PPC_WAIT | PPC_MFTB \ - | PPC_602_SPEC | PPC_ISEL | PPC_POPCNTB \ + | PPC_ISEL | PPC_POPCNTB \ | PPC_STRING | PPC_FLOAT | PPC_FLOAT_EXT \ | PPC_FLOAT_FSQRT | PPC_FLOAT_FRES \ | PPC_FLOAT_FRSQRTE | PPC_FLOAT_FRSQRTES \ diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c index 23a13036b2..bf60529d37 100644 --- a/target/ppc/cpu_init.c +++ b/target/ppc/cpu_init.c @@ -749,54 +749,6 @@ static void register_G2_sprs(CPUPPCState *env) 0x00000000); } -/* SPR specific to PowerPC 602 implementation */ -static void register_602_sprs(CPUPPCState *env) -{ - /* ESA registers */ - /* XXX : not implemented */ - spr_register(env, SPR_SER, "SER", - SPR_NOACCESS, SPR_NOACCESS, - &spr_read_generic, &spr_write_generic, - 0x00000000); - /* XXX : not implemented */ - spr_register(env, SPR_SEBR, "SEBR", - SPR_NOACCESS, SPR_NOACCESS, - &spr_read_generic, &spr_write_generic, - 0x00000000); - /* XXX : not implemented */ - spr_register(env, SPR_ESASRR, "ESASRR", - SPR_NOACCESS, SPR_NOACCESS, - &spr_read_generic, &spr_write_generic, - 0x00000000); - /* Floating point status */ - /* XXX : not implemented */ - spr_register(env, SPR_SP, "SP", - SPR_NOACCESS, SPR_NOACCESS, - &spr_read_generic, &spr_write_generic, - 0x00000000); - /* XXX : not implemented */ - spr_register(env, SPR_LT, "LT", - SPR_NOACCESS, SPR_NOACCESS, - &spr_read_generic, &spr_write_generic, - 0x00000000); - /* Watchdog timer */ - /* XXX : not implemented */ - spr_register(env, SPR_TCR, "TCR", - SPR_NOACCESS, SPR_NOACCESS, - &spr_read_generic, &spr_write_generic, - 0x00000000); - /* Interrupt base */ - spr_register(env, SPR_IBR, "IBR", - SPR_NOACCESS, SPR_NOACCESS, - &spr_read_generic, &spr_write_generic, - 0x00000000); - /* XXX : not implemented */ - spr_register(env, SPR_IABR, "IABR", - SPR_NOACCESS, SPR_NOACCESS, - &spr_read_generic, &spr_write_generic, - 0x00000000); -} - /* SPR specific to PowerPC 601 implementation */ static void register_601_sprs(CPUPPCState *env) { @@ -2128,33 +2080,6 @@ static void init_excp_601(CPUPPCState *env) #endif } -static void init_excp_602(CPUPPCState *env) -{ -#if !defined(CONFIG_USER_ONLY) - /* XXX: exception prefix has a special behavior on 602 */ - env->excp_vectors[POWERPC_EXCP_RESET] = 0x00000100; - env->excp_vectors[POWERPC_EXCP_MCHECK] = 0x00000200; - env->excp_vectors[POWERPC_EXCP_DSI] = 0x00000300; - env->excp_vectors[POWERPC_EXCP_ISI] = 0x00000400; - env->excp_vectors[POWERPC_EXCP_EXTERNAL] = 0x00000500; - env->excp_vectors[POWERPC_EXCP_ALIGN] = 0x00000600; - env->excp_vectors[POWERPC_EXCP_PROGRAM] = 0x00000700; - env->excp_vectors[POWERPC_EXCP_FPU] = 0x00000800; - env->excp_vectors[POWERPC_EXCP_DECR] = 0x00000900; - env->excp_vectors[POWERPC_EXCP_SYSCALL] = 0x00000C00; - env->excp_vectors[POWERPC_EXCP_TRACE] = 0x00000D00; - env->excp_vectors[POWERPC_EXCP_IFTLB] = 0x00001000; - env->excp_vectors[POWERPC_EXCP_DLTLB] = 0x00001100; - env->excp_vectors[POWERPC_EXCP_DSTLB] = 0x00001200; - env->excp_vectors[POWERPC_EXCP_IABR] = 0x00001300; - env->excp_vectors[POWERPC_EXCP_SMI] = 0x00001400; - env->excp_vectors[POWERPC_EXCP_WDT] = 0x00001500; - env->excp_vectors[POWERPC_EXCP_EMUL] = 0x00001600; - /* Hardware reset vector */ - env->hreset_vector = 0x00000100UL; -#endif -} - static void init_excp_603(CPUPPCState *env) { #if !defined(CONFIG_USER_ONLY) @@ -4081,76 +4006,6 @@ POWERPC_FAMILY(601v)(ObjectClass *oc, void *data) pcc->flags = POWERPC_FLAG_SE | POWERPC_FLAG_RTC_CLK | POWERPC_FLAG_HID0_LE; } -static void init_proc_602(CPUPPCState *env) -{ - register_ne_601_sprs(env); - register_sdr1_sprs(env); - register_602_sprs(env); - /* Time base */ - register_tbl(env); - /* hardware implementation registers */ - /* XXX : not implemented */ - spr_register(env, SPR_HID0, "HID0", - SPR_NOACCESS, SPR_NOACCESS, - &spr_read_generic, &spr_write_generic, - 0x00000000); - /* XXX : not implemented */ - spr_register(env, SPR_HID1, "HID1", - SPR_NOACCESS, SPR_NOACCESS, - &spr_read_generic, &spr_write_generic, - 0x00000000); - /* Memory management */ - register_low_BATs(env); - register_6xx_7xx_soft_tlb(env, 64, 2); - init_excp_602(env); - env->dcache_line_size = 32; - env->icache_line_size = 32; - /* Allocate hardware IRQ controller */ - ppc6xx_irq_init(env_archcpu(env)); -} - -POWERPC_FAMILY(602)(ObjectClass *oc, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(oc); - PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc); - - dc->desc = "PowerPC 602"; - pcc->init_proc = init_proc_602; - pcc->check_pow = check_pow_hid0; - pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB | - PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES | - PPC_FLOAT_FRSQRTE | PPC_FLOAT_STFIWX | - PPC_CACHE | PPC_CACHE_ICBI | PPC_CACHE_DCBZ | - PPC_MEM_SYNC | PPC_MEM_EIEIO | - PPC_MEM_TLBIE | PPC_6xx_TLB | PPC_MEM_TLBSYNC | - PPC_SEGMENT | PPC_602_SPEC; - pcc->msr_mask = (1ull << MSR_VSX) | - (1ull << MSR_SA) | - (1ull << MSR_POW) | - (1ull << MSR_TGPR) | - (1ull << MSR_ILE) | - (1ull << MSR_EE) | - (1ull << MSR_PR) | - (1ull << MSR_FP) | - (1ull << MSR_ME) | - (1ull << MSR_FE0) | - (1ull << MSR_SE) | - (1ull << MSR_DE) | - (1ull << MSR_FE1) | - (1ull << MSR_EP) | - (1ull << MSR_IR) | - (1ull << MSR_DR) | - (1ull << MSR_RI) | - (1ull << MSR_LE); - /* XXX: 602 MMU is quite specific. Should add a special case */ - pcc->mmu_model = POWERPC_MMU_SOFT_6xx; - pcc->excp_model = POWERPC_EXCP_602; - pcc->bus_model = PPC_FLAGS_INPUT_6xx; - pcc->bfd_mach = bfd_mach_ppc_602; - pcc->flags = POWERPC_FLAG_TGPR | POWERPC_FLAG_SE | - POWERPC_FLAG_BE | POWERPC_FLAG_BUS_CLK; -} - static void init_proc_603(CPUPPCState *env) { register_ne_601_sprs(env); @@ -8271,8 +8126,6 @@ static void ppc_cpu_reset(DeviceState *dev) msr = (target_ulong)0; msr |= (target_ulong)MSR_HVB; - msr |= (target_ulong)0 << MSR_AP; /* TO BE CHECKED */ - msr |= (target_ulong)0 << MSR_SA; /* TO BE CHECKED */ msr |= (target_ulong)1 << MSR_EP; #if defined(DO_SINGLE_STEP) && 0 /* Single step trace mode */ diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c index 4e6bb87b70..c107953dec 100644 --- a/target/ppc/excp_helper.c +++ b/target/ppc/excp_helper.c @@ -1422,7 +1422,6 @@ static inline void powerpc_excp_legacy(PowerPCCPU *cpu, int excp) case POWERPC_EXCP_DLTLB: /* Data load TLB miss */ case POWERPC_EXCP_DSTLB: /* Data store TLB miss */ switch (excp_model) { - case POWERPC_EXCP_602: case POWERPC_EXCP_603: case POWERPC_EXCP_G2: /* Swap temporary saved registers with GPRs */ diff --git a/target/ppc/helper.h b/target/ppc/helper.h index bdbbd5e1d9..f2e5060910 100644 --- a/target/ppc/helper.h +++ b/target/ppc/helper.h @@ -646,7 +646,6 @@ DEF_HELPER_FLAGS_2(slbieg, TCG_CALL_NO_RWG, void, env, tl) DEF_HELPER_FLAGS_2(load_sr, TCG_CALL_NO_RWG, tl, env, tl) DEF_HELPER_FLAGS_3(store_sr, TCG_CALL_NO_RWG, void, env, tl, tl) -DEF_HELPER_FLAGS_1(602_mfrom, TCG_CALL_NO_RWG_SE, tl, tl) DEF_HELPER_1(msgsnd, void, tl) DEF_HELPER_2(msgclr, void, env, tl) DEF_HELPER_1(book3s_msgsnd, void, tl) diff --git a/target/ppc/int_helper.c b/target/ppc/int_helper.c index 9bc327bcba..d7765fd3e3 100644 --- a/target/ppc/int_helper.c +++ b/target/ppc/int_helper.c @@ -488,27 +488,6 @@ target_ulong helper_divso(CPUPPCState *env, target_ulong arg1, } } -/*****************************************************************************/ -/* 602 specific instructions */ -/* mfrom is the most crazy instruction ever seen, imho ! */ -/* Real implementation uses a ROM table. Do the same */ -/* - * Extremely decomposed: - * -arg / 256 - * return 256 * log10(10 + 1.0) + 0.5 - */ -#if !defined(CONFIG_USER_ONLY) -target_ulong helper_602_mfrom(target_ulong arg) -{ - if (likely(arg < 602)) { -#include "mfrom_table.c.inc" - return mfrom_ROM_table[arg]; - } else { - return 0; - } -} -#endif - /*****************************************************************************/ /* Altivec extension helpers */ #if defined(HOST_WORDS_BIGENDIAN) diff --git a/target/ppc/mfrom_table.c.inc b/target/ppc/mfrom_table.c.inc deleted file mode 100644 index 1653b974a4..0000000000 --- a/target/ppc/mfrom_table.c.inc +++ /dev/null @@ -1,78 +0,0 @@ -static const uint8_t mfrom_ROM_table[602] = { - 77, 77, 76, 76, 75, 75, 74, 74, - 73, 73, 72, 72, 71, 71, 70, 70, - 69, 69, 68, 68, 68, 67, 67, 66, - 66, 65, 65, 64, 64, 64, 63, 63, - 62, 62, 61, 61, 61, 60, 60, 59, - 59, 58, 58, 58, 57, 57, 56, 56, - 56, 55, 55, 54, 54, 54, 53, 53, - 53, 52, 52, 51, 51, 51, 50, 50, - 50, 49, 49, 49, 48, 48, 47, 47, - 47, 46, 46, 46, 45, 45, 45, 44, - 44, 44, 43, 43, 43, 42, 42, 42, - 42, 41, 41, 41, 40, 40, 40, 39, - 39, 39, 39, 38, 38, 38, 37, 37, - 37, 37, 36, 36, 36, 35, 35, 35, - 35, 34, 34, 34, 34, 33, 33, 33, - 33, 32, 32, 32, 32, 31, 31, 31, - 31, 30, 30, 30, 30, 29, 29, 29, - 29, 28, 28, 28, 28, 28, 27, 27, - 27, 27, 26, 26, 26, 26, 26, 25, - 25, 25, 25, 25, 24, 24, 24, 24, - 24, 23, 23, 23, 23, 23, 23, 22, - 22, 22, 22, 22, 21, 21, 21, 21, - 21, 21, 20, 20, 20, 20, 20, 20, - 19, 19, 19, 19, 19, 19, 19, 18, - 18, 18, 18, 18, 18, 17, 17, 17, - 17, 17, 17, 17, 16, 16, 16, 16, - 16, 16, 16, 16, 15, 15, 15, 15, - 15, 15, 15, 15, 14, 14, 14, 14, - 14, 14, 14, 14, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, - 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, - 7, 6, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 3, - 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 0, -}; diff --git a/target/ppc/mfrom_table_gen.c b/target/ppc/mfrom_table_gen.c deleted file mode 100644 index f96c4268ba..0000000000 --- a/target/ppc/mfrom_table_gen.c +++ /dev/null @@ -1,34 +0,0 @@ -#define _GNU_SOURCE -#include "qemu/osdep.h" -#include - -int main(void) -{ - double d; - uint8_t n; - int i; - - printf("static const uint8_t mfrom_ROM_table[602] =\n{\n "); - for (i = 0; i < 602; i++) { - /* - * Extremely decomposed: - * -T0 / 256 - * T0 = 256 * log10(10 + 1.0) + 0.5 - */ - d = -i; - d /= 256.0; - d = exp10(d); - d += 1.0; - d = log10(d); - d *= 256; - d += 0.5; - n = d; - printf("%3d, ", n); - if ((i & 7) == 7) { - printf("\n "); - } - } - printf("\n};\n"); - - return 0; -} diff --git a/target/ppc/translate.c b/target/ppc/translate.c index d61c6f0e8f..c2f436f8d3 100644 --- a/target/ppc/translate.c +++ b/target/ppc/translate.c @@ -6272,33 +6272,6 @@ static void gen_srq(DisasContext *ctx) } } -/* PowerPC 602 specific instructions */ - -/* dsa */ -static void gen_dsa(DisasContext *ctx) -{ - /* XXX: TODO */ - gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL); -} - -/* esa */ -static void gen_esa(DisasContext *ctx) -{ - /* XXX: TODO */ - gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL); -} - -/* mfrom */ -static void gen_mfrom(DisasContext *ctx) -{ -#if defined(CONFIG_USER_ONLY) - GEN_PRIV; -#else - CHK_SV; - gen_helper_602_mfrom(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]); -#endif /* defined(CONFIG_USER_ONLY) */ -} - /* 602 - 603 - G2 TLB management */ /* tlbld */ @@ -7779,9 +7752,6 @@ GEN_HANDLER(sriq, 0x1F, 0x18, 0x15, 0x00000000, PPC_POWER_BR), GEN_HANDLER(srliq, 0x1F, 0x18, 0x17, 0x00000000, PPC_POWER_BR), GEN_HANDLER(srlq, 0x1F, 0x18, 0x16, 0x00000000, PPC_POWER_BR), GEN_HANDLER(srq, 0x1F, 0x18, 0x14, 0x00000000, PPC_POWER_BR), -GEN_HANDLER(dsa, 0x1F, 0x14, 0x13, 0x03FFF801, PPC_602_SPEC), -GEN_HANDLER(esa, 0x1F, 0x14, 0x12, 0x03FFF801, PPC_602_SPEC), -GEN_HANDLER(mfrom, 0x1F, 0x09, 0x08, 0x03E0F801, PPC_602_SPEC), GEN_HANDLER2(tlbld_6xx, "tlbld", 0x1F, 0x12, 0x1E, 0x03FF0001, PPC_6xx_TLB), GEN_HANDLER2(tlbli_6xx, "tlbli", 0x1F, 0x12, 0x1F, 0x03FF0001, PPC_6xx_TLB), GEN_HANDLER(clf, 0x1F, 0x16, 0x03, 0x03E00000, PPC_POWER),