@samitouri / QOSamiQemu / commits / 504810bbdf

powernv: boot OpenBSD on POWER9

The POWER9 Processor User's Manual, section 4.9.4, specifies that POWER9 ignores PTCR[PATS] and only supports a 64 KiB partition table. Use an effective PATS value of 4 on POWER9; other processors keep the existing ISA v3.0 interpretation. The PSI model now exposes POWER9 IRQ level and pending status registers, and keeps both updated while delivering through the existing XIVE LSI source. This lets guests that select the POWER9 PSI LSI IRQ method continue to receive LPC interrupts. The blast radius is probably minimal: the PTCR change is limited to POWER9, while the PSI change only touches POWER9 PSI state and reuses the existing delivery path. Acked-by: Chinmay Rath <rathc@linux.ibm.com> Signed-off-by: Kirill A. Korinsky <kirill@korins.ky> Reviewed-by: Aditya Gupta <adityag@linux.ibm.com> Link: https://lore.kernel.org/qemu-devel/20260719145559.94342-1-kirill@korins.ky Signed-off-by: Harsh Prateek Bora <harshpb@linux.ibm.com>

Kirill A. Korinsky committed Jul 19, 2026 at 16:55 UTC 504810bbdfd9c65a808b4684b2b0f6871f2d8c1c
4 files changed +79 -7
hw/ppc/pnv_psi.c
+8 -3
@@ -688,6 +688,8 @@ static uint64_t pnv_psi_p9_mmio_read(void *opaque, hwaddr addr, unsigned size)
688 case PSIHB9_ESB_CI_BASE:
689 case PSIHB9_ESB_NOTIF_ADDR:
690 case PSIHB9_IVT_OFFSET:
691 + case PSIHB9_IRQ_LEVEL:
692 + case PSIHB9_IRQ_STAT:
693 val = psi->regs[reg];
694 break;
695 default:
@@ -818,17 +820,20 @@ static void pnv_psi_power9_set_irq(void *opaque, int irq, int state)
820 {
821 PnvPsi *psi = opaque;
822 uint64_t irq_method = psi->regs[PSIHB_REG(PSIHB9_INTERRUPT_CONTROL)];
823 + uint64_t irq_bit = PPC_BIT(irq);
824
825 if (irq_method & PSIHB9_IRQ_METHOD) {
826 qemu_log_mask(LOG_GUEST_ERROR, "PSI: LSI IRQ method no supported\n");
827 return;
828 }
829
827 - /* Update LSI levels */
830 + /* Update LSI levels and pending status */
831 if (state) {
829 - psi->regs[PSIHB_REG(PSIHB9_IRQ_LEVEL)] |= PPC_BIT(irq);
832 + psi->regs[PSIHB_REG(PSIHB9_IRQ_LEVEL)] |= irq_bit;
833 + psi->regs[PSIHB_REG(PSIHB9_IRQ_STAT)] |= irq_bit;
834 } else {
831 - psi->regs[PSIHB_REG(PSIHB9_IRQ_LEVEL)] &= ~PPC_BIT(irq);
835 + psi->regs[PSIHB_REG(PSIHB9_IRQ_LEVEL)] &= ~irq_bit;
836 + psi->regs[PSIHB_REG(PSIHB9_IRQ_STAT)] &= ~irq_bit;
837 }
838
839 qemu_set_irq(psi->qirqs[irq], state);
target/ppc/mmu-book3s-v3.c
+17 -4
@@ -23,24 +23,37 @@
23 #include "mmu-hash64.h"
24 #include "mmu-book3s-v3.h"
25
26 +#define PPC64_V3_PATE_SIZE 16 /* two 64-bit words */
27 +
28 bool ppc64_v3_get_pate(PowerPCCPU *cpu, target_ulong lpid, ppc_v3_pate_t *entry)
29 {
30 uint64_t patb = cpu->env.spr[SPR_PTCR] & PTCR_PATB;
31 uint64_t pats = cpu->env.spr[SPR_PTCR] & PTCR_PATS;
32 + uint64_t table_size;
33 + uint64_t entries;
34 +
35 + /*
36 + * The POWER9 Processor User's Manual, section 4.9.4, specifies that
37 + * POWER9 ignores PTCR[PATS] and only supports a 64 KiB partition table.
38 + */
39 + if (cpu->env.excp_model == POWERPC_EXCP_POWER9) {
40 + pats = 4;
41 + }
42 + table_size = 1ULL << (pats + 12);
43
44 /* Check if partition table is properly aligned */
32 - if (patb & MAKE_64BIT_MASK(0, pats + 12)) {
45 + if (patb & (table_size - 1)) {
46 return false;
47 }
48
49 /* Calculate number of entries */
37 - pats = 1ull << (pats + 12 - 4);
38 - if (pats <= lpid) {
50 + entries = table_size / PPC64_V3_PATE_SIZE;
51 + if (entries <= lpid) {
52 return false;
53 }
54
55 /* Grab entry */
43 - patb += 16 * lpid;
56 + patb += PPC64_V3_PATE_SIZE * lpid;
57 entry->dw0 = ldq_phys(CPU(cpu)->as, patb);
58 entry->dw1 = ldq_phys(CPU(cpu)->as, patb + 8);
59 return true;
tests/functional/ppc64/meson.build
+2
@@ -4,6 +4,7 @@ test_ppc64_timeouts = {
4 'fadump' : 480,
5 'hv' : 1000,
6 'mac99' : 120,
7 + 'openbsd' : 240,
8 'powernv' : 480,
9 'pseries' : 480,
10 'replay' : 210,
@@ -20,6 +21,7 @@ tests_ppc64_system_thorough = [
21 'fadump',
22 'hv',
23 'mac99',
24 + 'openbsd',
25 'powernv',
26 'pseries',
27 'replay',
tests/functional/ppc64/test_openbsd.py new
+52
@@ -0,0 +1,52 @@
1 +#!/usr/bin/env python3
2 +#
3 +# Test that OpenBSD boots on a ppc powernv machine and reaches the installer.
4 +#
5 +# SPDX-License-Identifier: GPL-2.0-or-later
6 +
7 +from qemu_test import QemuSystemTest, Asset
8 +from qemu_test import wait_for_console_pattern
9 +
10 +
11 +class OpenBSDPowerNV(QemuSystemTest):
12 +
13 + ASSET_MINIROOT = Asset(
14 + 'https://kirill.korins.ky/pub/qemu-powerpc64-openbsd/miniroot79.img',
15 + '7829e42b75d81cafd732038b9d63228b79c1f5828d8375872a4bb655e1d6b13c')
16 +
17 + ASSET_BOOTKERNEL = Asset(
18 + 'https://kirill.korins.ky/pub/qemu-powerpc64-openbsd/pnor.BOOTKERNEL',
19 + '397ce43ce61910e1a2c4f13d301f957e61513a9ec5371bc3e87d3095411fae7b')
20 +
21 + def test_powernv9_openbsd_installer(self):
22 + self.set_machine('powernv9')
23 + self.require_accelerator('tcg')
24 +
25 + miniroot_path = self.ASSET_MINIROOT.fetch()
26 + bootkernel_path = self.ASSET_BOOTKERNEL.fetch()
27 +
28 + self.vm.set_console()
29 + self.vm.add_args('-cpu', 'power9',
30 + '-accel', 'tcg,thread=single',
31 + '-smp', '1,cores=1,threads=1',
32 + '-m', '2g',
33 + '-kernel', bootkernel_path,
34 + '-device',
35 + 'ich9-ahci,id=sata0,bus=pcie.0,addr=0x0',
36 + '-drive',
37 + f'file={miniroot_path},format=raw,if=none,'
38 + 'id=bootdisk,snapshot=on',
39 + '-device',
40 + 'ide-hd,bus=sata0.0,unit=0,drive=bootdisk,'
41 + 'bootindex=1')
42 + self.vm.launch()
43 +
44 + wait_for_console_pattern(self, 'OpenBSD 7.9 (RAMDISK)', 'panic:')
45 + wait_for_console_pattern(
46 + self,
47 + '(I)nstall, (U)pgrade, (A)utoinstall or (S)hell?',
48 + 'panic:')
49 +
50 +
51 +if __name__ == '__main__':
52 + QemuSystemTest.main()