Merge tag 'pull-ppc-for-11.1-sf-20260706' of https://gitlab.com/harshpb/qemu into staging

PPC PR for 11.1 Soft-freeze

# -----BEGIN PGP SIGNATURE-----
#
# iQIzBAABCAAdFiEEa4EM1tK+EPOIPSFCRUTplPnWj7sFAmpLZTwACgkQRUTplPnW
# j7vb/w//XmleEwlL+p+YKndc4Su+qj9c3lApEFEiFi78biATrXpFTNbOxhOpWdv4
# jaI1kWyINrTPgnXgHEKNJuhhsSjy5/HURCgkivPnnvhK95mWMi/0f1SzICmc9DCo
# hjDeQfHw5zhF6hu6QknTfcworpsdA9uVtbx0+8s0lMMDmWze2WLg6f9OXioxhseN
# vJoRaJoEo1f/vwwDFOdGngz36p0xD+eUynPTRlOymMJfW271KtNlZqouCCryI92I
# ksaYa+jorE16l608SyG1Yhf/oDSlj9BufFHmgAngvlDwPFglhoJx0kPeKIrT7QE0
# oGzwnOwXJH0lGuwQwISvgrtquD8unY9gTZvrF6NPIPtpMJSE+TGluoNdf/Sr2c3l
# xMG/+yIwHehgXa/Lh4UN3G7yALaIjVdkcSdexuo1pfFemUCwLYPDMGoaksda+SZd
# m4Xd05ZCvp2RZHRNbWheu6TxZKEHKWO8UV8U0zNgKZTz7muVURrtLpoQJFLRq9V7
# krqyeLOePZtGC15a8unAbIVJVK2vOOnoqQPbuqZ57GTVqcmmcTSIEkRDcbMTADKo
# Qv8WEqOWo9OYQvGF/BMP+ed1UiNzGXY2WnVrF40D3K/I/wT11mHbuKZY3gbFZ5At
# 1y2I59EvV/xYHdjBmDoT8smzuQwywSKZnzeKptbIVGFbuPPVFFs=
# =icWo
# -----END PGP SIGNATURE-----
# gpg: Signature made Mon 06 Jul 2026 10:20:12 CEST
# gpg:                using RSA key 6B810CD6D2BE10F3883D21424544E994F9D68FBB
# gpg: Good signature from "Harsh Prateek Bora <harsh.prateek.bora@gmail.com>" [full]
# gpg:                 aka "Harsh Prateek Bora <harshpb@linux.ibm.com>" [full]
# Primary key fingerprint: 6B81 0CD6 D2BE 10F3 883D  2142 4544 E994 F9D6 8FBB

* tag 'pull-ppc-for-11.1-sf-20260706' of https://gitlab.com/harshpb/qemu:
  MAINTAINERS: Add self as maintainer for PowerNV
  ppc/pnv: Remove Power8E and Power8NVL CPUs
  ppc/pnv: Remove Power8E and Power8NVL pnv chips
  ppc/pnv: Replace Power8E with Power11 for 'none' machine test
  tests/functional: Use default powernv machine instead of power10
  tests/qtest: Add Power11 chip & machine to qtests
  tests/qtest/pnv_spi: Test Power11 PNV_SPI
  tests/functional: Add remote interrupts test for PowerNV

Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
This commit is contained in:
Stefan Hajnoczi
2026-07-06 18:36:52 +02:00
21 changed files with 175 additions and 152 deletions

View File

@@ -53,7 +53,7 @@ class QEMUFadump(LinuxKernelTest):
self.require_accelerator("tcg")
if is_powernv:
self.set_machine("powernv10")
self.set_machine("powernv")
else:
# SLOF takes upto >20s in startup time, use VOF
self.set_machine("pseries")

View File

