From 19ac7b29f81196dc20c9d97cf36f9004fa7e60c4 Mon Sep 17 00:00:00 2001 From: BALATON Zoltan Date: Wed, 19 Jul 2023 02:32:54 +0200 Subject: [PATCH 1/7] ppc/pegasos2: Fix reset state of USB functions The original non-free board firmware sets the command register of the USB functions to 7 and some guests rely on this for working USB. Match what the board firmware does when using VOF instead. Signed-off-by: BALATON Zoltan Reviewed-by: Daniel Henrique Barboza Message-ID: <06a2b864431425f23d1f2b5abf0c027819ac11c6.1689725688.git.balaton@eik.bme.hu> Signed-off-by: Daniel Henrique Barboza --- hw/ppc/pegasos2.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/hw/ppc/pegasos2.c b/hw/ppc/pegasos2.c index 4447bbe8ec..4a2ab35f19 100644 --- a/hw/ppc/pegasos2.c +++ b/hw/ppc/pegasos2.c @@ -324,9 +324,13 @@ static void pegasos2_machine_reset(MachineState *machine, ShutdownCause reason) pegasos2_pci_config_write(pm, 1, (PCI_DEVFN(12, 2) << 8) | PCI_INTERRUPT_LINE, 2, 0x409); + pegasos2_pci_config_write(pm, 1, (PCI_DEVFN(12, 2) << 8) | + PCI_COMMAND, 2, 0x7); pegasos2_pci_config_write(pm, 1, (PCI_DEVFN(12, 3) << 8) | PCI_INTERRUPT_LINE, 2, 0x409); + pegasos2_pci_config_write(pm, 1, (PCI_DEVFN(12, 3) << 8) | + PCI_COMMAND, 2, 0x7); pegasos2_pci_config_write(pm, 1, (PCI_DEVFN(12, 4) << 8) | PCI_INTERRUPT_LINE, 2, 0x9); From aa1133475e0fdea0ab7d994c0a62b74d575cfcce Mon Sep 17 00:00:00 2001 From: BALATON Zoltan Date: Wed, 19 Jul 2023 02:32:55 +0200 Subject: [PATCH 2/7] ppc/pegasos2: Fix reg property of ROM BARs The register offset of the ROM BAR is 0x30 not 0x28. This fixes the reg property entry of the ROM region in the device tree. Signed-off-by: BALATON Zoltan Reviewed-by: Daniel Henrique Barboza Message-ID: <6abd73b1211f9d0776dfa5d71d6294f17eecb426.1689725688.git.balaton@eik.bme.hu> Signed-off-by: Daniel Henrique Barboza --- hw/ppc/pegasos2.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/hw/ppc/pegasos2.c b/hw/ppc/pegasos2.c index 4a2ab35f19..8ed13a42a2 100644 --- a/hw/ppc/pegasos2.c +++ b/hw/ppc/pegasos2.c @@ -766,7 +766,11 @@ static void add_pci_device(PCIBus *bus, PCIDevice *d, void *opaque) if (!d->io_regions[i].size) { continue; } - cells[j] = cpu_to_be32(d->devfn << 8 | (PCI_BASE_ADDRESS_0 + i * 4)); + cells[j] = PCI_BASE_ADDRESS_0 + i * 4; + if (cells[j] == 0x28) { + cells[j] = 0x30; + } + cells[j] = cpu_to_be32(d->devfn << 8 | cells[j]); if (d->io_regions[i].type & PCI_BASE_ADDRESS_SPACE_IO) { cells[j] |= cpu_to_be32(1 << 24); } else { From 889dd6c525852e341c737aaca273a92fae05886f Mon Sep 17 00:00:00 2001 From: BALATON Zoltan Date: Wed, 19 Jul 2023 02:32:56 +0200 Subject: [PATCH 3/7] ppc/pegasos2: Fix naming of device tree nodes The board firmware names devices by their class so match that for common devices. Also make sure the /rtas node has a name. This is needed because VOF otherwise does not include it in results got by nextprop which is how AmigaOS queries it and fails if no name property is found. Signed-off-by: BALATON Zoltan Reviewed-by: Daniel Henrique Barboza Message-ID: <808ade37aa141563d1ee349254151672bf7a5d59.1689725688.git.balaton@eik.bme.hu> Signed-off-by: Daniel Henrique Barboza --- hw/ppc/pegasos2.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/hw/ppc/pegasos2.c b/hw/ppc/pegasos2.c index 8ed13a42a2..6475acfbed 100644 --- a/hw/ppc/pegasos2.c +++ b/hw/ppc/pegasos2.c @@ -739,6 +739,13 @@ static void add_pci_device(PCIBus *bus, PCIDevice *d, void *opaque) pci_get_word(&d->config[PCI_VENDOR_ID]), pci_get_word(&d->config[PCI_DEVICE_ID])); + if (pci_get_word(&d->config[PCI_CLASS_DEVICE]) == + PCI_CLASS_NETWORK_ETHERNET) { + name = "ethernet"; + } else if (pci_get_word(&d->config[PCI_CLASS_DEVICE]) >> 8 == + PCI_BASE_CLASS_DISPLAY) { + name = "display"; + } for (i = 0; device_map[i].id; i++) { if (!strcmp(pn, device_map[i].id)) { name = device_map[i].name; @@ -929,6 +936,7 @@ static void *build_fdt(MachineState *machine, int *fdt_size) qemu_fdt_setprop_cell(fdt, "/rtas", "rtas-display-device", 0); qemu_fdt_setprop_cell(fdt, "/rtas", "rtas-size", 20); qemu_fdt_setprop_cell(fdt, "/rtas", "rtas-version", 1); + qemu_fdt_setprop_string(fdt, "/rtas", "name", "rtas"); /* cpus */ qemu_fdt_add_subnode(fdt, "/cpus"); From 6b6d4c1a0116c51098975131c16ecf7cefe68e79 Mon Sep 17 00:00:00 2001 From: BALATON Zoltan Date: Sat, 22 Jul 2023 00:13:20 +0200 Subject: [PATCH 4/7] ppc/pegasos2: Fix reg property of 64 bit BARs in device tree The board firmware handles this correctly following the Open Firmware standard which we missed. This fixes 64 bit BARs when using VOF. Signed-off-by: BALATON Zoltan Reviewed-by: Daniel Henrique Barboza Message-ID: <20230721221320.1311E7456AB@zero.eik.bme.hu> Signed-off-by: Daniel Henrique Barboza --- hw/ppc/pegasos2.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/hw/ppc/pegasos2.c b/hw/ppc/pegasos2.c index 6475acfbed..075367d94d 100644 --- a/hw/ppc/pegasos2.c +++ b/hw/ppc/pegasos2.c @@ -781,7 +781,11 @@ static void add_pci_device(PCIBus *bus, PCIDevice *d, void *opaque) if (d->io_regions[i].type & PCI_BASE_ADDRESS_SPACE_IO) { cells[j] |= cpu_to_be32(1 << 24); } else { - cells[j] |= cpu_to_be32(2 << 24); + if (d->io_regions[i].type & PCI_BASE_ADDRESS_MEM_TYPE_64) { + cells[j] |= cpu_to_be32(3 << 24); + } else { + cells[j] |= cpu_to_be32(2 << 24); + } if (d->io_regions[i].type & PCI_BASE_ADDRESS_MEM_PREFETCH) { cells[j] |= cpu_to_be32(4 << 28); } From 9201af096962a1967ce5d0b270ed16ae4edd3db6 Mon Sep 17 00:00:00 2001 From: Nicholas Piggin Date: Thu, 27 Jul 2023 04:22:25 +1000 Subject: [PATCH 5/7] target/ppc: Implement ASDR register for ISA v3.0 for HPT MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The ASDR register was introduced in ISA v3.0. It has not been implemented for HPT. With HPT, ASDR is the format of the slbmte RS operand (containing VSID), which matches the ppc_slb_t field. Fixes: 3367c62f522b ("target/ppc: Support for POWER9 native hash") Signed-off-by: Nicholas Piggin Reviewed-by: Cédric Le Goater Message-ID: <20230726182230.433945-2-npiggin@gmail.com> Signed-off-by: Daniel Henrique Barboza --- target/ppc/mmu-hash64.c | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/target/ppc/mmu-hash64.c b/target/ppc/mmu-hash64.c index 900f906990..a0c90df3ce 100644 --- a/target/ppc/mmu-hash64.c +++ b/target/ppc/mmu-hash64.c @@ -770,7 +770,8 @@ static bool ppc_hash64_use_vrma(CPUPPCState *env) } } -static void ppc_hash64_set_isi(CPUState *cs, int mmu_idx, uint64_t error_code) +static void ppc_hash64_set_isi(CPUState *cs, int mmu_idx, uint64_t slb_vsid, + uint64_t error_code) { CPUPPCState *env = &POWERPC_CPU(cs)->env; bool vpm; @@ -782,13 +783,15 @@ static void ppc_hash64_set_isi(CPUState *cs, int mmu_idx, uint64_t error_code) } if (vpm && !mmuidx_hv(mmu_idx)) { cs->exception_index = POWERPC_EXCP_HISI; + env->spr[SPR_ASDR] = slb_vsid; } else { cs->exception_index = POWERPC_EXCP_ISI; } env->error_code = error_code; } -static void ppc_hash64_set_dsi(CPUState *cs, int mmu_idx, uint64_t dar, uint64_t dsisr) +static void ppc_hash64_set_dsi(CPUState *cs, int mmu_idx, uint64_t slb_vsid, + uint64_t dar, uint64_t dsisr) { CPUPPCState *env = &POWERPC_CPU(cs)->env; bool vpm; @@ -802,6 +805,7 @@ static void ppc_hash64_set_dsi(CPUState *cs, int mmu_idx, uint64_t dar, uint64_t cs->exception_index = POWERPC_EXCP_HDSI; env->spr[SPR_HDAR] = dar; env->spr[SPR_HDSISR] = dsisr; + env->spr[SPR_ASDR] = slb_vsid; } else { cs->exception_index = POWERPC_EXCP_DSI; env->spr[SPR_DAR] = dar; @@ -963,13 +967,13 @@ bool ppc_hash64_xlate(PowerPCCPU *cpu, vaddr eaddr, MMUAccessType access_type, } switch (access_type) { case MMU_INST_FETCH: - ppc_hash64_set_isi(cs, mmu_idx, SRR1_PROTFAULT); + ppc_hash64_set_isi(cs, mmu_idx, 0, SRR1_PROTFAULT); break; case MMU_DATA_LOAD: - ppc_hash64_set_dsi(cs, mmu_idx, eaddr, DSISR_PROTFAULT); + ppc_hash64_set_dsi(cs, mmu_idx, 0, eaddr, DSISR_PROTFAULT); break; case MMU_DATA_STORE: - ppc_hash64_set_dsi(cs, mmu_idx, eaddr, + ppc_hash64_set_dsi(cs, mmu_idx, 0, eaddr, DSISR_PROTFAULT | DSISR_ISSTORE); break; default: @@ -1022,7 +1026,7 @@ bool ppc_hash64_xlate(PowerPCCPU *cpu, vaddr eaddr, MMUAccessType access_type, /* 3. Check for segment level no-execute violation */ if (access_type == MMU_INST_FETCH && (slb->vsid & SLB_VSID_N)) { if (guest_visible) { - ppc_hash64_set_isi(cs, mmu_idx, SRR1_NOEXEC_GUARD); + ppc_hash64_set_isi(cs, mmu_idx, slb->vsid, SRR1_NOEXEC_GUARD); } return false; } @@ -1035,13 +1039,14 @@ bool ppc_hash64_xlate(PowerPCCPU *cpu, vaddr eaddr, MMUAccessType access_type, } switch (access_type) { case MMU_INST_FETCH: - ppc_hash64_set_isi(cs, mmu_idx, SRR1_NOPTE); + ppc_hash64_set_isi(cs, mmu_idx, slb->vsid, SRR1_NOPTE); break; case MMU_DATA_LOAD: - ppc_hash64_set_dsi(cs, mmu_idx, eaddr, DSISR_NOPTE); + ppc_hash64_set_dsi(cs, mmu_idx, slb->vsid, eaddr, DSISR_NOPTE); break; case MMU_DATA_STORE: - ppc_hash64_set_dsi(cs, mmu_idx, eaddr, DSISR_NOPTE | DSISR_ISSTORE); + ppc_hash64_set_dsi(cs, mmu_idx, slb->vsid, eaddr, + DSISR_NOPTE | DSISR_ISSTORE); break; default: g_assert_not_reached(); @@ -1075,7 +1080,7 @@ bool ppc_hash64_xlate(PowerPCCPU *cpu, vaddr eaddr, MMUAccessType access_type, if (PAGE_EXEC & ~amr_prot) { srr1 |= SRR1_IAMR; /* Access violates virt pg class key prot */ } - ppc_hash64_set_isi(cs, mmu_idx, srr1); + ppc_hash64_set_isi(cs, mmu_idx, slb->vsid, srr1); } else { int dsisr = 0; if (need_prot & ~pp_prot) { @@ -1087,7 +1092,7 @@ bool ppc_hash64_xlate(PowerPCCPU *cpu, vaddr eaddr, MMUAccessType access_type, if (need_prot & ~amr_prot) { dsisr |= DSISR_AMR; } - ppc_hash64_set_dsi(cs, mmu_idx, eaddr, dsisr); + ppc_hash64_set_dsi(cs, mmu_idx, slb->vsid, eaddr, dsisr); } return false; } From 9915dac4847f3cc5ffd36e4c374a4eec83fe09b5 Mon Sep 17 00:00:00 2001 From: Nicholas Piggin Date: Thu, 27 Jul 2023 04:22:27 +1000 Subject: [PATCH 6/7] target/ppc: Fix pending HDEC when entering PM state MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit HDEC is defined to not wake from PM state. There is a check in the HDEC timer to avoid setting the interrupt if we are in a PM state, but no check on PM entry to lower HDEC if it already fired. This can cause a HDECR wake up and QEMU abort with unsupported exception in Power Save mode. Fixes: 4b236b621bf ("ppc: Initial HDEC support") Signed-off-by: Nicholas Piggin Reviewed-by: Cédric Le Goater Message-ID: <20230726182230.433945-4-npiggin@gmail.com> Signed-off-by: Daniel Henrique Barboza --- target/ppc/excp_helper.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c index 003805b202..9aa8e46566 100644 --- a/target/ppc/excp_helper.c +++ b/target/ppc/excp_helper.c @@ -2685,6 +2685,12 @@ void helper_pminsn(CPUPPCState *env, uint32_t insn) env->resume_as_sreset = (insn != PPC_PM_STOP) || (env->spr[SPR_PSSCR] & PSSCR_EC); + /* HDECR is not to wake from PM state, it may have already fired */ + if (env->resume_as_sreset) { + PowerPCCPU *cpu = env_archcpu(env); + ppc_set_irq(cpu, PPC_INTERRUPT_HDECR, 0); + } + ppc_maybe_interrupt(env); } #endif /* defined(TARGET_PPC64) */ From 0e2a3ec36885f6d79a96230f582d4455878c6373 Mon Sep 17 00:00:00 2001 From: Nicholas Piggin Date: Sun, 30 Jul 2023 21:18:42 +1000 Subject: [PATCH 7/7] target/ppc: Fix VRMA page size for ISA v3.0 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Until v2.07s, the VRMA page size (L||LP) was encoded in LPCR[VRMASD]. In v3.0 that moved to the partition table PS field. The powernv machine can now run KVM HPT guests on POWER9/10 CPUs with this fix and the patch to add ASDR. Fixes: 3367c62f522b ("target/ppc: Support for POWER9 native hash") Signed-off-by: Nicholas Piggin Reviewed-by: Cédric Le Goater Message-ID: <20230730111842.39292-1-npiggin@gmail.com> Signed-off-by: Daniel Henrique Barboza --- target/ppc/mmu-hash64.c | 45 +++++++++++++++++++++++++++++++++++------ target/ppc/mmu-hash64.h | 5 +++++ 2 files changed, 44 insertions(+), 6 deletions(-) diff --git a/target/ppc/mmu-hash64.c b/target/ppc/mmu-hash64.c index a0c90df3ce..d645c0bb94 100644 --- a/target/ppc/mmu-hash64.c +++ b/target/ppc/mmu-hash64.c @@ -874,12 +874,46 @@ static target_ulong rmls_limit(PowerPCCPU *cpu) return rma_sizes[rmls]; } -static int build_vrma_slbe(PowerPCCPU *cpu, ppc_slb_t *slb) +/* Return the LLP in SLB_VSID format */ +static uint64_t get_vrma_llp(PowerPCCPU *cpu) { CPUPPCState *env = &cpu->env; - target_ulong lpcr = env->spr[SPR_LPCR]; - uint32_t vrmasd = (lpcr & LPCR_VRMASD) >> LPCR_VRMASD_SHIFT; - target_ulong vsid = SLB_VSID_VRMA | ((vrmasd << 4) & SLB_VSID_LLP_MASK); + uint64_t llp; + + if (env->mmu_model == POWERPC_MMU_3_00) { + ppc_v3_pate_t pate; + uint64_t ps, l, lp; + + /* + * ISA v3.0 removes the LPCR[VRMASD] field and puts the VRMA base + * page size (L||LP equivalent) in the PS field in the HPT partition + * table entry. + */ + if (!ppc64_v3_get_pate(cpu, cpu->env.spr[SPR_LPIDR], &pate)) { + error_report("Bad VRMA with no partition table entry"); + return 0; + } + ps = PATE0_GET_PS(pate.dw0); + /* PS has L||LP in 3 consecutive bits, put them into SLB LLP format */ + l = (ps >> 2) & 0x1; + lp = ps & 0x3; + llp = (l << SLB_VSID_L_SHIFT) | (lp << SLB_VSID_LP_SHIFT); + + } else { + uint64_t lpcr = env->spr[SPR_LPCR]; + target_ulong vrmasd = (lpcr & LPCR_VRMASD) >> LPCR_VRMASD_SHIFT; + + /* VRMASD LLP matches SLB format, just shift and mask it */ + llp = (vrmasd << SLB_VSID_LP_SHIFT) & SLB_VSID_LLP_MASK; + } + + return llp; +} + +static int build_vrma_slbe(PowerPCCPU *cpu, ppc_slb_t *slb) +{ + uint64_t llp = get_vrma_llp(cpu); + target_ulong vsid = SLB_VSID_VRMA | llp; int i; for (i = 0; i < PPC_PAGE_SIZES_MAX_SZ; i++) { @@ -897,8 +931,7 @@ static int build_vrma_slbe(PowerPCCPU *cpu, ppc_slb_t *slb) } } - error_report("Bad page size encoding in LPCR[VRMASD]; LPCR=0x" - TARGET_FMT_lx, lpcr); + error_report("Bad VRMA page size encoding 0x" TARGET_FMT_lx, llp); return -1; } diff --git a/target/ppc/mmu-hash64.h b/target/ppc/mmu-hash64.h index 1496955d38..de653fcae5 100644 --- a/target/ppc/mmu-hash64.h +++ b/target/ppc/mmu-hash64.h @@ -41,8 +41,10 @@ void ppc_hash64_finalize(PowerPCCPU *cpu); #define SLB_VSID_KP 0x0000000000000400ULL #define SLB_VSID_N 0x0000000000000200ULL /* no-execute */ #define SLB_VSID_L 0x0000000000000100ULL +#define SLB_VSID_L_SHIFT PPC_BIT_NR(55) #define SLB_VSID_C 0x0000000000000080ULL /* class */ #define SLB_VSID_LP 0x0000000000000030ULL +#define SLB_VSID_LP_SHIFT PPC_BIT_NR(59) #define SLB_VSID_ATTR 0x0000000000000FFFULL #define SLB_VSID_LLP_MASK (SLB_VSID_L | SLB_VSID_LP) #define SLB_VSID_4K 0x0000000000000000ULL @@ -58,6 +60,9 @@ void ppc_hash64_finalize(PowerPCCPU *cpu); #define SDR_64_HTABSIZE 0x000000000000001FULL #define PATE0_HTABORG 0x0FFFFFFFFFFC0000ULL +#define PATE0_PS PPC_BITMASK(56, 58) +#define PATE0_GET_PS(dw0) (((dw0) & PATE0_PS) >> PPC_BIT_NR(58)) + #define HPTES_PER_GROUP 8 #define HASH_PTE_SIZE_64 16 #define HASH_PTEG_SIZE_64 (HASH_PTE_SIZE_64 * HPTES_PER_GROUP)