@@ -9,6 +9,7 @@
from qemu_test import LinuxKernelTest, Asset
from qemu_test import wait_for_console_pattern
from qemu_test import exec_command_and_wait_for_pattern
class PowernvMachine(LinuxKernelTest):
@@ -32,6 +33,17 @@ class PowernvMachine(LinuxKernelTest):
('https://github.com/roz3x/qemu/raw/refs/heads/sample-dtb/qemu-powernv11.dtb'),
'ea1271516264eea1eb58a067a99d0c2ca9528be8dc7d4e46bb2d5ae0d42fc568')
def shell_exec_command_check_fail(self, command):
fail_msg="Fail"
self.shell_exec_command(f"export __FAIL_MSG={fail_msg}")
# If the exit code for the command is non 0, print fail message
command = command + " || echo $__FAIL_MSG"
exec_command_and_wait_for_pattern(self, command, '#', fail_msg)
def shell_exec_command(self, command):
exec_command_and_wait_for_pattern(self, command, '#', self.panic_message)
def do_test_linux_boot(self, command_line = KERNEL_COMMON_COMMAND_LINE):
self.require_accelerator("tcg")
kernel_path = self.ASSET_KERNEL.fetch()
@@ -76,6 +88,89 @@ class PowernvMachine(LinuxKernelTest):
wait_for_console_pattern(self, console_pattern, self.panic_message)
wait_for_console_pattern(self, self.good_message, self.panic_message)
def test_linux_remote_interrupts(self):
self.require_accelerator("tcg")
self.set_machine('powernv')
# Have below setup in this test:
# 1. e1000e attached to pcie.6, which is from 7th PHB, belonging to 2nd
# socket (chip 1), in a powernv boot with default 6 PHBs per socket
# 2. CPU on 2nd socket (chip 1) disabled
# 3. RX IRQ's affinity to chip 2, and TX IRQ's affinity to chip 3
#
# Then ping is done, to generate interrupts from e1000e which should go
# to IRQ server on the remote sockets
self.vm.add_args('-smp', '4,sockets=4,cores=1,threads=1')
self.vm.add_args('-netdev', 'user,id=net0')
self.vm.add_args('-device', 'e1000e,netdev=net0,bus=pcie.6')
kernel_path = self.ASSET_KERNEL.fetch()
rootfs_path = self.ASSET_INITRD.fetch()
self.vm.set_console()
self.vm.add_args('-kernel', kernel_path,
'-drive',
f'file={rootfs_path},format=raw,if=none,id=drive0,readonly=on',
'-append', 'root=/dev/nvme0n1 console=hvc0',
'-device', 'nvme,drive=drive0,bus=pcie.2,addr=0x0,serial=1234')
self.vm.launch()
# Wait for boot to complete
console_pattern = 'CPU maps initialized for 1 thread per core'
wait_for_console_pattern(self, console_pattern, self.panic_message)
console_pattern = 'smp: Brought up 4 nodes, 4 CPUs'
wait_for_console_pattern(self, console_pattern, self.panic_message)
wait_for_console_pattern(self, 'Run /sbin/init as init process',
self.panic_message)
# Wait for login prompt and login as root (no password in buildroot)
wait_for_console_pattern(self, 'login:', self.panic_message)
exec_command_and_wait_for_pattern(self, 'root', '#', self.panic_message)
# e1000e is connected to socket 1, disable the CPU on socket 1
self.shell_exec_command("echo 0 > /sys/devices/system/cpu/cpu1/online")
self.shell_exec_command(
"export CPU1_STATE=$(cat /sys/devices/system/cpu/cpu1/online)")
self.shell_exec_command_check_fail("[ $CPU1_STATE -eq 0 ]")
# RX, TX interrupts to chip/cpu 2 & 3 respectively
self.shell_exec_command(
"export RX_IRQ=$(awk '/eth0-rx/ {print $1}' /proc/interrupts | tr -d ':')")
self.shell_exec_command(
"export TX_IRQ=$(awk '/eth0-tx/ {print $1}' /proc/interrupts | tr -d ':')")
self.shell_exec_command("echo 2 > /proc/irq/$RX_IRQ/smp_affinity_list")
self.shell_exec_command("echo 3 > /proc/irq/$TX_IRQ/smp_affinity_list")
# Capture interrupt counts before generating traffic
self.shell_exec_command(
"export RX_BEFORE=$(awk '/eth0-rx/ {print $3}' /proc/interrupts)")
self.shell_exec_command(
"export TX_BEFORE=$(awk '/eth0-tx/ {print $4}' /proc/interrupts)")
# Wait up to 15 seconds for eth0 link to come up
self.shell_exec_command(
"c=0; while ! ip addr show eth0 | grep 'inet 10.0.2'; do "
"sleep 1; c=$((c+1)); [ $c -gt 15 ] && break; done")
self.shell_exec_command_check_fail(
"ip addr show eth0 | grep 'inet 10.0.2'")
# Generate network traffic to trigger remote interrupts
# Ping QEMU's user-mode network gateway (10.0.2.2)
self.shell_exec_command("ping -W2 -c5 10.0.2.2")
# Show final interrupt counts to verify remote interrupts occurred
self.shell_exec_command("cat /proc/interrupts | grep eth0")
# Verify interrupt counts increased (whether interrupts were delivered)
self.shell_exec_command(
"export RX_AFTER=$(awk '/eth0-rx/ {print $3}' /proc/interrupts)")
self.shell_exec_command(
"export TX_AFTER=$(awk '/eth0-tx/ {print $4}' /proc/interrupts)")
# Check that interrupt counts increased
self.shell_exec_command_check_fail("[ $RX_AFTER -gt $RX_BEFORE ]")
self.shell_exec_command_check_fail("[ $TX_AFTER -gt $TX_BEFORE ]")
def test_linux_big_boot(self):
self.set_machine('powernv')
self.vm.add_args('-smp', '16,threads=4,cores=2,sockets=2')

View File

@@ -38,7 +38,7 @@ static struct arch2cpu cpus_map[] = {
{ "mips64el", "I6500" },
{ "or1k", "or1200" },
{ "ppc", "604" },
{ "ppc64", "power8e_v2.1" },
{ "ppc64", "power11_v2.0" },
{ "s390x", "qemu" },
{ "sh4", "sh7750r" },
{ "sh4eb", "sh7751r" },

View File

@@ -402,15 +402,14 @@ static void reset_all(QTestState *qts, const PnvChip *chip)
static void test_host_i2c(const void *data)
{
const PnvChip *chip = data;
const char *machine = pnv_get_machine_type(chip->chip_type);
QTestState *qts;
const char *machine = "powernv8";
PnvI2cCtlr ctlr;
PnvI2cDev pca9552;
PnvI2cDev pca9554;
if (chip->chip_type == PNV_CHIP_POWER9) {
machine = "powernv9";
} else if (chip->chip_type == PNV_CHIP_POWER10) {
/* i2c is initialised for rainier in case of P10 */
if (chip->chip_type == PNV_CHIP_POWER10) {
machine = "powernv10-rainier";
}
@@ -473,10 +472,9 @@ static void add_test(const char *name, void (*test)(const void *data))
int i;
for (i = 0; i < ARRAY_SIZE(pnv_chips); i++) {
char *tname = g_strdup_printf("pnv-xscom/%s/%s", name,
g_autofree char *tname = g_strdup_printf("pnv-xscom/%s/%s", name,
pnv_chips[i].cpu_model);
qtest_add_data_func(tname, &pnv_chips[i], test);
g_free(tname);
}
}

View File

@@ -77,6 +77,7 @@ static void test_spi_seeprom(const void *data)
const PnvChip *chip = data;
QTestState *qts = NULL;
g_autofree char *tmp_path = NULL;
const char *machine = pnv_get_machine_type(chip->chip_type);
int ret;
int fd;
@@ -87,11 +88,11 @@ static void test_spi_seeprom(const void *data)
g_assert(ret == 0);
close(fd);
qts = qtest_initf("-machine powernv10 -smp 2,cores=2,"
qts = qtest_initf("-machine %s -smp 2,cores=2,"
"threads=1 -accel tcg,thread=single -nographic "
"-blockdev node-name=pib_spic2,driver=file,"
"filename=%s -device 25csm04,bus=chip0.spi.2,cs=0,"
"drive=pib_spic2", tmp_path);
"drive=pib_spic2", machine, tmp_path);
spi_seeprom_transaction(qts, chip);
qtest_quit(qts);
unlink(tmp_path);
@@ -100,9 +101,16 @@ static void test_spi_seeprom(const void *data)
int main(int argc, char **argv)
{
g_test_init(&argc, &argv, NULL);
char *tname = g_strdup_printf("pnv-xscom/spi-seeprom/%s",
pnv_chips[3].cpu_model);
qtest_add_data_func(tname, &pnv_chips[3], test_spi_seeprom);
g_free(tname);
for (int i = 0; i < ARRAY_SIZE(pnv_chips); i++) {
/* TYPE_PNV_SPI is not instantiated for older Power8/9 machines */
if (pnv_chips[i].chip_type < PNV_CHIP_POWER10) {
continue;
}
g_autofree char *tname = g_strdup_printf("pnv-xscom/spi-seeprom/%s",
pnv_chips[i].cpu_model);
qtest_add_data_func(tname, &pnv_chips[i], test_spi_seeprom);
}
return g_test_run();
}

View File

@@ -14,6 +14,7 @@
#include "libqtest.h"
#include "pnv-xive2-common.h"
#include "pnv-xscom.h"
#include "hw/intc/pnv_xive2_regs.h"
#include "hw/ppc/xive_regs.h"
#include "hw/ppc/xive2_regs.h"
@@ -544,14 +545,16 @@ static void test_hw_group_irq_backlog(QTestState *qts)
g_assert_cmphex(lsmfb, ==, 0xFF);
}
static void test_xive(void)
static void test_xive(const void *data)
{
const PnvChip *chip = data;
const char *machine = pnv_get_machine_type(chip->chip_type);
QTestState *qts;
qts = qtest_initf("-M powernv10 -smp %d,cores=1,threads=%d -nographic "
qts = qtest_initf("-M %s -smp %d,cores=1,threads=%d -nographic "
"-nodefaults -serial mon:stdio -S "
"-d guest_errors -trace '*xive*'",
SMT, SMT);
machine, SMT, SMT);
init_xive(qts);
test_hw_irq(qts);
@@ -580,6 +583,16 @@ static void test_xive(void)
int main(int argc, char **argv)
{
g_test_init(&argc, &argv, NULL);
qtest_add_func("xive2", test_xive);
for (int i = 0; i < ARRAY_SIZE(pnv_chips); i++) {
/* xive2 exists from Power10 onwards */
if (pnv_chips[i].chip_type < PNV_CHIP_POWER10) {
continue;
}
g_autofree char *tname = g_strdup_printf("pnv-xive2/%s",
pnv_chips[i].cpu_model);
qtest_add_data_func(tname, &pnv_chips[i], test_xive);
}
return g_test_run();
}

View File

@@ -28,15 +28,9 @@ static void test_xscom_cfam_id(QTestState *qts, const PnvChip *chip)
static void test_cfam_id(const void *data)
{
const PnvChip *chip = data;
const char *machine = "powernv8";
const char *machine = pnv_get_machine_type(chip->chip_type);
QTestState *qts;
if (chip->chip_type == PNV_CHIP_POWER9) {
machine = "powernv9";
} else if (chip->chip_type == PNV_CHIP_POWER10) {
machine = "powernv10";
}
qts = qtest_initf("-M %s -accel tcg -cpu %s",
machine, chip->cpu_model);
test_xscom_cfam_id(qts, chip);
@@ -57,7 +51,8 @@ static void test_cfam_id(const void *data)
static void test_xscom_core(QTestState *qts, const PnvChip *chip)
{
if (chip->chip_type == PNV_CHIP_POWER10) {
if ((chip->chip_type == PNV_CHIP_POWER10) ||
(chip->chip_type == PNV_CHIP_POWER11)) {
uint32_t first_core_thread_state =
PNV_XSCOM_P10_EC_BASE(chip->first_core) + 0x412;
uint64_t thread_state;
@@ -84,14 +79,8 @@ static void test_xscom_core(QTestState *qts, const PnvChip *chip)
static void test_core(const void *data)
{
const PnvChip *chip = data;
const char *machine = pnv_get_machine_type(chip->chip_type);
QTestState *qts;
const char *machine = "powernv8";
if (chip->chip_type == PNV_CHIP_POWER9) {
machine = "powernv9";
} else if (chip->chip_type == PNV_CHIP_POWER10) {
machine = "powernv10";
}
qts = qtest_initf("-M %s -accel tcg -cpu %s",
machine, chip->cpu_model);
@@ -104,10 +93,9 @@ static void add_test(const char *name, void (*test)(const void *data))
int i;
for (i = 0; i < ARRAY_SIZE(pnv_chips); i++) {
char *tname = g_strdup_printf("pnv-xscom/%s/%s", name,
g_autofree char *tname = g_strdup_printf("pnv-xscom/%s/%s", name,
pnv_chips[i].cpu_model);
qtest_add_data_func(tname, &pnv_chips[i], test);
g_free(tname);
}
}

View File

@@ -12,11 +12,10 @@
#define SMT 4 /* some tests will break if less than 4 */
typedef enum PnvChipType {
PNV_CHIP_POWER8E, /* AKA Murano (default) */
PNV_CHIP_POWER8, /* AKA Venice */
PNV_CHIP_POWER8NVL, /* AKA Naples */
PNV_CHIP_POWER9, /* AKA Nimbus */
PNV_CHIP_POWER10,
PNV_CHIP_POWER11,
} PnvChipType;
typedef struct PnvChip {
@@ -36,13 +35,6 @@ static const PnvChip pnv_chips[] = {
.cfam_id = 0x220ea04980000000ull,
.first_core = 0x1,
.num_i2c = 0,
}, {
.chip_type = PNV_CHIP_POWER8NVL,
.cpu_model = "POWER8NVL",
.xscom_base = 0x0003fc0000000000ull,
.cfam_id = 0x120d304980000000ull,
.first_core = 0x1,
.num_i2c = 0,
},
{
.chip_type = PNV_CHIP_POWER9,
@@ -60,15 +52,23 @@ static const PnvChip pnv_chips[] = {
.first_core = 0x0,
.num_i2c = 4,
},
{
.chip_type = PNV_CHIP_POWER11,
.cpu_model = "Power11",
.xscom_base = 0x000603fc00000000ull,
.cfam_id = 0x220da04980000000ull,
.first_core = 0x0,
.num_i2c = 0,
},
};
static inline uint64_t pnv_xscom_addr(const PnvChip *chip, uint32_t pcba)
{
uint64_t addr = chip->xscom_base;
if (chip->chip_type == PNV_CHIP_POWER10) {
addr |= ((uint64_t) pcba << 3);
} else if (chip->chip_type == PNV_CHIP_POWER9) {
if ((chip->chip_type == PNV_CHIP_POWER11) ||
(chip->chip_type == PNV_CHIP_POWER10) ||
(chip->chip_type == PNV_CHIP_POWER9)) {
addr |= ((uint64_t) pcba << 3);
} else {
addr |= (((uint64_t) pcba << 4) & ~0xffull) |
@@ -77,4 +77,18 @@ static inline uint64_t pnv_xscom_addr(const PnvChip *chip, uint32_t pcba)
return addr;
}
static const char *pnv_get_machine_type(enum PnvChipType chip_type)
{
static const char *const machine_types[] = {
[PNV_CHIP_POWER8] = "powernv8",
[PNV_CHIP_POWER9] = "powernv9",
[PNV_CHIP_POWER10] = "powernv10",
[PNV_CHIP_POWER11] = "powernv11",
};
g_assert(chip_type <= PNV_CHIP_POWER11);
return machine_types[chip_type];
}
#endif /* PNV_XSCOM_H */