* [PULL RESEND 00/32] ppc-for-10.2 queue
@ 2025-10-23 12:16 Harsh Prateek Bora
2025-10-23 12:16 ` [PULL 01/32] ppc/spapr: remove deprecated machine pseries-3.0 Harsh Prateek Bora
` (32 more replies)
0 siblings, 33 replies; 39+ messages in thread
From: Harsh Prateek Bora @ 2025-10-23 12:16 UTC (permalink / raw)
To: qemu-devel
The following changes since commit c0e80879c876cbe4cbde43a92403329bcedf2ba0:
Merge tag 'pull-vfio-20251022' of https://github.com/legoater/qemu into staging (2025-10-22 08:01:21 -0500)
are available in the Git repository at:
https://gitlab.com/harshpb/qemu.git tags/pull-ppc-for-10.2-d2-20251023-1
for you to fetch changes up to 3db841bf1194b2720a08df2ee0a6ca517091ad0e:
MAINTAINERS: Add entry for FADump (pSeries) (2025-10-23 17:37:42 +0530)
----------------------------------------------------------------
ppc queue for 10.2
* FADUMP Support for pSeries
* Pegasos II cleanup and Pegasos I emulation
* Deprecation of pseries 3.0 up till 4.2
* Coverity fix for amigaone (CID: 1641398)
----------------------------------------------------------------
Aditya Gupta (8):
hw/ppc: Implement fadump register command
hw/ppc: Trigger Fadump boot if fadump is registered
hw/ppc: Preserve memory regions registered for fadump
hw/ppc: Implement saving CPU state in Fadump
hw/ppc: Pass dump-sizes property for fadump in device tree
hw/ppc: Enable fadump for PSeries
tests/functional: Add test for fadump in PSeries
MAINTAINERS: Add entry for FADump (pSeries)
BALATON Zoltan (13):
ppc/amigaone: Free allocated struct
ppc/vof: Make nextprop behave more like Open Firmware
hw/ppc/pegasos2: Remove explicit name properties from device tree
hw/ppc/pegasos2: Change device tree generation
hw/ppc/pegasos2: Remove fdt pointer from machine state
hw/ppc/pegasos2: Rename mv field in machine state
hw/ppc/pegasos2: Add south bridge pointer in the machine state
hw/ppc/pegasos2: Move PCI IRQ routing setup to a function
hw/ppc/pegasos2: Move hardware specific parts out of machine reset
hw/ppc/pegasos2: Introduce abstract superclass
hw/ppc/pegasos2: Add bus frequency to machine state
hw/ppc/pegasos2: Add Pegasos I emulation
hw/ppc/pegasos2: Add VOF support for pegasos1
Harsh Prateek Bora (5):
ppc/spapr: remove deprecated machine pseries-3.0
ppc/spapr: remove deprecated machine pseries-3.1
ppc/spapr: remove deprecated machine pseries-4.0
ppc/spapr: remove deprecated machine pseries-4.1
ppc/spapr: remove deprecated machine pseries-4.2
Philippe Mathieu-Daudé (6):
hw/ppc/spapr: Remove SpaprMachineClass::nr_xirqs field
hw/ppc/spapr: Inline spapr_dtb_needed()
hw/ppc/spapr: Inline few SPAPR_IRQ_* uses
target/ppc/kvm: Remove kvmppc_get_host_serial() as unused
target/ppc/kvm: Remove kvmppc_get_host_model() as unused
hw/ppc/spapr: Remove SpaprMachineClass::phb_placement callback
MAINTAINERS | 9 +
include/hw/ppc/spapr.h | 27 +-
include/hw/ppc/spapr_fadump.h | 124 +++++
include/hw/ppc/spapr_irq.h | 1 -
target/ppc/kvm_ppc.h | 12 -
hw/ppc/amigaone.c | 2 +-
hw/ppc/pegasos2.c | 769 +++++++++++++++---------------
hw/ppc/spapr.c | 368 +++++---------
hw/ppc/spapr_caps.c | 12 +-
hw/ppc/spapr_events.c | 20 +-
hw/ppc/spapr_fadump.c | 730 ++++++++++++++++++++++++++++
hw/ppc/spapr_hcall.c | 5 -
hw/ppc/spapr_irq.c | 36 +-
hw/ppc/spapr_pci.c | 32 +-
hw/ppc/spapr_rtas.c | 76 +++
hw/ppc/spapr_vio.c | 9 -
hw/ppc/vof.c | 50 +-
target/ppc/kvm.c | 11 -
hw/ppc/meson.build | 1 +
pc-bios/dtb/meson.build | 2 +
pc-bios/dtb/pegasos1.dtb | Bin 0 -> 857 bytes
pc-bios/dtb/pegasos1.dts | 125 +++++
pc-bios/dtb/pegasos2.dtb | Bin 0 -> 1701 bytes
pc-bios/dtb/pegasos2.dts | 167 +++++++
tests/functional/ppc64/meson.build | 2 +
tests/functional/ppc64/test_fadump.py | 182 +++++++
tests/functional/qemu_test/linuxkernel.py | 59 +++
27 files changed, 2042 insertions(+), 789 deletions(-)
create mode 100644 include/hw/ppc/spapr_fadump.h
create mode 100644 hw/ppc/spapr_fadump.c
create mode 100644 pc-bios/dtb/pegasos1.dtb
create mode 100644 pc-bios/dtb/pegasos1.dts
create mode 100644 pc-bios/dtb/pegasos2.dtb
create mode 100644 pc-bios/dtb/pegasos2.dts
create mode 100755 tests/functional/ppc64/test_fadump.py
^ permalink raw reply [flat|nested] 39+ messages in thread
* [PULL 01/32] ppc/spapr: remove deprecated machine pseries-3.0
2025-10-23 12:16 [PULL RESEND 00/32] ppc-for-10.2 queue Harsh Prateek Bora
@ 2025-10-23 12:16 ` Harsh Prateek Bora
2025-10-23 12:16 ` [PULL 02/32] hw/ppc/spapr: Remove SpaprMachineClass::nr_xirqs field Harsh Prateek Bora
` (31 subsequent siblings)
32 siblings, 0 replies; 39+ messages in thread
From: Harsh Prateek Bora @ 2025-10-23 12:16 UTC (permalink / raw)
To: qemu-devel
Cc: Cédric Le Goater, Cédric Le Goater,
Philippe Mathieu-Daudé
pseries-3.0 had been deprecated and due for removal now as per policy.
Also remove legacy irq support which existed for pre pseries-3.1 machines.
Suggested-by: Cédric Le Goater <clg@kaod.org>
Reviewed-by: Cédric Le Goater <clg@redhat.com>
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Link: https://lore.kernel.org/qemu-devel/20251021084346.73671-2-philmd@linaro.org
Signed-off-by: Harsh Prateek Bora <harshpb@linux.ibm.com>
---
include/hw/ppc/spapr.h | 1 -
include/hw/ppc/spapr_irq.h | 1 -
hw/ppc/spapr.c | 27 +--------------------------
hw/ppc/spapr_events.c | 8 --------
hw/ppc/spapr_irq.c | 16 +---------------
hw/ppc/spapr_pci.c | 32 ++++----------------------------
hw/ppc/spapr_vio.c | 9 ---------
7 files changed, 6 insertions(+), 88 deletions(-)
diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h
index 39bd5bd5ed..0c1e5132de 100644
--- a/include/hw/ppc/spapr.h
+++ b/include/hw/ppc/spapr.h
@@ -145,7 +145,6 @@ struct SpaprMachineClass {
/*< public >*/
bool dr_phb_enabled; /* enable dynamic-reconfig/hotplug of PHBs */
bool update_dt_enabled; /* enable KVMPPC_H_UPDATE_DT */
- bool legacy_irq_allocation;
uint32_t nr_xirqs;
bool broken_host_serial_model; /* present real host info to the guest */
bool pre_4_1_migration; /* don't migrate hpt-max-page-size */
diff --git a/include/hw/ppc/spapr_irq.h b/include/hw/ppc/spapr_irq.h
index cb9a85f657..5ddd1107c3 100644
--- a/include/hw/ppc/spapr_irq.h
+++ b/include/hw/ppc/spapr_irq.h
@@ -100,7 +100,6 @@ typedef struct SpaprIrq {
} SpaprIrq;
extern SpaprIrq spapr_irq_xics;
-extern SpaprIrq spapr_irq_xics_legacy;
extern SpaprIrq spapr_irq_xive;
extern SpaprIrq spapr_irq_dual;
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index e0a2e5a984..3728ae2a5e 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -3347,9 +3347,7 @@ static char *spapr_get_ic_mode(Object *obj, Error **errp)
{
SpaprMachineState *spapr = SPAPR_MACHINE(obj);
- if (spapr->irq == &spapr_irq_xics_legacy) {
- return g_strdup("legacy");
- } else if (spapr->irq == &spapr_irq_xics) {
+ if (spapr->irq == &spapr_irq_xics) {
return g_strdup("xics");
} else if (spapr->irq == &spapr_irq_xive) {
return g_strdup("xive");
@@ -3363,11 +3361,6 @@ static void spapr_set_ic_mode(Object *obj, const char *value, Error **errp)
{
SpaprMachineState *spapr = SPAPR_MACHINE(obj);
- if (SPAPR_MACHINE_GET_CLASS(spapr)->legacy_irq_allocation) {
- error_setg(errp, "This machine only uses the legacy XICS backend, don't pass ic-mode");
- return;
- }
-
/* The legacy IRQ backend can not be set */
if (strcmp(value, "xics") == 0) {
spapr->irq = &spapr_irq_xics;
@@ -5062,24 +5055,6 @@ static void spapr_machine_3_1_class_options(MachineClass *mc)
DEFINE_SPAPR_MACHINE(3, 1);
-/*
- * pseries-3.0
- */
-
-static void spapr_machine_3_0_class_options(MachineClass *mc)
-{
- SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
-
- spapr_machine_3_1_class_options(mc);
- compat_props_add(mc->compat_props, hw_compat_3_0, hw_compat_3_0_len);
-
- smc->legacy_irq_allocation = true;
- smc->nr_xirqs = 0x400;
- smc->irq = &spapr_irq_xics_legacy;
-}
-
-DEFINE_SPAPR_MACHINE(3, 0);
-
static void spapr_machine_register_types(void)
{
type_register_static(&spapr_machine_info);
diff --git a/hw/ppc/spapr_events.c b/hw/ppc/spapr_events.c
index 832b0212f3..548a190ce8 100644
--- a/hw/ppc/spapr_events.c
+++ b/hw/ppc/spapr_events.c
@@ -1043,10 +1043,6 @@ void spapr_events_init(SpaprMachineState *spapr)
{
int epow_irq = SPAPR_IRQ_EPOW;
- if (SPAPR_MACHINE_GET_CLASS(spapr)->legacy_irq_allocation) {
- epow_irq = spapr_irq_findone(spapr, &error_fatal);
- }
-
spapr_irq_claim(spapr, epow_irq, false, &error_fatal);
QTAILQ_INIT(&spapr->pending_events);
@@ -1067,10 +1063,6 @@ void spapr_events_init(SpaprMachineState *spapr)
if (spapr->use_hotplug_event_source) {
int hp_irq = SPAPR_IRQ_HOTPLUG;
- if (SPAPR_MACHINE_GET_CLASS(spapr)->legacy_irq_allocation) {
- hp_irq = spapr_irq_findone(spapr, &error_fatal);
- }
-
spapr_irq_claim(spapr, hp_irq, false, &error_fatal);
spapr_event_sources_register(spapr->event_sources, EVENT_CLASS_HOT_PLUG,
diff --git a/hw/ppc/spapr_irq.c b/hw/ppc/spapr_irq.c
index d6d368dd08..317d57a380 100644
--- a/hw/ppc/spapr_irq.c
+++ b/hw/ppc/spapr_irq.c
@@ -33,11 +33,6 @@ static const TypeInfo spapr_intc_info = {
static void spapr_irq_msi_init(SpaprMachineState *spapr)
{
- if (SPAPR_MACHINE_GET_CLASS(spapr)->legacy_irq_allocation) {
- /* Legacy mode doesn't use this allocator */
- return;
- }
-
spapr->irq_map_nr = spapr_irq_nr_msis(spapr);
spapr->irq_map = bitmap_new(spapr->irq_map_nr);
}
@@ -286,11 +281,7 @@ uint32_t spapr_irq_nr_msis(SpaprMachineState *spapr)
{
SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
- if (smc->legacy_irq_allocation) {
- return smc->nr_xirqs;
- } else {
- return SPAPR_XIRQ_BASE + smc->nr_xirqs - SPAPR_IRQ_MSI;
- }
+ return SPAPR_XIRQ_BASE + smc->nr_xirqs - SPAPR_IRQ_MSI;
}
void spapr_irq_init(SpaprMachineState *spapr, Error **errp)
@@ -588,11 +579,6 @@ int spapr_irq_find(SpaprMachineState *spapr, int num, bool align, Error **errp)
return first + ics->offset;
}
-SpaprIrq spapr_irq_xics_legacy = {
- .xics = true,
- .xive = false,
-};
-
static void spapr_irq_register_types(void)
{
type_register_static(&spapr_intc_info);
diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c
index f9095552e8..bdec8f0728 100644
--- a/hw/ppc/spapr_pci.c
+++ b/hw/ppc/spapr_pci.c
@@ -268,7 +268,6 @@ static void rtas_ibm_change_msi(PowerPCCPU *cpu, SpaprMachineState *spapr,
target_ulong args, uint32_t nret,
target_ulong rets)
{
- SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
uint32_t config_addr = rtas_ld(args, 0);
uint64_t buid = rtas_ldq(args, 1);
unsigned int func = rtas_ld(args, 3);
@@ -373,13 +372,8 @@ static void rtas_ibm_change_msi(PowerPCCPU *cpu, SpaprMachineState *spapr,
}
/* Allocate MSIs */
- if (smc->legacy_irq_allocation) {
- irq = spapr_irq_find(spapr, req_num, ret_intr_type == RTAS_TYPE_MSI,
- &err);
- } else {
- irq = spapr_irq_msi_alloc(spapr, req_num,
- ret_intr_type == RTAS_TYPE_MSI, &err);
- }
+ irq = spapr_irq_msi_alloc(spapr, req_num,
+ ret_intr_type == RTAS_TYPE_MSI, &err);
if (err) {
error_reportf_err(err, "Can't allocate MSIs for device %x: ",
config_addr);
@@ -393,9 +387,7 @@ static void rtas_ibm_change_msi(PowerPCCPU *cpu, SpaprMachineState *spapr,
if (i) {
spapr_irq_free(spapr, irq, i);
}
- if (!smc->legacy_irq_allocation) {
- spapr_irq_msi_free(spapr, irq, req_num);
- }
+ spapr_irq_msi_free(spapr, irq, req_num);
error_reportf_err(err, "Can't allocate MSIs for device %x: ",
config_addr);
rtas_st(rets, 0, RTAS_OUT_HW_ERROR);
@@ -1789,12 +1781,9 @@ static void spapr_phb_unrealize(DeviceState *dev)
static void spapr_phb_destroy_msi(gpointer opaque)
{
SpaprMachineState *spapr = SPAPR_MACHINE(qdev_get_machine());
- SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
SpaprPciMsi *msi = opaque;
- if (!smc->legacy_irq_allocation) {
- spapr_irq_msi_free(spapr, msi->first_irq, msi->num);
- }
+ spapr_irq_msi_free(spapr, msi->first_irq, msi->num);
spapr_irq_free(spapr, msi->first_irq, msi->num);
g_free(msi);
}
@@ -1808,7 +1797,6 @@ static void spapr_phb_realize(DeviceState *dev, Error **errp)
SpaprMachineState *spapr =
(SpaprMachineState *) object_dynamic_cast(qdev_get_machine(),
TYPE_SPAPR_MACHINE);
- SpaprMachineClass *smc = spapr ? SPAPR_MACHINE_GET_CLASS(spapr) : NULL;
SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
SpaprPhbState *sphb = SPAPR_PCI_HOST_BRIDGE(sbd);
PCIHostState *phb = PCI_HOST_BRIDGE(sbd);
@@ -1956,18 +1944,6 @@ static void spapr_phb_realize(DeviceState *dev, Error **errp)
for (i = 0; i < PCI_NUM_PINS; i++) {
int irq = SPAPR_IRQ_PCI_LSI + sphb->index * PCI_NUM_PINS + i;
- if (smc->legacy_irq_allocation) {
- irq = spapr_irq_findone(spapr, errp);
- if (irq < 0) {
- error_prepend(errp, "can't allocate LSIs: ");
- /*
- * Older machines will never support PHB hotplug, ie, this is an
- * init only path and QEMU will terminate. No need to rollback.
- */
- return;
- }
- }
-
if (spapr_irq_claim(spapr, irq, true, errp) < 0) {
error_prepend(errp, "can't allocate LSIs: ");
goto unrealize;
diff --git a/hw/ppc/spapr_vio.c b/hw/ppc/spapr_vio.c
index 7759436a4f..c21a2a3274 100644
--- a/hw/ppc/spapr_vio.c
+++ b/hw/ppc/spapr_vio.c
@@ -507,15 +507,6 @@ static void spapr_vio_busdev_realize(DeviceState *qdev, Error **errp)
dev->irq = spapr_vio_reg_to_irq(dev->reg);
- if (SPAPR_MACHINE_GET_CLASS(spapr)->legacy_irq_allocation) {
- int irq = spapr_irq_findone(spapr, errp);
-
- if (irq < 0) {
- return;
- }
- dev->irq = irq;
- }
-
if (spapr_irq_claim(spapr, dev->irq, false, errp) < 0) {
return;
}
--
2.43.5
^ permalink raw reply related [flat|nested] 39+ messages in thread
* [PULL 02/32] hw/ppc/spapr: Remove SpaprMachineClass::nr_xirqs field
2025-10-23 12:16 [PULL RESEND 00/32] ppc-for-10.2 queue Harsh Prateek Bora
2025-10-23 12:16 ` [PULL 01/32] ppc/spapr: remove deprecated machine pseries-3.0 Harsh Prateek Bora
@ 2025-10-23 12:16 ` Harsh Prateek Bora
2025-10-23 12:16 ` [PULL 03/32] ppc/spapr: remove deprecated machine pseries-3.1 Harsh Prateek Bora
` (30 subsequent siblings)
32 siblings, 0 replies; 39+ messages in thread
From: Harsh Prateek Bora @ 2025-10-23 12:16 UTC (permalink / raw)
To: qemu-devel; +Cc: Philippe Mathieu-Daudé
From: Philippe Mathieu-Daudé <philmd@linaro.org>
The SpaprMachineClass::nr_xirqs field was only used by the
pseries-3.0 machine, which got removed. Remove it as now unused.
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Link: https://lore.kernel.org/qemu-devel/20251021084346.73671-3-philmd@linaro.org
Signed-off-by: Harsh Prateek Bora <harshpb@linux.ibm.com>
---
include/hw/ppc/spapr.h | 1 -
hw/ppc/spapr.c | 1 -
hw/ppc/spapr_irq.c | 22 +++++++---------------
3 files changed, 7 insertions(+), 17 deletions(-)
diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h
index 0c1e5132de..494367fb99 100644
--- a/include/hw/ppc/spapr.h
+++ b/include/hw/ppc/spapr.h
@@ -145,7 +145,6 @@ struct SpaprMachineClass {
/*< public >*/
bool dr_phb_enabled; /* enable dynamic-reconfig/hotplug of PHBs */
bool update_dt_enabled; /* enable KVMPPC_H_UPDATE_DT */
- uint32_t nr_xirqs;
bool broken_host_serial_model; /* present real host info to the guest */
bool pre_4_1_migration; /* don't migrate hpt-max-page-size */
bool linux_pci_probe;
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index 3728ae2a5e..7be7fdaed8 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -4691,7 +4691,6 @@ static void spapr_machine_class_init(ObjectClass *oc, const void *data)
smc->dr_phb_enabled = true;
smc->linux_pci_probe = true;
smc->smp_threads_vsmt = true;
- smc->nr_xirqs = SPAPR_NR_XIRQS;
xfc->match_nvt = spapr_match_nvt;
vmc->client_architecture_support = spapr_vof_client_architecture_support;
vmc->quiesce = spapr_vof_quiesce;
diff --git a/hw/ppc/spapr_irq.c b/hw/ppc/spapr_irq.c
index 317d57a380..2ce323457b 100644
--- a/hw/ppc/spapr_irq.c
+++ b/hw/ppc/spapr_irq.c
@@ -279,15 +279,11 @@ void spapr_irq_dt(SpaprMachineState *spapr, uint32_t nr_servers,
uint32_t spapr_irq_nr_msis(SpaprMachineState *spapr)
{
- SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
-
- return SPAPR_XIRQ_BASE + smc->nr_xirqs - SPAPR_IRQ_MSI;
+ return SPAPR_NR_XIRQS + SPAPR_XIRQ_BASE - SPAPR_IRQ_MSI;
}
void spapr_irq_init(SpaprMachineState *spapr, Error **errp)
{
- SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
-
if (kvm_enabled() && kvm_kernel_irqchip_split()) {
error_setg(errp, "kernel_irqchip split mode not supported on pseries");
return;
@@ -308,7 +304,7 @@ void spapr_irq_init(SpaprMachineState *spapr, Error **errp)
object_property_add_child(OBJECT(spapr), "ics", obj);
object_property_set_link(obj, ICS_PROP_XICS, OBJECT(spapr),
&error_abort);
- object_property_set_int(obj, "nr-irqs", smc->nr_xirqs, &error_abort);
+ object_property_set_int(obj, "nr-irqs", SPAPR_NR_XIRQS, &error_abort);
if (!qdev_realize(DEVICE(obj), NULL, errp)) {
return;
}
@@ -322,7 +318,7 @@ void spapr_irq_init(SpaprMachineState *spapr, Error **errp)
int i;
dev = qdev_new(TYPE_SPAPR_XIVE);
- qdev_prop_set_uint32(dev, "nr-irqs", smc->nr_xirqs + SPAPR_IRQ_NR_IPIS);
+ qdev_prop_set_uint32(dev, "nr-irqs", SPAPR_NR_XIRQS + SPAPR_IRQ_NR_IPIS);
/*
* 8 XIVE END structures per CPU. One for each available
* priority
@@ -349,7 +345,7 @@ void spapr_irq_init(SpaprMachineState *spapr, Error **errp)
}
spapr->qirqs = qemu_allocate_irqs(spapr_set_irq, spapr,
- smc->nr_xirqs + SPAPR_IRQ_NR_IPIS);
+ SPAPR_NR_XIRQS + SPAPR_IRQ_NR_IPIS);
/*
* Mostly we don't actually need this until reset, except that not
@@ -364,11 +360,10 @@ int spapr_irq_claim(SpaprMachineState *spapr, int irq, bool lsi, Error **errp)
{
SpaprInterruptController *intcs[] = ALL_INTCS(spapr);
int i;
- SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
int rc;
assert(irq >= SPAPR_XIRQ_BASE);
- assert(irq < (smc->nr_xirqs + SPAPR_XIRQ_BASE));
+ assert(irq < (SPAPR_NR_XIRQS + SPAPR_XIRQ_BASE));
for (i = 0; i < ARRAY_SIZE(intcs); i++) {
SpaprInterruptController *intc = intcs[i];
@@ -388,10 +383,9 @@ void spapr_irq_free(SpaprMachineState *spapr, int irq, int num)
{
SpaprInterruptController *intcs[] = ALL_INTCS(spapr);
int i, j;
- SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
assert(irq >= SPAPR_XIRQ_BASE);
- assert((irq + num) <= (smc->nr_xirqs + SPAPR_XIRQ_BASE));
+ assert((irq + num) <= (SPAPR_NR_XIRQS + SPAPR_XIRQ_BASE));
for (i = irq; i < (irq + num); i++) {
for (j = 0; j < ARRAY_SIZE(intcs); j++) {
@@ -408,8 +402,6 @@ void spapr_irq_free(SpaprMachineState *spapr, int irq, int num)
qemu_irq spapr_qirq(SpaprMachineState *spapr, int irq)
{
- SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
-
/*
* This interface is basically for VIO and PHB devices to find the
* right qemu_irq to manipulate, so we only allow access to the
@@ -418,7 +410,7 @@ qemu_irq spapr_qirq(SpaprMachineState *spapr, int irq)
* interfaces, we can change this if we need to in future.
*/
assert(irq >= SPAPR_XIRQ_BASE);
- assert(irq < (smc->nr_xirqs + SPAPR_XIRQ_BASE));
+ assert(irq < (SPAPR_NR_XIRQS + SPAPR_XIRQ_BASE));
if (spapr->ics) {
assert(ics_valid_irq(spapr->ics, irq));
--
2.43.5
^ permalink raw reply related [flat|nested] 39+ messages in thread
* [PULL 03/32] ppc/spapr: remove deprecated machine pseries-3.1
2025-10-23 12:16 [PULL RESEND 00/32] ppc-for-10.2 queue Harsh Prateek Bora
2025-10-23 12:16 ` [PULL 01/32] ppc/spapr: remove deprecated machine pseries-3.0 Harsh Prateek Bora
2025-10-23 12:16 ` [PULL 02/32] hw/ppc/spapr: Remove SpaprMachineClass::nr_xirqs field Harsh Prateek Bora
@ 2025-10-23 12:16 ` Harsh Prateek Bora
2025-10-23 12:16 ` [PULL 04/32] hw/ppc/spapr: Inline spapr_dtb_needed() Harsh Prateek Bora
` (29 subsequent siblings)
32 siblings, 0 replies; 39+ messages in thread
From: Harsh Prateek Bora @ 2025-10-23 12:16 UTC (permalink / raw)
To: qemu-devel
Cc: Cédric Le Goater, Cédric Le Goater,
Philippe Mathieu-Daudé
pseries-3.1 had been deprecated and due for removal now as per policy.
Also remove backward compatibility flags and related code introduced for
pre pseries-4.0 machines.
Suggested-by: Cédric Le Goater <clg@kaod.org>
Reviewed-by: Cédric Le Goater <clg@redhat.com>
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Link: https://lore.kernel.org/qemu-devel/20251021084346.73671-4-philmd@linaro.org
Signed-off-by: Harsh Prateek Bora <harshpb@linux.ibm.com>
---
include/hw/ppc/spapr.h | 3 --
hw/ppc/spapr.c | 62 ++++--------------------------------------
hw/ppc/spapr_hcall.c | 5 ----
3 files changed, 5 insertions(+), 65 deletions(-)
diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h
index 494367fb99..1db67784de 100644
--- a/include/hw/ppc/spapr.h
+++ b/include/hw/ppc/spapr.h
@@ -143,9 +143,6 @@ struct SpaprMachineClass {
MachineClass parent_class;
/*< public >*/
- bool dr_phb_enabled; /* enable dynamic-reconfig/hotplug of PHBs */
- bool update_dt_enabled; /* enable KVMPPC_H_UPDATE_DT */
- bool broken_host_serial_model; /* present real host info to the guest */
bool pre_4_1_migration; /* don't migrate hpt-max-page-size */
bool linux_pci_probe;
bool smp_threads_vsmt; /* set VSMT to smp_threads by default */
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index 7be7fdaed8..efeea03741 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -1182,7 +1182,6 @@ void *spapr_build_fdt(SpaprMachineState *spapr, bool reset, size_t space)
{
MachineState *machine = MACHINE(spapr);
MachineClass *mc = MACHINE_GET_CLASS(machine);
- SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(machine);
uint32_t root_drc_type_mask = 0;
int ret;
void *fdt;
@@ -1213,16 +1212,10 @@ void *spapr_build_fdt(SpaprMachineState *spapr, bool reset, size_t space)
/* Host Model & Serial Number */
if (spapr->host_model) {
_FDT(fdt_setprop_string(fdt, 0, "host-model", spapr->host_model));
- } else if (smc->broken_host_serial_model && kvmppc_get_host_model(&buf)) {
- _FDT(fdt_setprop_string(fdt, 0, "host-model", buf));
- g_free(buf);
}
if (spapr->host_serial) {
_FDT(fdt_setprop_string(fdt, 0, "host-serial", spapr->host_serial));
- } else if (smc->broken_host_serial_model && kvmppc_get_host_serial(&buf)) {
- _FDT(fdt_setprop_string(fdt, 0, "host-serial", buf));
- g_free(buf);
}
_FDT(fdt_setprop_cell(fdt, 0, "#address-cells", 2));
@@ -1260,9 +1253,8 @@ void *spapr_build_fdt(SpaprMachineState *spapr, bool reset, size_t space)
/* ibm,drc-indexes and friends */
root_drc_type_mask |= SPAPR_DR_CONNECTOR_TYPE_LMB;
- if (smc->dr_phb_enabled) {
- root_drc_type_mask |= SPAPR_DR_CONNECTOR_TYPE_PHB;
- }
+ root_drc_type_mask |= SPAPR_DR_CONNECTOR_TYPE_PHB;
+
if (mc->nvdimm_supported) {
root_drc_type_mask |= SPAPR_DR_CONNECTOR_TYPE_PMEM;
}
@@ -2063,9 +2055,7 @@ static const VMStateDescription vmstate_spapr_irq_map = {
static bool spapr_dtb_needed(void *opaque)
{
- SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(opaque);
-
- return smc->update_dt_enabled;
+ return true; /* backward migration compat */
}
static int spapr_dtb_pre_load(void *opaque)
@@ -3009,10 +2999,8 @@ static void spapr_machine_init(MachineState *machine)
* connectors for a PHBs PCI slots) are added as needed during their
* parent's realization.
*/
- if (smc->dr_phb_enabled) {
- for (i = 0; i < SPAPR_MAX_PHBS; i++) {
- spapr_dr_connector_new(OBJECT(machine), TYPE_SPAPR_DRC_PHB, i);
- }
+ for (i = 0; i < SPAPR_MAX_PHBS; i++) {
+ spapr_dr_connector_new(OBJECT(machine), TYPE_SPAPR_DRC_PHB, i);
}
/* Set up PCI */
@@ -4095,11 +4083,6 @@ static bool spapr_phb_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
const unsigned windows_supported = spapr_phb_windows_supported(sphb);
SpaprDrc *drc;
- if (dev->hotplugged && !smc->dr_phb_enabled) {
- error_setg(errp, "PHB hotplug not supported for this machine");
- return false;
- }
-
if (sphb->index == (uint32_t)-1) {
error_setg(errp, "\"index\" for PAPR PHB is mandatory");
return false;
@@ -4125,16 +4108,10 @@ static bool spapr_phb_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
static void spapr_phb_plug(HotplugHandler *hotplug_dev, DeviceState *dev)
{
- SpaprMachineState *spapr = SPAPR_MACHINE(OBJECT(hotplug_dev));
- SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
SpaprPhbState *sphb = SPAPR_PCI_HOST_BRIDGE(dev);
SpaprDrc *drc;
bool hotplugged = spapr_drc_hotplugged(dev);
- if (!smc->dr_phb_enabled) {
- return;
- }
-
drc = spapr_drc_by_id(TYPE_SPAPR_DRC_PHB, sphb->index);
/* hotplug hooks should check it's enabled before getting this far */
assert(drc);
@@ -4260,7 +4237,6 @@ static void spapr_machine_device_unplug_request(HotplugHandler *hotplug_dev,
{
SpaprMachineState *sms = SPAPR_MACHINE(OBJECT(hotplug_dev));
MachineClass *mc = MACHINE_GET_CLASS(sms);
- SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) {
if (spapr_memory_hot_unplug_supported(sms)) {
@@ -4275,10 +4251,6 @@ static void spapr_machine_device_unplug_request(HotplugHandler *hotplug_dev,
}
spapr_core_unplug_request(hotplug_dev, dev, errp);
} else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_PCI_HOST_BRIDGE)) {
- if (!smc->dr_phb_enabled) {
- error_setg(errp, "PHB hot unplug not supported on this machine");
- return;
- }
spapr_phb_unplug_request(hotplug_dev, dev, errp);
} else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_TPM_PROXY)) {
spapr_tpm_proxy_unplug(hotplug_dev, dev);
@@ -4634,7 +4606,6 @@ static void spapr_machine_class_init(ObjectClass *oc, const void *data)
hc->unplug_request = spapr_machine_device_unplug_request;
hc->unplug = spapr_machine_device_unplug;
- smc->update_dt_enabled = true;
mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power10_v2.0");
mc->has_hotpluggable_cpus = true;
mc->nvdimm_supported = true;
@@ -4688,7 +4659,6 @@ static void spapr_machine_class_init(ObjectClass *oc, const void *data)
smc->default_caps.caps[SPAPR_CAP_AIL_MODE_3] = SPAPR_CAP_ON;
spapr_caps_add_properties(smc);
smc->irq = &spapr_irq_dual;
- smc->dr_phb_enabled = true;
smc->linux_pci_probe = true;
smc->smp_threads_vsmt = true;
xfc->match_nvt = spapr_match_nvt;
@@ -5032,28 +5002,6 @@ static void spapr_machine_4_0_class_options(MachineClass *mc)
DEFINE_SPAPR_MACHINE(4, 0);
-/*
- * pseries-3.1
- */
-static void spapr_machine_3_1_class_options(MachineClass *mc)
-{
- SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
-
- spapr_machine_4_0_class_options(mc);
- compat_props_add(mc->compat_props, hw_compat_3_1, hw_compat_3_1_len);
-
- mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power8_v2.0");
- smc->update_dt_enabled = false;
- smc->dr_phb_enabled = false;
- smc->broken_host_serial_model = true;
- smc->default_caps.caps[SPAPR_CAP_CFPC] = SPAPR_CAP_BROKEN;
- smc->default_caps.caps[SPAPR_CAP_SBBC] = SPAPR_CAP_BROKEN;
- smc->default_caps.caps[SPAPR_CAP_IBS] = SPAPR_CAP_BROKEN;
- smc->default_caps.caps[SPAPR_CAP_LARGE_DECREMENTER] = SPAPR_CAP_OFF;
-}
-
-DEFINE_SPAPR_MACHINE(3, 1);
-
static void spapr_machine_register_types(void)
{
type_register_static(&spapr_machine_info);
diff --git a/hw/ppc/spapr_hcall.c b/hw/ppc/spapr_hcall.c
index 8c1e0a4817..8f03b3e776 100644
--- a/hw/ppc/spapr_hcall.c
+++ b/hw/ppc/spapr_hcall.c
@@ -1475,16 +1475,11 @@ static target_ulong h_update_dt(PowerPCCPU *cpu, SpaprMachineState *spapr,
target_ulong dt = ppc64_phys_to_real(args[0]);
struct fdt_header hdr = { 0 };
unsigned cb;
- SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
void *fdt;
cpu_physical_memory_read(dt, &hdr, sizeof(hdr));
cb = fdt32_to_cpu(hdr.totalsize);
- if (!smc->update_dt_enabled) {
- return H_SUCCESS;
- }
-
/* Check that the fdt did not grow out of proportion */
if (cb > spapr->fdt_initial_size * 2) {
trace_spapr_update_dt_failed_size(spapr->fdt_initial_size, cb,
--
2.43.5
^ permalink raw reply related [flat|nested] 39+ messages in thread
* [PULL 04/32] hw/ppc/spapr: Inline spapr_dtb_needed()
2025-10-23 12:16 [PULL RESEND 00/32] ppc-for-10.2 queue Harsh Prateek Bora
` (2 preceding siblings ...)
2025-10-23 12:16 ` [PULL 03/32] ppc/spapr: remove deprecated machine pseries-3.1 Harsh Prateek Bora
@ 2025-10-23 12:16 ` Harsh Prateek Bora
2025-10-23 12:16 ` [PULL 05/32] hw/ppc/spapr: Inline few SPAPR_IRQ_* uses Harsh Prateek Bora
` (28 subsequent siblings)
32 siblings, 0 replies; 39+ messages in thread
From: Harsh Prateek Bora @ 2025-10-23 12:16 UTC (permalink / raw)
To: qemu-devel; +Cc: Philippe Mathieu-Daudé
From: Philippe Mathieu-Daudé <philmd@linaro.org>
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Link: https://lore.kernel.org/qemu-devel/20251021084346.73671-5-philmd@linaro.org
Signed-off-by: Harsh Prateek Bora <harshpb@linux.ibm.com>
---
hw/ppc/spapr.c | 6 ------
1 file changed, 6 deletions(-)
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index efeea03741..ab46e3bd60 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -2053,11 +2053,6 @@ static const VMStateDescription vmstate_spapr_irq_map = {
},
};
-static bool spapr_dtb_needed(void *opaque)
-{
- return true; /* backward migration compat */
-}
-
static int spapr_dtb_pre_load(void *opaque)
{
SpaprMachineState *spapr = (SpaprMachineState *)opaque;
@@ -2073,7 +2068,6 @@ static const VMStateDescription vmstate_spapr_dtb = {
.name = "spapr_dtb",
.version_id = 1,
.minimum_version_id = 1,
- .needed = spapr_dtb_needed,
.pre_load = spapr_dtb_pre_load,
.fields = (const VMStateField[]) {
VMSTATE_UINT32(fdt_initial_size, SpaprMachineState),
--
2.43.5
^ permalink raw reply related [flat|nested] 39+ messages in thread
* [PULL 05/32] hw/ppc/spapr: Inline few SPAPR_IRQ_* uses
2025-10-23 12:16 [PULL RESEND 00/32] ppc-for-10.2 queue Harsh Prateek Bora
` (3 preceding siblings ...)
2025-10-23 12:16 ` [PULL 04/32] hw/ppc/spapr: Inline spapr_dtb_needed() Harsh Prateek Bora
@ 2025-10-23 12:16 ` Harsh Prateek Bora
2025-10-23 12:16 ` [PULL 06/32] target/ppc/kvm: Remove kvmppc_get_host_serial() as unused Harsh Prateek Bora
` (27 subsequent siblings)
32 siblings, 0 replies; 39+ messages in thread
From: Harsh Prateek Bora @ 2025-10-23 12:16 UTC (permalink / raw)
To: qemu-devel; +Cc: Philippe Mathieu-Daudé, Chinmay Rath
From: Philippe Mathieu-Daudé <philmd@linaro.org>
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Reviewed-by: Chinmay Rath <rathc@linux.ibm.com>
Link: https://lore.kernel.org/qemu-devel/20251021084346.73671-6-philmd@linaro.org
Signed-off-by: Harsh Prateek Bora <harshpb@linux.ibm.com>
---
hw/ppc/spapr_events.c | 12 ++++--------
1 file changed, 4 insertions(+), 8 deletions(-)
diff --git a/hw/ppc/spapr_events.c b/hw/ppc/spapr_events.c
index 548a190ce8..892ddc7f8f 100644
--- a/hw/ppc/spapr_events.c
+++ b/hw/ppc/spapr_events.c
@@ -1041,16 +1041,14 @@ void spapr_clear_pending_hotplug_events(SpaprMachineState *spapr)
void spapr_events_init(SpaprMachineState *spapr)
{
- int epow_irq = SPAPR_IRQ_EPOW;
-
- spapr_irq_claim(spapr, epow_irq, false, &error_fatal);
+ spapr_irq_claim(spapr, SPAPR_IRQ_EPOW, false, &error_fatal);
QTAILQ_INIT(&spapr->pending_events);
spapr->event_sources = spapr_event_sources_new();
spapr_event_sources_register(spapr->event_sources, EVENT_CLASS_EPOW,
- epow_irq);
+ SPAPR_IRQ_EPOW);
/* NOTE: if machine supports modern/dedicated hotplug event source,
* we add it to the device-tree unconditionally. This means we may
@@ -1061,12 +1059,10 @@ void spapr_events_init(SpaprMachineState *spapr)
* checking that it's enabled.
*/
if (spapr->use_hotplug_event_source) {
- int hp_irq = SPAPR_IRQ_HOTPLUG;
-
- spapr_irq_claim(spapr, hp_irq, false, &error_fatal);
+ spapr_irq_claim(spapr, SPAPR_IRQ_HOTPLUG, false, &error_fatal);
spapr_event_sources_register(spapr->event_sources, EVENT_CLASS_HOT_PLUG,
- hp_irq);
+ SPAPR_IRQ_HOTPLUG);
}
spapr->epow_notifier.notify = spapr_powerdown_req;
--
2.43.5
^ permalink raw reply related [flat|nested] 39+ messages in thread
* [PULL 06/32] target/ppc/kvm: Remove kvmppc_get_host_serial() as unused
2025-10-23 12:16 [PULL RESEND 00/32] ppc-for-10.2 queue Harsh Prateek Bora
` (4 preceding siblings ...)
2025-10-23 12:16 ` [PULL 05/32] hw/ppc/spapr: Inline few SPAPR_IRQ_* uses Harsh Prateek Bora
@ 2025-10-23 12:16 ` Harsh Prateek Bora
2025-10-23 12:16 ` [PULL 07/32] target/ppc/kvm: Remove kvmppc_get_host_model() " Harsh Prateek Bora
` (26 subsequent siblings)
32 siblings, 0 replies; 39+ messages in thread
From: Harsh Prateek Bora @ 2025-10-23 12:16 UTC (permalink / raw)
To: qemu-devel; +Cc: Philippe Mathieu-Daudé, Chinmay Rath
From: Philippe Mathieu-Daudé <philmd@linaro.org>
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Reviewed-by: Chinmay Rath <rathc@linux.ibm.com>
Link: https://lore.kernel.org/qemu-devel/20251021084346.73671-7-philmd@linaro.org
Signed-off-by: Harsh Prateek Bora <harshpb@linux.ibm.com>
---
target/ppc/kvm_ppc.h | 6 ------
target/ppc/kvm.c | 6 ------
2 files changed, 12 deletions(-)
diff --git a/target/ppc/kvm_ppc.h b/target/ppc/kvm_ppc.h
index a1d9ce9f9a..f24cc4de3c 100644
--- a/target/ppc/kvm_ppc.h
+++ b/target/ppc/kvm_ppc.h
@@ -22,7 +22,6 @@
uint32_t kvmppc_get_tbfreq(void);
uint64_t kvmppc_get_clockfreq(void);
bool kvmppc_get_host_model(char **buf);
-bool kvmppc_get_host_serial(char **buf);
int kvmppc_get_hasidle(CPUPPCState *env);
int kvmppc_get_hypercall(CPUPPCState *env, uint8_t *buf, int buf_len);
int kvmppc_set_interrupt(PowerPCCPU *cpu, int irq, int level);
@@ -134,11 +133,6 @@ static inline bool kvmppc_get_host_model(char **buf)
return false;
}
-static inline bool kvmppc_get_host_serial(char **buf)
-{
- return false;
-}
-
static inline uint64_t kvmppc_get_clockfreq(void)
{
return 0;
diff --git a/target/ppc/kvm.c b/target/ppc/kvm.c
index cd60893a17..cb61e99f9d 100644
--- a/target/ppc/kvm.c
+++ b/target/ppc/kvm.c
@@ -1864,12 +1864,6 @@ uint32_t kvmppc_get_tbfreq(void)
return cached_tbfreq;
}
-bool kvmppc_get_host_serial(char **value)
-{
- return g_file_get_contents("/proc/device-tree/system-id", value, NULL,
- NULL);
-}
-
bool kvmppc_get_host_model(char **value)
{
return g_file_get_contents("/proc/device-tree/model", value, NULL, NULL);
--
2.43.5
^ permalink raw reply related [flat|nested] 39+ messages in thread
* [PULL 07/32] target/ppc/kvm: Remove kvmppc_get_host_model() as unused
2025-10-23 12:16 [PULL RESEND 00/32] ppc-for-10.2 queue Harsh Prateek Bora
` (5 preceding siblings ...)
2025-10-23 12:16 ` [PULL 06/32] target/ppc/kvm: Remove kvmppc_get_host_serial() as unused Harsh Prateek Bora
@ 2025-10-23 12:16 ` Harsh Prateek Bora
2025-10-23 12:16 ` [PULL 08/32] ppc/spapr: remove deprecated machine pseries-4.0 Harsh Prateek Bora
` (25 subsequent siblings)
32 siblings, 0 replies; 39+ messages in thread
From: Harsh Prateek Bora @ 2025-10-23 12:16 UTC (permalink / raw)
To: qemu-devel; +Cc: Philippe Mathieu-Daudé, Chinmay Rath
From: Philippe Mathieu-Daudé <philmd@linaro.org>
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Reviewed-by: Chinmay Rath <rathc@linux.ibm.com>
Link: https://lore.kernel.org/qemu-devel/20251021084346.73671-8-philmd@linaro.org
Signed-off-by: Harsh Prateek Bora <harshpb@linux.ibm.com>
---
target/ppc/kvm_ppc.h | 6 ------
target/ppc/kvm.c | 5 -----
2 files changed, 11 deletions(-)
diff --git a/target/ppc/kvm_ppc.h b/target/ppc/kvm_ppc.h
index f24cc4de3c..742881231e 100644
--- a/target/ppc/kvm_ppc.h
+++ b/target/ppc/kvm_ppc.h
@@ -21,7 +21,6 @@
uint32_t kvmppc_get_tbfreq(void);
uint64_t kvmppc_get_clockfreq(void);
-bool kvmppc_get_host_model(char **buf);
int kvmppc_get_hasidle(CPUPPCState *env);
int kvmppc_get_hypercall(CPUPPCState *env, uint8_t *buf, int buf_len);
int kvmppc_set_interrupt(PowerPCCPU *cpu, int irq, int level);
@@ -128,11 +127,6 @@ static inline uint32_t kvmppc_get_tbfreq(void)
return 0;
}
-static inline bool kvmppc_get_host_model(char **buf)
-{
- return false;
-}
-
static inline uint64_t kvmppc_get_clockfreq(void)
{
return 0;
diff --git a/target/ppc/kvm.c b/target/ppc/kvm.c
index cb61e99f9d..43124bf1c7 100644
--- a/target/ppc/kvm.c
+++ b/target/ppc/kvm.c
@@ -1864,11 +1864,6 @@ uint32_t kvmppc_get_tbfreq(void)
return cached_tbfreq;
}
-bool kvmppc_get_host_model(char **value)
-{
- return g_file_get_contents("/proc/device-tree/model", value, NULL, NULL);
-}
-
/* Try to find a device tree node for a CPU with clock-frequency property */
static int kvmppc_find_cpu_dt(char *buf, int buf_len)
{
--
2.43.5
^ permalink raw reply related [flat|nested] 39+ messages in thread
* [PULL 08/32] ppc/spapr: remove deprecated machine pseries-4.0
2025-10-23 12:16 [PULL RESEND 00/32] ppc-for-10.2 queue Harsh Prateek Bora
` (6 preceding siblings ...)
2025-10-23 12:16 ` [PULL 07/32] target/ppc/kvm: Remove kvmppc_get_host_model() " Harsh Prateek Bora
@ 2025-10-23 12:16 ` Harsh Prateek Bora
2025-10-23 12:16 ` [PULL 09/32] hw/ppc/spapr: Remove SpaprMachineClass::phb_placement callback Harsh Prateek Bora
` (24 subsequent siblings)
32 siblings, 0 replies; 39+ messages in thread
From: Harsh Prateek Bora @ 2025-10-23 12:16 UTC (permalink / raw)
To: qemu-devel
Cc: Cédric Le Goater, Cédric Le Goater,
Philippe Mathieu-Daudé
pseries-4.0 had been deprecated and due for removal now as per policy.
Also remove pre-4.1 migration hacks which were introduced for backward
compatibility.
Suggested-by: Cédric Le Goater <clg@kaod.org>
Reviewed-by: Cédric Le Goater <clg@redhat.com>
[PMD: Remove SpaprMachineClass::pre_4_1_migration field]
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Link: https://lore.kernel.org/qemu-devel/20251021084346.73671-9-philmd@linaro.org
Signed-off-by: Harsh Prateek Bora <harshpb@linux.ibm.com>
---
include/hw/ppc/spapr.h | 3 ---
hw/ppc/spapr.c | 27 ---------------------------
hw/ppc/spapr_caps.c | 12 +-----------
3 files changed, 1 insertion(+), 41 deletions(-)
diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h
index 1db67784de..58d31b096c 100644
--- a/include/hw/ppc/spapr.h
+++ b/include/hw/ppc/spapr.h
@@ -139,11 +139,8 @@ struct SpaprCapabilities {
* SpaprMachineClass:
*/
struct SpaprMachineClass {
- /*< private >*/
MachineClass parent_class;
- /*< public >*/
- bool pre_4_1_migration; /* don't migrate hpt-max-page-size */
bool linux_pci_probe;
bool smp_threads_vsmt; /* set VSMT to smp_threads by default */
hwaddr rma_limit; /* clamp the RMA to this size */
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index ab46e3bd60..ea7d2a03aa 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -4969,33 +4969,6 @@ static void spapr_machine_4_1_class_options(MachineClass *mc)
DEFINE_SPAPR_MACHINE(4, 1);
-/*
- * pseries-4.0
- */
-static bool phb_placement_4_0(SpaprMachineState *spapr, uint32_t index,
- uint64_t *buid, hwaddr *pio,
- hwaddr *mmio32, hwaddr *mmio64,
- unsigned n_dma, uint32_t *liobns, Error **errp)
-{
- if (!spapr_phb_placement(spapr, index, buid, pio, mmio32, mmio64, n_dma,
- liobns, errp)) {
- return false;
- }
- return true;
-}
-static void spapr_machine_4_0_class_options(MachineClass *mc)
-{
- SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
-
- spapr_machine_4_1_class_options(mc);
- compat_props_add(mc->compat_props, hw_compat_4_0, hw_compat_4_0_len);
- smc->phb_placement = phb_placement_4_0;
- smc->irq = &spapr_irq_xics;
- smc->pre_4_1_migration = true;
-}
-
-DEFINE_SPAPR_MACHINE(4, 0);
-
static void spapr_machine_register_types(void)
{
type_register_static(&spapr_machine_info);
diff --git a/hw/ppc/spapr_caps.c b/hw/ppc/spapr_caps.c
index 0f94c192fd..170795ad6a 100644
--- a/hw/ppc/spapr_caps.c
+++ b/hw/ppc/spapr_caps.c
@@ -66,7 +66,6 @@ typedef struct SpaprCapabilityInfo {
void (*apply)(SpaprMachineState *spapr, uint8_t val, Error **errp);
void (*cpu_apply)(SpaprMachineState *spapr, PowerPCCPU *cpu,
uint8_t val, Error **errp);
- bool (*migrate_needed)(void *opaque);
} SpaprCapabilityInfo;
static void spapr_cap_get_bool(Object *obj, Visitor *v, const char *name,
@@ -336,11 +335,6 @@ static void cap_hpt_maxpagesize_apply(SpaprMachineState *spapr,
spapr_check_pagesize(spapr, qemu_minrampagesize(), errp);
}
-static bool cap_hpt_maxpagesize_migrate_needed(void *opaque)
-{
- return !SPAPR_MACHINE_GET_CLASS(opaque)->pre_4_1_migration;
-}
-
static bool spapr_pagesize_cb(void *opaque, uint32_t seg_pshift,
uint32_t pshift)
{
@@ -793,7 +787,6 @@ SpaprCapabilityInfo capability_table[SPAPR_CAP_NUM] = {
.type = "int",
.apply = cap_hpt_maxpagesize_apply,
.cpu_apply = cap_hpt_maxpagesize_cpu_apply,
- .migrate_needed = cap_hpt_maxpagesize_migrate_needed,
},
[SPAPR_CAP_NESTED_KVM_HV] = {
.name = "nested-hv",
@@ -982,11 +975,8 @@ int spapr_caps_post_migration(SpaprMachineState *spapr)
static bool spapr_cap_##sname##_needed(void *opaque) \
{ \
SpaprMachineState *spapr = opaque; \
- bool (*needed)(void *opaque) = \
- capability_table[cap].migrate_needed; \
\
- return needed ? needed(opaque) : true && \
- spapr->cmd_line_caps[cap] && \
+ return spapr->cmd_line_caps[cap] && \
(spapr->eff.caps[cap] != \
spapr->def.caps[cap]); \
} \
--
2.43.5
^ permalink raw reply related [flat|nested] 39+ messages in thread
* [PULL 09/32] hw/ppc/spapr: Remove SpaprMachineClass::phb_placement callback
2025-10-23 12:16 [PULL RESEND 00/32] ppc-for-10.2 queue Harsh Prateek Bora
` (7 preceding siblings ...)
2025-10-23 12:16 ` [PULL 08/32] ppc/spapr: remove deprecated machine pseries-4.0 Harsh Prateek Bora
@ 2025-10-23 12:16 ` Harsh Prateek Bora
2025-10-23 12:16 ` [PULL 10/32] ppc/spapr: remove deprecated machine pseries-4.1 Harsh Prateek Bora
` (23 subsequent siblings)
32 siblings, 0 replies; 39+ messages in thread
From: Harsh Prateek Bora @ 2025-10-23 12:16 UTC (permalink / raw)
To: qemu-devel; +Cc: Philippe Mathieu-Daudé, Chinmay Rath
From: Philippe Mathieu-Daudé <philmd@linaro.org>
The SpaprMachineClass::phb_placement callback was only used by
the pseries-4.0 machine, which got removed. Remove it as now
unused, directly calling spapr_phb_placement().
Move spapr_phb_placement() definition to avoid forward declaration.
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Reviewed-by: Chinmay Rath <rathc@linux.ibm.com>
Link: https://lore.kernel.org/qemu-devel/20251021084346.73671-10-philmd@linaro.org
Signed-off-by: Harsh Prateek Bora <harshpb@linux.ibm.com>
---
include/hw/ppc/spapr.h | 5 --
hw/ppc/spapr.c | 114 ++++++++++++++++++++---------------------
2 files changed, 55 insertions(+), 64 deletions(-)
diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h
index 58d31b096c..bd783e92e1 100644
--- a/include/hw/ppc/spapr.h
+++ b/include/hw/ppc/spapr.h
@@ -147,11 +147,6 @@ struct SpaprMachineClass {
bool pre_5_1_assoc_refpoints;
bool pre_5_2_numa_associativity;
bool pre_6_2_numa_affinity;
-
- bool (*phb_placement)(SpaprMachineState *spapr, uint32_t index,
- uint64_t *buid, hwaddr *pio,
- hwaddr *mmio32, hwaddr *mmio64,
- unsigned n_dma, uint32_t *liobns, Error **errp);
SpaprResizeHpt resize_hpt_default;
SpaprCapabilities default_caps;
SpaprIrq *irq;
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index ea7d2a03aa..371593d0b5 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -4068,12 +4068,62 @@ int spapr_phb_dt_populate(SpaprDrc *drc, SpaprMachineState *spapr,
return 0;
}
+static bool spapr_phb_placement(SpaprMachineState *spapr, uint32_t index,
+ uint64_t *buid, hwaddr *pio,
+ hwaddr *mmio32, hwaddr *mmio64,
+ unsigned n_dma, uint32_t *liobns, Error **errp)
+{
+ /*
+ * New-style PHB window placement.
+ *
+ * Goals: Gives large (1TiB), naturally aligned 64-bit MMIO window
+ * for each PHB, in addition to 2GiB 32-bit MMIO and 64kiB PIO
+ * windows.
+ *
+ * Some guest kernels can't work with MMIO windows above 1<<46
+ * (64TiB), so we place up to 31 PHBs in the area 32TiB..64TiB
+ *
+ * 32TiB..(33TiB+1984kiB) contains the 64kiB PIO windows for each
+ * PHB stacked together. (32TiB+2GiB)..(32TiB+64GiB) contains the
+ * 2GiB 32-bit MMIO windows for each PHB. Then 33..64TiB has the
+ * 1TiB 64-bit MMIO windows for each PHB.
+ */
+ const uint64_t base_buid = 0x800000020000000ULL;
+ int i;
+
+ /* Sanity check natural alignments */
+ QEMU_BUILD_BUG_ON((SPAPR_PCI_BASE % SPAPR_PCI_MEM64_WIN_SIZE) != 0);
+ QEMU_BUILD_BUG_ON((SPAPR_PCI_LIMIT % SPAPR_PCI_MEM64_WIN_SIZE) != 0);
+ QEMU_BUILD_BUG_ON((SPAPR_PCI_MEM64_WIN_SIZE % SPAPR_PCI_MEM32_WIN_SIZE) != 0);
+ QEMU_BUILD_BUG_ON((SPAPR_PCI_MEM32_WIN_SIZE % SPAPR_PCI_IO_WIN_SIZE) != 0);
+ /* Sanity check bounds */
+ QEMU_BUILD_BUG_ON((SPAPR_MAX_PHBS * SPAPR_PCI_IO_WIN_SIZE) >
+ SPAPR_PCI_MEM32_WIN_SIZE);
+ QEMU_BUILD_BUG_ON((SPAPR_MAX_PHBS * SPAPR_PCI_MEM32_WIN_SIZE) >
+ SPAPR_PCI_MEM64_WIN_SIZE);
+
+ if (index >= SPAPR_MAX_PHBS) {
+ error_setg(errp, "\"index\" for PAPR PHB is too large (max %llu)",
+ SPAPR_MAX_PHBS - 1);
+ return false;
+ }
+
+ *buid = base_buid + index;
+ for (i = 0; i < n_dma; ++i) {
+ liobns[i] = SPAPR_PCI_LIOBN(index, i);
+ }
+
+ *pio = SPAPR_PCI_BASE + index * SPAPR_PCI_IO_WIN_SIZE;
+ *mmio32 = SPAPR_PCI_BASE + (index + 1) * SPAPR_PCI_MEM32_WIN_SIZE;
+ *mmio64 = SPAPR_PCI_BASE + (index + 1) * SPAPR_PCI_MEM64_WIN_SIZE;
+ return true;
+}
+
static bool spapr_phb_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
Error **errp)
{
SpaprMachineState *spapr = SPAPR_MACHINE(OBJECT(hotplug_dev));
SpaprPhbState *sphb = SPAPR_PCI_HOST_BRIDGE(dev);
- SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
const unsigned windows_supported = spapr_phb_windows_supported(sphb);
SpaprDrc *drc;
@@ -4092,12 +4142,10 @@ static bool spapr_phb_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
* This will check that sphb->index doesn't exceed the maximum number of
* PHBs for the current machine type.
*/
- return
- smc->phb_placement(spapr, sphb->index,
- &sphb->buid, &sphb->io_win_addr,
- &sphb->mem_win_addr, &sphb->mem64_win_addr,
- windows_supported, sphb->dma_liobn,
- errp);
+ return spapr_phb_placement(spapr, sphb->index,
+ &sphb->buid, &sphb->io_win_addr,
+ &sphb->mem_win_addr, &sphb->mem64_win_addr,
+ windows_supported, sphb->dma_liobn, errp);
}
static void spapr_phb_plug(HotplugHandler *hotplug_dev, DeviceState *dev)
@@ -4345,57 +4393,6 @@ static const CPUArchIdList *spapr_possible_cpu_arch_ids(MachineState *machine)
return machine->possible_cpus;
}
-static bool spapr_phb_placement(SpaprMachineState *spapr, uint32_t index,
- uint64_t *buid, hwaddr *pio,
- hwaddr *mmio32, hwaddr *mmio64,
- unsigned n_dma, uint32_t *liobns, Error **errp)
-{
- /*
- * New-style PHB window placement.
- *
- * Goals: Gives large (1TiB), naturally aligned 64-bit MMIO window
- * for each PHB, in addition to 2GiB 32-bit MMIO and 64kiB PIO
- * windows.
- *
- * Some guest kernels can't work with MMIO windows above 1<<46
- * (64TiB), so we place up to 31 PHBs in the area 32TiB..64TiB
- *
- * 32TiB..(33TiB+1984kiB) contains the 64kiB PIO windows for each
- * PHB stacked together. (32TiB+2GiB)..(32TiB+64GiB) contains the
- * 2GiB 32-bit MMIO windows for each PHB. Then 33..64TiB has the
- * 1TiB 64-bit MMIO windows for each PHB.
- */
- const uint64_t base_buid = 0x800000020000000ULL;
- int i;
-
- /* Sanity check natural alignments */
- QEMU_BUILD_BUG_ON((SPAPR_PCI_BASE % SPAPR_PCI_MEM64_WIN_SIZE) != 0);
- QEMU_BUILD_BUG_ON((SPAPR_PCI_LIMIT % SPAPR_PCI_MEM64_WIN_SIZE) != 0);
- QEMU_BUILD_BUG_ON((SPAPR_PCI_MEM64_WIN_SIZE % SPAPR_PCI_MEM32_WIN_SIZE) != 0);
- QEMU_BUILD_BUG_ON((SPAPR_PCI_MEM32_WIN_SIZE % SPAPR_PCI_IO_WIN_SIZE) != 0);
- /* Sanity check bounds */
- QEMU_BUILD_BUG_ON((SPAPR_MAX_PHBS * SPAPR_PCI_IO_WIN_SIZE) >
- SPAPR_PCI_MEM32_WIN_SIZE);
- QEMU_BUILD_BUG_ON((SPAPR_MAX_PHBS * SPAPR_PCI_MEM32_WIN_SIZE) >
- SPAPR_PCI_MEM64_WIN_SIZE);
-
- if (index >= SPAPR_MAX_PHBS) {
- error_setg(errp, "\"index\" for PAPR PHB is too large (max %llu)",
- SPAPR_MAX_PHBS - 1);
- return false;
- }
-
- *buid = base_buid + index;
- for (i = 0; i < n_dma; ++i) {
- liobns[i] = SPAPR_PCI_LIOBN(index, i);
- }
-
- *pio = SPAPR_PCI_BASE + index * SPAPR_PCI_IO_WIN_SIZE;
- *mmio32 = SPAPR_PCI_BASE + (index + 1) * SPAPR_PCI_MEM32_WIN_SIZE;
- *mmio64 = SPAPR_PCI_BASE + (index + 1) * SPAPR_PCI_MEM64_WIN_SIZE;
- return true;
-}
-
static ICSState *spapr_ics_get(XICSFabric *dev, int irq)
{
SpaprMachineState *spapr = SPAPR_MACHINE(dev);
@@ -4606,7 +4603,6 @@ static void spapr_machine_class_init(ObjectClass *oc, const void *data)
smc->resize_hpt_default = SPAPR_RESIZE_HPT_ENABLED;
fwc->get_dev_path = spapr_get_fw_dev_path;
nc->nmi_monitor_handler = spapr_nmi;
- smc->phb_placement = spapr_phb_placement;
vhc->cpu_in_nested = spapr_cpu_in_nested;
vhc->deliver_hv_excp = spapr_exit_nested;
vhc->hypercall = emulate_spapr_hypercall;
--
2.43.5
^ permalink raw reply related [flat|nested] 39+ messages in thread
* [PULL 10/32] ppc/spapr: remove deprecated machine pseries-4.1
2025-10-23 12:16 [PULL RESEND 00/32] ppc-for-10.2 queue Harsh Prateek Bora
` (8 preceding siblings ...)
2025-10-23 12:16 ` [PULL 09/32] hw/ppc/spapr: Remove SpaprMachineClass::phb_placement callback Harsh Prateek Bora
@ 2025-10-23 12:16 ` Harsh Prateek Bora
2025-10-23 12:16 ` [PULL 11/32] ppc/spapr: remove deprecated machine pseries-4.2 Harsh Prateek Bora
` (22 subsequent siblings)
32 siblings, 0 replies; 39+ messages in thread
From: Harsh Prateek Bora @ 2025-10-23 12:16 UTC (permalink / raw)
To: qemu-devel
Cc: Cédric Le Goater, Cédric Le Goater,
Philippe Mathieu-Daudé
Remove the pseries-4.1 machine specific logic as had been deprecated and
due for removal now as per policy.
Suggested-by: Cédric Le Goater <clg@kaod.org>
Reviewed-by: Cédric Le Goater <clg@redhat.com>
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Link: https://lore.kernel.org/qemu-devel/20251021084346.73671-11-philmd@linaro.org
Signed-off-by: Harsh Prateek Bora <harshpb@linux.ibm.com>
---
include/hw/ppc/spapr.h | 2 --
hw/ppc/spapr.c | 37 +------------------------------------
2 files changed, 1 insertion(+), 38 deletions(-)
diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h
index bd783e92e1..60d9a8a037 100644
--- a/include/hw/ppc/spapr.h
+++ b/include/hw/ppc/spapr.h
@@ -141,8 +141,6 @@ struct SpaprCapabilities {
struct SpaprMachineClass {
MachineClass parent_class;
- bool linux_pci_probe;
- bool smp_threads_vsmt; /* set VSMT to smp_threads by default */
hwaddr rma_limit; /* clamp the RMA to this size */
bool pre_5_1_assoc_refpoints;
bool pre_5_2_numa_associativity;
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index 371593d0b5..0e6218dc9c 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -1072,7 +1072,6 @@ static void spapr_dt_ov5_platform_support(SpaprMachineState *spapr, void *fdt,
static void spapr_dt_chosen(SpaprMachineState *spapr, void *fdt, bool reset)
{
MachineState *machine = MACHINE(spapr);
- SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(machine);
int chosen;
_FDT(chosen = fdt_add_subnode(fdt, 0, "chosen"));
@@ -1143,9 +1142,7 @@ static void spapr_dt_chosen(SpaprMachineState *spapr, void *fdt, bool reset)
* We can deal with BAR reallocation just fine, advertise it
* to the guest
*/
- if (smc->linux_pci_probe) {
- _FDT(fdt_setprop_cell(fdt, chosen, "linux,pci-probe-only", 0));
- }
+ _FDT(fdt_setprop_cell(fdt, chosen, "linux,pci-probe-only", 0));
spapr_dt_ov5_platform_support(spapr, fdt, chosen);
}
@@ -2589,7 +2586,6 @@ static CPUArchId *spapr_find_cpu_slot(MachineState *ms, uint32_t id, int *idx)
static void spapr_set_vsmt_mode(SpaprMachineState *spapr, Error **errp)
{
MachineState *ms = MACHINE(spapr);
- SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
Error *local_err = NULL;
bool vsmt_user = !!spapr->vsmt;
int kvm_smt = kvmppc_smt_threads();
@@ -2625,15 +2621,6 @@ static void spapr_set_vsmt_mode(SpaprMachineState *spapr, Error **errp)
return;
}
/* In this case, spapr->vsmt has been set by the command line */
- } else if (!smc->smp_threads_vsmt) {
- /*
- * Default VSMT value is tricky, because we need it to be as
- * consistent as possible (for migration), but this requires
- * changing it for at least some existing cases. We pick 8 as
- * the value that we'd get with KVM on POWER8, the
- * overwhelmingly common case in production systems.
- */
- spapr->vsmt = MAX(8, smp_threads);
} else {
spapr->vsmt = smp_threads;
}
@@ -4649,8 +4636,6 @@ static void spapr_machine_class_init(ObjectClass *oc, const void *data)
smc->default_caps.caps[SPAPR_CAP_AIL_MODE_3] = SPAPR_CAP_ON;
spapr_caps_add_properties(smc);
smc->irq = &spapr_irq_dual;
- smc->linux_pci_probe = true;
- smc->smp_threads_vsmt = true;
xfc->match_nvt = spapr_match_nvt;
vmc->client_architecture_support = spapr_vof_client_architecture_support;
vmc->quiesce = spapr_vof_quiesce;
@@ -4945,26 +4930,6 @@ static void spapr_machine_4_2_class_options(MachineClass *mc)
DEFINE_SPAPR_MACHINE(4, 2);
-/*
- * pseries-4.1
- */
-static void spapr_machine_4_1_class_options(MachineClass *mc)
-{
- SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
- static GlobalProperty compat[] = {
- /* Only allow 4kiB and 64kiB IOMMU pagesizes */
- { TYPE_SPAPR_PCI_HOST_BRIDGE, "pgsz", "0x11000" },
- };
-
- spapr_machine_4_2_class_options(mc);
- smc->linux_pci_probe = false;
- smc->smp_threads_vsmt = false;
- compat_props_add(mc->compat_props, hw_compat_4_1, hw_compat_4_1_len);
- compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat));
-}
-
-DEFINE_SPAPR_MACHINE(4, 1);
-
static void spapr_machine_register_types(void)
{
type_register_static(&spapr_machine_info);
--
2.43.5
^ permalink raw reply related [flat|nested] 39+ messages in thread
* [PULL 11/32] ppc/spapr: remove deprecated machine pseries-4.2
2025-10-23 12:16 [PULL RESEND 00/32] ppc-for-10.2 queue Harsh Prateek Bora
` (9 preceding siblings ...)
2025-10-23 12:16 ` [PULL 10/32] ppc/spapr: remove deprecated machine pseries-4.1 Harsh Prateek Bora
@ 2025-10-23 12:16 ` Harsh Prateek Bora
2025-10-23 12:16 ` [PULL 12/32] ppc/amigaone: Free allocated struct Harsh Prateek Bora
` (21 subsequent siblings)
32 siblings, 0 replies; 39+ messages in thread
From: Harsh Prateek Bora @ 2025-10-23 12:16 UTC (permalink / raw)
To: qemu-devel
Cc: Cédric Le Goater, Cédric Le Goater,
Philippe Mathieu-Daudé
Remove the pseries-4.2 machine specific logic as had been deprecated and
due for removal now as per policy.
Suggested-by: Cédric Le Goater <clg@kaod.org>
Reviewed-by: Cédric Le Goater <clg@redhat.com>
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Link: https://lore.kernel.org/qemu-devel/20251021084346.73671-12-philmd@linaro.org
Signed-off-by: Harsh Prateek Bora <harshpb@linux.ibm.com>
---
include/hw/ppc/spapr.h | 1 -
hw/ppc/spapr.c | 27 ---------------------------
2 files changed, 28 deletions(-)
diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h
index 60d9a8a037..b9d884745f 100644
--- a/include/hw/ppc/spapr.h
+++ b/include/hw/ppc/spapr.h
@@ -141,7 +141,6 @@ struct SpaprCapabilities {
struct SpaprMachineClass {
MachineClass parent_class;
- hwaddr rma_limit; /* clamp the RMA to this size */
bool pre_5_1_assoc_refpoints;
bool pre_5_2_numa_associativity;
bool pre_6_2_numa_affinity;
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index 0e6218dc9c..117da76a3d 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -2729,7 +2729,6 @@ static PCIHostState *spapr_create_default_phb(void)
static hwaddr spapr_rma_size(SpaprMachineState *spapr, Error **errp)
{
MachineState *machine = MACHINE(spapr);
- SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
hwaddr rma_size = machine->ram_size;
hwaddr node0_size = spapr_node0_size(machine);
@@ -2742,15 +2741,6 @@ static hwaddr spapr_rma_size(SpaprMachineState *spapr, Error **errp)
*/
rma_size = MIN(rma_size, 1 * TiB);
- /*
- * Clamp the RMA size based on machine type. This is for
- * migration compatibility with older qemu versions, which limited
- * the RMA size for complicated and mostly bad reasons.
- */
- if (smc->rma_limit) {
- rma_size = MIN(rma_size, smc->rma_limit);
- }
-
if (rma_size < MIN_RMA_SLOF) {
error_setg(errp,
"pSeries SLOF firmware requires >= %" HWADDR_PRIx
@@ -4913,23 +4903,6 @@ static void spapr_machine_5_0_class_options(MachineClass *mc)
DEFINE_SPAPR_MACHINE(5, 0);
-/*
- * pseries-4.2
- */
-static void spapr_machine_4_2_class_options(MachineClass *mc)
-{
- SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
-
- spapr_machine_5_0_class_options(mc);
- compat_props_add(mc->compat_props, hw_compat_4_2, hw_compat_4_2_len);
- smc->default_caps.caps[SPAPR_CAP_CCF_ASSIST] = SPAPR_CAP_OFF;
- smc->default_caps.caps[SPAPR_CAP_FWNMI] = SPAPR_CAP_OFF;
- smc->rma_limit = 16 * GiB;
- mc->nvdimm_supported = false;
-}
-
-DEFINE_SPAPR_MACHINE(4, 2);
-
static void spapr_machine_register_types(void)
{
type_register_static(&spapr_machine_info);
--
2.43.5
^ permalink raw reply related [flat|nested] 39+ messages in thread
* [PULL 12/32] ppc/amigaone: Free allocated struct
2025-10-23 12:16 [PULL RESEND 00/32] ppc-for-10.2 queue Harsh Prateek Bora
` (10 preceding siblings ...)
2025-10-23 12:16 ` [PULL 11/32] ppc/spapr: remove deprecated machine pseries-4.2 Harsh Prateek Bora
@ 2025-10-23 12:16 ` Harsh Prateek Bora
2025-10-23 12:16 ` [PULL 13/32] ppc/vof: Make nextprop behave more like Open Firmware Harsh Prateek Bora
` (20 subsequent siblings)
32 siblings, 0 replies; 39+ messages in thread
From: Harsh Prateek Bora @ 2025-10-23 12:16 UTC (permalink / raw)
To: qemu-devel; +Cc: BALATON Zoltan
From: BALATON Zoltan <balaton@eik.bme.hu>
In create_bd_info function a bd_info struct is allocated but never
freed. Mark it g_autofree to avoid leaking it.
Fixes: 34f053d86b (ppc/amigaone: Add kernel and initrd support)
Resolves: Coverity CID 1641398
Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>
Reviewed-by: Harsh Prateek Bora <harshpb@linux.ibm.com>
Link: https://lore.kernel.org/qemu-devel/20251022211649.9A09E5972E5@zero.eik.bme.hu
Signed-off-by: Harsh Prateek Bora <harshpb@linux.ibm.com>
---
hw/ppc/amigaone.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/hw/ppc/amigaone.c b/hw/ppc/amigaone.c
index 12279f42bc..47fb016b4a 100644
--- a/hw/ppc/amigaone.c
+++ b/hw/ppc/amigaone.c
@@ -221,7 +221,7 @@ struct bd_info {
static void create_bd_info(hwaddr addr, ram_addr_t ram_size)
{
- struct bd_info *bd = g_new0(struct bd_info, 1);
+ g_autofree struct bd_info *bd = g_new0(struct bd_info, 1);
bd->bi_memsize = cpu_to_be32(ram_size);
bd->bi_flashstart = cpu_to_be32(PROM_ADDR);
--
2.43.5
^ permalink raw reply related [flat|nested] 39+ messages in thread
* [PULL 13/32] ppc/vof: Make nextprop behave more like Open Firmware
2025-10-23 12:16 [PULL RESEND 00/32] ppc-for-10.2 queue Harsh Prateek Bora
` (11 preceding siblings ...)
2025-10-23 12:16 ` [PULL 12/32] ppc/amigaone: Free allocated struct Harsh Prateek Bora
@ 2025-10-23 12:16 ` Harsh Prateek Bora
2025-10-23 12:16 ` [PULL 14/32] hw/ppc/pegasos2: Remove explicit name properties from device tree Harsh Prateek Bora
` (19 subsequent siblings)
32 siblings, 0 replies; 39+ messages in thread
From: Harsh Prateek Bora @ 2025-10-23 12:16 UTC (permalink / raw)
To: qemu-devel; +Cc: BALATON Zoltan, Alexey Kardashevskiy
From: BALATON Zoltan <balaton@eik.bme.hu>
The FDT does not normally store name properties but reconstructs it
from path but Open Firmware specification says each node should at
least have this property. This is correctly handled in getprop but
nextprop should also return it even if not present as a property.
Explicit name properties are still allowed because they are needed
e.g. on the root node that guests expect to have specific names as
seen on real machines instead of being empty so sometimes the node
name may need to be overriden. For example on pegasos MorphOS checks
the name of "/" and expects to find bplan,Pegasos2 which is how it
identifies the machine.
Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>
Reviewed-by: Alexey Kardashevskiy <aik@ozlabs.ru>
Link: https://lore.kernel.org/qemu-devel/366f14ce852415cc079727c54ac21a2aa6ff3917.1761176219.git.balaton@eik.bme.hu
Signed-off-by: Harsh Prateek Bora <harshpb@linux.ibm.com>
---
hw/ppc/vof.c | 50 +++++++++++++++++++++++++++++++++-----------------
1 file changed, 33 insertions(+), 17 deletions(-)
diff --git a/hw/ppc/vof.c b/hw/ppc/vof.c
index f14efa3a7c..5ecfc68910 100644
--- a/hw/ppc/vof.c
+++ b/hw/ppc/vof.c
@@ -353,34 +353,50 @@ static uint32_t vof_nextprop(const void *fdt, uint32_t phandle,
{
int offset, nodeoff = fdt_node_offset_by_phandle(fdt, phandle);
char prev[OF_PROPNAME_LEN_MAX + 1];
- const char *tmp;
+ const char *tmp = NULL;
+ bool match = false;
if (readstr(prevaddr, prev, sizeof(prev))) {
return PROM_ERROR;
}
-
- fdt_for_each_property_offset(offset, fdt, nodeoff) {
- if (!fdt_getprop_by_offset(fdt, offset, &tmp, NULL)) {
- return 0;
+ /*
+ * "name" may or may not be present in fdt but we should still return it.
+ * Do that first and then skip it if seen later.
+ */
+ if (prev[0] == '\0') {
+ tmp = "name";
+ } else {
+ if (strcmp(prev, "name") == 0) {
+ prev[0] = '\0';
}
- if (prev[0] == '\0' || strcmp(prev, tmp) == 0) {
- if (prev[0] != '\0') {
- offset = fdt_next_property_offset(fdt, offset);
- if (offset < 0) {
- return 0;
- }
- }
+ fdt_for_each_property_offset(offset, fdt, nodeoff) {
if (!fdt_getprop_by_offset(fdt, offset, &tmp, NULL)) {
return 0;
}
-
- if (VOF_MEM_WRITE(nameaddr, tmp, strlen(tmp) + 1) != MEMTX_OK) {
- return PROM_ERROR;
+ if (strcmp(tmp, "name") == 0) {
+ continue;
+ }
+ if (match) {
+ break;
}
- return 1;
+ if (strcmp(prev, tmp) == 0) {
+ match = true;
+ continue;
+ }
+ if (prev[0] == '\0') {
+ break;
+ }
+ }
+ if (offset < 0) {
+ return 0;
}
}
-
+ if (tmp) {
+ if (VOF_MEM_WRITE(nameaddr, tmp, strlen(tmp) + 1) != MEMTX_OK) {
+ return PROM_ERROR;
+ }
+ return 1;
+ }
return 0;
}
--
2.43.5
^ permalink raw reply related [flat|nested] 39+ messages in thread
* [PULL 14/32] hw/ppc/pegasos2: Remove explicit name properties from device tree
2025-10-23 12:16 [PULL RESEND 00/32] ppc-for-10.2 queue Harsh Prateek Bora
` (12 preceding siblings ...)
2025-10-23 12:16 ` [PULL 13/32] ppc/vof: Make nextprop behave more like Open Firmware Harsh Prateek Bora
@ 2025-10-23 12:16 ` Harsh Prateek Bora
2025-10-23 12:16 ` [PULL 15/32] hw/ppc/pegasos2: Change device tree generation Harsh Prateek Bora
` (18 subsequent siblings)
32 siblings, 0 replies; 39+ messages in thread
From: Harsh Prateek Bora @ 2025-10-23 12:16 UTC (permalink / raw)
To: qemu-devel; +Cc: BALATON Zoltan
From: BALATON Zoltan <balaton@eik.bme.hu>
These are not needed any more now that VOF can handle it.
Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>
Reviewed-by: Harsh Prateek Bora <harshpb@linux.ibm.com>
Link: https://lore.kernel.org/qemu-devel/fa36ab5a04e10c6acb89583f646aad83df2b0b13.1761176219.git.balaton@eik.bme.hu
Signed-off-by: Harsh Prateek Bora <harshpb@linux.ibm.com>
---
hw/ppc/pegasos2.c | 17 -----------------
1 file changed, 17 deletions(-)
diff --git a/hw/ppc/pegasos2.c b/hw/ppc/pegasos2.c
index e15cf96427..73995624e5 100644
--- a/hw/ppc/pegasos2.c
+++ b/hw/ppc/pegasos2.c
@@ -662,7 +662,6 @@ static void dt_isa(PCIBus *bus, PCIDevice *d, FDTInfo *fi)
qemu_fdt_setprop_cell(fi->fdt, fi->path, "#size-cells", 1);
qemu_fdt_setprop_cell(fi->fdt, fi->path, "#address-cells", 2);
qemu_fdt_setprop_string(fi->fdt, fi->path, "device_type", "isa");
- qemu_fdt_setprop_string(fi->fdt, fi->path, "name", "isa");
/* additional devices */
g_string_printf(name, "%s/lpt@i3bc", fi->path);
@@ -677,7 +676,6 @@ static void dt_isa(PCIBus *bus, PCIDevice *d, FDTInfo *fi)
cells[2] = cpu_to_be32(8);
qemu_fdt_setprop(fi->fdt, name->str, "reg", cells, 3 * sizeof(cells[0]));
qemu_fdt_setprop_string(fi->fdt, name->str, "device_type", "lpt");
- qemu_fdt_setprop_string(fi->fdt, name->str, "name", "lpt");
g_string_printf(name, "%s/fdc@i3f0", fi->path);
qemu_fdt_add_subnode(fi->fdt, name->str);
@@ -691,7 +689,6 @@ static void dt_isa(PCIBus *bus, PCIDevice *d, FDTInfo *fi)
cells[2] = cpu_to_be32(8);
qemu_fdt_setprop(fi->fdt, name->str, "reg", cells, 3 * sizeof(cells[0]));
qemu_fdt_setprop_string(fi->fdt, name->str, "device_type", "fdc");
- qemu_fdt_setprop_string(fi->fdt, name->str, "name", "fdc");
g_string_printf(name, "%s/timer@i40", fi->path);
qemu_fdt_add_subnode(fi->fdt, name->str);
@@ -701,7 +698,6 @@ static void dt_isa(PCIBus *bus, PCIDevice *d, FDTInfo *fi)
cells[2] = cpu_to_be32(8);
qemu_fdt_setprop(fi->fdt, name->str, "reg", cells, 3 * sizeof(cells[0]));
qemu_fdt_setprop_string(fi->fdt, name->str, "device_type", "timer");
- qemu_fdt_setprop_string(fi->fdt, name->str, "name", "timer");
g_string_printf(name, "%s/rtc@i70", fi->path);
qemu_fdt_add_subnode(fi->fdt, name->str);
@@ -716,7 +712,6 @@ static void dt_isa(PCIBus *bus, PCIDevice *d, FDTInfo *fi)
cells[2] = cpu_to_be32(2);
qemu_fdt_setprop(fi->fdt, name->str, "reg", cells, 3 * sizeof(cells[0]));
qemu_fdt_setprop_string(fi->fdt, name->str, "device_type", "rtc");
- qemu_fdt_setprop_string(fi->fdt, name->str, "name", "rtc");
g_string_printf(name, "%s/keyboard@i60", fi->path);
qemu_fdt_add_subnode(fi->fdt, name->str);
@@ -729,7 +724,6 @@ static void dt_isa(PCIBus *bus, PCIDevice *d, FDTInfo *fi)
cells[2] = cpu_to_be32(5);
qemu_fdt_setprop(fi->fdt, name->str, "reg", cells, 3 * sizeof(cells[0]));
qemu_fdt_setprop_string(fi->fdt, name->str, "device_type", "keyboard");
- qemu_fdt_setprop_string(fi->fdt, name->str, "name", "keyboard");
g_string_printf(name, "%s/8042@i60", fi->path);
qemu_fdt_add_subnode(fi->fdt, name->str);
@@ -743,7 +737,6 @@ static void dt_isa(PCIBus *bus, PCIDevice *d, FDTInfo *fi)
cells[2] = cpu_to_be32(5);
qemu_fdt_setprop(fi->fdt, name->str, "reg", cells, 3 * sizeof(cells[0]));
qemu_fdt_setprop_string(fi->fdt, name->str, "device_type", "");
- qemu_fdt_setprop_string(fi->fdt, name->str, "name", "8042");
g_string_printf(name, "%s/serial@i2f8", fi->path);
qemu_fdt_add_subnode(fi->fdt, name->str);
@@ -757,7 +750,6 @@ static void dt_isa(PCIBus *bus, PCIDevice *d, FDTInfo *fi)
cells[2] = cpu_to_be32(8);
qemu_fdt_setprop(fi->fdt, name->str, "reg", cells, 3 * sizeof(cells[0]));
qemu_fdt_setprop_string(fi->fdt, name->str, "device_type", "serial");
- qemu_fdt_setprop_string(fi->fdt, name->str, "name", "serial");
g_string_free(name, TRUE);
}
@@ -846,7 +838,6 @@ static void add_pci_device(PCIBus *bus, PCIDevice *d, void *opaque)
j += 5;
}
qemu_fdt_setprop(fi->fdt, node->str, "reg", cells, j * sizeof(cells[0]));
- qemu_fdt_setprop_string(fi->fdt, node->str, "name", name ?: pn);
if (pci_get_byte(&d->config[PCI_INTERRUPT_PIN])) {
qemu_fdt_setprop_cell(fi->fdt, node->str, "interrupts",
pci_get_byte(&d->config[PCI_INTERRUPT_PIN]));
@@ -916,7 +907,6 @@ static void *build_fdt(MachineState *machine, int *fdt_size)
qemu_fdt_setprop_cell(fdt, "/pci@c0000000", "#size-cells", 2);
qemu_fdt_setprop_cell(fdt, "/pci@c0000000", "#address-cells", 3);
qemu_fdt_setprop_string(fdt, "/pci@c0000000", "device_type", "pci");
- qemu_fdt_setprop_string(fdt, "/pci@c0000000", "name", "pci");
fi.path = "/pci@c0000000";
pci_bus = mv64361_get_pci_bus(pm->mv, 0);
@@ -951,7 +941,6 @@ static void *build_fdt(MachineState *machine, int *fdt_size)
qemu_fdt_setprop_cell(fdt, "/pci@80000000", "#size-cells", 2);
qemu_fdt_setprop_cell(fdt, "/pci@80000000", "#address-cells", 3);
qemu_fdt_setprop_string(fdt, "/pci@80000000", "device_type", "pci");
- qemu_fdt_setprop_string(fdt, "/pci@80000000", "name", "pci");
fi.path = "/pci@80000000";
pci_bus = mv64361_get_pci_bus(pm->mv, 1);
@@ -959,7 +948,6 @@ static void *build_fdt(MachineState *machine, int *fdt_size)
qemu_fdt_add_subnode(fdt, "/failsafe");
qemu_fdt_setprop_string(fdt, "/failsafe", "device_type", "serial");
- qemu_fdt_setprop_string(fdt, "/failsafe", "name", "failsafe");
qemu_fdt_add_subnode(fdt, "/rtas");
qemu_fdt_setprop_cell(fdt, "/rtas", "system-reboot", RTAS_SYSTEM_REBOOT);
@@ -989,14 +977,12 @@ 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");
qemu_fdt_setprop_cell(fdt, "/cpus", "#cpus", 1);
qemu_fdt_setprop_cell(fdt, "/cpus", "#address-cells", 1);
qemu_fdt_setprop_cell(fdt, "/cpus", "#size-cells", 0);
- qemu_fdt_setprop_string(fdt, "/cpus", "name", "cpus");
/* FIXME Get CPU name from CPU object */
const char *cp = "/cpus/PowerPC,G4";
@@ -1048,7 +1034,6 @@ static void *build_fdt(MachineState *machine, int *fdt_size)
cells[1] = 0;
qemu_fdt_setprop(fdt, cp, "reg", cells, 2 * sizeof(cells[0]));
qemu_fdt_setprop_string(fdt, cp, "device_type", "cpu");
- qemu_fdt_setprop_string(fdt, cp, "name", strrchr(cp, '/') + 1);
/* memory */
qemu_fdt_add_subnode(fdt, "/memory@0");
@@ -1056,7 +1041,6 @@ static void *build_fdt(MachineState *machine, int *fdt_size)
cells[1] = cpu_to_be32(machine->ram_size);
qemu_fdt_setprop(fdt, "/memory@0", "reg", cells, 2 * sizeof(cells[0]));
qemu_fdt_setprop_string(fdt, "/memory@0", "device_type", "memory");
- qemu_fdt_setprop_string(fdt, "/memory@0", "name", "memory");
qemu_fdt_add_subnode(fdt, "/chosen");
if (pm->initrd_addr && pm->initrd_size) {
@@ -1067,7 +1051,6 @@ static void *build_fdt(MachineState *machine, int *fdt_size)
}
qemu_fdt_setprop_string(fdt, "/chosen", "bootargs",
machine->kernel_cmdline ?: "");
- qemu_fdt_setprop_string(fdt, "/chosen", "name", "chosen");
qemu_fdt_add_subnode(fdt, "/openprom");
qemu_fdt_setprop_string(fdt, "/openprom", "model", "Pegasos2,1.1");
--
2.43.5
^ permalink raw reply related [flat|nested] 39+ messages in thread
* [PULL 15/32] hw/ppc/pegasos2: Change device tree generation
2025-10-23 12:16 [PULL RESEND 00/32] ppc-for-10.2 queue Harsh Prateek Bora
` (13 preceding siblings ...)
2025-10-23 12:16 ` [PULL 14/32] hw/ppc/pegasos2: Remove explicit name properties from device tree Harsh Prateek Bora
@ 2025-10-23 12:16 ` Harsh Prateek Bora
2025-10-27 13:14 ` Peter Maydell
2025-10-23 12:16 ` [PULL 16/32] hw/ppc/pegasos2: Remove fdt pointer from machine state Harsh Prateek Bora
` (17 subsequent siblings)
32 siblings, 1 reply; 39+ messages in thread
From: Harsh Prateek Bora @ 2025-10-23 12:16 UTC (permalink / raw)
To: qemu-devel; +Cc: BALATON Zoltan, Philippe Mathieu-Daudé
From: BALATON Zoltan <balaton@eik.bme.hu>
We generate a flattened device tree programmatically for VOF. Change
this to load the static parts from a device tree blob and only
generate the parts that depend on run time conditions such as CPU
type, memory size and PCI devices. Moving the static parts in a dts
makes the board code simpler and more generic.
Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Link: https://lore.kernel.org/qemu-devel/383891fc2696609b27d2de9773efe1b4f493e333.1761176219.git.balaton@eik.bme.hu
Signed-off-by: Harsh Prateek Bora <harshpb@linux.ibm.com>
---
hw/ppc/pegasos2.c | 291 +++++++--------------------------------
pc-bios/dtb/meson.build | 1 +
pc-bios/dtb/pegasos2.dtb | Bin 0 -> 1701 bytes
pc-bios/dtb/pegasos2.dts | 167 ++++++++++++++++++++++
4 files changed, 219 insertions(+), 240 deletions(-)
create mode 100644 pc-bios/dtb/pegasos2.dtb
create mode 100644 pc-bios/dtb/pegasos2.dts
diff --git a/hw/ppc/pegasos2.c b/hw/ppc/pegasos2.c
index 73995624e5..f4787397dc 100644
--- a/hw/ppc/pegasos2.c
+++ b/hw/ppc/pegasos2.c
@@ -58,16 +58,8 @@
#define BUS_FREQ_HZ 133333333
#define PCI0_CFG_ADDR 0xcf8
-#define PCI0_MEM_BASE 0xc0000000
-#define PCI0_MEM_SIZE 0x20000000
-#define PCI0_IO_BASE 0xf8000000
-#define PCI0_IO_SIZE 0x10000
-
#define PCI1_CFG_ADDR 0xc78
-#define PCI1_MEM_BASE 0x80000000
-#define PCI1_MEM_SIZE 0x40000000
#define PCI1_IO_BASE 0xfe000000
-#define PCI1_IO_SIZE 0x10000
#define TYPE_PEGASOS2_MACHINE MACHINE_TYPE_NAME("pegasos2")
OBJECT_DECLARE_TYPE(Pegasos2MachineState, MachineClass, PEGASOS2_MACHINE)
@@ -411,7 +403,11 @@ static void pegasos2_machine_reset(MachineState *machine, ResetType type)
error_report("Memory for initrd is in use");
exit(1);
}
+
fdt = build_fdt(machine, &sz);
+ if (!fdt) {
+ exit(1);
+ }
/* FIXME: VOF assumes entry is same as load address */
d[0] = cpu_to_be64(pm->kernel_entry);
d[1] = cpu_to_be64(pm->kernel_size - (pm->kernel_entry - pm->kernel_addr));
@@ -654,113 +650,12 @@ static void dt_usb(PCIBus *bus, PCIDevice *d, FDTInfo *fi)
qemu_fdt_setprop_string(fi->fdt, fi->path, "device_type", "usb");
}
-static void dt_isa(PCIBus *bus, PCIDevice *d, FDTInfo *fi)
-{
- GString *name = g_string_sized_new(64);
- uint32_t cells[3];
-
- qemu_fdt_setprop_cell(fi->fdt, fi->path, "#size-cells", 1);
- qemu_fdt_setprop_cell(fi->fdt, fi->path, "#address-cells", 2);
- qemu_fdt_setprop_string(fi->fdt, fi->path, "device_type", "isa");
-
- /* additional devices */
- g_string_printf(name, "%s/lpt@i3bc", fi->path);
- qemu_fdt_add_subnode(fi->fdt, name->str);
- qemu_fdt_setprop_cell(fi->fdt, name->str, "clock-frequency", 0);
- cells[0] = cpu_to_be32(7);
- cells[1] = 0;
- qemu_fdt_setprop(fi->fdt, name->str, "interrupts",
- cells, 2 * sizeof(cells[0]));
- cells[0] = cpu_to_be32(1);
- cells[1] = cpu_to_be32(0x3bc);
- cells[2] = cpu_to_be32(8);
- qemu_fdt_setprop(fi->fdt, name->str, "reg", cells, 3 * sizeof(cells[0]));
- qemu_fdt_setprop_string(fi->fdt, name->str, "device_type", "lpt");
-
- g_string_printf(name, "%s/fdc@i3f0", fi->path);
- qemu_fdt_add_subnode(fi->fdt, name->str);
- qemu_fdt_setprop_cell(fi->fdt, name->str, "clock-frequency", 0);
- cells[0] = cpu_to_be32(6);
- cells[1] = 0;
- qemu_fdt_setprop(fi->fdt, name->str, "interrupts",
- cells, 2 * sizeof(cells[0]));
- cells[0] = cpu_to_be32(1);
- cells[1] = cpu_to_be32(0x3f0);
- cells[2] = cpu_to_be32(8);
- qemu_fdt_setprop(fi->fdt, name->str, "reg", cells, 3 * sizeof(cells[0]));
- qemu_fdt_setprop_string(fi->fdt, name->str, "device_type", "fdc");
-
- g_string_printf(name, "%s/timer@i40", fi->path);
- qemu_fdt_add_subnode(fi->fdt, name->str);
- qemu_fdt_setprop_cell(fi->fdt, name->str, "clock-frequency", 0);
- cells[0] = cpu_to_be32(1);
- cells[1] = cpu_to_be32(0x40);
- cells[2] = cpu_to_be32(8);
- qemu_fdt_setprop(fi->fdt, name->str, "reg", cells, 3 * sizeof(cells[0]));
- qemu_fdt_setprop_string(fi->fdt, name->str, "device_type", "timer");
-
- g_string_printf(name, "%s/rtc@i70", fi->path);
- qemu_fdt_add_subnode(fi->fdt, name->str);
- qemu_fdt_setprop_string(fi->fdt, name->str, "compatible", "ds1385-rtc");
- qemu_fdt_setprop_cell(fi->fdt, name->str, "clock-frequency", 0);
- cells[0] = cpu_to_be32(8);
- cells[1] = 0;
- qemu_fdt_setprop(fi->fdt, name->str, "interrupts",
- cells, 2 * sizeof(cells[0]));
- cells[0] = cpu_to_be32(1);
- cells[1] = cpu_to_be32(0x70);
- cells[2] = cpu_to_be32(2);
- qemu_fdt_setprop(fi->fdt, name->str, "reg", cells, 3 * sizeof(cells[0]));
- qemu_fdt_setprop_string(fi->fdt, name->str, "device_type", "rtc");
-
- g_string_printf(name, "%s/keyboard@i60", fi->path);
- qemu_fdt_add_subnode(fi->fdt, name->str);
- cells[0] = cpu_to_be32(1);
- cells[1] = 0;
- qemu_fdt_setprop(fi->fdt, name->str, "interrupts",
- cells, 2 * sizeof(cells[0]));
- cells[0] = cpu_to_be32(1);
- cells[1] = cpu_to_be32(0x60);
- cells[2] = cpu_to_be32(5);
- qemu_fdt_setprop(fi->fdt, name->str, "reg", cells, 3 * sizeof(cells[0]));
- qemu_fdt_setprop_string(fi->fdt, name->str, "device_type", "keyboard");
-
- g_string_printf(name, "%s/8042@i60", fi->path);
- qemu_fdt_add_subnode(fi->fdt, name->str);
- qemu_fdt_setprop_cell(fi->fdt, name->str, "#interrupt-cells", 2);
- qemu_fdt_setprop_cell(fi->fdt, name->str, "#size-cells", 0);
- qemu_fdt_setprop_cell(fi->fdt, name->str, "#address-cells", 1);
- qemu_fdt_setprop_string(fi->fdt, name->str, "interrupt-controller", "");
- qemu_fdt_setprop_cell(fi->fdt, name->str, "clock-frequency", 0);
- cells[0] = cpu_to_be32(1);
- cells[1] = cpu_to_be32(0x60);
- cells[2] = cpu_to_be32(5);
- qemu_fdt_setprop(fi->fdt, name->str, "reg", cells, 3 * sizeof(cells[0]));
- qemu_fdt_setprop_string(fi->fdt, name->str, "device_type", "");
-
- g_string_printf(name, "%s/serial@i2f8", fi->path);
- qemu_fdt_add_subnode(fi->fdt, name->str);
- qemu_fdt_setprop_cell(fi->fdt, name->str, "clock-frequency", 0);
- cells[0] = cpu_to_be32(3);
- cells[1] = 0;
- qemu_fdt_setprop(fi->fdt, name->str, "interrupts",
- cells, 2 * sizeof(cells[0]));
- cells[0] = cpu_to_be32(1);
- cells[1] = cpu_to_be32(0x2f8);
- cells[2] = cpu_to_be32(8);
- qemu_fdt_setprop(fi->fdt, name->str, "reg", cells, 3 * sizeof(cells[0]));
- qemu_fdt_setprop_string(fi->fdt, name->str, "device_type", "serial");
-
- g_string_free(name, TRUE);
-}
-
static struct {
const char *id;
const char *name;
void (*dtf)(PCIBus *bus, PCIDevice *d, FDTInfo *fi);
} device_map[] = {
{ "pci11ab,6460", "host", NULL },
- { "pci1106,8231", "isa", dt_isa },
{ "pci1106,571", "ide", dt_ide },
{ "pci1106,3044", "firewire", NULL },
{ "pci1106,3038", "usb", dt_usb },
@@ -780,7 +675,10 @@ 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]) ==
+ if (!strcmp(pn, "pci1106,8231")) {
+ return; /* ISA bridge and devices are included in dtb */
+ }
+ 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 ==
@@ -858,131 +756,9 @@ static void add_pci_device(PCIBus *bus, PCIDevice *d, void *opaque)
g_string_free(node, TRUE);
}
-static void *build_fdt(MachineState *machine, int *fdt_size)
+static void add_cpu_info(void *fdt, PowerPCCPU *cpu)
{
- Pegasos2MachineState *pm = PEGASOS2_MACHINE(machine);
- PowerPCCPU *cpu = pm->cpu;
- PCIBus *pci_bus;
- FDTInfo fi;
- uint32_t cells[16];
- void *fdt = create_device_tree(fdt_size);
-
- fi.fdt = fdt;
-
- /* root node */
- qemu_fdt_setprop_string(fdt, "/", "CODEGEN,description",
- "Pegasos CHRP PowerPC System");
- qemu_fdt_setprop_string(fdt, "/", "CODEGEN,board", "Pegasos2");
- qemu_fdt_setprop_string(fdt, "/", "CODEGEN,vendor", "bplan GmbH");
- qemu_fdt_setprop_string(fdt, "/", "revision", "2B");
- qemu_fdt_setprop_string(fdt, "/", "model", "Pegasos2");
- qemu_fdt_setprop_string(fdt, "/", "device_type", "chrp");
- qemu_fdt_setprop_cell(fdt, "/", "#address-cells", 1);
- qemu_fdt_setprop_string(fdt, "/", "name", "bplan,Pegasos2");
-
- /* pci@c0000000 */
- qemu_fdt_add_subnode(fdt, "/pci@c0000000");
- cells[0] = 0;
- cells[1] = 0;
- qemu_fdt_setprop(fdt, "/pci@c0000000", "bus-range",
- cells, 2 * sizeof(cells[0]));
- qemu_fdt_setprop_cell(fdt, "/pci@c0000000", "pci-bridge-number", 1);
- cells[0] = cpu_to_be32(PCI0_MEM_BASE);
- cells[1] = cpu_to_be32(PCI0_MEM_SIZE);
- qemu_fdt_setprop(fdt, "/pci@c0000000", "reg", cells, 2 * sizeof(cells[0]));
- cells[0] = cpu_to_be32(0x01000000);
- cells[1] = 0;
- cells[2] = 0;
- cells[3] = cpu_to_be32(PCI0_IO_BASE);
- cells[4] = 0;
- cells[5] = cpu_to_be32(PCI0_IO_SIZE);
- cells[6] = cpu_to_be32(0x02000000);
- cells[7] = 0;
- cells[8] = cpu_to_be32(PCI0_MEM_BASE);
- cells[9] = cpu_to_be32(PCI0_MEM_BASE);
- cells[10] = 0;
- cells[11] = cpu_to_be32(PCI0_MEM_SIZE);
- qemu_fdt_setprop(fdt, "/pci@c0000000", "ranges",
- cells, 12 * sizeof(cells[0]));
- qemu_fdt_setprop_cell(fdt, "/pci@c0000000", "#size-cells", 2);
- qemu_fdt_setprop_cell(fdt, "/pci@c0000000", "#address-cells", 3);
- qemu_fdt_setprop_string(fdt, "/pci@c0000000", "device_type", "pci");
-
- fi.path = "/pci@c0000000";
- pci_bus = mv64361_get_pci_bus(pm->mv, 0);
- pci_for_each_device_reverse(pci_bus, 0, add_pci_device, &fi);
-
- /* pci@80000000 */
- qemu_fdt_add_subnode(fdt, "/pci@80000000");
- cells[0] = 0;
- cells[1] = 0;
- qemu_fdt_setprop(fdt, "/pci@80000000", "bus-range",
- cells, 2 * sizeof(cells[0]));
- qemu_fdt_setprop_cell(fdt, "/pci@80000000", "pci-bridge-number", 0);
- cells[0] = cpu_to_be32(PCI1_MEM_BASE);
- cells[1] = cpu_to_be32(PCI1_MEM_SIZE);
- qemu_fdt_setprop(fdt, "/pci@80000000", "reg", cells, 2 * sizeof(cells[0]));
- qemu_fdt_setprop_cell(fdt, "/pci@80000000", "8259-interrupt-acknowledge",
- 0xf1000cb4);
- cells[0] = cpu_to_be32(0x01000000);
- cells[1] = 0;
- cells[2] = 0;
- cells[3] = cpu_to_be32(PCI1_IO_BASE);
- cells[4] = 0;
- cells[5] = cpu_to_be32(PCI1_IO_SIZE);
- cells[6] = cpu_to_be32(0x02000000);
- cells[7] = 0;
- cells[8] = cpu_to_be32(PCI1_MEM_BASE);
- cells[9] = cpu_to_be32(PCI1_MEM_BASE);
- cells[10] = 0;
- cells[11] = cpu_to_be32(PCI1_MEM_SIZE);
- qemu_fdt_setprop(fdt, "/pci@80000000", "ranges",
- cells, 12 * sizeof(cells[0]));
- qemu_fdt_setprop_cell(fdt, "/pci@80000000", "#size-cells", 2);
- qemu_fdt_setprop_cell(fdt, "/pci@80000000", "#address-cells", 3);
- qemu_fdt_setprop_string(fdt, "/pci@80000000", "device_type", "pci");
-
- fi.path = "/pci@80000000";
- pci_bus = mv64361_get_pci_bus(pm->mv, 1);
- pci_for_each_device_reverse(pci_bus, 0, add_pci_device, &fi);
-
- qemu_fdt_add_subnode(fdt, "/failsafe");
- qemu_fdt_setprop_string(fdt, "/failsafe", "device_type", "serial");
-
- qemu_fdt_add_subnode(fdt, "/rtas");
- qemu_fdt_setprop_cell(fdt, "/rtas", "system-reboot", RTAS_SYSTEM_REBOOT);
- qemu_fdt_setprop_cell(fdt, "/rtas", "hibernate", RTAS_HIBERNATE);
- qemu_fdt_setprop_cell(fdt, "/rtas", "suspend", RTAS_SUSPEND);
- qemu_fdt_setprop_cell(fdt, "/rtas", "power-off", RTAS_POWER_OFF);
- qemu_fdt_setprop_cell(fdt, "/rtas", "set-indicator", RTAS_SET_INDICATOR);
- qemu_fdt_setprop_cell(fdt, "/rtas", "display-character",
- RTAS_DISPLAY_CHARACTER);
- qemu_fdt_setprop_cell(fdt, "/rtas", "write-pci-config",
- RTAS_WRITE_PCI_CONFIG);
- qemu_fdt_setprop_cell(fdt, "/rtas", "read-pci-config",
- RTAS_READ_PCI_CONFIG);
- /* Pegasos2 firmware misspells check-exception and guests use that */
- qemu_fdt_setprop_cell(fdt, "/rtas", "check-execption",
- RTAS_CHECK_EXCEPTION);
- qemu_fdt_setprop_cell(fdt, "/rtas", "event-scan", RTAS_EVENT_SCAN);
- qemu_fdt_setprop_cell(fdt, "/rtas", "set-time-of-day",
- RTAS_SET_TIME_OF_DAY);
- qemu_fdt_setprop_cell(fdt, "/rtas", "get-time-of-day",
- RTAS_GET_TIME_OF_DAY);
- qemu_fdt_setprop_cell(fdt, "/rtas", "nvram-store", RTAS_NVRAM_STORE);
- qemu_fdt_setprop_cell(fdt, "/rtas", "nvram-fetch", RTAS_NVRAM_FETCH);
- qemu_fdt_setprop_cell(fdt, "/rtas", "restart-rtas", RTAS_RESTART_RTAS);
- qemu_fdt_setprop_cell(fdt, "/rtas", "rtas-error-log-max", 0);
- qemu_fdt_setprop_cell(fdt, "/rtas", "rtas-event-scan-rate", 0);
- 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);
-
- /* cpus */
- qemu_fdt_add_subnode(fdt, "/cpus");
- qemu_fdt_setprop_cell(fdt, "/cpus", "#cpus", 1);
- qemu_fdt_setprop_cell(fdt, "/cpus", "#address-cells", 1);
- qemu_fdt_setprop_cell(fdt, "/cpus", "#size-cells", 0);
+ uint32_t cells[2];
/* FIXME Get CPU name from CPU object */
const char *cp = "/cpus/PowerPC,G4";
@@ -1034,15 +810,43 @@ static void *build_fdt(MachineState *machine, int *fdt_size)
cells[1] = 0;
qemu_fdt_setprop(fdt, cp, "reg", cells, 2 * sizeof(cells[0]));
qemu_fdt_setprop_string(fdt, cp, "device_type", "cpu");
+}
+
+static void *load_dtb(const char *filename, int *fdt_size)
+{
+ void *fdt;
+ g_autofree char *name = qemu_find_file(QEMU_FILE_TYPE_DTB, filename);
+
+ if (!name) {
+ error_report("Could not find dtb file '%s'", filename);
+ return NULL;
+ }
+ fdt = load_device_tree(name, fdt_size);
+ if (!fdt) {
+ error_report("Could not load dtb file '%s'", name);
+ }
+ return fdt;
+}
- /* memory */
- qemu_fdt_add_subnode(fdt, "/memory@0");
+static void *build_fdt(MachineState *machine, int *fdt_size)
+{
+ Pegasos2MachineState *pm = PEGASOS2_MACHINE(machine);
+ FDTInfo fi;
+ PCIBus *pci_bus;
+ uint32_t cells[2];
+ void *fdt = load_dtb("pegasos2.dtb", fdt_size);
+
+ if (!fdt) {
+ return NULL;
+ }
+ qemu_fdt_setprop_string(fdt, "/", "name", "bplan,Pegasos2");
+
+ /* Set memory size */
cells[0] = 0;
cells[1] = cpu_to_be32(machine->ram_size);
qemu_fdt_setprop(fdt, "/memory@0", "reg", cells, 2 * sizeof(cells[0]));
- qemu_fdt_setprop_string(fdt, "/memory@0", "device_type", "memory");
- qemu_fdt_add_subnode(fdt, "/chosen");
+ /* Boot parameters */
if (pm->initrd_addr && pm->initrd_size) {
qemu_fdt_setprop_cell(fdt, "/chosen", "linux,initrd-end",
pm->initrd_addr + pm->initrd_size);
@@ -1052,8 +856,15 @@ static void *build_fdt(MachineState *machine, int *fdt_size)
qemu_fdt_setprop_string(fdt, "/chosen", "bootargs",
machine->kernel_cmdline ?: "");
- qemu_fdt_add_subnode(fdt, "/openprom");
- qemu_fdt_setprop_string(fdt, "/openprom", "model", "Pegasos2,1.1");
+ add_cpu_info(fdt, pm->cpu);
+
+ fi.fdt = fdt;
+ fi.path = "/pci@c0000000";
+ pci_bus = mv64361_get_pci_bus(pm->mv, 0);
+ pci_for_each_device_reverse(pci_bus, 0, add_pci_device, &fi);
+ fi.path = "/pci@80000000";
+ pci_bus = mv64361_get_pci_bus(pm->mv, 1);
+ pci_for_each_device_reverse(pci_bus, 0, add_pci_device, &fi);
return fdt;
}
diff --git a/pc-bios/dtb/meson.build b/pc-bios/dtb/meson.build
index 993032949f..f14648f3a4 100644
--- a/pc-bios/dtb/meson.build
+++ b/pc-bios/dtb/meson.build
@@ -1,6 +1,7 @@
dtbs = [
'bamboo.dtb',
'canyonlands.dtb',
+ 'pegasos2.dtb',
'petalogix-ml605.dtb',
'petalogix-s3adsp1800.dtb',
]
diff --git a/pc-bios/dtb/pegasos2.dtb b/pc-bios/dtb/pegasos2.dtb
new file mode 100644
index 0000000000000000000000000000000000000000..29c35216ec2d77e4083a3ef618ca185925fb5d61
GIT binary patch
literal 1701
zcmb_cyKWRQ6!nns2oQw;9TbZ~fl!Q+2&AN25u&7m6$nwJh`gS=yH;k#6WhC+r9h#h
zgAYK01`0YPJ|IXGlptz8fP#XKNGRf7&v-N0P;#X^bI!5v!;hISllwmzJMo4ww#eA{
zXMA5npGH52juw4K{Y8NfJ)@G1;d{Kqq!B-kJ|#OQFLlx;&@VNhEv&W+6`jVeEZp`A
z;WOyhn|UI#+G^Td8|oCl^pE(<sIQiKZF%i}qt?)UFpcHfgMoFBQi4e5kmW{uf}HA1
zq7VC-oxd@Uoa`8SBs<zdcED3ewHegsyi&xUL_AgKUZtF;(APaH9!0LaYfFvh&|Ynf
zaH3)FXneEeKHfMn8oxC%{|WMo=pp|z#AJcLEa;HGAK{-y_*dlBe((<XeF^z~ASWF7
z9%Aad<Pn|Ki3+FQXurbvRm8Mcf!{<-F@dijK3(CD5YxQ~<A8X&!ZqUa72ZdDp~9ac
zrXKu$wuDNoXi*L_%IVM2f>9#znxB_TRbQMd%&WutYzoInD*N%HgafDZr5q)Xo=1OP
zKP)-kq39KDZm|6TP^2KToze-{>2Z+j?JsurL&^Pp+d)!CM+@~n7SwZ`6MZW=y{JS)
zYm@(JZDV`&cbJoEA6eUP6uni}wu=HeS<OE~pKN{iu!eUkqP1Xjm~&(;w4R9>5yu9s
z<r0#_vKV?w!iF2<z)~GU!VD@_>5MJkyR)*oa(A`|S**>FHnlMEki}r7QMsc418p{A
z)nh1g&q(^7>7(R5Fg~XzG^LPZW%2hl;6)dO23XH=D@DeQaOFfWMjM{!Hc!Pi7P3wl
z$Nl%7^^8b)3!Ln*0$ZmIur@gER0>?Tcq|6Yj_`vzOm;wSa@YnL79wJf2hXL>TB^<Z
zMmeYop>Np{Mo0(7XIELQq`=}Vr~fJzZZX@n_(P3ZM>WA@v>xmKwcJ2cYsX}wv2@G8
zRu?ikU`AwZuxxSR))H44W;Wg2aUnM|-A^EH1Eap0Mj_-`H^r>1*|oS;7{~qsTcHaV
literal 0
HcmV?d00001
diff --git a/pc-bios/dtb/pegasos2.dts b/pc-bios/dtb/pegasos2.dts
new file mode 100644
index 0000000000..0ddb9e3bec
--- /dev/null
+++ b/pc-bios/dtb/pegasos2.dts
@@ -0,0 +1,167 @@
+/*
+ * QEMU Pegasos2 Device Tree Source
+ *
+ * Copyright 2025 BALATON Zoltan
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ *
+ * This is partial source, more info will be filled in by board code.
+ */
+
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ device_type = "chrp";
+ model = "Pegasos2";
+ revision = "2B";
+ CODEGEN,vendor = "bplan GmbH";
+ CODEGEN,board = "Pegasos2";
+ CODEGEN,description = "Pegasos CHRP PowerPC System";
+
+ openprom {
+ model = "Pegasos2,1.1";
+ };
+
+ chosen {
+ };
+
+ memory@0 {
+ device_type = "memory";
+ reg = <0 0>;
+ };
+
+ cpus {
+ #size-cells = <0>;
+ #address-cells = <1>;
+ #cpus = <1>;
+ };
+
+ rtas {
+ rtas-version = <1>;
+ rtas-size = <20>;
+ rtas-display-device = <0>;
+ rtas-event-scan-rate = <0>;
+ rtas-error-log-max = <0>;
+ restart-rtas = <0>;
+ nvram-fetch = <1>;
+ nvram-store = <2>;
+ get-time-of-day = <3>;
+ set-time-of-day = <4>;
+ event-scan = <6>;
+ /* Pegasos2 firmware misspells check-exception */
+ check-execption = <7>;
+ read-pci-config = <8>;
+ write-pci-config = <9>;
+ display-character = <10>;
+ set-indicator = <11>;
+ power-off = <17>;
+ suspend = <18>;
+ hibernate = <19>;
+ system-reboot = <20>;
+ };
+
+ failsafe {
+ device_type = "serial";
+ };
+
+ pci@80000000 {
+ device_type = "pci";
+ #address-cells = <3>;
+ #size-cells = <2>;
+ clock-frequency = <33333333>;
+ ranges = <0x01000000 0 0x00000000 0xfe000000 0 0x00010000
+ 0x02000000 0 0x80000000 0x80000000 0 0x40000000>;
+ 8259-interrupt-acknowledge = <0xf1000cb4>;
+ reg = <0x80000000 0x40000000>;
+ pci-bridge-number = <0>;
+ bus-range = <0 0>;
+
+ isa@c {
+ vendor-id = <0x1106>;
+ device-id = <0x8231>;
+ revision-id = <0x10>;
+ class-code = <0x60100>;
+ /* Pegasos firmware has subsystem-id and
+ subsystem-vendor-id swapped */
+ subsystem-id = <0x1af4>;
+ subsystem-vendor-id = <0x1100>;
+ reg = <0x6000 0 0 0 0>;
+ device_type = "isa";
+ #address-cells = <2>;
+ #size-cells = <1>;
+ eisa-slots = <0>;
+ clock-frequency = <8333333>;
+ slot-names = <0>;
+
+ serial@i2f8 {
+ device_type = "serial";
+ reg = <1 0x2f8 8>;
+ interrupts = <3 0>;
+ clock-frequency = <1843200>;
+ compatible = "pnpPNP,501";
+ };
+
+ 8042@i60 {
+ device_type = "";
+ reg = <1 0x60 5>;
+ clock-frequency = <0>;
+ compatible = "chrp,8042";
+ interrupt-controller = "";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ #interrupt-cells = <2>;
+
+ };
+
+ keyboard@i60 {
+ device_type = "keyboard";
+ reg = <1 0x60 5>;
+ interrupts = <1 0>;
+ compatible = "pnpPNP,303";
+ };
+
+ rtc@i70 {
+ device_type = "rtc";
+ reg = <1 0x70 2>;
+ interrupts = <8 0>;
+ clock-frequency = <0>;
+ compatible = "ds1385-rtc";
+ };
+
+ timer@i40 {
+ device_type = "timer";
+ reg = <1 0x40 8>;
+ clock-frequency = <0>;
+ compatible = "pnpPNP,100";
+ };
+
+ fdc@i3f0 {
+ device_type = "fdc";
+ reg = <1 0x3f0 8>;
+ interrupts = <6 0>;
+ clock-frequency = <0>;
+ compatible = "pnpPNP,700";
+ };
+
+ lpt@i3bc {
+ device_type = "lpt";
+ reg = <1 0x3bc 8>;
+ interrupts = <7 0>;
+ clock-frequency = <0>;
+ compatible = "pnpPNP,400";
+ };
+ };
+ };
+
+ pci@c0000000 {
+ device_type = "pci";
+ #address-cells = <3>;
+ #size-cells = <2>;
+ clock-frequency = <66666666>;
+ ranges = <0x01000000 0 0x00000000 0xf8000000 0 0x00010000
+ 0x02000000 0 0xc0000000 0xc0000000 0 0x20000000>;
+ reg = <0xc0000000 0x20000000>;
+ pci-bridge-number = <1>;
+ bus-range = <0 0>;
+ };
+};
--
2.43.5
^ permalink raw reply related [flat|nested] 39+ messages in thread
* [PULL 16/32] hw/ppc/pegasos2: Remove fdt pointer from machine state
2025-10-23 12:16 [PULL RESEND 00/32] ppc-for-10.2 queue Harsh Prateek Bora
` (14 preceding siblings ...)
2025-10-23 12:16 ` [PULL 15/32] hw/ppc/pegasos2: Change device tree generation Harsh Prateek Bora
@ 2025-10-23 12:16 ` Harsh Prateek Bora
2025-10-23 12:16 ` [PULL 17/32] hw/ppc/pegasos2: Rename mv field in " Harsh Prateek Bora
` (16 subsequent siblings)
32 siblings, 0 replies; 39+ messages in thread
From: Harsh Prateek Bora @ 2025-10-23 12:16 UTC (permalink / raw)
To: qemu-devel; +Cc: BALATON Zoltan, Philippe Mathieu-Daudé
From: BALATON Zoltan <balaton@eik.bme.hu>
The machine class has a field for storing the fdt so we don't need our
own and can use that instead.
Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Link: https://lore.kernel.org/qemu-devel/f4355b8d2889aba19d28001e61ac3f9937fc5250.1761176219.git.balaton@eik.bme.hu
Signed-off-by: Harsh Prateek Bora <harshpb@linux.ibm.com>
---
hw/ppc/pegasos2.c | 7 ++-----
1 file changed, 2 insertions(+), 5 deletions(-)
diff --git a/hw/ppc/pegasos2.c b/hw/ppc/pegasos2.c
index f4787397dc..2ba579dddf 100644
--- a/hw/ppc/pegasos2.c
+++ b/hw/ppc/pegasos2.c
@@ -74,7 +74,6 @@ struct Pegasos2MachineState {
qemu_irq mv_pirq[PCI_NUM_PINS];
qemu_irq via_pirq[PCI_NUM_PINS];
Vof *vof;
- void *fdt_blob;
uint64_t kernel_addr;
uint64_t kernel_entry;
uint64_t kernel_size;
@@ -413,13 +412,11 @@ static void pegasos2_machine_reset(MachineState *machine, ResetType type)
d[1] = cpu_to_be64(pm->kernel_size - (pm->kernel_entry - pm->kernel_addr));
qemu_fdt_setprop(fdt, "/chosen", "qemu,boot-kernel", d, sizeof(d));
- g_free(pm->fdt_blob);
- pm->fdt_blob = fdt;
-
vof_build_dt(fdt, pm->vof);
vof_client_open_store(fdt, pm->vof, "/chosen", "stdout", "/failsafe");
/* Set machine->fdt for 'dumpdtb' QMP/HMP command */
+ g_free(machine->fdt);
machine->fdt = fdt;
pm->cpu->vhyp = PPC_VIRTUAL_HYPERVISOR(machine);
@@ -559,7 +556,7 @@ static void pegasos2_hypercall(PPCVirtualHypervisor *vhyp, PowerPCCPU *cpu)
} else if (env->gpr[3] == KVMPPC_H_RTAS) {
env->gpr[3] = pegasos2_rtas(cpu, pm, env->gpr[4]);
} else if (env->gpr[3] == KVMPPC_H_VOF_CLIENT) {
- int ret = vof_client_call(MACHINE(pm), pm->vof, pm->fdt_blob,
+ int ret = vof_client_call(MACHINE(pm), pm->vof, MACHINE(pm)->fdt,
env->gpr[4]);
env->gpr[3] = (ret ? H_PARAMETER : H_SUCCESS);
} else {
--
2.43.5
^ permalink raw reply related [flat|nested] 39+ messages in thread
* [PULL 17/32] hw/ppc/pegasos2: Rename mv field in machine state
2025-10-23 12:16 [PULL RESEND 00/32] ppc-for-10.2 queue Harsh Prateek Bora
` (15 preceding siblings ...)
2025-10-23 12:16 ` [PULL 16/32] hw/ppc/pegasos2: Remove fdt pointer from machine state Harsh Prateek Bora
@ 2025-10-23 12:16 ` Harsh Prateek Bora
2025-10-23 12:16 ` [PULL 18/32] hw/ppc/pegasos2: Add south bridge pointer in the " Harsh Prateek Bora
` (15 subsequent siblings)
32 siblings, 0 replies; 39+ messages in thread
From: Harsh Prateek Bora @ 2025-10-23 12:16 UTC (permalink / raw)
To: qemu-devel; +Cc: BALATON Zoltan, Philippe Mathieu-Daudé
From: BALATON Zoltan <balaton@eik.bme.hu>
Use more generic name for the field used to store the north bridge in
the machine state.
Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Link: https://lore.kernel.org/qemu-devel/f1c189f16a260377abe0d270e778f2738649446a.1761176219.git.balaton@eik.bme.hu
Signed-off-by: Harsh Prateek Bora <harshpb@linux.ibm.com>
---
hw/ppc/pegasos2.c | 20 ++++++++++----------
1 file changed, 10 insertions(+), 10 deletions(-)
diff --git a/hw/ppc/pegasos2.c b/hw/ppc/pegasos2.c
index 2ba579dddf..9b89c7ecc2 100644
--- a/hw/ppc/pegasos2.c
+++ b/hw/ppc/pegasos2.c
@@ -68,7 +68,7 @@ struct Pegasos2MachineState {
MachineState parent_obj;
PowerPCCPU *cpu;
- DeviceState *mv;
+ DeviceState *nb; /* north bridge */
IRQState pci_irqs[PCI_NUM_PINS];
OrIRQState orirq[PCI_NUM_PINS];
qemu_irq mv_pirq[PCI_NUM_PINS];
@@ -166,12 +166,12 @@ static void pegasos2_init(MachineState *machine)
}
/* Marvell Discovery II system controller */
- pm->mv = DEVICE(sysbus_create_simple(TYPE_MV64361, -1,
+ pm->nb = DEVICE(sysbus_create_simple(TYPE_MV64361, -1,
qdev_get_gpio_in(DEVICE(pm->cpu), PPC6xx_INPUT_INT)));
for (i = 0; i < PCI_NUM_PINS; i++) {
- pm->mv_pirq[i] = qdev_get_gpio_in_named(pm->mv, "gpp", 12 + i);
+ pm->mv_pirq[i] = qdev_get_gpio_in_named(pm->nb, "gpp", 12 + i);
}
- pci_bus = mv64361_get_pci_bus(pm->mv, 1);
+ pci_bus = mv64361_get_pci_bus(pm->nb, 1);
/* VIA VT8231 South Bridge (multifunction PCI device) */
via = OBJECT(pci_new_multifunction(PCI_DEVFN(12, 0), TYPE_VT8231_ISA));
@@ -190,7 +190,7 @@ static void pegasos2_init(MachineState *machine)
object_resolve_path_component(via, "rtc"),
"date");
qdev_connect_gpio_out_named(DEVICE(via), "intr", 0,
- qdev_get_gpio_in_named(pm->mv, "gpp", 31));
+ qdev_get_gpio_in_named(pm->nb, "gpp", 31));
dev = PCI_DEVICE(object_resolve_path_component(via, "ide"));
pci_ide_create_devs(dev);
@@ -208,7 +208,7 @@ static void pegasos2_init(MachineState *machine)
DeviceState *pd;
g_autofree const char *pn = g_strdup_printf("pcihost%d", h);
- pd = DEVICE(object_resolve_path_component(OBJECT(pm->mv), pn));
+ pd = DEVICE(object_resolve_path_component(OBJECT(pm->nb), pn));
assert(pd);
for (i = 0; i < PCI_NUM_PINS; i++) {
OrIRQState *ori = &pm->orirq[i];
@@ -267,7 +267,7 @@ static void pegasos2_init(MachineState *machine)
static uint32_t pegasos2_mv_reg_read(Pegasos2MachineState *pm,
uint32_t addr, uint32_t len)
{
- MemoryRegion *r = sysbus_mmio_get_region(SYS_BUS_DEVICE(pm->mv), 0);
+ MemoryRegion *r = sysbus_mmio_get_region(SYS_BUS_DEVICE(pm->nb), 0);
uint64_t val = 0xffffffffULL;
memory_region_dispatch_read(r, addr, &val, size_memop(len) | MO_LE,
MEMTXATTRS_UNSPECIFIED);
@@ -277,7 +277,7 @@ static uint32_t pegasos2_mv_reg_read(Pegasos2MachineState *pm,
static void pegasos2_mv_reg_write(Pegasos2MachineState *pm, uint32_t addr,
uint32_t len, uint32_t val)
{
- MemoryRegion *r = sysbus_mmio_get_region(SYS_BUS_DEVICE(pm->mv), 0);
+ MemoryRegion *r = sysbus_mmio_get_region(SYS_BUS_DEVICE(pm->nb), 0);
memory_region_dispatch_write(r, addr, val, size_memop(len) | MO_LE,
MEMTXATTRS_UNSPECIFIED);
}
@@ -857,10 +857,10 @@ static void *build_fdt(MachineState *machine, int *fdt_size)
fi.fdt = fdt;
fi.path = "/pci@c0000000";
- pci_bus = mv64361_get_pci_bus(pm->mv, 0);
+ pci_bus = mv64361_get_pci_bus(pm->nb, 0);
pci_for_each_device_reverse(pci_bus, 0, add_pci_device, &fi);
fi.path = "/pci@80000000";
- pci_bus = mv64361_get_pci_bus(pm->mv, 1);
+ pci_bus = mv64361_get_pci_bus(pm->nb, 1);
pci_for_each_device_reverse(pci_bus, 0, add_pci_device, &fi);
return fdt;
--
2.43.5
^ permalink raw reply related [flat|nested] 39+ messages in thread
* [PULL 18/32] hw/ppc/pegasos2: Add south bridge pointer in the machine state
2025-10-23 12:16 [PULL RESEND 00/32] ppc-for-10.2 queue Harsh Prateek Bora
` (16 preceding siblings ...)
2025-10-23 12:16 ` [PULL 17/32] hw/ppc/pegasos2: Rename mv field in " Harsh Prateek Bora
@ 2025-10-23 12:16 ` Harsh Prateek Bora
2025-10-23 12:16 ` [PULL 19/32] hw/ppc/pegasos2: Move PCI IRQ routing setup to a function Harsh Prateek Bora
` (14 subsequent siblings)
32 siblings, 0 replies; 39+ messages in thread
From: Harsh Prateek Bora @ 2025-10-23 12:16 UTC (permalink / raw)
To: qemu-devel; +Cc: BALATON Zoltan, Philippe Mathieu-Daudé
From: BALATON Zoltan <balaton@eik.bme.hu>
Add field for the south bridge in machine state to have both north and
south bridges in it.
Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Link: https://lore.kernel.org/qemu-devel/654d3223b418d5bb2ba08a2b014375c2abf341aa.1761176219.git.balaton@eik.bme.hu
Signed-off-by: Harsh Prateek Bora <harshpb@linux.ibm.com>
---
hw/ppc/pegasos2.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/hw/ppc/pegasos2.c b/hw/ppc/pegasos2.c
index 9b89c7ecc2..4b63f0e175 100644
--- a/hw/ppc/pegasos2.c
+++ b/hw/ppc/pegasos2.c
@@ -69,6 +69,7 @@ struct Pegasos2MachineState {
PowerPCCPU *cpu;
DeviceState *nb; /* north bridge */
+ DeviceState *sb; /* south bridge */
IRQState pci_irqs[PCI_NUM_PINS];
OrIRQState orirq[PCI_NUM_PINS];
qemu_irq mv_pirq[PCI_NUM_PINS];
@@ -174,7 +175,8 @@ static void pegasos2_init(MachineState *machine)
pci_bus = mv64361_get_pci_bus(pm->nb, 1);
/* VIA VT8231 South Bridge (multifunction PCI device) */
- via = OBJECT(pci_new_multifunction(PCI_DEVFN(12, 0), TYPE_VT8231_ISA));
+ pm->sb = DEVICE(pci_new_multifunction(PCI_DEVFN(12, 0), TYPE_VT8231_ISA));
+ via = OBJECT(pm->sb);
/* Set properties on individual devices before realizing the south bridge */
if (machine->audiodev) {
--
2.43.5
^ permalink raw reply related [flat|nested] 39+ messages in thread
* [PULL 19/32] hw/ppc/pegasos2: Move PCI IRQ routing setup to a function
2025-10-23 12:16 [PULL RESEND 00/32] ppc-for-10.2 queue Harsh Prateek Bora
` (17 preceding siblings ...)
2025-10-23 12:16 ` [PULL 18/32] hw/ppc/pegasos2: Add south bridge pointer in the " Harsh Prateek Bora
@ 2025-10-23 12:16 ` Harsh Prateek Bora
2025-10-23 12:16 ` [PULL 20/32] hw/ppc/pegasos2: Move hardware specific parts out of machine reset Harsh Prateek Bora
` (13 subsequent siblings)
32 siblings, 0 replies; 39+ messages in thread
From: Harsh Prateek Bora @ 2025-10-23 12:16 UTC (permalink / raw)
To: qemu-devel; +Cc: BALATON Zoltan, Philippe Mathieu-Daudé
From: BALATON Zoltan <balaton@eik.bme.hu>
Collect steps of setting up PCI IRQ routing in one function.
Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Link: https://lore.kernel.org/qemu-devel/f5ff16a6933ab6e1f9e194d16ef85364ac3cf6df.1761176219.git.balaton@eik.bme.hu
Signed-off-by: Harsh Prateek Bora <harshpb@linux.ibm.com>
---
hw/ppc/pegasos2.c | 66 +++++++++++++++++++++++------------------------
1 file changed, 33 insertions(+), 33 deletions(-)
diff --git a/hw/ppc/pegasos2.c b/hw/ppc/pegasos2.c
index 4b63f0e175..2f9bd3eac5 100644
--- a/hw/ppc/pegasos2.c
+++ b/hw/ppc/pegasos2.c
@@ -107,6 +107,38 @@ static void pegasos2_pci_irq(void *opaque, int n, int level)
qemu_set_irq(pm->via_pirq[n], level);
}
+/* Set up PCI interrupt routing: lines from pci.0 and pci.1 are ORed */
+static void pegasos2_setup_pci_irq(Pegasos2MachineState *pm)
+{
+ for (int h = 0; h < 2; h++) {
+ DeviceState *pd;
+ g_autofree const char *pn = g_strdup_printf("pcihost%d", h);
+
+ pd = DEVICE(object_resolve_path_component(OBJECT(pm->nb), pn));
+ assert(pd);
+ for (int i = 0; i < PCI_NUM_PINS; i++) {
+ OrIRQState *ori = &pm->orirq[i];
+
+ if (h == 0) {
+ g_autofree const char *n = g_strdup_printf("pci-orirq[%d]", i);
+
+ object_initialize_child_with_props(OBJECT(pm), n,
+ ori, sizeof(*ori),
+ TYPE_OR_IRQ, &error_fatal,
+ "num-lines", "2", NULL);
+ qdev_realize(DEVICE(ori), NULL, &error_fatal);
+ qemu_init_irq(&pm->pci_irqs[i], pegasos2_pci_irq, pm, i);
+ qdev_connect_gpio_out(DEVICE(ori), 0, &pm->pci_irqs[i]);
+ pm->mv_pirq[i] = qdev_get_gpio_in_named(pm->nb, "gpp", 12 + i);
+ pm->via_pirq[i] = qdev_get_gpio_in_named(pm->sb, "pirq", i);
+ }
+ qdev_connect_gpio_out(pd, i, qdev_get_gpio_in(DEVICE(ori), h));
+ }
+ }
+ qdev_connect_gpio_out_named(pm->sb, "intr", 0,
+ qdev_get_gpio_in_named(pm->nb, "gpp", 31));
+}
+
static void pegasos2_init(MachineState *machine)
{
Pegasos2MachineState *pm = PEGASOS2_MACHINE(machine);
@@ -118,7 +150,6 @@ static void pegasos2_init(MachineState *machine)
I2CBus *i2c_bus;
const char *fwname = machine->firmware ?: PROM_FILENAME;
char *filename;
- int i;
ssize_t sz;
uint8_t *spd_data;
@@ -169,9 +200,6 @@ static void pegasos2_init(MachineState *machine)
/* Marvell Discovery II system controller */
pm->nb = DEVICE(sysbus_create_simple(TYPE_MV64361, -1,
qdev_get_gpio_in(DEVICE(pm->cpu), PPC6xx_INPUT_INT)));
- for (i = 0; i < PCI_NUM_PINS; i++) {
- pm->mv_pirq[i] = qdev_get_gpio_in_named(pm->nb, "gpp", 12 + i);
- }
pci_bus = mv64361_get_pci_bus(pm->nb, 1);
/* VIA VT8231 South Bridge (multifunction PCI device) */
@@ -185,14 +213,9 @@ static void pegasos2_init(MachineState *machine)
}
pci_realize_and_unref(PCI_DEVICE(via), pci_bus, &error_abort);
- for (i = 0; i < PCI_NUM_PINS; i++) {
- pm->via_pirq[i] = qdev_get_gpio_in_named(DEVICE(via), "pirq", i);
- }
object_property_add_alias(OBJECT(machine), "rtc-time",
object_resolve_path_component(via, "rtc"),
"date");
- qdev_connect_gpio_out_named(DEVICE(via), "intr", 0,
- qdev_get_gpio_in_named(pm->nb, "gpp", 31));
dev = PCI_DEVICE(object_resolve_path_component(via, "ide"));
pci_ide_create_devs(dev);
@@ -205,30 +228,7 @@ static void pegasos2_init(MachineState *machine)
/* other PC hardware */
pci_vga_init(pci_bus);
- /* PCI interrupt routing: lines from pci.0 and pci.1 are ORed */
- for (int h = 0; h < 2; h++) {
- DeviceState *pd;
- g_autofree const char *pn = g_strdup_printf("pcihost%d", h);
-
- pd = DEVICE(object_resolve_path_component(OBJECT(pm->nb), pn));
- assert(pd);
- for (i = 0; i < PCI_NUM_PINS; i++) {
- OrIRQState *ori = &pm->orirq[i];
-
- if (h == 0) {
- g_autofree const char *n = g_strdup_printf("pci-orirq[%d]", i);
-
- object_initialize_child_with_props(OBJECT(pm), n,
- ori, sizeof(*ori),
- TYPE_OR_IRQ, &error_fatal,
- "num-lines", "2", NULL);
- qdev_realize(DEVICE(ori), NULL, &error_fatal);
- qemu_init_irq(&pm->pci_irqs[i], pegasos2_pci_irq, pm, i);
- qdev_connect_gpio_out(DEVICE(ori), 0, &pm->pci_irqs[i]);
- }
- qdev_connect_gpio_out(pd, i, qdev_get_gpio_in(DEVICE(ori), h));
- }
- }
+ pegasos2_setup_pci_irq(pm);
if (machine->kernel_filename) {
sz = load_elf(machine->kernel_filename, NULL, NULL, NULL,
--
2.43.5
^ permalink raw reply related [flat|nested] 39+ messages in thread
* [PULL 20/32] hw/ppc/pegasos2: Move hardware specific parts out of machine reset
2025-10-23 12:16 [PULL RESEND 00/32] ppc-for-10.2 queue Harsh Prateek Bora
` (18 preceding siblings ...)
2025-10-23 12:16 ` [PULL 19/32] hw/ppc/pegasos2: Move PCI IRQ routing setup to a function Harsh Prateek Bora
@ 2025-10-23 12:16 ` Harsh Prateek Bora
2025-10-23 12:16 ` [PULL 21/32] hw/ppc/pegasos2: Introduce abstract superclass Harsh Prateek Bora
` (12 subsequent siblings)
32 siblings, 0 replies; 39+ messages in thread
From: Harsh Prateek Bora @ 2025-10-23 12:16 UTC (permalink / raw)
To: qemu-devel; +Cc: BALATON Zoltan, Philippe Mathieu-Daudé
From: BALATON Zoltan <balaton@eik.bme.hu>
Move the pegasos2 specific chipset reset out from machine reset to a
separate function and move generic parts that are not pegasos2
specific from build_fdt to machine reset so now build_fdt only
contains pegasos2 specific parts and can be renamed accordingly.
Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Link: https://lore.kernel.org/qemu-devel/f6633a68a72aad4fefb8d2373b52561f8ca8d41d.1761176219.git.balaton@eik.bme.hu
Signed-off-by: Harsh Prateek Bora <harshpb@linux.ibm.com>
---
hw/ppc/pegasos2.c | 79 ++++++++++++++++++++++++-----------------------
1 file changed, 41 insertions(+), 38 deletions(-)
diff --git a/hw/ppc/pegasos2.c b/hw/ppc/pegasos2.c
index 2f9bd3eac5..ed3070204b 100644
--- a/hw/ppc/pegasos2.c
+++ b/hw/ppc/pegasos2.c
@@ -57,10 +57,6 @@
#define BUS_FREQ_HZ 133333333
-#define PCI0_CFG_ADDR 0xcf8
-#define PCI1_CFG_ADDR 0xc78
-#define PCI1_IO_BASE 0xfe000000
-
#define TYPE_PEGASOS2_MACHINE MACHINE_TYPE_NAME("pegasos2")
OBJECT_DECLARE_TYPE(Pegasos2MachineState, MachineClass, PEGASOS2_MACHINE)
@@ -82,7 +78,7 @@ struct Pegasos2MachineState {
uint64_t initrd_size;
};
-static void *build_fdt(MachineState *machine, int *fdt_size);
+static void *pegasos2_build_fdt(Pegasos2MachineState *pm, int *fdt_size);
static void pegasos2_cpu_reset(void *opaque)
{
@@ -284,6 +280,9 @@ static void pegasos2_mv_reg_write(Pegasos2MachineState *pm, uint32_t addr,
MEMTXATTRS_UNSPECIFIED);
}
+#define PCI0_CFG_ADDR 0xcf8
+#define PCI1_CFG_ADDR 0xc78
+
static uint32_t pegasos2_pci_config_read(Pegasos2MachineState *pm, int bus,
uint32_t addr, uint32_t len)
{
@@ -308,23 +307,12 @@ static void pegasos2_pci_config_write(Pegasos2MachineState *pm, int bus,
static void pegasos2_superio_write(uint8_t addr, uint8_t val)
{
- cpu_physical_memory_write(PCI1_IO_BASE + 0x3f0, &addr, 1);
- cpu_physical_memory_write(PCI1_IO_BASE + 0x3f1, &val, 1);
+ cpu_physical_memory_write(0xfe0003f0, &addr, 1);
+ cpu_physical_memory_write(0xfe0003f1, &val, 1);
}
-static void pegasos2_machine_reset(MachineState *machine, ResetType type)
+static void pegasos2_chipset_reset(Pegasos2MachineState *pm)
{
- Pegasos2MachineState *pm = PEGASOS2_MACHINE(machine);
- void *fdt;
- uint64_t d[2];
- int sz;
-
- qemu_devices_reset(type);
- if (!pm->vof) {
- return; /* Firmware should set up machine so nothing to do */
- }
-
- /* Otherwise, set up devices that board firmware would normally do */
pegasos2_mv_reg_write(pm, 0, 4, 0x28020ff);
pegasos2_mv_reg_write(pm, 0x278, 4, 0xa31fc);
pegasos2_mv_reg_write(pm, 0xf300, 4, 0x11ff0400);
@@ -387,6 +375,23 @@ static void pegasos2_machine_reset(MachineState *machine, ResetType type)
pegasos2_pci_config_write(pm, 1, (PCI_DEVFN(12, 6) << 8) |
PCI_INTERRUPT_LINE, 2, 0x309);
+}
+
+static void pegasos2_machine_reset(MachineState *machine, ResetType type)
+{
+ Pegasos2MachineState *pm = PEGASOS2_MACHINE(machine);
+ void *fdt;
+ uint32_t c[2];
+ uint64_t d[2];
+ int sz;
+
+ qemu_devices_reset(type);
+ if (!pm->vof) {
+ return; /* Firmware should set up machine so nothing to do */
+ }
+
+ /* Otherwise, set up devices that board firmware would normally do */
+ pegasos2_chipset_reset(pm);
/* Device tree and VOF set up */
vof_init(pm->vof, machine->ram_size, &error_fatal);
@@ -405,10 +410,25 @@ static void pegasos2_machine_reset(MachineState *machine, ResetType type)
exit(1);
}
- fdt = build_fdt(machine, &sz);
+ fdt = pegasos2_build_fdt(pm, &sz);
if (!fdt) {
exit(1);
}
+
+ /* Set memory size */
+ c[0] = 0;
+ c[1] = cpu_to_be32(machine->ram_size);
+ qemu_fdt_setprop(fdt, "/memory@0", "reg", c, sizeof(c));
+
+ /* Boot parameters */
+ if (pm->initrd_addr && pm->initrd_size) {
+ qemu_fdt_setprop_cell(fdt, "/chosen", "linux,initrd-end",
+ pm->initrd_addr + pm->initrd_size);
+ qemu_fdt_setprop_cell(fdt, "/chosen", "linux,initrd-start",
+ pm->initrd_addr);
+ }
+ qemu_fdt_setprop_string(fdt, "/chosen", "bootargs",
+ machine->kernel_cmdline ?: "");
/* FIXME: VOF assumes entry is same as load address */
d[0] = cpu_to_be64(pm->kernel_entry);
d[1] = cpu_to_be64(pm->kernel_size - (pm->kernel_entry - pm->kernel_addr));
@@ -827,12 +847,10 @@ static void *load_dtb(const char *filename, int *fdt_size)
return fdt;
}
-static void *build_fdt(MachineState *machine, int *fdt_size)
+static void *pegasos2_build_fdt(Pegasos2MachineState *pm, int *fdt_size)
{
- Pegasos2MachineState *pm = PEGASOS2_MACHINE(machine);
FDTInfo fi;
PCIBus *pci_bus;
- uint32_t cells[2];
void *fdt = load_dtb("pegasos2.dtb", fdt_size);
if (!fdt) {
@@ -840,21 +858,6 @@ static void *build_fdt(MachineState *machine, int *fdt_size)
}
qemu_fdt_setprop_string(fdt, "/", "name", "bplan,Pegasos2");
- /* Set memory size */
- cells[0] = 0;
- cells[1] = cpu_to_be32(machine->ram_size);
- qemu_fdt_setprop(fdt, "/memory@0", "reg", cells, 2 * sizeof(cells[0]));
-
- /* Boot parameters */
- if (pm->initrd_addr && pm->initrd_size) {
- qemu_fdt_setprop_cell(fdt, "/chosen", "linux,initrd-end",
- pm->initrd_addr + pm->initrd_size);
- qemu_fdt_setprop_cell(fdt, "/chosen", "linux,initrd-start",
- pm->initrd_addr);
- }
- qemu_fdt_setprop_string(fdt, "/chosen", "bootargs",
- machine->kernel_cmdline ?: "");
-
add_cpu_info(fdt, pm->cpu);
fi.fdt = fdt;
--
2.43.5
^ permalink raw reply related [flat|nested] 39+ messages in thread
* [PULL 21/32] hw/ppc/pegasos2: Introduce abstract superclass
2025-10-23 12:16 [PULL RESEND 00/32] ppc-for-10.2 queue Harsh Prateek Bora
` (19 preceding siblings ...)
2025-10-23 12:16 ` [PULL 20/32] hw/ppc/pegasos2: Move hardware specific parts out of machine reset Harsh Prateek Bora
@ 2025-10-23 12:16 ` Harsh Prateek Bora
2025-10-23 12:16 ` [PULL 22/32] hw/ppc/pegasos2: Add bus frequency to machine state Harsh Prateek Bora
` (11 subsequent siblings)
32 siblings, 0 replies; 39+ messages in thread
From: Harsh Prateek Bora @ 2025-10-23 12:16 UTC (permalink / raw)
To: qemu-devel; +Cc: BALATON Zoltan, Philippe Mathieu-Daudé
From: BALATON Zoltan <balaton@eik.bme.hu>
Rename machine state struct to PegasosMachineState as it will be used
for pegasos1 too.
Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Link: https://lore.kernel.org/qemu-devel/a09590a5da4572c9d392542f5c3793e6eb08ab9e.1761176219.git.balaton@eik.bme.hu
Signed-off-by: Harsh Prateek Bora <harshpb@linux.ibm.com>
---
hw/ppc/pegasos2.c | 66 ++++++++++++++++++++++++-----------------------
1 file changed, 34 insertions(+), 32 deletions(-)
diff --git a/hw/ppc/pegasos2.c b/hw/ppc/pegasos2.c
index ed3070204b..f5b56c0e94 100644
--- a/hw/ppc/pegasos2.c
+++ b/hw/ppc/pegasos2.c
@@ -57,10 +57,10 @@
#define BUS_FREQ_HZ 133333333
-#define TYPE_PEGASOS2_MACHINE MACHINE_TYPE_NAME("pegasos2")
-OBJECT_DECLARE_TYPE(Pegasos2MachineState, MachineClass, PEGASOS2_MACHINE)
+#define TYPE_PEGASOS_MACHINE MACHINE_TYPE_NAME("pegasos")
+OBJECT_DECLARE_SIMPLE_TYPE(PegasosMachineState, PEGASOS_MACHINE)
-struct Pegasos2MachineState {
+struct PegasosMachineState {
MachineState parent_obj;
PowerPCCPU *cpu;
@@ -78,12 +78,12 @@ struct Pegasos2MachineState {
uint64_t initrd_size;
};
-static void *pegasos2_build_fdt(Pegasos2MachineState *pm, int *fdt_size);
+static void *pegasos2_build_fdt(PegasosMachineState *pm, int *fdt_size);
static void pegasos2_cpu_reset(void *opaque)
{
PowerPCCPU *cpu = opaque;
- Pegasos2MachineState *pm = PEGASOS2_MACHINE(current_machine);
+ PegasosMachineState *pm = PEGASOS_MACHINE(current_machine);
cpu_reset(CPU(cpu));
cpu->env.spr[SPR_HID1] = 7ULL << 28;
@@ -96,7 +96,7 @@ static void pegasos2_cpu_reset(void *opaque)
static void pegasos2_pci_irq(void *opaque, int n, int level)
{
- Pegasos2MachineState *pm = opaque;
+ PegasosMachineState *pm = opaque;
/* PCI interrupt lines are connected to both MV64361 and VT8231 */
qemu_set_irq(pm->mv_pirq[n], level);
@@ -104,7 +104,7 @@ static void pegasos2_pci_irq(void *opaque, int n, int level)
}
/* Set up PCI interrupt routing: lines from pci.0 and pci.1 are ORed */
-static void pegasos2_setup_pci_irq(Pegasos2MachineState *pm)
+static void pegasos2_setup_pci_irq(PegasosMachineState *pm)
{
for (int h = 0; h < 2; h++) {
DeviceState *pd;
@@ -137,7 +137,7 @@ static void pegasos2_setup_pci_irq(Pegasos2MachineState *pm)
static void pegasos2_init(MachineState *machine)
{
- Pegasos2MachineState *pm = PEGASOS2_MACHINE(machine);
+ PegasosMachineState *pm = PEGASOS_MACHINE(machine);
CPUPPCState *env;
MemoryRegion *rom = g_new(MemoryRegion, 1);
PCIBus *pci_bus;
@@ -262,7 +262,7 @@ static void pegasos2_init(MachineState *machine)
}
}
-static uint32_t pegasos2_mv_reg_read(Pegasos2MachineState *pm,
+static uint32_t pegasos2_mv_reg_read(PegasosMachineState *pm,
uint32_t addr, uint32_t len)
{
MemoryRegion *r = sysbus_mmio_get_region(SYS_BUS_DEVICE(pm->nb), 0);
@@ -272,7 +272,7 @@ static uint32_t pegasos2_mv_reg_read(Pegasos2MachineState *pm,
return val;
}
-static void pegasos2_mv_reg_write(Pegasos2MachineState *pm, uint32_t addr,
+static void pegasos2_mv_reg_write(PegasosMachineState *pm, uint32_t addr,
uint32_t len, uint32_t val)
{
MemoryRegion *r = sysbus_mmio_get_region(SYS_BUS_DEVICE(pm->nb), 0);
@@ -283,7 +283,7 @@ static void pegasos2_mv_reg_write(Pegasos2MachineState *pm, uint32_t addr,
#define PCI0_CFG_ADDR 0xcf8
#define PCI1_CFG_ADDR 0xc78
-static uint32_t pegasos2_pci_config_read(Pegasos2MachineState *pm, int bus,
+static uint32_t pegasos2_pci_config_read(PegasosMachineState *pm, int bus,
uint32_t addr, uint32_t len)
{
hwaddr pcicfg = bus ? PCI1_CFG_ADDR : PCI0_CFG_ADDR;
@@ -296,7 +296,7 @@ static uint32_t pegasos2_pci_config_read(Pegasos2MachineState *pm, int bus,
return val;
}
-static void pegasos2_pci_config_write(Pegasos2MachineState *pm, int bus,
+static void pegasos2_pci_config_write(PegasosMachineState *pm, int bus,
uint32_t addr, uint32_t len, uint32_t val)
{
hwaddr pcicfg = bus ? PCI1_CFG_ADDR : PCI0_CFG_ADDR;
@@ -311,7 +311,7 @@ static void pegasos2_superio_write(uint8_t addr, uint8_t val)
cpu_physical_memory_write(0xfe0003f1, &val, 1);
}
-static void pegasos2_chipset_reset(Pegasos2MachineState *pm)
+static void pegasos2_chipset_reset(PegasosMachineState *pm)
{
pegasos2_mv_reg_write(pm, 0, 4, 0x28020ff);
pegasos2_mv_reg_write(pm, 0x278, 4, 0xa31fc);
@@ -379,7 +379,7 @@ static void pegasos2_chipset_reset(Pegasos2MachineState *pm)
static void pegasos2_machine_reset(MachineState *machine, ResetType type)
{
- Pegasos2MachineState *pm = PEGASOS2_MACHINE(machine);
+ PegasosMachineState *pm = PEGASOS_MACHINE(machine);
void *fdt;
uint32_t c[2];
uint64_t d[2];
@@ -463,7 +463,7 @@ enum pegasos2_rtas_tokens {
RTAS_SYSTEM_REBOOT = 20,
};
-static target_ulong pegasos2_rtas(PowerPCCPU *cpu, Pegasos2MachineState *pm,
+static target_ulong pegasos2_rtas(PowerPCCPU *cpu, PegasosMachineState *pm,
target_ulong args_real)
{
AddressSpace *as = CPU(cpu)->as;
@@ -566,7 +566,7 @@ static bool pegasos2_cpu_in_nested(PowerPCCPU *cpu)
static void pegasos2_hypercall(PPCVirtualHypervisor *vhyp, PowerPCCPU *cpu)
{
- Pegasos2MachineState *pm = PEGASOS2_MACHINE(vhyp);
+ PegasosMachineState *pm = PEGASOS_MACHINE(vhyp);
CPUPPCState *env = &cpu->env;
/* The TCG path should also be holding the BQL at this point */
@@ -629,24 +629,26 @@ static void pegasos2_machine_class_init(ObjectClass *oc, const void *data)
vmc->setprop = pegasos2_setprop;
}
-static const TypeInfo pegasos2_machine_info = {
- .name = TYPE_PEGASOS2_MACHINE,
- .parent = TYPE_MACHINE,
- .class_init = pegasos2_machine_class_init,
- .instance_size = sizeof(Pegasos2MachineState),
- .interfaces = (const InterfaceInfo[]) {
- { TYPE_PPC_VIRTUAL_HYPERVISOR },
- { TYPE_VOF_MACHINE_IF },
- { }
+static const TypeInfo pegasos_machine_types[] = {
+ {
+ .name = TYPE_PEGASOS_MACHINE,
+ .parent = TYPE_MACHINE,
+ .instance_size = sizeof(PegasosMachineState),
+ .abstract = true,
+ .interfaces = (const InterfaceInfo[]) {
+ { TYPE_PPC_VIRTUAL_HYPERVISOR },
+ { TYPE_VOF_MACHINE_IF },
+ { }
+ },
+ },
+ {
+ .name = MACHINE_TYPE_NAME("pegasos2"),
+ .parent = TYPE_PEGASOS_MACHINE,
+ .class_init = pegasos2_machine_class_init,
},
};
-static void pegasos2_machine_register_types(void)
-{
- type_register_static(&pegasos2_machine_info);
-}
-
-type_init(pegasos2_machine_register_types)
+DEFINE_TYPES(pegasos_machine_types)
/* FDT creation for passing to firmware */
@@ -847,7 +849,7 @@ static void *load_dtb(const char *filename, int *fdt_size)
return fdt;
}
-static void *pegasos2_build_fdt(Pegasos2MachineState *pm, int *fdt_size)
+static void *pegasos2_build_fdt(PegasosMachineState *pm, int *fdt_size)
{
FDTInfo fi;
PCIBus *pci_bus;
--
2.43.5
^ permalink raw reply related [flat|nested] 39+ messages in thread
* [PULL 22/32] hw/ppc/pegasos2: Add bus frequency to machine state
2025-10-23 12:16 [PULL RESEND 00/32] ppc-for-10.2 queue Harsh Prateek Bora
` (20 preceding siblings ...)
2025-10-23 12:16 ` [PULL 21/32] hw/ppc/pegasos2: Introduce abstract superclass Harsh Prateek Bora
@ 2025-10-23 12:16 ` Harsh Prateek Bora
2025-10-23 12:16 ` [PULL 23/32] hw/ppc/pegasos2: Add Pegasos I emulation Harsh Prateek Bora
` (10 subsequent siblings)
32 siblings, 0 replies; 39+ messages in thread
From: Harsh Prateek Bora @ 2025-10-23 12:16 UTC (permalink / raw)
To: qemu-devel; +Cc: BALATON Zoltan, Philippe Mathieu-Daudé
From: BALATON Zoltan <balaton@eik.bme.hu>
Store the bus frequency in the machine state and set it from instance
init method.
Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Link: https://lore.kernel.org/qemu-devel/b69e21e353b7d7f22a34db5f13443f60f51c7238.1761176219.git.balaton@eik.bme.hu
Signed-off-by: Harsh Prateek Bora <harshpb@linux.ibm.com>
---
hw/ppc/pegasos2.c | 25 ++++++++++++++++---------
1 file changed, 16 insertions(+), 9 deletions(-)
diff --git a/hw/ppc/pegasos2.c b/hw/ppc/pegasos2.c
index f5b56c0e94..7eaefcf9a0 100644
--- a/hw/ppc/pegasos2.c
+++ b/hw/ppc/pegasos2.c
@@ -55,8 +55,6 @@
#define H_PRIVILEGE -3 /* Caller not privileged */
#define H_PARAMETER -4 /* Parameter invalid, out-of-range or conflicting */
-#define BUS_FREQ_HZ 133333333
-
#define TYPE_PEGASOS_MACHINE MACHINE_TYPE_NAME("pegasos")
OBJECT_DECLARE_SIMPLE_TYPE(PegasosMachineState, PEGASOS_MACHINE)
@@ -66,6 +64,7 @@ struct PegasosMachineState {
PowerPCCPU *cpu;
DeviceState *nb; /* north bridge */
DeviceState *sb; /* south bridge */
+ int bus_freq_hz;
IRQState pci_irqs[PCI_NUM_PINS];
OrIRQState orirq[PCI_NUM_PINS];
qemu_irq mv_pirq[PCI_NUM_PINS];
@@ -135,7 +134,7 @@ static void pegasos2_setup_pci_irq(PegasosMachineState *pm)
qdev_get_gpio_in_named(pm->nb, "gpp", 31));
}
-static void pegasos2_init(MachineState *machine)
+static void pegasos_init(MachineState *machine)
{
PegasosMachineState *pm = PEGASOS_MACHINE(machine);
CPUPPCState *env;
@@ -158,7 +157,7 @@ static void pegasos2_init(MachineState *machine)
}
/* Set time-base frequency */
- cpu_ppc_tb_init(env, BUS_FREQ_HZ / 4);
+ cpu_ppc_tb_init(env, pm->bus_freq_hz / 4);
qemu_register_reset(pegasos2_cpu_reset, pm->cpu);
/* RAM */
@@ -610,7 +609,7 @@ static void pegasos2_machine_class_init(ObjectClass *oc, const void *data)
VofMachineIfClass *vmc = VOF_MACHINE_CLASS(oc);
mc->desc = "Genesi/bPlan Pegasos II";
- mc->init = pegasos2_init;
+ mc->init = pegasos_init;
mc->reset = pegasos2_machine_reset;
mc->block_default_type = IF_IDE;
mc->default_boot_order = "cd";
@@ -629,6 +628,13 @@ static void pegasos2_machine_class_init(ObjectClass *oc, const void *data)
vmc->setprop = pegasos2_setprop;
}
+static void pegasos2_init(Object *obj)
+{
+ PegasosMachineState *pm = PEGASOS_MACHINE(obj);
+
+ pm->bus_freq_hz = 133333333;
+}
+
static const TypeInfo pegasos_machine_types[] = {
{
.name = TYPE_PEGASOS_MACHINE,
@@ -645,6 +651,7 @@ static const TypeInfo pegasos_machine_types[] = {
.name = MACHINE_TYPE_NAME("pegasos2"),
.parent = TYPE_PEGASOS_MACHINE,
.class_init = pegasos2_machine_class_init,
+ .instance_init = pegasos2_init,
},
};
@@ -777,7 +784,7 @@ static void add_pci_device(PCIBus *bus, PCIDevice *d, void *opaque)
g_string_free(node, TRUE);
}
-static void add_cpu_info(void *fdt, PowerPCCPU *cpu)
+static void add_cpu_info(void *fdt, PowerPCCPU *cpu, int bus_freq)
{
uint32_t cells[2];
@@ -824,8 +831,8 @@ static void add_cpu_info(void *fdt, PowerPCCPU *cpu)
qemu_fdt_setprop_cell(fdt, cp, "reservation-granule-size", 4);
qemu_fdt_setprop_cell(fdt, cp, "timebase-frequency",
cpu->env.tb_env->tb_freq);
- qemu_fdt_setprop_cell(fdt, cp, "bus-frequency", BUS_FREQ_HZ);
- qemu_fdt_setprop_cell(fdt, cp, "clock-frequency", BUS_FREQ_HZ * 7.5);
+ qemu_fdt_setprop_cell(fdt, cp, "bus-frequency", bus_freq);
+ qemu_fdt_setprop_cell(fdt, cp, "clock-frequency", bus_freq * 7.5);
qemu_fdt_setprop_cell(fdt, cp, "cpu-version", cpu->env.spr[SPR_PVR]);
cells[0] = 0;
cells[1] = 0;
@@ -860,7 +867,7 @@ static void *pegasos2_build_fdt(PegasosMachineState *pm, int *fdt_size)
}
qemu_fdt_setprop_string(fdt, "/", "name", "bplan,Pegasos2");
- add_cpu_info(fdt, pm->cpu);
+ add_cpu_info(fdt, pm->cpu, pm->bus_freq_hz);
fi.fdt = fdt;
fi.path = "/pci@c0000000";
--
2.43.5
^ permalink raw reply related [flat|nested] 39+ messages in thread
* [PULL 23/32] hw/ppc/pegasos2: Add Pegasos I emulation
2025-10-23 12:16 [PULL RESEND 00/32] ppc-for-10.2 queue Harsh Prateek Bora
` (21 preceding siblings ...)
2025-10-23 12:16 ` [PULL 22/32] hw/ppc/pegasos2: Add bus frequency to machine state Harsh Prateek Bora
@ 2025-10-23 12:16 ` Harsh Prateek Bora
2025-10-23 12:16 ` [PULL 24/32] hw/ppc/pegasos2: Add VOF support for pegasos1 Harsh Prateek Bora
` (9 subsequent siblings)
32 siblings, 0 replies; 39+ messages in thread
From: Harsh Prateek Bora @ 2025-10-23 12:16 UTC (permalink / raw)
To: qemu-devel; +Cc: BALATON Zoltan, Philippe Mathieu-Daudé
From: BALATON Zoltan <balaton@eik.bme.hu>
The Pegasos II is a redesign of the original Pegasos (later marked I)
that replaces the north bridge and has updated firmware but otherwise
these are very similar. The Pegasos uses the same north bridge that
AmigaOne used which we already emulate so we can also easily emulate
Pegasos I.
Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Link: https://lore.kernel.org/qemu-devel/8f5bd07553b41d83a54f9df0bb93b76b22dea5c5.1761176219.git.balaton@eik.bme.hu
Signed-off-by: Harsh Prateek Bora <harshpb@linux.ibm.com>
---
hw/ppc/pegasos2.c | 156 ++++++++++++++++++++++++++++++++++------------
1 file changed, 117 insertions(+), 39 deletions(-)
diff --git a/hw/ppc/pegasos2.c b/hw/ppc/pegasos2.c
index 7eaefcf9a0..a11f3c99ed 100644
--- a/hw/ppc/pegasos2.c
+++ b/hw/ppc/pegasos2.c
@@ -1,5 +1,5 @@
/*
- * QEMU PowerPC CHRP (Genesi/bPlan Pegasos II) hardware System Emulator
+ * QEMU PowerPC CHRP (Genesi/bPlan Pegasos I/II) hardware System Emulator
*
* Copyright (c) 2018-2021 BALATON Zoltan
*
@@ -15,6 +15,7 @@
#include "hw/pci/pci_host.h"
#include "hw/irq.h"
#include "hw/or-irq.h"
+#include "hw/pci-host/articia.h"
#include "hw/pci-host/mv64361.h"
#include "hw/isa/vt82c686.h"
#include "hw/ide/pci.h"
@@ -55,12 +56,18 @@
#define H_PRIVILEGE -3 /* Caller not privileged */
#define H_PARAMETER -4 /* Parameter invalid, out-of-range or conflicting */
+typedef enum {
+ PEGASOS1 = 1,
+ PEGASOS2 = 2,
+} PegasosMachineType;
+
#define TYPE_PEGASOS_MACHINE MACHINE_TYPE_NAME("pegasos")
OBJECT_DECLARE_SIMPLE_TYPE(PegasosMachineState, PEGASOS_MACHINE)
struct PegasosMachineState {
MachineState parent_obj;
+ PegasosMachineType type;
PowerPCCPU *cpu;
DeviceState *nb; /* north bridge */
DeviceState *sb; /* south bridge */
@@ -79,7 +86,7 @@ struct PegasosMachineState {
static void *pegasos2_build_fdt(PegasosMachineState *pm, int *fdt_size);
-static void pegasos2_cpu_reset(void *opaque)
+static void pegasos_cpu_reset(void *opaque)
{
PowerPCCPU *cpu = opaque;
PegasosMachineState *pm = PEGASOS_MACHINE(current_machine);
@@ -89,6 +96,8 @@ static void pegasos2_cpu_reset(void *opaque)
if (pm->vof) {
cpu->env.gpr[1] = 2 * VOF_STACK_SIZE - 0x20;
cpu->env.nip = 0x100;
+ } else if (pm->type == PEGASOS1) {
+ cpu->env.nip = 0xfffc0100;
}
cpu_ppc_tb_reset(&cpu->env);
}
@@ -139,13 +148,15 @@ static void pegasos_init(MachineState *machine)
PegasosMachineState *pm = PEGASOS_MACHINE(machine);
CPUPPCState *env;
MemoryRegion *rom = g_new(MemoryRegion, 1);
- PCIBus *pci_bus;
+ PCIBus *pci_bus = NULL;
Object *via;
PCIDevice *dev;
I2CBus *i2c_bus;
const char *fwname = machine->firmware ?: PROM_FILENAME;
char *filename;
+ hwaddr prom_addr;
ssize_t sz;
+ int devfn;
uint8_t *spd_data;
/* init CPU */
@@ -158,7 +169,7 @@ static void pegasos_init(MachineState *machine)
/* Set time-base frequency */
cpu_ppc_tb_init(env, pm->bus_freq_hz / 4);
- qemu_register_reset(pegasos2_cpu_reset, pm->cpu);
+ qemu_register_reset(pegasos_cpu_reset, pm->cpu);
/* RAM */
if (machine->ram_size > 2 * GiB) {
@@ -176,12 +187,16 @@ static void pegasos_init(MachineState *machine)
if (!machine->firmware && !pm->vof) {
pm->vof = g_malloc0(sizeof(*pm->vof));
}
- memory_region_init_rom(rom, NULL, "pegasos2.rom", PROM_SIZE, &error_fatal);
- memory_region_add_subregion(get_system_memory(), PROM_ADDR, rom);
+ prom_addr = PROM_ADDR;
+ if (pm->type == PEGASOS1) {
+ prom_addr += PROM_SIZE;
+ }
+ memory_region_init_rom(rom, NULL, "rom", PROM_SIZE, &error_fatal);
+ memory_region_add_subregion(get_system_memory(), prom_addr, rom);
sz = load_elf(filename, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
ELFDATA2MSB, PPC_ELF_MACHINE, 0, 0);
if (sz <= 0) {
- sz = load_image_targphys(filename, pm->vof ? 0 : PROM_ADDR, PROM_SIZE);
+ sz = load_image_targphys(filename, pm->vof ? 0 : prom_addr, PROM_SIZE);
}
if (sz <= 0 || sz > PROM_SIZE) {
error_report("Could not load firmware '%s'", filename);
@@ -192,13 +207,37 @@ static void pegasos_init(MachineState *machine)
pm->vof->fw_size = sz;
}
- /* Marvell Discovery II system controller */
- pm->nb = DEVICE(sysbus_create_simple(TYPE_MV64361, -1,
- qdev_get_gpio_in(DEVICE(pm->cpu), PPC6xx_INPUT_INT)));
- pci_bus = mv64361_get_pci_bus(pm->nb, 1);
+ /* north bridge */
+ switch (pm->type) {
+ case PEGASOS1:
+ {
+ MemoryRegion *pci_mem, *mr;
+
+ /* Articia S */
+ pm->nb = DEVICE(sysbus_create_simple(TYPE_ARTICIA, 0xfe000000, NULL));
+ pci_mem = sysbus_mmio_get_region(SYS_BUS_DEVICE(pm->nb), 1);
+ mr = g_new(MemoryRegion, 1);
+ memory_region_init_alias(mr, OBJECT(pm->nb), "pci-mem-low", pci_mem,
+ 0, 0x1000000);
+ memory_region_add_subregion(get_system_memory(), 0xfd000000, mr);
+ mr = g_new(MemoryRegion, 1);
+ memory_region_init_alias(mr, OBJECT(pm->nb), "pci-mem-high", pci_mem,
+ 0x80000000, 0x7d000000);
+ memory_region_add_subregion(get_system_memory(), 0x80000000, mr);
+ pci_bus = PCI_BUS(qdev_get_child_bus(pm->nb, "pci.0"));
+ break;
+ }
+ case PEGASOS2:
+ /* Marvell Discovery II system controller */
+ pm->nb = DEVICE(sysbus_create_simple(TYPE_MV64361, -1,
+ qdev_get_gpio_in(DEVICE(pm->cpu), PPC6xx_INPUT_INT)));
+ pci_bus = mv64361_get_pci_bus(pm->nb, 1);
+ break;
+ }
/* VIA VT8231 South Bridge (multifunction PCI device) */
- pm->sb = DEVICE(pci_new_multifunction(PCI_DEVFN(12, 0), TYPE_VT8231_ISA));
+ devfn = PCI_DEVFN(pm->type == PEGASOS1 ? 7 : 12, 0);
+ pm->sb = DEVICE(pci_new_multifunction(devfn, TYPE_VT8231_ISA));
via = OBJECT(pm->sb);
/* Set properties on individual devices before realizing the south bridge */
@@ -223,7 +262,21 @@ static void pegasos_init(MachineState *machine)
/* other PC hardware */
pci_vga_init(pci_bus);
- pegasos2_setup_pci_irq(pm);
+ /* pci interrupt routing */
+ switch (pm->type) {
+ case PEGASOS1:
+ qdev_connect_gpio_out_named(pm->sb, "intr", 0,
+ qdev_get_gpio_in(DEVICE(pm->cpu),
+ PPC6xx_INPUT_INT));
+ for (int i = 0; i < PCI_NUM_PINS; i++) {
+ qdev_connect_gpio_out(pm->nb, i,
+ qdev_get_gpio_in_named(pm->sb, "pirq", i));
+ }
+ break;
+ case PEGASOS2:
+ pegasos2_setup_pci_irq(pm);
+ break;
+ }
if (machine->kernel_filename) {
sz = load_elf(machine->kernel_filename, NULL, NULL, NULL,
@@ -376,7 +429,7 @@ static void pegasos2_chipset_reset(PegasosMachineState *pm)
PCI_INTERRUPT_LINE, 2, 0x309);
}
-static void pegasos2_machine_reset(MachineState *machine, ResetType type)
+static void pegasos_machine_reset(MachineState *machine, ResetType type)
{
PegasosMachineState *pm = PEGASOS_MACHINE(machine);
void *fdt;
@@ -387,6 +440,9 @@ static void pegasos2_machine_reset(MachineState *machine, ResetType type)
qemu_devices_reset(type);
if (!pm->vof) {
return; /* Firmware should set up machine so nothing to do */
+ } else if (pm->type == PEGASOS1) {
+ error_report("VOF is not supported by this machine");
+ exit(1);
}
/* Otherwise, set up devices that board firmware would normally do */
@@ -558,12 +614,12 @@ static target_ulong pegasos2_rtas(PowerPCCPU *cpu, PegasosMachineState *pm,
}
}
-static bool pegasos2_cpu_in_nested(PowerPCCPU *cpu)
+static bool pegasos_cpu_in_nested(PowerPCCPU *cpu)
{
return false;
}
-static void pegasos2_hypercall(PPCVirtualHypervisor *vhyp, PowerPCCPU *cpu)
+static void pegasos_hypercall(PPCVirtualHypervisor *vhyp, PowerPCCPU *cpu)
{
PegasosMachineState *pm = PEGASOS_MACHINE(vhyp);
CPUPPCState *env = &cpu->env;
@@ -574,7 +630,7 @@ static void pegasos2_hypercall(PPCVirtualHypervisor *vhyp, PowerPCCPU *cpu)
if (FIELD_EX64(env->msr, MSR, PR)) {
qemu_log_mask(LOG_GUEST_ERROR, "Hypercall made with MSR[PR]=1\n");
env->gpr[3] = H_PRIVILEGE;
- } else if (env->gpr[3] == KVMPPC_H_RTAS) {
+ } else if (env->gpr[3] == KVMPPC_H_RTAS && pm->type == PEGASOS2) {
env->gpr[3] = pegasos2_rtas(cpu, pm, env->gpr[4]);
} else if (env->gpr[3] == KVMPPC_H_VOF_CLIENT) {
int ret = vof_client_call(MACHINE(pm), pm->vof, MACHINE(pm)->fdt,
@@ -596,56 +652,78 @@ static target_ulong vhyp_encode_hpt_for_kvm_pr(PPCVirtualHypervisor *vhyp)
return POWERPC_CPU(current_cpu)->env.spr[SPR_SDR1];
}
-static bool pegasos2_setprop(MachineState *ms, const char *path,
- const char *propname, void *val, int vallen)
+static bool pegasos_setprop(MachineState *ms, const char *path,
+ const char *propname, void *val, int vallen)
{
return true;
}
-static void pegasos2_machine_class_init(ObjectClass *oc, const void *data)
+static void pegasos_machine_init(MachineClass *mc)
{
- MachineClass *mc = MACHINE_CLASS(oc);
- PPCVirtualHypervisorClass *vhc = PPC_VIRTUAL_HYPERVISOR_CLASS(oc);
- VofMachineIfClass *vmc = VOF_MACHINE_CLASS(oc);
+ PPCVirtualHypervisorClass *vhc = PPC_VIRTUAL_HYPERVISOR_CLASS(mc);
+ VofMachineIfClass *vmc = VOF_MACHINE_CLASS(mc);
- mc->desc = "Genesi/bPlan Pegasos II";
mc->init = pegasos_init;
- mc->reset = pegasos2_machine_reset;
+ mc->reset = pegasos_machine_reset;
mc->block_default_type = IF_IDE;
mc->default_boot_order = "cd";
mc->default_display = "std";
- mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("7457_v1.2");
- mc->default_ram_id = "pegasos2.ram";
+ mc->default_ram_id = "ram";
mc->default_ram_size = 512 * MiB;
machine_add_audiodev_property(mc);
- vhc->cpu_in_nested = pegasos2_cpu_in_nested;
- vhc->hypercall = pegasos2_hypercall;
+ vhc->cpu_in_nested = pegasos_cpu_in_nested;
+ vhc->hypercall = pegasos_hypercall;
vhc->cpu_exec_enter = vhyp_nop;
vhc->cpu_exec_exit = vhyp_nop;
vhc->encode_hpt_for_kvm_pr = vhyp_encode_hpt_for_kvm_pr;
- vmc->setprop = pegasos2_setprop;
+ vmc->setprop = pegasos_setprop;
+}
+
+static void pegasos1_init(Object *obj)
+{
+ PegasosMachineState *pm = PEGASOS_MACHINE(obj);
+
+ pm->type = PEGASOS1;
+ pm->bus_freq_hz = 33000000;
+}
+
+static void pegasos1_machine_class_init(ObjectClass *oc, const void *data)
+{
+ MachineClass *mc = MACHINE_CLASS(oc);
+
+ mc->desc = "Genesi/bPlan Pegasos I";
+ mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("750cxe_v3.1b");
}
static void pegasos2_init(Object *obj)
{
PegasosMachineState *pm = PEGASOS_MACHINE(obj);
+ pm->type = PEGASOS2;
pm->bus_freq_hz = 133333333;
}
+static void pegasos2_machine_class_init(ObjectClass *oc, const void *data)
+{
+ MachineClass *mc = MACHINE_CLASS(oc);
+
+ mc->desc = "Genesi/bPlan Pegasos II";
+ mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("7457_v1.2");
+}
+
+DEFINE_MACHINE_EXTENDED("pegasos", MACHINE, PegasosMachineState,
+ pegasos_machine_init, true, (const InterfaceInfo[]) {
+ { TYPE_PPC_VIRTUAL_HYPERVISOR },
+ { TYPE_VOF_MACHINE_IF }, { } })
+
static const TypeInfo pegasos_machine_types[] = {
{
- .name = TYPE_PEGASOS_MACHINE,
- .parent = TYPE_MACHINE,
- .instance_size = sizeof(PegasosMachineState),
- .abstract = true,
- .interfaces = (const InterfaceInfo[]) {
- { TYPE_PPC_VIRTUAL_HYPERVISOR },
- { TYPE_VOF_MACHINE_IF },
- { }
- },
+ .name = MACHINE_TYPE_NAME("pegasos1"),
+ .parent = TYPE_PEGASOS_MACHINE,
+ .class_init = pegasos1_machine_class_init,
+ .instance_init = pegasos1_init,
},
{
.name = MACHINE_TYPE_NAME("pegasos2"),
--
2.43.5
^ permalink raw reply related [flat|nested] 39+ messages in thread
* [PULL 24/32] hw/ppc/pegasos2: Add VOF support for pegasos1
2025-10-23 12:16 [PULL RESEND 00/32] ppc-for-10.2 queue Harsh Prateek Bora
` (22 preceding siblings ...)
2025-10-23 12:16 ` [PULL 23/32] hw/ppc/pegasos2: Add Pegasos I emulation Harsh Prateek Bora
@ 2025-10-23 12:16 ` Harsh Prateek Bora
2025-10-23 12:16 ` [PULL 25/32] hw/ppc: Implement fadump register command Harsh Prateek Bora
` (8 subsequent siblings)
32 siblings, 0 replies; 39+ messages in thread
From: Harsh Prateek Bora @ 2025-10-23 12:16 UTC (permalink / raw)
To: qemu-devel; +Cc: BALATON Zoltan, Philippe Mathieu-Daudé
From: BALATON Zoltan <balaton@eik.bme.hu>
When running without firmware ROM using Virtual Open Firmware we need
to do some hardware initialisation and provide the device tree as the
machine firmware would normally do.
Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Link: https://lore.kernel.org/qemu-devel/d2d7f173dbd436b47382f384d5a93eb7e713424e.1761176219.git.balaton@eik.bme.hu
Signed-off-by: Harsh Prateek Bora <harshpb@linux.ibm.com>
---
MAINTAINERS | 1 +
hw/ppc/pegasos2.c | 140 +++++++++++++++++++++++++++++++++------
pc-bios/dtb/meson.build | 1 +
pc-bios/dtb/pegasos1.dtb | Bin 0 -> 857 bytes
pc-bios/dtb/pegasos1.dts | 125 ++++++++++++++++++++++++++++++++++
5 files changed, 246 insertions(+), 21 deletions(-)
create mode 100644 pc-bios/dtb/pegasos1.dtb
create mode 100644 pc-bios/dtb/pegasos1.dts
diff --git a/MAINTAINERS b/MAINTAINERS
index 36eef27b41..684d7a5b37 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1652,6 +1652,7 @@ F: hw/ppc/pegasos2.c
F: hw/pci-host/mv64361.c
F: hw/pci-host/mv643xx.h
F: include/hw/pci-host/mv64361.h
+F: pc-bios/dtb/pegasos[12].dt[sb]
amigaone
M: BALATON Zoltan <balaton@eik.bme.hu>
diff --git a/hw/ppc/pegasos2.c b/hw/ppc/pegasos2.c
index a11f3c99ed..93696ed381 100644
--- a/hw/ppc/pegasos2.c
+++ b/hw/ppc/pegasos2.c
@@ -84,6 +84,7 @@ struct PegasosMachineState {
uint64_t initrd_size;
};
+static void *pegasos1_build_fdt(PegasosMachineState *pm, int *fdt_size);
static void *pegasos2_build_fdt(PegasosMachineState *pm, int *fdt_size);
static void pegasos_cpu_reset(void *opaque)
@@ -314,6 +315,82 @@ static void pegasos_init(MachineState *machine)
}
}
+static void pegasos_superio_write(uint8_t addr, uint8_t val)
+{
+ cpu_physical_memory_write(0xfe0003f0, &addr, 1);
+ cpu_physical_memory_write(0xfe0003f1, &val, 1);
+}
+
+static void pegasos1_pci_config_write(PegasosMachineState *pm, int bus,
+ uint32_t addr, uint32_t len, uint32_t val)
+{
+ addr |= BIT(31);
+ cpu_physical_memory_write(0xfec00cf8, &addr, 4);
+ cpu_physical_memory_write(0xfee00cfc, &val, len);
+}
+
+static void pegasos1_chipset_reset(PegasosMachineState *pm)
+{
+ uint8_t elcr = 0x2e;
+ cpu_physical_memory_write(0xfe0004d1, &elcr, sizeof(elcr));
+
+ pegasos1_pci_config_write(pm, 0, PCI_COMMAND, 2, PCI_COMMAND_IO |
+ PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
+
+ pegasos1_pci_config_write(pm, 0, (PCI_DEVFN(7, 0) << 8) |
+ PCI_INTERRUPT_LINE, 2, 0x9);
+ pegasos1_pci_config_write(pm, 0, (PCI_DEVFN(7, 0) << 8) |
+ 0x50, 1, 0x6);
+ pegasos_superio_write(0xf4, 0xbe);
+ pegasos_superio_write(0xf6, 0xef);
+ pegasos_superio_write(0xf7, 0xfc);
+ pegasos_superio_write(0xf2, 0x14);
+ pegasos1_pci_config_write(pm, 0, (PCI_DEVFN(7, 0) << 8) |
+ 0x51, 1, 0x3d);
+ pegasos1_pci_config_write(pm, 0, (PCI_DEVFN(7, 0) << 8) |
+ 0x55, 1, 0x90);
+ pegasos1_pci_config_write(pm, 0, (PCI_DEVFN(7, 0) << 8) |
+ 0x56, 1, 0x99);
+ pegasos1_pci_config_write(pm, 0, (PCI_DEVFN(7, 0) << 8) |
+ 0x57, 1, 0x90);
+
+ pegasos1_pci_config_write(pm, 0, (PCI_DEVFN(7, 1) << 8) |
+ PCI_INTERRUPT_LINE, 2, 0x10e);
+ pegasos1_pci_config_write(pm, 0, (PCI_DEVFN(7, 1) << 8) |
+ PCI_CLASS_PROG, 1, 0xf);
+ pegasos1_pci_config_write(pm, 0, (PCI_DEVFN(7, 1) << 8) |
+ 0x40, 1, 0xb);
+ pegasos1_pci_config_write(pm, 0, (PCI_DEVFN(7, 1) << 8) |
+ 0x50, 4, 0x17171717);
+ pegasos1_pci_config_write(pm, 0, (PCI_DEVFN(7, 1) << 8) |
+ PCI_COMMAND, 2, 0x87);
+
+ pegasos1_pci_config_write(pm, 0, (PCI_DEVFN(7, 2) << 8) |
+ PCI_INTERRUPT_LINE, 2, 0x409);
+ pegasos1_pci_config_write(pm, 0, (PCI_DEVFN(7, 2) << 8) |
+ PCI_COMMAND, 2, 0x7);
+
+ pegasos1_pci_config_write(pm, 0, (PCI_DEVFN(7, 3) << 8) |
+ PCI_INTERRUPT_LINE, 2, 0x409);
+ pegasos1_pci_config_write(pm, 0, (PCI_DEVFN(7, 3) << 8) |
+ PCI_COMMAND, 2, 0x7);
+
+ pegasos1_pci_config_write(pm, 0, (PCI_DEVFN(7, 4) << 8) |
+ PCI_INTERRUPT_LINE, 2, 0x9);
+ pegasos1_pci_config_write(pm, 0, (PCI_DEVFN(7, 4) << 8) |
+ 0x48, 4, 0x2001);
+ pegasos1_pci_config_write(pm, 0, (PCI_DEVFN(7, 4) << 8) |
+ 0x41, 1, 0);
+ pegasos1_pci_config_write(pm, 0, (PCI_DEVFN(7, 4) << 8) |
+ 0x90, 4, 0x1000);
+
+ pegasos1_pci_config_write(pm, 0, (PCI_DEVFN(7, 5) << 8) |
+ PCI_INTERRUPT_LINE, 2, 0x309);
+
+ pegasos1_pci_config_write(pm, 0, (PCI_DEVFN(7, 6) << 8) |
+ PCI_INTERRUPT_LINE, 2, 0x309);
+}
+
static uint32_t pegasos2_mv_reg_read(PegasosMachineState *pm,
uint32_t addr, uint32_t len)
{
@@ -357,12 +434,6 @@ static void pegasos2_pci_config_write(PegasosMachineState *pm, int bus,
pegasos2_mv_reg_write(pm, pcicfg + 4, len, val);
}
-static void pegasos2_superio_write(uint8_t addr, uint8_t val)
-{
- cpu_physical_memory_write(0xfe0003f0, &addr, 1);
- cpu_physical_memory_write(0xfe0003f1, &val, 1);
-}
-
static void pegasos2_chipset_reset(PegasosMachineState *pm)
{
pegasos2_mv_reg_write(pm, 0, 4, 0x28020ff);
@@ -379,10 +450,10 @@ static void pegasos2_chipset_reset(PegasosMachineState *pm)
PCI_INTERRUPT_LINE, 2, 0x9);
pegasos2_pci_config_write(pm, 1, (PCI_DEVFN(12, 0) << 8) |
0x50, 1, 0x6);
- pegasos2_superio_write(0xf4, 0xbe);
- pegasos2_superio_write(0xf6, 0xef);
- pegasos2_superio_write(0xf7, 0xfc);
- pegasos2_superio_write(0xf2, 0x14);
+ pegasos_superio_write(0xf4, 0xbe);
+ pegasos_superio_write(0xf6, 0xef);
+ pegasos_superio_write(0xf7, 0xfc);
+ pegasos_superio_write(0xf2, 0x14);
pegasos2_pci_config_write(pm, 1, (PCI_DEVFN(12, 0) << 8) |
0x50, 1, 0x2);
pegasos2_pci_config_write(pm, 1, (PCI_DEVFN(12, 0) << 8) |
@@ -432,7 +503,7 @@ static void pegasos2_chipset_reset(PegasosMachineState *pm)
static void pegasos_machine_reset(MachineState *machine, ResetType type)
{
PegasosMachineState *pm = PEGASOS_MACHINE(machine);
- void *fdt;
+ void *fdt = NULL;
uint32_t c[2];
uint64_t d[2];
int sz;
@@ -440,13 +511,22 @@ static void pegasos_machine_reset(MachineState *machine, ResetType type)
qemu_devices_reset(type);
if (!pm->vof) {
return; /* Firmware should set up machine so nothing to do */
- } else if (pm->type == PEGASOS1) {
- error_report("VOF is not supported by this machine");
- exit(1);
}
/* Otherwise, set up devices that board firmware would normally do */
- pegasos2_chipset_reset(pm);
+ switch (pm->type) {
+ case PEGASOS1:
+ pegasos1_chipset_reset(pm);
+ fdt = pegasos1_build_fdt(pm, &sz);
+ break;
+ case PEGASOS2:
+ pegasos2_chipset_reset(pm);
+ fdt = pegasos2_build_fdt(pm, &sz);
+ break;
+ }
+ if (!fdt) {
+ exit(1);
+ }
/* Device tree and VOF set up */
vof_init(pm->vof, machine->ram_size, &error_fatal);
@@ -465,11 +545,6 @@ static void pegasos_machine_reset(MachineState *machine, ResetType type)
exit(1);
}
- fdt = pegasos2_build_fdt(pm, &sz);
- if (!fdt) {
- exit(1);
- }
-
/* Set memory size */
c[0] = 0;
c[1] = cpu_to_be32(machine->ram_size);
@@ -761,6 +836,8 @@ static struct {
const char *name;
void (*dtf)(PCIBus *bus, PCIDevice *d, FDTInfo *fi);
} device_map[] = {
+ { "pci10cc,660", "host", NULL },
+ { "pci10cc,661", "host", NULL },
{ "pci11ab,6460", "host", NULL },
{ "pci1106,571", "ide", dt_ide },
{ "pci1106,3044", "firewire", NULL },
@@ -846,7 +923,7 @@ static void add_pci_device(PCIBus *bus, PCIDevice *d, void *opaque)
qemu_fdt_setprop_cell(fi->fdt, node->str, "interrupts",
pci_get_byte(&d->config[PCI_INTERRUPT_PIN]));
}
- /* Pegasos2 firmware has subsystem-id amd subsystem-vendor-id swapped */
+ /* Pegasos firmware has subsystem-id and subsystem-vendor-id swapped */
qemu_fdt_setprop_cell(fi->fdt, node->str, "subsystem-vendor-id",
pci_get_word(&d->config[PCI_SUBSYSTEM_ID]));
qemu_fdt_setprop_cell(fi->fdt, node->str, "subsystem-id",
@@ -934,6 +1011,27 @@ static void *load_dtb(const char *filename, int *fdt_size)
return fdt;
}
+static void *pegasos1_build_fdt(PegasosMachineState *pm, int *fdt_size)
+{
+ FDTInfo fi;
+ PCIBus *pci_bus;
+ void *fdt = load_dtb("pegasos1.dtb", fdt_size);
+
+ if (!fdt) {
+ return NULL;
+ }
+ qemu_fdt_setprop_string(fdt, "/", "name", "bplan,Pegasos");
+
+ add_cpu_info(fdt, pm->cpu, pm->bus_freq_hz);
+
+ fi.fdt = fdt;
+ fi.path = "/pci@80000000";
+ pci_bus = PCI_BUS(qdev_get_child_bus(pm->nb, "pci.0"));
+ pci_for_each_device_reverse(pci_bus, 0, add_pci_device, &fi);
+
+ return fdt;
+}
+
static void *pegasos2_build_fdt(PegasosMachineState *pm, int *fdt_size)
{
FDTInfo fi;
diff --git a/pc-bios/dtb/meson.build b/pc-bios/dtb/meson.build
index f14648f3a4..81bdd7580e 100644
--- a/pc-bios/dtb/meson.build
+++ b/pc-bios/dtb/meson.build
@@ -1,6 +1,7 @@
dtbs = [
'bamboo.dtb',
'canyonlands.dtb',
+ 'pegasos1.dtb',
'pegasos2.dtb',
'petalogix-ml605.dtb',
'petalogix-s3adsp1800.dtb',
diff --git a/pc-bios/dtb/pegasos1.dtb b/pc-bios/dtb/pegasos1.dtb
new file mode 100644
index 0000000000000000000000000000000000000000..3b863b25288a59bcede9459ff42afad713dde741
GIT binary patch
literal 857
zcmZ8fO>Yx15OvxjK&T3w=^-c=RCQ5Ogp}S|g(^KkM8yI1P<g$Rbd_D(wKuI&2~qwB
z2PCfWU-%<P`~ZlU=k<oRBR$W&=lQVL`*U;oONjLkLWqG7Yv0*FXFOp%X25>1Ue)2P
zwH4Vq`;8bw1HZ>;t21Y#4($Qs>6oU{8xI*8@T`9T8sbOnw^Lh4-5HhX(Mm_{-ksVl
z)<#k543FN8J7aT6ZanN9FMLHMid)8#w$22?9P@Cm<{Ue{7yY!q`;sNG#%QTC<4J?o
zyrj~&#eOd+b^U#g+qE9l=58l32d?gA=i#Evk%Mn^%78T-ar4cvKZ`unPh?(rIUyvm
zp(f1s<Z@XAE#z61?+<#l1@(XbHt#{YIS+BeaUS$&_<8Hk*Y`L0=jCr^^*-L<<eHaH
z3^vr@g}yXD0>mX2*md1FhM>Vd@`{15zY&OI5A?*GZ_uJ49eCK4S?0+5L{U+Ak<mr2
z=(Ji`5~azg5RMg}8!d)!UmuPR-|SqF&Wu~p)JT`DSVmsC+*T-XG!<Q+Us3GcRd_p9
s7&S{Kj?U+#)j|w*U+pEiuE@E$trDqb+FTZtO-VSZr{qOC_eluFKX>nfX#fBK
literal 0
HcmV?d00001
diff --git a/pc-bios/dtb/pegasos1.dts b/pc-bios/dtb/pegasos1.dts
new file mode 100644
index 0000000000..e5ef9db866
--- /dev/null
+++ b/pc-bios/dtb/pegasos1.dts
@@ -0,0 +1,125 @@
+/*
+ * QEMU Pegasos1 Device Tree Source
+ *
+ * Copyright 2025 BALATON Zoltan
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ *
+ * This is partial source, more info will be filled in by board code.
+ */
+
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ device_type = "chrp";
+ model = "Pegasos";
+ revision = "1A";
+ CODEGEN,vendor = "bplan GmbH";
+ CODEGEN,board = "Pegasos";
+ CODEGEN,description = "Pegasos CHRP PowerPC System";
+
+ openprom {
+ model = "Pegasos,0.1b123";
+ };
+
+ chosen {
+ };
+
+ memory@0 {
+ device_type = "memory";
+ reg = <0 0>;
+ };
+
+ cpus {
+ #size-cells = <0>;
+ #address-cells = <1>;
+ #cpus = <1>;
+ };
+
+ failsafe {
+ device_type = "serial";
+ };
+
+ pci@80000000 {
+ device_type = "pci";
+ #address-cells = <3>;
+ #size-cells = <2>;
+ clock-frequency = <33333333>;
+ 8259-interrupt-acknowledge = <0xfef00000>;
+ reg = <0x80000000 0x7f000000>;
+ ranges = <0x01000000 0 0x00000000 0xfe000000 0 0x00800000
+ 0x02000000 0 0x80000000 0x80000000 0 0x7d000000
+ 0x02000000 0 0xfd000000 0xfd000000 0 0x01000000>;
+ bus-range = <0 0>;
+
+ isa@7 {
+ vendor-id = <0x1106>;
+ device-id = <0x8231>;
+ revision-id = <0x10>;
+ class-code = <0x60100>;
+ /* Pegasos firmware has subsystem-id and */
+ /* subsystem-vendor-id swapped */
+ subsystem-id = <0x1af4>;
+ subsystem-vendor-id = <0x1100>;
+ reg = <0x3800 0 0 0 0>;
+ device_type = "isa";
+ #address-cells = <2>;
+ #size-cells = <1>;
+ eisa-slots = <0>;
+ clock-frequency = <8333333>;
+ slot-names = <0>;
+
+ serial@i2f8 {
+ device_type = "serial";
+ reg = <1 0x2f8 8>;
+ interrupts = <3 0>;
+ clock-frequency = <0>;
+ };
+
+ 8042@i60 {
+ device_type = "";
+ reg = <1 0x60 5>;
+ clock-frequency = <0>;
+ interrupt-controller = "";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ #interrupt-cells = <2>;
+
+ };
+
+ keyboard@i60 {
+ device_type = "keyboard";
+ reg = <1 0x60 5>;
+ interrupts = <1 0>;
+ };
+
+ rtc@i70 {
+ device_type = "rtc";
+ reg = <1 0x70 2>;
+ interrupts = <8 0>;
+ clock-frequency = <0>;
+ compatible = "ds1385-rtc";
+ };
+
+ timer@i40 {
+ device_type = "timer";
+ reg = <1 0x40 8>;
+ clock-frequency = <0>;
+ };
+
+ fdc@i3f0 {
+ device_type = "fdc";
+ reg = <1 0x3f0 8>;
+ interrupts = <6 0>;
+ clock-frequency = <0>;
+ };
+
+ lpt@i3bc {
+ device_type = "lpt";
+ reg = <1 0x3bc 8>;
+ interrupts = <7 0>;
+ clock-frequency = <0>;
+ };
+ };
+ };
+};
--
2.43.5
^ permalink raw reply related [flat|nested] 39+ messages in thread
* [PULL 25/32] hw/ppc: Implement fadump register command
2025-10-23 12:16 [PULL RESEND 00/32] ppc-for-10.2 queue Harsh Prateek Bora
` (23 preceding siblings ...)
2025-10-23 12:16 ` [PULL 24/32] hw/ppc/pegasos2: Add VOF support for pegasos1 Harsh Prateek Bora
@ 2025-10-23 12:16 ` Harsh Prateek Bora
2025-10-23 12:16 ` [PULL 26/32] hw/ppc: Trigger Fadump boot if fadump is registered Harsh Prateek Bora
` (7 subsequent siblings)
32 siblings, 0 replies; 39+ messages in thread
From: Harsh Prateek Bora @ 2025-10-23 12:16 UTC (permalink / raw)
To: qemu-devel; +Cc: Aditya Gupta, Sourabh Jain, Shivang Upadhyay
From: Aditya Gupta <adityag@linux.ibm.com>
Add skeleton to handle "ibm,configure-kernel-dump" rtas call in QEMU,
including register, unregister and invalidate commands.
The register just verifies the structure of the fadump memory structure
passed by kernel, and set fadump_registered in spapr state to true.
Verify basic details mandated by the PAPR, such as number of
inputs/output, and add handling for the three fadump commands:
regiser/unregister/invalidate.
The checks are based on the table in following requirement in PAPR v2.13:
"R1–7.3.30–1. For the Configure Platform Assisted Kernel Dump option ..."
Relevant section for the register command in PAPR is:
Section 7.3.30: "ibm,configure-kernel-dump RTAS call" (PAPR v2.13)
Note: Any modifications made by the kernel to the fadump memory
structure after the 'ibm,configure-kernel-dump' RTAS call returns will
not be reflected in QEMU, as QEMU retains the fadump memory structure
that was provided during fadump registration.
The kernel must unregister and re-register fadump to apply any changes
to the fadump memory structure.
Signed-off-by: Aditya Gupta <adityag@linux.ibm.com>
Reviewed-by: Sourabh Jain <sourabhjain@linux.ibm.com>
Tested-by: Shivang Upadhyay <shivangu@linux.ibm.com>
Link: https://lore.kernel.org/qemu-devel/20251021134823.1861675-2-adityag@linux.ibm.com
Signed-off-by: Harsh Prateek Bora <harshpb@linux.ibm.com>
---
include/hw/ppc/spapr.h | 11 ++-
include/hw/ppc/spapr_fadump.h | 69 +++++++++++++++++++
hw/ppc/spapr_fadump.c | 123 ++++++++++++++++++++++++++++++++++
hw/ppc/spapr_rtas.c | 71 ++++++++++++++++++++
hw/ppc/meson.build | 1 +
5 files changed, 274 insertions(+), 1 deletion(-)
create mode 100644 include/hw/ppc/spapr_fadump.h
create mode 100644 hw/ppc/spapr_fadump.c
diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h
index b9d884745f..28cf2723d8 100644
--- a/include/hw/ppc/spapr.h
+++ b/include/hw/ppc/spapr.h
@@ -13,6 +13,7 @@
#include "hw/ppc/xics.h" /* For ICSState */
#include "hw/ppc/spapr_tpm_proxy.h"
#include "hw/ppc/spapr_nested.h" /* For SpaprMachineStateNested */
+#include "hw/ppc/spapr_fadump.h" /* For FadumpMemStruct */
struct SpaprVioBus;
struct SpaprPhbState;
@@ -267,6 +268,11 @@ struct SpaprMachineState {
Error *fwnmi_migration_blocker;
SpaprWatchdog wds[WDT_MAX_WATCHDOGS];
+
+ /* Fadump State */
+ bool fadump_registered;
+ bool fadump_dump_active;
+ FadumpMemStruct registered_fdm;
};
#define H_SUCCESS 0
@@ -692,6 +698,8 @@ void push_sregs_to_kvm_pr(SpaprMachineState *spapr);
#define RTAS_OUT_PARAM_ERROR -3
#define RTAS_OUT_NOT_SUPPORTED -3
#define RTAS_OUT_NO_SUCH_INDICATOR -3
+#define RTAS_OUT_DUMP_ALREADY_REGISTERED -9
+#define RTAS_OUT_DUMP_ACTIVE -10
#define RTAS_OUT_NOT_AUTHORIZED -9002
#define RTAS_OUT_SYSPARM_PARAM_ERROR -9999
@@ -754,8 +762,9 @@ void push_sregs_to_kvm_pr(SpaprMachineState *spapr);
#define RTAS_IBM_SUSPEND_ME (RTAS_TOKEN_BASE + 0x2A)
#define RTAS_IBM_NMI_REGISTER (RTAS_TOKEN_BASE + 0x2B)
#define RTAS_IBM_NMI_INTERLOCK (RTAS_TOKEN_BASE + 0x2C)
+#define RTAS_CONFIGURE_KERNEL_DUMP (RTAS_TOKEN_BASE + 0x2D)
-#define RTAS_TOKEN_MAX (RTAS_TOKEN_BASE + 0x2D)
+#define RTAS_TOKEN_MAX (RTAS_TOKEN_BASE + 0x2E)
/* RTAS ibm,get-system-parameter token values */
#define RTAS_SYSPARM_SPLPAR_CHARACTERISTICS 20
diff --git a/include/hw/ppc/spapr_fadump.h b/include/hw/ppc/spapr_fadump.h
new file mode 100644
index 0000000000..f64f339204
--- /dev/null
+++ b/include/hw/ppc/spapr_fadump.h
@@ -0,0 +1,69 @@
+/*
+ * Firmware Assisted Dump in PSeries
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+#ifndef PPC_SPAPR_FADUMP_H
+#define PPC_SPAPR_FADUMP_H
+
+#include "qemu/osdep.h"
+#include "cpu.h"
+
+/* Fadump commands */
+#define FADUMP_CMD_REGISTER 1
+#define FADUMP_CMD_UNREGISTER 2
+#define FADUMP_CMD_INVALIDATE 3
+
+#define FADUMP_VERSION 1
+
+/*
+ * The Firmware Assisted Dump Memory structure supports a maximum of 10 sections
+ * in the dump memory structure. Presently, three sections are used for
+ * CPU state data, HPTE & Parameters area, while the remaining seven sections
+ * can be used for boot memory regions.
+ */
+#define FADUMP_MAX_SECTIONS 10
+
+typedef struct FadumpSection FadumpSection;
+typedef struct FadumpSectionHeader FadumpSectionHeader;
+typedef struct FadumpMemStruct FadumpMemStruct;
+
+struct SpaprMachineState;
+
+/* Kernel Dump section info */
+/* All fields are in big-endian */
+struct FadumpSection {
+ uint32_t request_flag;
+ uint16_t source_data_type;
+ uint16_t error_flags;
+ uint64_t source_address;
+ uint64_t source_len;
+ uint64_t bytes_dumped;
+ uint64_t destination_address;
+};
+
+/* ibm,configure-kernel-dump header. */
+struct FadumpSectionHeader {
+ uint32_t dump_format_version;
+ uint16_t dump_num_sections;
+ uint16_t dump_status_flag;
+ uint32_t offset_first_dump_section;
+
+ /* Fields for disk dump option. */
+ uint32_t dd_block_size;
+ uint64_t dd_block_offset;
+ uint64_t dd_num_blocks;
+ uint32_t dd_offset_disk_path;
+
+ /* Maximum time allowed to prevent an automatic dump-reboot. */
+ uint32_t max_time_auto;
+};
+
+/* Note: All the data in these structures is in big-endian */
+struct FadumpMemStruct {
+ FadumpSectionHeader header;
+ FadumpSection rgn[FADUMP_MAX_SECTIONS];
+};
+
+uint32_t do_fadump_register(struct SpaprMachineState *, target_ulong);
+#endif /* PPC_SPAPR_FADUMP_H */
diff --git a/hw/ppc/spapr_fadump.c b/hw/ppc/spapr_fadump.c
new file mode 100644
index 0000000000..2c9f024c2d
--- /dev/null
+++ b/hw/ppc/spapr_fadump.c
@@ -0,0 +1,123 @@
+/*
+ * Firmware Assisted Dump in PSeries
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/log.h"
+#include "hw/ppc/spapr.h"
+
+/*
+ * Handle the "FADUMP_CMD_REGISTER" command in 'ibm,configure-kernel-dump'
+ *
+ * Note: Any changes made by the kernel to the fadump memory struct won't
+ * reflect in QEMU after the 'ibm,configure-kernel-dump' RTAS call has returned,
+ * as we store the passed fadump memory structure passed during fadump
+ * registration.
+ * Kernel has to invalidate & re-register fadump, if it intends to make any
+ * changes to the fadump memory structure
+ *
+ * Returns:
+ * * RTAS_OUT_SUCCESS: On successful registration
+ * * RTAS_OUT_PARAM_ERROR: If parameters are not correct, eg. too many
+ * sections, invalid memory addresses that we are
+ * unable to read, etc
+ * * RTAS_OUT_DUMP_ALREADY_REGISTERED: Dump already registered
+ * * RTAS_OUT_HW_ERROR: Misc issue such as memory access failures
+ */
+uint32_t do_fadump_register(SpaprMachineState *spapr, target_ulong args)
+{
+ FadumpSectionHeader header;
+ FadumpSection regions[FADUMP_MAX_SECTIONS] = {0};
+ target_ulong fdm_addr = rtas_ld(args, 1);
+ target_ulong fdm_size = rtas_ld(args, 2);
+ AddressSpace *default_as = &address_space_memory;
+ MemTxResult io_result;
+ MemTxAttrs attrs;
+ uint64_t next_section_addr;
+ uint16_t dump_num_sections;
+
+ /* Mark the memory transaction as privileged memory access */
+ attrs.user = 0;
+ attrs.memory = 1;
+
+ if (spapr->fadump_registered) {
+ /* FADump already registered */
+ return RTAS_OUT_DUMP_ALREADY_REGISTERED;
+ }
+
+ if (spapr->fadump_dump_active) {
+ return RTAS_OUT_DUMP_ACTIVE;
+ }
+
+ if (fdm_size < sizeof(FadumpSectionHeader)) {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "FADump: Header size is invalid: " TARGET_FMT_lu "\n", fdm_size);
+ return RTAS_OUT_PARAM_ERROR;
+ }
+
+ /* Ensure fdm_addr points to a valid RMR-memory/RMA-memory buffer */
+ if ((fdm_addr <= 0) || ((fdm_addr + fdm_size) > spapr->rma_size)) {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "FADump: Invalid fdm address: " TARGET_FMT_lu "\n", fdm_addr);
+ return RTAS_OUT_PARAM_ERROR;
+ }
+
+ /* Try to read the passed fadump header */
+ io_result = address_space_read(default_as, fdm_addr, attrs,
+ &header, sizeof(header));
+ if (io_result != MEMTX_OK) {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "FADump: Unable to read fdm: " TARGET_FMT_lu "\n", fdm_addr);
+
+ return RTAS_OUT_HW_ERROR;
+ }
+
+ /* Verify that we understand the fadump header version */
+ if (header.dump_format_version != cpu_to_be32(FADUMP_VERSION)) {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "FADump: Unknown fadump header version: 0x%x\n",
+ header.dump_format_version);
+ return RTAS_OUT_PARAM_ERROR;
+ }
+
+ /* Reset dump status flags */
+ header.dump_status_flag = 0;
+
+ dump_num_sections = be16_to_cpu(header.dump_num_sections);
+
+ if (dump_num_sections > FADUMP_MAX_SECTIONS) {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "FADump: Too many sections: %d sections\n", dump_num_sections);
+ return RTAS_OUT_PARAM_ERROR;
+ }
+
+ next_section_addr =
+ fdm_addr +
+ be32_to_cpu(header.offset_first_dump_section);
+
+ for (int i = 0; i < dump_num_sections; ++i) {
+ /* Read the fadump section from memory */
+ io_result = address_space_read(default_as, next_section_addr, attrs,
+ ®ions[i], sizeof(regions[i]));
+ if (io_result != MEMTX_OK) {
+ qemu_log_mask(LOG_UNIMP,
+ "FADump: Unable to read fadump %dth section\n", i);
+ return RTAS_OUT_PARAM_ERROR;
+ }
+
+ next_section_addr += sizeof(regions[i]);
+ }
+
+ spapr->fadump_registered = true;
+ spapr->fadump_dump_active = false;
+
+ /* Store the registered fadump memory struct */
+ spapr->registered_fdm.header = header;
+ for (int i = 0; i < dump_num_sections; ++i) {
+ spapr->registered_fdm.rgn[i] = regions[i];
+ }
+
+ return RTAS_OUT_SUCCESS;
+}
diff --git a/hw/ppc/spapr_rtas.c b/hw/ppc/spapr_rtas.c
index 143bc8c379..6042fc72e5 100644
--- a/hw/ppc/spapr_rtas.c
+++ b/hw/ppc/spapr_rtas.c
@@ -344,6 +344,73 @@ static void rtas_ibm_set_system_parameter(PowerPCCPU *cpu,
rtas_st(rets, 0, ret);
}
+/* Papr Section 7.4.9 ibm,configure-kernel-dump RTAS call */
+static void rtas_configure_kernel_dump(PowerPCCPU *cpu,
+ SpaprMachineState *spapr,
+ uint32_t token, uint32_t nargs,
+ target_ulong args,
+ uint32_t nret, target_ulong rets)
+{
+ target_ulong cmd = rtas_ld(args, 0);
+ uint32_t ret_val;
+
+ /* Number of outputs has to be 1 */
+ if (nret != 1) {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "FADump: ibm,configure-kernel-dump called with nret != 1.\n");
+ rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
+ return;
+ }
+
+ /* Number of inputs has to be 3 */
+ if (nargs != 3) {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "FADump: ibm,configure-kernel-dump called with nargs != 3.\n");
+ rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
+ return;
+ }
+
+ switch (cmd) {
+ case FADUMP_CMD_REGISTER:
+ ret_val = do_fadump_register(spapr, args);
+ if (ret_val != RTAS_OUT_SUCCESS) {
+ rtas_st(rets, 0, ret_val);
+ return;
+ }
+ break;
+ case FADUMP_CMD_UNREGISTER:
+ if (spapr->fadump_dump_active) {
+ rtas_st(rets, 0, RTAS_OUT_DUMP_ACTIVE);
+ return;
+ }
+
+ spapr->fadump_registered = false;
+ spapr->fadump_dump_active = false;
+ memset(&spapr->registered_fdm, 0, sizeof(spapr->registered_fdm));
+ break;
+ case FADUMP_CMD_INVALIDATE:
+ if (!spapr->fadump_dump_active) {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "FADump: Nothing to invalidate, no dump active\n");
+
+ rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
+ }
+
+ spapr->fadump_registered = false;
+ spapr->fadump_dump_active = false;
+ memset(&spapr->registered_fdm, 0, sizeof(spapr->registered_fdm));
+ break;
+ default:
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "FADump: Unknown command: " TARGET_FMT_lu "\n", cmd);
+
+ rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
+ return;
+ }
+
+ rtas_st(rets, 0, RTAS_OUT_SUCCESS);
+}
+
static void rtas_ibm_os_term(PowerPCCPU *cpu,
SpaprMachineState *spapr,
uint32_t token, uint32_t nargs,
@@ -659,6 +726,10 @@ static void core_rtas_register_types(void)
spapr_rtas_register(RTAS_IBM_NMI_INTERLOCK, "ibm,nmi-interlock",
rtas_ibm_nmi_interlock);
+ /* Register fadump rtas call */
+ spapr_rtas_register(RTAS_CONFIGURE_KERNEL_DUMP, "ibm,configure-kernel-dump",
+ rtas_configure_kernel_dump);
+
qtest_set_command_cb(spapr_qtest_callback);
}
diff --git a/hw/ppc/meson.build b/hw/ppc/meson.build
index 170b90ae7d..6b7c1f4f49 100644
--- a/hw/ppc/meson.build
+++ b/hw/ppc/meson.build
@@ -26,6 +26,7 @@ ppc_ss.add(when: 'CONFIG_PSERIES', if_true: files(
'spapr_nvdimm.c',
'spapr_rtas_ddw.c',
'spapr_numa.c',
+ 'spapr_fadump.c',
'pef.c',
))
ppc_ss.add(when: ['CONFIG_PSERIES', 'CONFIG_TCG'], if_true: files(
--
2.43.5
^ permalink raw reply related [flat|nested] 39+ messages in thread
* [PULL 26/32] hw/ppc: Trigger Fadump boot if fadump is registered
2025-10-23 12:16 [PULL RESEND 00/32] ppc-for-10.2 queue Harsh Prateek Bora
` (24 preceding siblings ...)
2025-10-23 12:16 ` [PULL 25/32] hw/ppc: Implement fadump register command Harsh Prateek Bora
@ 2025-10-23 12:16 ` Harsh Prateek Bora
2025-10-23 12:16 ` [PULL 27/32] hw/ppc: Preserve memory regions registered for fadump Harsh Prateek Bora
` (6 subsequent siblings)
32 siblings, 0 replies; 39+ messages in thread
From: Harsh Prateek Bora @ 2025-10-23 12:16 UTC (permalink / raw)
To: qemu-devel; +Cc: Aditya Gupta, Sourabh Jain, Shivang Upadhyay
From: Aditya Gupta <adityag@linux.ibm.com>
According to PAPR:
R1–7.3.30–3. When the platform receives an ibm,os-term RTAS call, or
on a system reset without an ibm,nmi-interlock RTAS call, if the
platform has a dump structure registered through the
ibm,configure-kernel-dump call, the platform must process each
registered kernel dump section as required and, when available,
present the dump structure information to the operating system
through the “ibm,kernel-dump” property, updated with status for each
dump section, until the dump has been invalidated through the
ibm,configure-kernel-dump RTAS call.
If Fadump has been registered, trigger an Fadump boot (memory preserving
boot), if QEMU recieves a 'ibm,os-term' rtas call.
Implementing the fadump boot as:
* pause all vcpus (will need to save registers later)
* preserve memory regions specified by fadump (will be implemented
in future)
* do a memory preserving reboot (GUEST_RESET in QEMU doesn't clear
the memory)
Memory regions registered by fadump will be handled in a later patch.
Note: Preserving memory regions is not implemented yet so on an
"ibm,os-term" call will just trigger a reboot in QEMU if fadump is
registered, and the second kernel will boot as a normal boot (not
fadump boot)
Signed-off-by: Aditya Gupta <adityag@linux.ibm.com>
Reviewed-by: Sourabh Jain <sourabhjain@linux.ibm.com>
Tested-by: Shivang Upadhyay <shivangu@linux.ibm.com>
Link: https://lore.kernel.org/qemu-devel/20251021134823.1861675-3-adityag@linux.ibm.com
Signed-off-by: Harsh Prateek Bora <harshpb@linux.ibm.com>
---
include/hw/ppc/spapr_fadump.h | 6 +++
hw/ppc/spapr_fadump.c | 77 +++++++++++++++++++++++++++++++++++
hw/ppc/spapr_rtas.c | 5 +++
3 files changed, 88 insertions(+)
diff --git a/include/hw/ppc/spapr_fadump.h b/include/hw/ppc/spapr_fadump.h
index f64f339204..1cb90c9d63 100644
--- a/include/hw/ppc/spapr_fadump.h
+++ b/include/hw/ppc/spapr_fadump.h
@@ -16,6 +16,11 @@
#define FADUMP_VERSION 1
+/* Dump status flags */
+#define FADUMP_STATUS_DUMP_PERFORMED 0x8000
+#define FADUMP_STATUS_DUMP_TRIGGERED 0x4000
+#define FADUMP_STATUS_DUMP_ERROR 0x2000
+
/*
* The Firmware Assisted Dump Memory structure supports a maximum of 10 sections
* in the dump memory structure. Presently, three sections are used for
@@ -66,4 +71,5 @@ struct FadumpMemStruct {
};
uint32_t do_fadump_register(struct SpaprMachineState *, target_ulong);
+void trigger_fadump_boot(struct SpaprMachineState *, target_ulong);
#endif /* PPC_SPAPR_FADUMP_H */
diff --git a/hw/ppc/spapr_fadump.c b/hw/ppc/spapr_fadump.c
index 2c9f024c2d..53e5c12c76 100644
--- a/hw/ppc/spapr_fadump.c
+++ b/hw/ppc/spapr_fadump.c
@@ -7,6 +7,7 @@
#include "qemu/osdep.h"
#include "qemu/log.h"
#include "hw/ppc/spapr.h"
+#include "system/cpus.h"
/*
* Handle the "FADUMP_CMD_REGISTER" command in 'ibm,configure-kernel-dump'
@@ -121,3 +122,79 @@ uint32_t do_fadump_register(SpaprMachineState *spapr, target_ulong args)
return RTAS_OUT_SUCCESS;
}
+
+/* Preserve the memory locations registered for fadump */
+static bool fadump_preserve_mem(void)
+{
+ /*
+ * TODO: Implement preserving memory regions requested during fadump
+ * registration
+ */
+ return false;
+}
+
+/*
+ * Trigger a fadump boot, ie. next boot will be a crashkernel/fadump boot
+ * with fadump dump active.
+ *
+ * This is triggered by ibm,os-term RTAS call, if fadump was registered.
+ *
+ * It preserves the memory and sets 'FADUMP_STATUS_DUMP_TRIGGERED' as
+ * fadump status, which can be used later to add the "ibm,kernel-dump"
+ * device tree node as presence of 'FADUMP_STATUS_DUMP_TRIGGERED' signifies
+ * next boot as fadump boot in our case
+ */
+void trigger_fadump_boot(SpaprMachineState *spapr, target_ulong spapr_retcode)
+{
+ FadumpSectionHeader *header = &spapr->registered_fdm.header;
+
+ pause_all_vcpus();
+
+ /* Preserve the memory locations registered for fadump */
+ if (!fadump_preserve_mem()) {
+ /* Failed to preserve the registered memory regions */
+ rtas_st(spapr_retcode, 0, RTAS_OUT_HW_ERROR);
+
+ /* Cause a reboot */
+ qemu_system_guest_panicked(NULL);
+ return;
+ }
+
+ /*
+ * Mark next boot as fadump boot
+ *
+ * Note: These is some bit of assumption involved here, as PAPR doesn't
+ * specify any use of the dump status flags, nor does the kernel use it
+ *
+ * But from description in Table 136 in PAPR v2.13, it looks like:
+ * FADUMP_STATUS_DUMP_TRIGGERED
+ * = Dump was triggered by the previous system boot (PAPR says)
+ * = Next boot will be a fadump boot (Assumed)
+ *
+ * FADUMP_STATUS_DUMP_PERFORMED
+ * = Dump performed (Set to 0 by caller of the
+ * ibm,configure-kernel-dump call) (PAPR says)
+ * = Firmware has performed the copying/dump of requested regions
+ * (Assumed)
+ * = Dump is active for the next boot (Assumed)
+ */
+ header->dump_status_flag = cpu_to_be16(
+ FADUMP_STATUS_DUMP_TRIGGERED | /* Next boot will be fadump boot */
+ FADUMP_STATUS_DUMP_PERFORMED /* Dump is active */
+ );
+
+ /* Reset fadump_registered for next boot */
+ spapr->fadump_registered = false;
+ spapr->fadump_dump_active = true;
+
+ /*
+ * Then do a guest reset
+ *
+ * Requirement:
+ * GUEST_RESET is expected to NOT clear the memory, as is the case when
+ * this is merged
+ */
+ qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
+
+ rtas_st(spapr_retcode, 0, RTAS_OUT_SUCCESS);
+}
diff --git a/hw/ppc/spapr_rtas.c b/hw/ppc/spapr_rtas.c
index 6042fc72e5..1f78fe406e 100644
--- a/hw/ppc/spapr_rtas.c
+++ b/hw/ppc/spapr_rtas.c
@@ -420,6 +420,11 @@ static void rtas_ibm_os_term(PowerPCCPU *cpu,
target_ulong msgaddr = rtas_ld(args, 0);
char msg[512];
+ if (spapr->fadump_registered) {
+ /* If fadump boot works, control won't come back here */
+ return trigger_fadump_boot(spapr, rets);
+ }
+
cpu_physical_memory_read(msgaddr, msg, sizeof(msg) - 1);
msg[sizeof(msg) - 1] = 0;
--
2.43.5
^ permalink raw reply related [flat|nested] 39+ messages in thread
* [PULL 27/32] hw/ppc: Preserve memory regions registered for fadump
2025-10-23 12:16 [PULL RESEND 00/32] ppc-for-10.2 queue Harsh Prateek Bora
` (25 preceding siblings ...)
2025-10-23 12:16 ` [PULL 26/32] hw/ppc: Trigger Fadump boot if fadump is registered Harsh Prateek Bora
@ 2025-10-23 12:16 ` Harsh Prateek Bora
2025-10-27 13:06 ` Peter Maydell
2025-10-23 12:16 ` [PULL 28/32] hw/ppc: Implement saving CPU state in Fadump Harsh Prateek Bora
` (5 subsequent siblings)
32 siblings, 1 reply; 39+ messages in thread
From: Harsh Prateek Bora @ 2025-10-23 12:16 UTC (permalink / raw)
To: qemu-devel; +Cc: Aditya Gupta, Sourabh Jain, Shivang Upadhyay
From: Aditya Gupta <adityag@linux.ibm.com>
While the first kernel boots, it registers memory regions for fadump
such as:
* CPU state data (has to be populated by the platform)
* HPTE state data (has to be populated by the platform)
* Real Mode Regions (platform should copy it to requested
destination addresses)
* OS defined regions (such as parameter save area)
Platform is also expected to modify the 'bytes_dumped' to the length of
data preserved/copied by platform (ideally same as the source length
passed by kernel).
The kernel passes source address and length for the memory regions, and
a destination address to where the memory is to be copied.
Implement the preserving/copying of the Real Mode Regions and the
Parameter Save Area in QEMU Pseries
The regions are copied in chunks instead of copying all at once.
Signed-off-by: Aditya Gupta <adityag@linux.ibm.com>
Reviewed-by: Sourabh Jain <sourabhjain@linux.ibm.com>
Tested-by: Shivang Upadhyay <shivangu@linux.ibm.com>
Link: https://lore.kernel.org/qemu-devel/20251021134823.1861675-4-adityag@linux.ibm.com
Signed-off-by: Harsh Prateek Bora <harshpb@linux.ibm.com>
---
include/hw/ppc/spapr_fadump.h | 18 ++++
hw/ppc/spapr_fadump.c | 183 +++++++++++++++++++++++++++++++++-
2 files changed, 196 insertions(+), 5 deletions(-)
diff --git a/include/hw/ppc/spapr_fadump.h b/include/hw/ppc/spapr_fadump.h
index 1cb90c9d63..71be2ad92c 100644
--- a/include/hw/ppc/spapr_fadump.h
+++ b/include/hw/ppc/spapr_fadump.h
@@ -16,11 +16,29 @@
#define FADUMP_VERSION 1
+/* Firmware provided dump sections */
+#define FADUMP_CPU_STATE_DATA 0x0001
+#define FADUMP_HPTE_REGION 0x0002
+#define FADUMP_REAL_MODE_REGION 0x0011
+
+/* OS defined sections */
+#define FADUMP_PARAM_AREA 0x0100
+
+/* Dump request flag */
+#define FADUMP_REQUEST_FLAG 0x00000001
+
/* Dump status flags */
#define FADUMP_STATUS_DUMP_PERFORMED 0x8000
#define FADUMP_STATUS_DUMP_TRIGGERED 0x4000
#define FADUMP_STATUS_DUMP_ERROR 0x2000
+/* Region dump error flags */
+#define FADUMP_ERROR_INVALID_DATA_TYPE 0x8000
+#define FADUMP_ERROR_INVALID_SOURCE_ADDR 0x4000
+#define FADUMP_ERROR_LENGTH_EXCEEDS_SOURCE 0x2000
+#define FADUMP_ERROR_INVALID_DEST_ADDR 0x1000
+#define FAUDMP_ERROR_DEST_TOO_SMALL 0x0800
+
/*
* The Firmware Assisted Dump Memory structure supports a maximum of 10 sections
* in the dump memory structure. Presently, three sections are used for
diff --git a/hw/ppc/spapr_fadump.c b/hw/ppc/spapr_fadump.c
index 53e5c12c76..5068a9d83d 100644
--- a/hw/ppc/spapr_fadump.c
+++ b/hw/ppc/spapr_fadump.c
@@ -7,7 +7,9 @@
#include "qemu/osdep.h"
#include "qemu/log.h"
#include "hw/ppc/spapr.h"
+#include "qemu/units.h"
#include "system/cpus.h"
+#include <math.h>
/*
* Handle the "FADUMP_CMD_REGISTER" command in 'ibm,configure-kernel-dump'
@@ -123,14 +125,185 @@ uint32_t do_fadump_register(SpaprMachineState *spapr, target_ulong args)
return RTAS_OUT_SUCCESS;
}
+/*
+ * Copy the source region of given fadump section, to the destination
+ * address mentioned in the region
+ *
+ * Also set the region's error flag, if the copy fails due to non-existent
+ * address (MEMTX_DECODE_ERROR) or permission issues (MEMTX_ACCESS_ERROR)
+ *
+ * Returns true if successful copy
+ *
+ * Returns false in case of any other error, being treated as hardware
+ * error for fadump purposes
+ */
+static bool do_preserve_region(FadumpSection *region)
+{
+ AddressSpace *default_as = &address_space_memory;
+ MemTxResult io_result;
+ MemTxAttrs attrs;
+ uint64_t src_addr, src_len, dest_addr;
+ uint64_t num_chunks;
+ g_autofree void *copy_buffer = NULL;
+
+ src_addr = be64_to_cpu(region->source_address);
+ src_len = be64_to_cpu(region->source_len);
+ dest_addr = be64_to_cpu(region->destination_address);
+
+ /* Mark the memory transaction as privileged memory access */
+ attrs.user = 0;
+ attrs.memory = 1;
+
+ /*
+ * Optimisation: Skip copy if source and destination are same
+ * (eg. param area)
+ */
+ if (src_addr == dest_addr) {
+ region->bytes_dumped = cpu_to_be64(src_len);
+ return true;
+ }
+
+#define FADUMP_CHUNK_SIZE ((size_t)(32 * MiB))
+ copy_buffer = g_try_malloc(FADUMP_CHUNK_SIZE);
+ if (copy_buffer == NULL) {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "FADump: Failed allocating memory (size: %zu) for copying"
+ " reserved memory regions\n", FADUMP_CHUNK_SIZE);
+ }
+
+ num_chunks = ceil((src_len * 1.0f) / FADUMP_CHUNK_SIZE);
+ for (uint64_t chunk_id = 0; chunk_id < num_chunks; ++chunk_id) {
+ /* Take minimum of bytes left to copy, and chunk size */
+ uint64_t copy_len = MIN(
+ src_len - (chunk_id * FADUMP_CHUNK_SIZE),
+ FADUMP_CHUNK_SIZE
+ );
+
+ /* Copy the source region to destination */
+ io_result = address_space_read(default_as, src_addr, attrs,
+ copy_buffer, copy_len);
+ if ((io_result & MEMTX_DECODE_ERROR) ||
+ (io_result & MEMTX_ACCESS_ERROR)) {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "FADump: Failed to decode/access address in section: %d\n",
+ region->source_data_type);
+
+ /*
+ * Invalid source address is not an hardware error, instead
+ * wrong parameter from the kernel.
+ * Return true to let caller know to continue reading other
+ * sections
+ */
+ region->error_flags = FADUMP_ERROR_INVALID_SOURCE_ADDR;
+ region->bytes_dumped = 0;
+ return true;
+ } else if (io_result != MEMTX_OK) {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "FADump: Failed to read source region in section: %d\n",
+ region->source_data_type);
+
+ return false;
+ }
+
+ io_result = address_space_write(default_as, dest_addr, attrs,
+ copy_buffer, copy_len);
+ if ((io_result & MEMTX_DECODE_ERROR) ||
+ (io_result & MEMTX_ACCESS_ERROR)) {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "FADump: Failed to decode/access address in section: %d\n",
+ region->source_data_type);
+
+ /*
+ * Invalid destination address is not an hardware error,
+ * instead wrong parameter from the kernel.
+ * Return true to let caller know to continue reading other
+ * sections
+ */
+ region->error_flags = FADUMP_ERROR_INVALID_DEST_ADDR;
+ region->bytes_dumped = 0;
+ return true;
+ } else if (io_result != MEMTX_OK) {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "FADump: Failed to write destination in section: %d\n",
+ region->source_data_type);
+
+ return false;
+ }
+
+ src_addr += FADUMP_CHUNK_SIZE;
+ dest_addr += FADUMP_CHUNK_SIZE;
+ }
+#undef FADUMP_CHUNK_SIZE
+
+ /*
+ * Considering address_space_write would have copied the
+ * complete region
+ */
+ region->bytes_dumped = cpu_to_be64(src_len);
+ return true;
+}
+
/* Preserve the memory locations registered for fadump */
-static bool fadump_preserve_mem(void)
+static bool fadump_preserve_mem(SpaprMachineState *spapr)
{
+ FadumpMemStruct *fdm = &spapr->registered_fdm;
+ uint16_t dump_num_sections, data_type;
+
+ assert(spapr->fadump_registered);
+
/*
- * TODO: Implement preserving memory regions requested during fadump
- * registration
+ * Handle all sections
+ *
+ * CPU State Data and HPTE regions are handled in their own cases
+ *
+ * RMR regions and any custom OS reserved regions such as parameter
+ * save area, are handled by simply copying the source region to
+ * destination address
*/
- return false;
+ dump_num_sections = be16_to_cpu(fdm->header.dump_num_sections);
+ for (int i = 0; i < dump_num_sections; ++i) {
+ data_type = be16_to_cpu(fdm->rgn[i].source_data_type);
+
+ /* Reset error_flags & bytes_dumped for now */
+ fdm->rgn[i].error_flags = 0;
+ fdm->rgn[i].bytes_dumped = 0;
+
+ /* If kernel did not request for the memory region, then skip it */
+ if (be32_to_cpu(fdm->rgn[i].request_flag) != FADUMP_REQUEST_FLAG) {
+ qemu_log_mask(LOG_UNIMP,
+ "FADump: Skipping copying region as not requested\n");
+ continue;
+ }
+
+ switch (data_type) {
+ case FADUMP_CPU_STATE_DATA:
+ /* TODO: Add CPU state data */
+ break;
+ case FADUMP_HPTE_REGION:
+ /* TODO: Add hpte state data */
+ break;
+ case FADUMP_REAL_MODE_REGION:
+ case FADUMP_PARAM_AREA:
+ /* Copy the memory region from region's source to its destination */
+ if (!do_preserve_region(&fdm->rgn[i])) {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "FADump: Failed to preserve dump section: %d\n",
+ be16_to_cpu(fdm->rgn[i].source_data_type));
+ fdm->header.dump_status_flag |=
+ cpu_to_be16(FADUMP_STATUS_DUMP_ERROR);
+ }
+
+ break;
+ default:
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "FADump: Skipping unknown source data type: %d\n", data_type);
+
+ fdm->rgn[i].error_flags =
+ cpu_to_be16(FADUMP_ERROR_INVALID_DATA_TYPE);
+ }
+ }
+
+ return true;
}
/*
@@ -151,7 +324,7 @@ void trigger_fadump_boot(SpaprMachineState *spapr, target_ulong spapr_retcode)
pause_all_vcpus();
/* Preserve the memory locations registered for fadump */
- if (!fadump_preserve_mem()) {
+ if (!fadump_preserve_mem(spapr)) {
/* Failed to preserve the registered memory regions */
rtas_st(spapr_retcode, 0, RTAS_OUT_HW_ERROR);
--
2.43.5
^ permalink raw reply related [flat|nested] 39+ messages in thread
* [PULL 28/32] hw/ppc: Implement saving CPU state in Fadump
2025-10-23 12:16 [PULL RESEND 00/32] ppc-for-10.2 queue Harsh Prateek Bora
` (26 preceding siblings ...)
2025-10-23 12:16 ` [PULL 27/32] hw/ppc: Preserve memory regions registered for fadump Harsh Prateek Bora
@ 2025-10-23 12:16 ` Harsh Prateek Bora
2025-10-27 13:03 ` Peter Maydell
2025-10-23 12:16 ` [PULL 29/32] hw/ppc: Pass dump-sizes property for fadump in device tree Harsh Prateek Bora
` (4 subsequent siblings)
32 siblings, 1 reply; 39+ messages in thread
From: Harsh Prateek Bora @ 2025-10-23 12:16 UTC (permalink / raw)
To: qemu-devel; +Cc: Aditya Gupta, Sourabh Jain, Shivang Upadhyay
From: Aditya Gupta <adityag@linux.ibm.com>
Kernel expects CPU states/register states in the format mentioned in
"Register Save Area" in PAPR.
The platform (in our case, QEMU) saves each CPU register in the form of
an array of "register entries", the start and end of this array is
signified by "CPUSTRT" and "CPUEND" register entries respectively.
The CPUSTRT and CPUEND register entry also has 4-byte logical CPU ID,
thus storing the CPU ID corresponding to the array of register entries.
Each register, and CPUSTRT, CPUEND has a predefined identifier.
Implement calculating identifier for a given register in
'fadump_str_to_u64', which has been taken from the linux kernel
Similarly GPRs also have predefined identifiers, and a corresponding
64-bit resiter value (split into two 32-bit cells). Implement
calculation of GPR identifiers with 'fadump_gpr_id_to_u64'
PAPR has restrictions on particular order of few registers, and is
free to be in any order for other registers.
Some registers mentioned in PAPR have not been exported as they are not
implemented in QEMU / don't make sense in QEMU.
Implement saving of CPU state according to the PAPR document
Signed-off-by: Aditya Gupta <adityag@linux.ibm.com>
Reviewed-by: Sourabh Jain <sourabhjain@linux.ibm.com>
Tested-by: Shivang Upadhyay <shivangu@linux.ibm.com>
Link: https://lore.kernel.org/qemu-devel/20251021134823.1861675-5-adityag@linux.ibm.com
Signed-off-by: Harsh Prateek Bora <harshpb@linux.ibm.com>
---
include/hw/ppc/spapr_fadump.h | 31 +++
hw/ppc/spapr_fadump.c | 361 +++++++++++++++++++++++++++++++++-
2 files changed, 390 insertions(+), 2 deletions(-)
diff --git a/include/hw/ppc/spapr_fadump.h b/include/hw/ppc/spapr_fadump.h
index 71be2ad92c..fde2830e94 100644
--- a/include/hw/ppc/spapr_fadump.h
+++ b/include/hw/ppc/spapr_fadump.h
@@ -47,9 +47,17 @@
*/
#define FADUMP_MAX_SECTIONS 10
+/* Number of register entries stored per cpu */
+#define FADUMP_PER_CPU_REG_ENTRIES (32 /*GPR*/ + 45 /*others*/ + 2 /*STRT & END*/)
+
+/* Mask of CPU ID in CPUSTRT and CPUEND entries */
+#define FADUMP_CPU_ID_MASK ((1ULL << 32) - 1)
+
typedef struct FadumpSection FadumpSection;
typedef struct FadumpSectionHeader FadumpSectionHeader;
typedef struct FadumpMemStruct FadumpMemStruct;
+typedef struct FadumpRegSaveAreaHeader FadumpRegSaveAreaHeader;
+typedef struct FadumpRegEntry FadumpRegEntry;
struct SpaprMachineState;
@@ -88,6 +96,29 @@ struct FadumpMemStruct {
FadumpSection rgn[FADUMP_MAX_SECTIONS];
};
+/*
+ * The firmware-assisted dump format.
+ *
+ * The register save area is an area in the partition's memory used to preserve
+ * the register contents (CPU state data) for the active CPUs during a firmware
+ * assisted dump. The dump format contains register save area header followed
+ * by register entries. Each list of registers for a CPU starts with "CPUSTRT"
+ * and ends with "CPUEND".
+ */
+
+/* Register save area header. */
+struct FadumpRegSaveAreaHeader {
+ uint64_t magic_number;
+ uint32_t version;
+ uint32_t num_cpu_offset;
+};
+
+/* Register entry. */
+struct FadumpRegEntry {
+ uint64_t reg_id;
+ uint64_t reg_value;
+};
+
uint32_t do_fadump_register(struct SpaprMachineState *, target_ulong);
void trigger_fadump_boot(struct SpaprMachineState *, target_ulong);
#endif /* PPC_SPAPR_FADUMP_H */
diff --git a/hw/ppc/spapr_fadump.c b/hw/ppc/spapr_fadump.c
index 5068a9d83d..fdd4929148 100644
--- a/hw/ppc/spapr_fadump.c
+++ b/hw/ppc/spapr_fadump.c
@@ -9,8 +9,73 @@
#include "hw/ppc/spapr.h"
#include "qemu/units.h"
#include "system/cpus.h"
+#include "system/hw_accel.h"
#include <math.h>
+/*
+ * Copy the ascii values for first 8 characters from a string into u64
+ * variable at their respective indexes.
+ * e.g.
+ * The string "FADMPINF" will be converted into 0x4641444d50494e46
+ */
+static uint64_t fadump_str_to_u64(const char *str)
+{
+ uint64_t val = 0;
+ int i;
+
+ for (i = 0; i < sizeof(val); i++) {
+ val = (*str) ? (val << 8) | *str++ : val << 8;
+ }
+ return val;
+}
+
+/**
+ * Get the identifier id for register entries of GPRs
+ *
+ * It gives the same id as 'fadump_str_to_u64' when the complete string id
+ * of the GPR is given, ie.
+ *
+ * fadump_str_to_u64("GPR05") == fadump_gpr_id_to_u64(5);
+ * fadump_str_to_u64("GPR12") == fadump_gpr_id_to_u64(12);
+ *
+ * And so on. Hence this can be implemented by creating a dynamic
+ * string for each GPR, such as "GPR00", "GPR01", ... "GPR31"
+ * Instead of allocating a string, an observation from the math of
+ * 'fadump_str_to_u64' or from PAPR tells us that there's a pattern
+ * in the identifier IDs, such that the first 4 bytes are affected only by
+ * whether it is GPR0*, GPR1*, GPR2*, GPR3*.
+ * Upper half of 5th byte is always 0x3. Lower half (nibble) of 5th byte
+ * is the tens digit of the GPR id, ie. GPR ID / 10.
+ * Upper half of 6th byte is always 0x3. Lower half (nibble) of 5th byte
+ * is the ones digit of the GPR id, ie. GPR ID % 10
+ *
+ * For example, for GPR 29, the 5th and 6th byte will be 0x32 and 0x39
+ */
+static uint64_t fadump_gpr_id_to_u64(uint32_t gpr_id)
+{
+ uint64_t val = 0;
+
+ /* Valid range of GPR id is only GPR0 to GPR31 */
+ assert(gpr_id < 32);
+
+ /* Below calculations set the 0th to 5th byte */
+ if (gpr_id <= 9) {
+ val = fadump_str_to_u64("GPR0");
+ } else if (gpr_id <= 19) {
+ val = fadump_str_to_u64("GPR1");
+ } else if (gpr_id <= 29) {
+ val = fadump_str_to_u64("GPR2");
+ } else {
+ val = fadump_str_to_u64("GPR3");
+ }
+
+ /* Set the 6th byte */
+ val |= 0x30000000;
+ val |= ((gpr_id % 10) << 24);
+
+ return val;
+}
+
/*
* Handle the "FADUMP_CMD_REGISTER" command in 'ibm,configure-kernel-dump'
*
@@ -243,7 +308,291 @@ static bool do_preserve_region(FadumpSection *region)
return true;
}
-/* Preserve the memory locations registered for fadump */
+/*
+ * Populate the passed CPUs register entries, in the buffer starting at
+ * the argument 'curr_reg_entry'
+ *
+ * The register entries is an array of pair of register id and register
+ * value, as described in Table 591/592 in section "H.1 Register Save Area"
+ * in PAPR v2.13
+ *
+ * Returns pointer just past this CPU's register entries, which can be used
+ * as the start address for next CPU's register entries
+ */
+static FadumpRegEntry *populate_cpu_reg_entries(CPUState *cpu,
+ FadumpRegEntry *curr_reg_entry)
+{
+ CPUPPCState *env;
+ PowerPCCPU *ppc_cpu;
+ uint32_t num_regs_per_cpu = 0;
+
+ ppc_cpu = POWERPC_CPU(cpu);
+ env = cpu_env(cpu);
+ num_regs_per_cpu = 0;
+
+ /*
+ * CPUSTRT and CPUEND register entries follow this format:
+ *
+ * 8 Bytes Reg ID (BE) | 4 Bytes (0x0) | 4 Bytes Logical CPU ID (BE)
+ */
+ curr_reg_entry->reg_id =
+ cpu_to_be64(fadump_str_to_u64("CPUSTRT"));
+ curr_reg_entry->reg_value = cpu_to_be64(
+ ppc_cpu->vcpu_id & FADUMP_CPU_ID_MASK);
+ ++curr_reg_entry;
+
+#define REG_ENTRY(id, val) \
+ do { \
+ curr_reg_entry->reg_id = \
+ cpu_to_be64(fadump_str_to_u64(#id)); \
+ curr_reg_entry->reg_value = cpu_to_be64(val); \
+ ++curr_reg_entry; \
+ ++num_regs_per_cpu; \
+ } while (0)
+
+ REG_ENTRY(ACOP, env->spr[SPR_ACOP]);
+ REG_ENTRY(AMR, env->spr[SPR_AMR]);
+ REG_ENTRY(BESCR, env->spr[SPR_BESCR]);
+ REG_ENTRY(CFAR, env->spr[SPR_CFAR]);
+ REG_ENTRY(CIABR, env->spr[SPR_CIABR]);
+
+ /* Save the condition register */
+ REG_ENTRY(CR, ppc_get_cr(env));
+
+ REG_ENTRY(CTR, env->spr[SPR_CTR]);
+ REG_ENTRY(CTRL, env->spr[SPR_CTRL]);
+ REG_ENTRY(DABR, env->spr[SPR_DABR]);
+ REG_ENTRY(DABRX, env->spr[SPR_DABRX]);
+ REG_ENTRY(DAR, env->spr[SPR_DAR]);
+ REG_ENTRY(DAWR0, env->spr[SPR_DAWR0]);
+ REG_ENTRY(DAWR1, env->spr[SPR_DAWR1]);
+ REG_ENTRY(DAWRX0, env->spr[SPR_DAWRX0]);
+ REG_ENTRY(DAWRX1, env->spr[SPR_DAWRX1]);
+ REG_ENTRY(DPDES, env->spr[SPR_DPDES]);
+ REG_ENTRY(DSCR, env->spr[SPR_DSCR]);
+ REG_ENTRY(DSISR, env->spr[SPR_DSISR]);
+ REG_ENTRY(EBBHR, env->spr[SPR_EBBHR]);
+ REG_ENTRY(EBBRR, env->spr[SPR_EBBRR]);
+
+ REG_ENTRY(FPSCR, env->fpscr);
+ REG_ENTRY(FSCR, env->spr[SPR_FSCR]);
+
+ /* Save the GPRs */
+ for (int gpr_id = 0; gpr_id < 32; ++gpr_id) {
+ curr_reg_entry->reg_id =
+ cpu_to_be64(fadump_gpr_id_to_u64(gpr_id));
+ curr_reg_entry->reg_value =
+ cpu_to_be64(env->gpr[gpr_id]);
+ ++curr_reg_entry;
+ ++num_regs_per_cpu;
+ }
+
+ REG_ENTRY(IAMR, env->spr[SPR_IAMR]);
+ REG_ENTRY(IC, env->spr[SPR_IC]);
+ REG_ENTRY(LR, env->spr[SPR_LR]);
+
+ REG_ENTRY(MSR, env->msr);
+ REG_ENTRY(NIA, env->nip); /* NIA */
+ REG_ENTRY(PIR, env->spr[SPR_PIR]);
+ REG_ENTRY(PSPB, env->spr[SPR_PSPB]);
+ REG_ENTRY(PVR, env->spr[SPR_PVR]);
+ REG_ENTRY(RPR, env->spr[SPR_RPR]);
+ REG_ENTRY(SPURR, env->spr[SPR_SPURR]);
+ REG_ENTRY(SRR0, env->spr[SPR_SRR0]);
+ REG_ENTRY(SRR1, env->spr[SPR_SRR1]);
+ REG_ENTRY(TAR, env->spr[SPR_TAR]);
+ REG_ENTRY(TEXASR, env->spr[SPR_TEXASR]);
+ REG_ENTRY(TFHAR, env->spr[SPR_TFHAR]);
+ REG_ENTRY(TFIAR, env->spr[SPR_TFIAR]);
+ REG_ENTRY(TIR, env->spr[SPR_TIR]);
+ REG_ENTRY(UAMOR, env->spr[SPR_UAMOR]);
+ REG_ENTRY(VRSAVE, env->spr[SPR_VRSAVE]);
+ REG_ENTRY(VSCR, env->vscr);
+ REG_ENTRY(VTB, env->spr[SPR_VTB]);
+ REG_ENTRY(WORT, env->spr[SPR_WORT]);
+ REG_ENTRY(XER, env->spr[SPR_XER]);
+
+ /*
+ * Ignoring transaction checkpoint and few other registers
+ * mentioned in PAPR as not supported in QEMU
+ */
+#undef REG_ENTRY
+
+ /* End the registers for this CPU with "CPUEND" reg entry */
+ curr_reg_entry->reg_id =
+ cpu_to_be64(fadump_str_to_u64("CPUEND"));
+ curr_reg_entry->reg_value = cpu_to_be64(
+ ppc_cpu->vcpu_id & FADUMP_CPU_ID_MASK);
+
+ /*
+ * Ensure number of register entries saved matches the expected
+ * 'FADUMP_PER_CPU_REG_ENTRIES' count
+ *
+ * This will help catch an error if in future a new register entry
+ * is added/removed while not modifying FADUMP_PER_CPU_REG_ENTRIES
+ */
+ assert(FADUMP_PER_CPU_REG_ENTRIES == num_regs_per_cpu + 2 /*CPUSTRT+CPUEND*/);
+
+ ++curr_reg_entry;
+
+ return curr_reg_entry;
+}
+
+/*
+ * Populate the "Register Save Area"/CPU State as mentioned in section "H.1
+ * Register Save Area" in PAPR v2.13
+ *
+ * It allocates the buffer for this region, then populates the register
+ * entries
+ *
+ * Returns the pointer to the buffer (which should be deallocated by the
+ * callers), and sets the size of this buffer in the argument
+ * 'cpu_state_len'
+ */
+static void *get_cpu_state_data(uint64_t *cpu_state_len)
+{
+ FadumpRegSaveAreaHeader reg_save_hdr;
+ FadumpRegEntry *reg_entries;
+ FadumpRegEntry *curr_reg_entry;
+ CPUState *cpu;
+
+ uint32_t num_reg_entries;
+ uint32_t reg_entries_size;
+ uint32_t num_cpus = 0;
+
+ void *cpu_state_buffer = NULL;
+ uint64_t offset = 0;
+
+ CPU_FOREACH(cpu) {
+ ++num_cpus;
+ }
+
+ reg_save_hdr.version = cpu_to_be32(0);
+ reg_save_hdr.magic_number =
+ cpu_to_be64(fadump_str_to_u64("REGSAVE"));
+
+ /* Reg save area header is immediately followed by num cpus */
+ reg_save_hdr.num_cpu_offset =
+ cpu_to_be32(sizeof(FadumpRegSaveAreaHeader));
+
+ num_reg_entries = num_cpus * FADUMP_PER_CPU_REG_ENTRIES;
+ reg_entries_size = num_reg_entries * sizeof(FadumpRegEntry);
+
+ reg_entries = g_new(FadumpRegEntry, num_reg_entries);
+
+ /* Pointer to current CPU's registers */
+ curr_reg_entry = reg_entries;
+
+ /* Populate register entries for all CPUs */
+ CPU_FOREACH(cpu) {
+ cpu_synchronize_state(cpu);
+ curr_reg_entry = populate_cpu_reg_entries(cpu, curr_reg_entry);
+ }
+
+ *cpu_state_len = 0;
+ *cpu_state_len += sizeof(reg_save_hdr); /* reg save header */
+ *cpu_state_len += 0xc; /* padding as in PAPR */
+ *cpu_state_len += sizeof(__be32); /* num_cpus */
+ *cpu_state_len += reg_entries_size; /* reg entries */
+
+ cpu_state_buffer = g_malloc(*cpu_state_len);
+
+ memcpy(cpu_state_buffer + offset,
+ ®_save_hdr, sizeof(reg_save_hdr));
+ offset += sizeof(reg_save_hdr);
+
+ /* Write num_cpus */
+ num_cpus = cpu_to_be32(num_cpus);
+ memcpy(cpu_state_buffer + offset, &num_cpus, sizeof(__be32));
+ offset += sizeof(__be32);
+
+ /* Write the register entries */
+ memcpy(cpu_state_buffer + offset, reg_entries, reg_entries_size);
+ offset += reg_entries_size;
+
+ return cpu_state_buffer;
+}
+
+/*
+ * Save the CPU State Data (aka "Register Save Area") in given region
+ *
+ * Region argument is expected to be of CPU_STATE_DATA type
+ *
+ * Returns false only in case of Hardware Error, such as failure to
+ * read/write a valid address.
+ *
+ * Otherwise, even in case of unsuccessful copy of CPU state data for reasons
+ * such as invalid destination address or non-fatal error errors likely
+ * caused due to invalid parameters, return true and set region->error_flags
+ */
+static bool do_populate_cpu_state(FadumpSection *region)
+{
+ uint64_t dest_addr = be64_to_cpu(region->destination_address);
+ uint64_t cpu_state_len = 0;
+ g_autofree void *cpu_state_buffer = NULL;
+ AddressSpace *default_as = &address_space_memory;
+ MemTxResult io_result;
+ MemTxAttrs attrs;
+
+ assert(region->source_data_type == cpu_to_be16(FADUMP_CPU_STATE_DATA));
+
+ /* Mark the memory transaction as privileged memory access */
+ attrs.user = 0;
+ attrs.memory = 1;
+
+ cpu_state_buffer = get_cpu_state_data(&cpu_state_len);
+
+ io_result = address_space_write(default_as, dest_addr, attrs,
+ cpu_state_buffer, cpu_state_len);
+ if ((io_result & MEMTX_DECODE_ERROR) ||
+ (io_result & MEMTX_ACCESS_ERROR)) {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "FADump: Failed to decode/access address in CPU State Region's"
+ " destination address: 0x%016" PRIx64 "\n", dest_addr);
+
+ /*
+ * Invalid source address is not an hardware error, instead
+ * wrong parameter from the kernel.
+ * Return true to let caller know to continue reading other
+ * sections
+ */
+ region->error_flags = FADUMP_ERROR_INVALID_SOURCE_ADDR;
+ region->bytes_dumped = 0;
+ return true;
+ } else if (io_result != MEMTX_OK) {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "FADump: Failed to write CPU state region.\n");
+
+ return false;
+ }
+
+ /*
+ * Set bytes_dumped in cpu state region, so kernel knows platform have
+ * exported it
+ */
+ region->bytes_dumped = cpu_to_be64(cpu_state_len);
+
+ if (region->source_len != region->bytes_dumped) {
+ /*
+ * Log the error, but don't fail the dump collection here, let
+ * kernel handle the mismatch
+ */
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "FADump: Mismatch in CPU State region's length exported:"
+ " Kernel expected: 0x%" PRIx64 " bytes,"
+ " QEMU exported: 0x%" PRIx64 " bytes\n",
+ be64_to_cpu(region->source_len),
+ be64_to_cpu(region->bytes_dumped));
+ }
+
+ return true;
+}
+
+/*
+ * Preserve the memory locations registered for fadump
+ *
+ * Returns false only in case of RTAS_OUT_HW_ERROR, otherwise true
+ */
static bool fadump_preserve_mem(SpaprMachineState *spapr)
{
FadumpMemStruct *fdm = &spapr->registered_fdm;
@@ -277,7 +626,15 @@ static bool fadump_preserve_mem(SpaprMachineState *spapr)
switch (data_type) {
case FADUMP_CPU_STATE_DATA:
- /* TODO: Add CPU state data */
+ if (!do_populate_cpu_state(&fdm->rgn[i])) {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "FADump: Failed to store CPU State Data");
+ fdm->header.dump_status_flag |=
+ cpu_to_be16(FADUMP_STATUS_DUMP_ERROR);
+
+ return false;
+ }
+
break;
case FADUMP_HPTE_REGION:
/* TODO: Add hpte state data */
--
2.43.5
^ permalink raw reply related [flat|nested] 39+ messages in thread
* [PULL 29/32] hw/ppc: Pass dump-sizes property for fadump in device tree
2025-10-23 12:16 [PULL RESEND 00/32] ppc-for-10.2 queue Harsh Prateek Bora
` (27 preceding siblings ...)
2025-10-23 12:16 ` [PULL 28/32] hw/ppc: Implement saving CPU state in Fadump Harsh Prateek Bora
@ 2025-10-23 12:16 ` Harsh Prateek Bora
2025-10-23 12:16 ` [PULL 30/32] hw/ppc: Enable fadump for PSeries Harsh Prateek Bora
` (3 subsequent siblings)
32 siblings, 0 replies; 39+ messages in thread
From: Harsh Prateek Bora @ 2025-10-23 12:16 UTC (permalink / raw)
To: qemu-devel; +Cc: Aditya Gupta, Sourabh Jain, Shivang Upadhyay
From: Aditya Gupta <adityag@linux.ibm.com>
Platform (ie. QEMU) is expected to pass few device tree properties for
details for fadump:
* "ibm,configure-kernel-dump-sizes": Space required to store dump data
for firmware provided dump sections (ie. CPU & HPTE regions)
* "ibm,configure-kernel-dump-version": Versions of fadump supported
Pass the above device tree nodes so that kernel can reserve sufficient
space for preserving the CPU state data
Signed-off-by: Aditya Gupta <adityag@linux.ibm.com>
Reviewed-by: Sourabh Jain <sourabhjain@linux.ibm.com>
Tested-by: Shivang Upadhyay <shivangu@linux.ibm.com>
Link: https://lore.kernel.org/qemu-devel/20251021134823.1861675-6-adityag@linux.ibm.com
Signed-off-by: Harsh Prateek Bora <harshpb@linux.ibm.com>
---
hw/ppc/spapr.c | 57 +++++++++++++++++++++++++++++++++++++++++++
hw/ppc/spapr_fadump.c | 6 ++---
2 files changed, 60 insertions(+), 3 deletions(-)
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index 117da76a3d..d6cfb9acbc 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -900,6 +900,61 @@ static int spapr_dt_rng(void *fdt)
return ret ? -1 : 0;
}
+static void spapr_dt_rtas_fadump(SpaprMachineState *spapr, void *fdt, int rtas)
+{
+ MachineState *ms = MACHINE(spapr);
+ MachineClass *mc = MACHINE_GET_CLASS(ms);
+
+ uint32_t max_possible_cpus = mc->possible_cpu_arch_ids(ms)->len;
+ uint64_t fadump_cpu_state_size = 0;
+ uint16_t fadump_versions[2] = {
+ FADUMP_VERSION /* min supported version */,
+ FADUMP_VERSION /* max supported version */
+ };
+ uint32_t fadump_rgn_sizes[2][3] = {
+ {
+ cpu_to_be32(FADUMP_CPU_STATE_DATA),
+ 0, 0 /* Calculated later */
+ },
+ {
+ cpu_to_be32(FADUMP_HPTE_REGION),
+ 0, 0 /* HPTE region not implemented */
+ }
+ };
+
+ /*
+ * CPU State Data contains multiple fields such as header, num_cpus and
+ * register entries
+ *
+ * Calculate the maximum CPU State Data size, according to maximum
+ * possible CPUs the QEMU VM can have
+ *
+ * This calculation must match the 'cpu_state_len' calculation done in
+ * 'populate_cpu_state_data' in spapr_fadump.c
+ */
+ fadump_cpu_state_size += sizeof(struct FadumpRegSaveAreaHeader);
+ fadump_cpu_state_size += 0xc; /* padding as in PAPR */
+ fadump_cpu_state_size += sizeof(uint32_t); /* num_cpus */
+ fadump_cpu_state_size += max_possible_cpus * /* reg entries */
+ FADUMP_PER_CPU_REG_ENTRIES *
+ sizeof(struct FadumpRegEntry);
+
+ /* Set maximum size for CPU state data region */
+ assert(fadump_rgn_sizes[0][0] == cpu_to_be32(FADUMP_CPU_STATE_DATA));
+
+ /* Upper 32 bits of size, usually 0 */
+ fadump_rgn_sizes[0][1] = cpu_to_be32(fadump_cpu_state_size >> 32);
+
+ /* Lower 32 bits of size */
+ fadump_rgn_sizes[0][2] = cpu_to_be32(fadump_cpu_state_size & 0xffffffff);
+
+ /* Add device tree properties required from platform for fadump */
+ _FDT((fdt_setprop(fdt, rtas, "ibm,configure-kernel-dump-version",
+ fadump_versions, sizeof(fadump_versions))));
+ _FDT((fdt_setprop(fdt, rtas, "ibm,configure-kernel-dump-sizes",
+ fadump_rgn_sizes, sizeof(fadump_rgn_sizes))));
+}
+
static void spapr_dt_rtas(SpaprMachineState *spapr, void *fdt)
{
MachineState *ms = MACHINE(spapr);
@@ -1015,6 +1070,8 @@ static void spapr_dt_rtas(SpaprMachineState *spapr, void *fdt)
_FDT(fdt_setprop(fdt, rtas, "ibm,lrdr-capacity",
lrdr_capacity, sizeof(lrdr_capacity)));
+ spapr_dt_rtas_fadump(spapr, fdt, rtas);
+
spapr_dt_rtas_tokens(fdt, rtas);
}
diff --git a/hw/ppc/spapr_fadump.c b/hw/ppc/spapr_fadump.c
index fdd4929148..fa3aeac94c 100644
--- a/hw/ppc/spapr_fadump.c
+++ b/hw/ppc/spapr_fadump.c
@@ -492,7 +492,7 @@ static void *get_cpu_state_data(uint64_t *cpu_state_len)
*cpu_state_len = 0;
*cpu_state_len += sizeof(reg_save_hdr); /* reg save header */
*cpu_state_len += 0xc; /* padding as in PAPR */
- *cpu_state_len += sizeof(__be32); /* num_cpus */
+ *cpu_state_len += sizeof(num_cpus); /* num_cpus */
*cpu_state_len += reg_entries_size; /* reg entries */
cpu_state_buffer = g_malloc(*cpu_state_len);
@@ -503,8 +503,8 @@ static void *get_cpu_state_data(uint64_t *cpu_state_len)
/* Write num_cpus */
num_cpus = cpu_to_be32(num_cpus);
- memcpy(cpu_state_buffer + offset, &num_cpus, sizeof(__be32));
- offset += sizeof(__be32);
+ memcpy(cpu_state_buffer + offset, &num_cpus, sizeof(num_cpus));
+ offset += sizeof(num_cpus);
/* Write the register entries */
memcpy(cpu_state_buffer + offset, reg_entries, reg_entries_size);
--
2.43.5
^ permalink raw reply related [flat|nested] 39+ messages in thread
* [PULL 30/32] hw/ppc: Enable fadump for PSeries
2025-10-23 12:16 [PULL RESEND 00/32] ppc-for-10.2 queue Harsh Prateek Bora
` (28 preceding siblings ...)
2025-10-23 12:16 ` [PULL 29/32] hw/ppc: Pass dump-sizes property for fadump in device tree Harsh Prateek Bora
@ 2025-10-23 12:16 ` Harsh Prateek Bora
2025-10-23 12:16 ` [PULL 31/32] tests/functional: Add test for fadump in PSeries Harsh Prateek Bora
` (2 subsequent siblings)
32 siblings, 0 replies; 39+ messages in thread
From: Harsh Prateek Bora @ 2025-10-23 12:16 UTC (permalink / raw)
To: qemu-devel; +Cc: Aditya Gupta, Sourabh Jain, Shivang Upadhyay
From: Aditya Gupta <adityag@linux.ibm.com>
With all support in place for preserving memory regions, enable fadump by
exporting the "ibm,kernel-dump" property in the device tree, representing
the fadump dump information, in case of a crash.
Currently "ibm,configure-kernel-dump" RTAS call is already registered,
which tells the kernel that the platform (QEMU) supports fadump.
Now, in case of a crash, if fadump was registered, we also pass
"ibm,kernel-dump" in device tree, which tells the kernel that the fadump
dump is active.
Pass "fadump=on" to enable Linux to use firmware assisted dump.
Logs of a linux boot with firmware assisted dump:
$ ./build/qemu-system-ppc64 -M pseries,x-vof=on --cpu power10 --smp 4 -m 4G -kernel some-vmlinux -initrd some-initrd -append "debug fadump=on crashkernel=1G" -nographic
[ 0.000000] fadump: Reserved 1024MB of memory at 0x00000040000000 (System RAM: 4096MB)
[ 0.000000] fadump: Initialized 0x40000000 bytes cma area at 1024MB from 0x400102a8 bytes of memory reserved for firmware-assisted dump
...
[ 1.084686] rtas fadump: Registration is successful!
...
# cat /sys/kernel/debug/powerpc/fadump_region
CPU :[0x00000040000000-0x000000400013df] 0x13e0 bytes, Dumped: 0x0
HPTE:[0x000000400013e0-0x000000400013df] 0x0 bytes, Dumped: 0x0
DUMP: Src: 0x00000000000000, Dest: 0x00000040010000, Size: 0x40000000, Dumped: 0x0 bytes
[0x0000000921a000-0x0000000921a7ff]: cmdline append: ''
# echo c > /proc/sysrq-trigger
The fadump boot after crash:
[ 0.000000] rtas fadump: Firmware-assisted dump is active.
[ 0.000000] fadump: Updated cmdline: debug fadump=on crashkernel=1G
[ 0.000000] fadump: Firmware-assisted dump is active.
[ 0.000000] fadump: Reserving 3072MB of memory at 0x00000040000000 for preserving crash data
....
# file /proc/vmcore
/proc/vmcore: ELF 64-bit LSB core file, 64-bit PowerPC or cisco 7500, OpenPOWER ELF V2 ABI, version 1 (SYSV), SVR4-style
Analysing the vmcore with crash-utility:
KERNEL: vmlinux-6.14-rc2
DUMPFILE: vmcore-fc92fb373aa0
CPUS: 4
DATE: Wed Mar 12 23:39:23 CDT 2025
UPTIME: 00:00:22
LOAD AVERAGE: 0.13, 0.03, 0.01
TASKS: 95
NODENAME: buildroot
RELEASE: 6.12.0-rc4+
VERSION: #1 SMP Fri Jan 3 00:15:17 IST 2025
MACHINE: ppc64le (1000 Mhz)
MEMORY: 4 GB
PANIC: "Kernel panic - not syncing: sysrq triggered crash"
PID: 269
COMMAND: "sh"
TASK: c00000000a050b00 [THREAD_INFO: c00000000a050b00]
CPU: 0
STATE: TASK_RUNNING (PANIC)
Signed-off-by: Aditya Gupta <adityag@linux.ibm.com>
Reviewed-by: Sourabh Jain <sourabhjain@linux.ibm.com>
Tested-by: Shivang Upadhyay <shivangu@linux.ibm.com>
Link: https://lore.kernel.org/qemu-devel/20251021134823.1861675-7-adityag@linux.ibm.com
Signed-off-by: Harsh Prateek Bora <harshpb@linux.ibm.com>
---
hw/ppc/spapr.c | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index d6cfb9acbc..6764730beb 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -904,6 +904,8 @@ static void spapr_dt_rtas_fadump(SpaprMachineState *spapr, void *fdt, int rtas)
{
MachineState *ms = MACHINE(spapr);
MachineClass *mc = MACHINE_GET_CLASS(ms);
+ FadumpMemStruct *fdm = &spapr->registered_fdm;
+ uint16_t dump_status_flag;
uint32_t max_possible_cpus = mc->possible_cpu_arch_ids(ms)->len;
uint64_t fadump_cpu_state_size = 0;
@@ -953,6 +955,16 @@ static void spapr_dt_rtas_fadump(SpaprMachineState *spapr, void *fdt, int rtas)
fadump_versions, sizeof(fadump_versions))));
_FDT((fdt_setprop(fdt, rtas, "ibm,configure-kernel-dump-sizes",
fadump_rgn_sizes, sizeof(fadump_rgn_sizes))));
+
+ dump_status_flag = be16_to_cpu(fdm->header.dump_status_flag);
+ if (dump_status_flag & FADUMP_STATUS_DUMP_TRIGGERED) {
+ uint64_t fdm_size =
+ sizeof(struct FadumpSectionHeader) +
+ (be16_to_cpu(fdm->header.dump_num_sections) *
+ sizeof(struct FadumpSection));
+
+ _FDT((fdt_setprop(fdt, rtas, "ibm,kernel-dump", fdm, fdm_size)));
+ }
}
static void spapr_dt_rtas(SpaprMachineState *spapr, void *fdt)
--
2.43.5
^ permalink raw reply related [flat|nested] 39+ messages in thread
* [PULL 31/32] tests/functional: Add test for fadump in PSeries
2025-10-23 12:16 [PULL RESEND 00/32] ppc-for-10.2 queue Harsh Prateek Bora
` (29 preceding siblings ...)
2025-10-23 12:16 ` [PULL 30/32] hw/ppc: Enable fadump for PSeries Harsh Prateek Bora
@ 2025-10-23 12:16 ` Harsh Prateek Bora
2025-10-23 12:16 ` [PULL 32/32] MAINTAINERS: Add entry for FADump (pSeries) Harsh Prateek Bora
2025-10-23 19:33 ` [PULL RESEND 00/32] ppc-for-10.2 queue Richard Henderson
32 siblings, 0 replies; 39+ messages in thread
From: Harsh Prateek Bora @ 2025-10-23 12:16 UTC (permalink / raw)
To: qemu-devel; +Cc: Aditya Gupta, Shivang Upadhyay
From: Aditya Gupta <adityag@linux.ibm.com>
Add testcases for testing fadump with PSeries and PSeries+KVM
combinations
It tests if fadump is successfully detected and registered in the first
kernel boot. Then crashes the kernel, and verifies whether we have a
/proc/vmcore in the 2nd boot
Also introduce 'wait_for_regex_console_pattern' to check for cases where
there is a single success message, but can have multiple failure
messages.
This is particularly useful for cases such as fadump, where the
success message is
"Reserved 1024MB ... successfully"
But at the same point, it can fail with multiple errors such as
"Not supported" or "Allocation failed"
'wait_for_regex_console_pattern' also has a timeout, for cases when we
know the success/failure should appear in a short amount of time,
instead of waiting for the much longer test timeout, such as kernels
with support of fadump will print the success/failure in earlyboot of
the kernel, while kernel without support of fadump won't print anything
for long time, and without a timeout the testcase keeps waiting till
longer test timeout
Signed-off-by: Aditya Gupta <adityag@linux.ibm.com>
Tested-by: Shivang Upadhyay <shivangu@linux.ibm.com>
Link: https://lore.kernel.org/qemu-devel/20251021134823.1861675-8-adityag@linux.ibm.com
Signed-off-by: Harsh Prateek Bora <harshpb@linux.ibm.com>
---
tests/functional/ppc64/meson.build | 2 +
tests/functional/ppc64/test_fadump.py | 182 ++++++++++++++++++++++
tests/functional/qemu_test/linuxkernel.py | 59 +++++++
3 files changed, 243 insertions(+)
create mode 100755 tests/functional/ppc64/test_fadump.py
diff --git a/tests/functional/ppc64/meson.build b/tests/functional/ppc64/meson.build
index 1fa0a70f7e..f0f8ab8f61 100644
--- a/tests/functional/ppc64/meson.build
+++ b/tests/functional/ppc64/meson.build
@@ -1,6 +1,7 @@
# SPDX-License-Identifier: GPL-2.0-or-later
test_ppc64_timeouts = {
+ 'fadump' : 480,
'hv' : 1000,
'mac99' : 120,
'powernv' : 480,
@@ -16,6 +17,7 @@ tests_ppc64_system_quick = [
tests_ppc64_system_thorough = [
'e500',
+ 'fadump',
'hv',
'mac99',
'powernv',
diff --git a/tests/functional/ppc64/test_fadump.py b/tests/functional/ppc64/test_fadump.py
new file mode 100755
index 0000000000..2d6b8017e8
--- /dev/null
+++ b/tests/functional/ppc64/test_fadump.py
@@ -0,0 +1,182 @@
+#!/usr/bin/env python3
+#
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+from unittest import skip
+from qemu_test import Asset
+from qemu_test import wait_for_console_pattern
+from qemu_test import LinuxKernelTest
+from qemu_test import exec_command, exec_command_and_wait_for_pattern
+
+class QEMUFadump(LinuxKernelTest):
+ """
+ Functional test to verify Fadump is working in following scenarios:
+
+ 1. test_fadump_pseries: PSeries
+ 2. test_fadump_pseries_kvm: PSeries + KVM
+ """
+
+ timeout = 90
+ KERNEL_COMMON_COMMAND_LINE = 'console=hvc0 fadump=on '
+ msg_panic = 'Kernel panic - not syncing'
+ msg_not_supported = 'Firmware-Assisted Dump is not supported on this hardware'
+ msg_registered_success = ''
+ msg_registered_failed = ''
+ msg_dump_active = ''
+
+ ASSET_EPAPR_KERNEL = Asset(
+ ('https://github.com/open-power/op-build/releases/download/v2.7/'
+ 'zImage.epapr'),
+ '0ab237df661727e5392cee97460e8674057a883c5f74381a128fa772588d45cd')
+
+ ASSET_VMLINUZ_KERNEL = Asset(
+ ('https://archives.fedoraproject.org/pub/archive/fedora-secondary/'
+ 'releases/39/Everything/ppc64le/os/ppc/ppc64/vmlinuz'),
+ ('81e5541d243b50c8f9568906c6918dda22239744d637bb9a7b22d23c3d661226'
+ '8d5302beb2ca5c06f93bdbc9736c414ef5120756c8bf496ff488ad07d116d67f')
+ )
+
+ ASSET_FEDORA_INITRD = Asset(
+ ('https://archives.fedoraproject.org/pub/archive/fedora-secondary/'
+ 'releases/39/Everything/ppc64le/os/ppc/ppc64/initrd.img'),
+ 'e7f24b44cb2aaa67d30e551db6ac8d29cc57c934b158dabca6b7f885f2cfdd9b')
+
+ def do_test_fadump(self, is_kvm=False, is_powernv=False):
+ """
+ Helper Function for Fadump tests below
+
+ It boots the VM with fadump enabled, checks if fadump is correctly
+ registered.
+ Then crashes the system causing a QEMU_SYSTEM_RESET, after which
+ dump should be available in the kernel.
+ Finally it checks the filesize of the exported /proc/vmcore in 2nd
+ kernel to verify it's same as the VM's memory size
+ """
+ if is_kvm:
+ self.require_accelerator("kvm")
+ self.vm.add_args("-accel", "kvm")
+ else:
+ self.require_accelerator("tcg")
+
+ if is_powernv:
+ self.set_machine("powernv10")
+ else:
+ # SLOF takes upto >20s in startup time, use VOF
+ self.set_machine("pseries")
+ self.vm.add_args("-machine", "x-vof=on")
+ self.vm.add_args("-m", "6G")
+
+ self.vm.set_console()
+
+ kernel_path = None
+
+ if is_powernv:
+ kernel_path = self.ASSET_EPAPR_KERNEL.fetch()
+ else:
+ kernel_path = self.ASSET_VMLINUZ_KERNEL.fetch()
+
+ initrd_path = self.ASSET_FEDORA_INITRD.fetch()
+
+ self.vm.add_args('-kernel', kernel_path)
+ self.vm.add_args('-initrd', initrd_path)
+ self.vm.add_args('-append', "fadump=on"\
+ " -nodefaults -serial mon:stdio crashkernel=2G"\
+ " rdinit=/bin/sh ")
+
+ self.vm.launch()
+
+ # If kernel detects fadump support, and "fadump=on" is in command
+ # line which we add above, it will print something like:
+ #
+ # fadump: Reserved 1024MB of memory at 0x00000040000000 ...
+ #
+ # Else, if the kernel doesn't detect fadump support, it prints:
+ #
+ # fadump: Firmware-Assisted Dump is not supported on this hardware
+ #
+ # Timeout after 20s if kernel doesn't print any fadump logs, this
+ # can happen due to fadump being disabled in the kernel
+ self.wait_for_regex_console_pattern(
+ success_pattern="fadump: Reserved ",
+ failure_pattern=r"fadump: (Firmware-Assisted Dump is not"\
+ " supported on this hardware|Failed to find memory chunk for"\
+ " reservation!)",
+ timeout=20
+ )
+
+ # Ensure fadump is registered successfully, if registration
+ # succeeds, we get a log from rtas fadump:
+ #
+ # rtas fadump: Registration is successful!
+ self.wait_for_console_pattern(
+ "rtas fadump: Registration is successful!"
+ )
+
+ # Wait for the shell
+ self.wait_for_console_pattern("#")
+
+ # Mount /proc since not available in the initrd used
+ exec_command(self, command="mount -t proc proc /proc")
+
+ # Crash the kernel
+ exec_command(self, command="echo c > /proc/sysrq-trigger")
+
+ # Check for the kernel panic message, setting timeout to 20s as it
+ # should occur almost immediately after previous echo c
+ self.wait_for_regex_console_pattern(
+ success_pattern="Kernel panic - not syncing: sysrq" \
+ " triggered crash",
+ timeout=20
+ )
+
+ # Check if fadump is active
+ # If the kernel shows that fadump is active, that implies it's a
+ # crashkernel boot
+ # Else if the kernel shows "fadump: Reserved ..." then it's
+ # treating this as the first kernel boot, this is likely the case
+ # that qemu didn't pass the 'ibm,kernel-dump' device tree node
+ wait_for_console_pattern(
+ test=self,
+ success_message="rtas fadump: Firmware-assisted dump is active",
+ failure_message="fadump: Reserved "
+ )
+
+ # In a successful fadump boot, we get these logs:
+ #
+ # [ 0.000000] fadump: Firmware-assisted dump is active.
+ # [ 0.000000] fadump: Reserving <>MB of memory at <> for preserving crash data
+ #
+ # Check if these logs are present in the fadump boot
+ self.wait_for_console_pattern("preserving crash data")
+
+ # Wait for prompt
+ self.wait_for_console_pattern("sh-5.2#")
+
+ # Mount /proc since not available in the initrd used
+ exec_command_and_wait_for_pattern(self,
+ command="mount -t proc proc /proc",
+ success_message="#"
+ )
+
+ # Check if vmcore exists
+ exec_command_and_wait_for_pattern(self,
+ command="stat /proc/vmcore",
+ success_message="File: /proc/vmcore",
+ failure_message="No such file or directory"
+ )
+
+ def test_fadump_pseries(self):
+ return self.do_test_fadump(is_kvm=False, is_powernv=False)
+
+ @skip("PowerNV Fadump not supported yet")
+ def test_fadump_powernv(self):
+ return
+
+ def test_fadump_pseries_kvm(self):
+ """
+ Test Fadump in PSeries with KVM accel
+ """
+ self.do_test_fadump(is_kvm=True, is_powernv=False)
+
+if __name__ == '__main__':
+ QEMUFadump.main()
diff --git a/tests/functional/qemu_test/linuxkernel.py b/tests/functional/qemu_test/linuxkernel.py
index 2aca0ee3cd..c4767527da 100644
--- a/tests/functional/qemu_test/linuxkernel.py
+++ b/tests/functional/qemu_test/linuxkernel.py
@@ -5,6 +5,9 @@
import hashlib
import urllib.request
+import logging
+import re
+import time
from .cmd import wait_for_console_pattern, exec_command_and_wait_for_pattern
from .testcase import QemuSystemTest
@@ -19,6 +22,62 @@ def wait_for_console_pattern(self, success_message, vm=None):
failure_message='Kernel panic - not syncing',
vm=vm)
+ def wait_for_regex_console_pattern(self, success_pattern,
+ failure_pattern=None,
+ timeout=None):
+ """
+ Similar to 'wait_for_console_pattern', but supports regex patterns,
+ hence multiple failure/success patterns can be detected at a time.
+
+ Args:
+ success_pattern (str | re.Pattern): A regex pattern that indicates
+ a successful event. If found, the method exits normally.
+ failure_pattern (str | re.Pattern, optional): A regex pattern that
+ indicates a failure event. If found, the test fails
+ timeout (int, optional): The maximum time (in seconds) to wait for
+ a match.
+ If exceeded, the test fails.
+ """
+
+ console = self.vm.console_file
+ console_logger = logging.getLogger('console')
+
+ self.log.debug(
+ f"Console interaction: success_msg='{success_pattern}' " +
+ f"failure_msg='{failure_pattern}' timeout='{timeout}s'")
+
+ # Only consume console output if waiting for something
+ if success_pattern is None and failure_pattern is None:
+ return
+
+ start_time = time.time()
+
+ while time.time() - start_time < timeout:
+ try:
+ msg = console.readline().decode().strip()
+ except UnicodeDecodeError:
+ msg = None
+ if not msg:
+ continue
+ console_logger.debug(msg)
+ if success_pattern is None or re.search(success_pattern, msg):
+ break
+ if failure_pattern:
+ # Find the matching error to print in log
+ match = re.search(failure_pattern, msg)
+ if not match:
+ continue
+
+ console.close()
+ fail = 'Failure message found in console: "%s".' \
+ ' Expected: "%s"' % \
+ (match.group(), success_pattern)
+ self.fail(fail)
+
+ if time.time() - start_time >= timeout:
+ fail = f"Timeout ({timeout}s) while trying to search pattern"
+ self.fail(fail)
+
def launch_kernel(self, kernel, initrd=None, dtb=None, console_index=0,
wait_for=None):
self.vm.set_console(console_index=console_index)
--
2.43.5
^ permalink raw reply related [flat|nested] 39+ messages in thread
* [PULL 32/32] MAINTAINERS: Add entry for FADump (pSeries)
2025-10-23 12:16 [PULL RESEND 00/32] ppc-for-10.2 queue Harsh Prateek Bora
` (30 preceding siblings ...)
2025-10-23 12:16 ` [PULL 31/32] tests/functional: Add test for fadump in PSeries Harsh Prateek Bora
@ 2025-10-23 12:16 ` Harsh Prateek Bora
2025-10-23 19:33 ` [PULL RESEND 00/32] ppc-for-10.2 queue Richard Henderson
32 siblings, 0 replies; 39+ messages in thread
From: Harsh Prateek Bora @ 2025-10-23 12:16 UTC (permalink / raw)
To: qemu-devel; +Cc: Aditya Gupta, Sourabh Jain, Shivang Upadhyay
From: Aditya Gupta <adityag@linux.ibm.com>
Add maintainer and reviewer for fadump subsystem.
Signed-off-by: Aditya Gupta <adityag@linux.ibm.com>
Acked-by: Sourabh Jain <sourabhjain@linux.ibm.com>
Tested-by: Shivang Upadhyay <shivangu@linux.ibm.com>
Link: https://lore.kernel.org/qemu-devel/20251021134823.1861675-9-adityag@linux.ibm.com
Signed-off-by: Harsh Prateek Bora <harshpb@linux.ibm.com>
---
MAINTAINERS | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/MAINTAINERS b/MAINTAINERS
index 684d7a5b37..53dbf915ea 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -3215,6 +3215,14 @@ F: scripts/coccinelle/remove_local_err.cocci
F: scripts/coccinelle/use-error_fatal.cocci
F: scripts/coccinelle/errp-guard.cocci
+Firmware Assisted Dump (fadump) for sPAPR (pseries)
+M: Aditya Gupta <adityag@linux.ibm.com>
+R: Sourabh Jain <sourabhjain@linux.ibm.com>
+S: Maintained
+F: include/hw/ppc/spapr_fadump.h
+F: hw/ppc/spapr_fadump.c
+F: tests/functional/ppc64/test_fadump.py
+
GDB stub
M: Alex Bennée <alex.bennee@linaro.org>
R: Philippe Mathieu-Daudé <philmd@linaro.org>
--
2.43.5
^ permalink raw reply related [flat|nested] 39+ messages in thread
* Re: [PULL RESEND 00/32] ppc-for-10.2 queue
2025-10-23 12:16 [PULL RESEND 00/32] ppc-for-10.2 queue Harsh Prateek Bora
` (31 preceding siblings ...)
2025-10-23 12:16 ` [PULL 32/32] MAINTAINERS: Add entry for FADump (pSeries) Harsh Prateek Bora
@ 2025-10-23 19:33 ` Richard Henderson
32 siblings, 0 replies; 39+ messages in thread
From: Richard Henderson @ 2025-10-23 19:33 UTC (permalink / raw)
To: qemu-devel
On 10/23/25 07:16, Harsh Prateek Bora wrote:
> The following changes since commit c0e80879c876cbe4cbde43a92403329bcedf2ba0:
>
> Merge tag 'pull-vfio-20251022' ofhttps://github.com/legoater/qemu into staging (2025-10-22 08:01:21 -0500)
>
> are available in the Git repository at:
>
> https://gitlab.com/harshpb/qemu.git tags/pull-ppc-for-10.2-d2-20251023-1
>
> for you to fetch changes up to 3db841bf1194b2720a08df2ee0a6ca517091ad0e:
>
> MAINTAINERS: Add entry for FADump (pSeries) (2025-10-23 17:37:42 +0530)
>
> ----------------------------------------------------------------
> ppc queue for 10.2
>
> * FADUMP Support for pSeries
> * Pegasos II cleanup and Pegasos I emulation
> * Deprecation of pseries 3.0 up till 4.2
> * Coverity fix for amigaone (CID: 1641398)
Applied, thanks. Please update https://wiki.qemu.org/ChangeLog/10.2 as appropriate.
r~
^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: [PULL 28/32] hw/ppc: Implement saving CPU state in Fadump
2025-10-23 12:16 ` [PULL 28/32] hw/ppc: Implement saving CPU state in Fadump Harsh Prateek Bora
@ 2025-10-27 13:03 ` Peter Maydell
0 siblings, 0 replies; 39+ messages in thread
From: Peter Maydell @ 2025-10-27 13:03 UTC (permalink / raw)
To: Harsh Prateek Bora
Cc: qemu-devel, Aditya Gupta, Sourabh Jain, Shivang Upadhyay
On Thu, 23 Oct 2025 at 13:23, Harsh Prateek Bora <harshpb@linux.ibm.com> wrote:
>
> From: Aditya Gupta <adityag@linux.ibm.com>
>
> Kernel expects CPU states/register states in the format mentioned in
> "Register Save Area" in PAPR.
>
> The platform (in our case, QEMU) saves each CPU register in the form of
> an array of "register entries", the start and end of this array is
> signified by "CPUSTRT" and "CPUEND" register entries respectively.
>
> The CPUSTRT and CPUEND register entry also has 4-byte logical CPU ID,
> thus storing the CPU ID corresponding to the array of register entries.
>
> Each register, and CPUSTRT, CPUEND has a predefined identifier.
> Implement calculating identifier for a given register in
> 'fadump_str_to_u64', which has been taken from the linux kernel
>
> Similarly GPRs also have predefined identifiers, and a corresponding
> 64-bit resiter value (split into two 32-bit cells). Implement
> calculation of GPR identifiers with 'fadump_gpr_id_to_u64'
>
> PAPR has restrictions on particular order of few registers, and is
> free to be in any order for other registers.
> Some registers mentioned in PAPR have not been exported as they are not
> implemented in QEMU / don't make sense in QEMU.
>
> Implement saving of CPU state according to the PAPR document
Hi; Coverity points out what looks like a memory leak in this
code (CID 1642024):
> +static void *get_cpu_state_data(uint64_t *cpu_state_len)
> +{
> + FadumpRegSaveAreaHeader reg_save_hdr;
> + FadumpRegEntry *reg_entries;
> + FadumpRegEntry *curr_reg_entry;
> + CPUState *cpu;
> +
> + uint32_t num_reg_entries;
> + uint32_t reg_entries_size;
> + uint32_t num_cpus = 0;
> +
> + void *cpu_state_buffer = NULL;
> + uint64_t offset = 0;
> +
> + CPU_FOREACH(cpu) {
> + ++num_cpus;
> + }
> +
> + reg_save_hdr.version = cpu_to_be32(0);
> + reg_save_hdr.magic_number =
> + cpu_to_be64(fadump_str_to_u64("REGSAVE"));
> +
> + /* Reg save area header is immediately followed by num cpus */
> + reg_save_hdr.num_cpu_offset =
> + cpu_to_be32(sizeof(FadumpRegSaveAreaHeader));
> +
> + num_reg_entries = num_cpus * FADUMP_PER_CPU_REG_ENTRIES;
> + reg_entries_size = num_reg_entries * sizeof(FadumpRegEntry);
> +
> + reg_entries = g_new(FadumpRegEntry, num_reg_entries);
Here we allocate memory into reg_entries...
> +
> + /* Pointer to current CPU's registers */
> + curr_reg_entry = reg_entries;
> +
> + /* Populate register entries for all CPUs */
> + CPU_FOREACH(cpu) {
> + cpu_synchronize_state(cpu);
> + curr_reg_entry = populate_cpu_reg_entries(cpu, curr_reg_entry);
> + }
...then we populate reg_entries with data...
> +
> + *cpu_state_len = 0;
> + *cpu_state_len += sizeof(reg_save_hdr); /* reg save header */
> + *cpu_state_len += 0xc; /* padding as in PAPR */
> + *cpu_state_len += sizeof(__be32); /* num_cpus */
> + *cpu_state_len += reg_entries_size; /* reg entries */
> +
> + cpu_state_buffer = g_malloc(*cpu_state_len);
> +
> + memcpy(cpu_state_buffer + offset,
> + ®_save_hdr, sizeof(reg_save_hdr));
> + offset += sizeof(reg_save_hdr);
> +
> + /* Write num_cpus */
> + num_cpus = cpu_to_be32(num_cpus);
> + memcpy(cpu_state_buffer + offset, &num_cpus, sizeof(__be32));
> + offset += sizeof(__be32);
> +
> + /* Write the register entries */
> + memcpy(cpu_state_buffer + offset, reg_entries, reg_entries_size);
> + offset += reg_entries_size;
...and then we eventually copy the reg_entries data into
the cpu_state_buffer. But then we never free reg_entries.
g_autofree would fix this.
> +
> + return cpu_state_buffer;
> +}
thanks
-- PMM
^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: [PULL 27/32] hw/ppc: Preserve memory regions registered for fadump
2025-10-23 12:16 ` [PULL 27/32] hw/ppc: Preserve memory regions registered for fadump Harsh Prateek Bora
@ 2025-10-27 13:06 ` Peter Maydell
0 siblings, 0 replies; 39+ messages in thread
From: Peter Maydell @ 2025-10-27 13:06 UTC (permalink / raw)
To: Harsh Prateek Bora
Cc: qemu-devel, Aditya Gupta, Sourabh Jain, Shivang Upadhyay
On Thu, 23 Oct 2025 at 13:25, Harsh Prateek Bora <harshpb@linux.ibm.com> wrote:
>
> From: Aditya Gupta <adityag@linux.ibm.com>
>
> While the first kernel boots, it registers memory regions for fadump
> such as:
> * CPU state data (has to be populated by the platform)
> * HPTE state data (has to be populated by the platform)
> * Real Mode Regions (platform should copy it to requested
> destination addresses)
> * OS defined regions (such as parameter save area)
>
> Platform is also expected to modify the 'bytes_dumped' to the length of
> data preserved/copied by platform (ideally same as the source length
> passed by kernel).
>
> The kernel passes source address and length for the memory regions, and
> a destination address to where the memory is to be copied.
>
> Implement the preserving/copying of the Real Mode Regions and the
> Parameter Save Area in QEMU Pseries
>
> The regions are copied in chunks instead of copying all at once.
Hi; Coverity notes a bug in this code (CID 1642026):
> +static bool do_preserve_region(FadumpSection *region)
> +{
> + AddressSpace *default_as = &address_space_memory;
> + MemTxResult io_result;
> + MemTxAttrs attrs;
> + uint64_t src_addr, src_len, dest_addr;
> + uint64_t num_chunks;
> + g_autofree void *copy_buffer = NULL;
> +
> + src_addr = be64_to_cpu(region->source_address);
> + src_len = be64_to_cpu(region->source_len);
> + dest_addr = be64_to_cpu(region->destination_address);
> +
> + /* Mark the memory transaction as privileged memory access */
> + attrs.user = 0;
> + attrs.memory = 1;
> +
> + /*
> + * Optimisation: Skip copy if source and destination are same
> + * (eg. param area)
> + */
> + if (src_addr == dest_addr) {
> + region->bytes_dumped = cpu_to_be64(src_len);
> + return true;
> + }
> +
> +#define FADUMP_CHUNK_SIZE ((size_t)(32 * MiB))
> + copy_buffer = g_try_malloc(FADUMP_CHUNK_SIZE);
> + if (copy_buffer == NULL) {
> + qemu_log_mask(LOG_GUEST_ERROR,
> + "FADump: Failed allocating memory (size: %zu) for copying"
> + " reserved memory regions\n", FADUMP_CHUNK_SIZE);
> + }
Here we do a might-fail malloc, and check for error. But the
error case doesn't return, so after logging the error
execution will keep going in the function and segfault
when we try to use the NULL pointer as a destination buffer.
thanks
-- PMM
^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: [PULL 15/32] hw/ppc/pegasos2: Change device tree generation
2025-10-23 12:16 ` [PULL 15/32] hw/ppc/pegasos2: Change device tree generation Harsh Prateek Bora
@ 2025-10-27 13:14 ` Peter Maydell
2025-10-30 9:06 ` Harsh Prateek Bora
0 siblings, 1 reply; 39+ messages in thread
From: Peter Maydell @ 2025-10-27 13:14 UTC (permalink / raw)
To: Harsh Prateek Bora
Cc: qemu-devel, BALATON Zoltan, Philippe Mathieu-Daudé
On Thu, 23 Oct 2025 at 13:22, Harsh Prateek Bora <harshpb@linux.ibm.com> wrote:
>
> From: BALATON Zoltan <balaton@eik.bme.hu>
>
> We generate a flattened device tree programmatically for VOF. Change
> this to load the static parts from a device tree blob and only
> generate the parts that depend on run time conditions such as CPU
> type, memory size and PCI devices. Moving the static parts in a dts
> makes the board code simpler and more generic.
>
> Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>
> Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
> Link: https://lore.kernel.org/qemu-devel/383891fc2696609b27d2de9773efe1b4f493e333.1761176219.git.balaton@eik.bme.hu
> Signed-off-by: Harsh Prateek Bora <harshpb@linux.ibm.com>
Hi; Coverity points out (CID 1642027) that this change
accidentally introduces a memory leak:
> @@ -780,7 +675,10 @@ 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]) ==
> + if (!strcmp(pn, "pci1106,8231")) {
> + return; /* ISA bridge and devices are included in dtb */
> + }
In this function we define at the top:
GString *node = g_string_new(NULL);
This change introduces an early-return which does not free
the GString.
The simplest fix is probably to declare node as
g_autoptr(GString) node = g_string_new(NULL);
and delete the now-superfluous g_string_free() from the
bottom of the function.
thanks
-- PMM
^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: [PULL 15/32] hw/ppc/pegasos2: Change device tree generation
2025-10-27 13:14 ` Peter Maydell
@ 2025-10-30 9:06 ` Harsh Prateek Bora
2025-10-30 10:18 ` BALATON Zoltan
0 siblings, 1 reply; 39+ messages in thread
From: Harsh Prateek Bora @ 2025-10-30 9:06 UTC (permalink / raw)
To: BALATON Zoltan; +Cc: qemu-devel, Philippe Mathieu-Daudé, Peter Maydell
Hi BALATON,
Would you be taking care of this coverity issue?
regards,
Harsh
On 10/27/25 18:44, Peter Maydell wrote:
> On Thu, 23 Oct 2025 at 13:22, Harsh Prateek Bora <harshpb@linux.ibm.com> wrote:
>>
>> From: BALATON Zoltan <balaton@eik.bme.hu>
>>
>> We generate a flattened device tree programmatically for VOF. Change
>> this to load the static parts from a device tree blob and only
>> generate the parts that depend on run time conditions such as CPU
>> type, memory size and PCI devices. Moving the static parts in a dts
>> makes the board code simpler and more generic.
>>
>> Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>
>> Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
>> Link: https://lore.kernel.org/qemu-devel/383891fc2696609b27d2de9773efe1b4f493e333.1761176219.git.balaton@eik.bme.hu
>> Signed-off-by: Harsh Prateek Bora <harshpb@linux.ibm.com>
>
> Hi; Coverity points out (CID 1642027) that this change
> accidentally introduces a memory leak:
>
>> @@ -780,7 +675,10 @@ 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]) ==
>> + if (!strcmp(pn, "pci1106,8231")) {
>> + return; /* ISA bridge and devices are included in dtb */
>> + }
>
> In this function we define at the top:
> GString *node = g_string_new(NULL);
>
> This change introduces an early-return which does not free
> the GString.
>
> The simplest fix is probably to declare node as
> g_autoptr(GString) node = g_string_new(NULL);
>
> and delete the now-superfluous g_string_free() from the
> bottom of the function.
>
> thanks
> -- PMM
^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: [PULL 15/32] hw/ppc/pegasos2: Change device tree generation
2025-10-30 9:06 ` Harsh Prateek Bora
@ 2025-10-30 10:18 ` BALATON Zoltan
0 siblings, 0 replies; 39+ messages in thread
From: BALATON Zoltan @ 2025-10-30 10:18 UTC (permalink / raw)
To: Harsh Prateek Bora; +Cc: qemu-devel, Philippe Mathieu-Daudé, Peter Maydell
[-- Attachment #1: Type: text/plain, Size: 2092 bytes --]
On Thu, 30 Oct 2025, Harsh Prateek Bora wrote:
> Would you be taking care of this coverity issue?
Yes. As this is a fix it's OK to fix during the freeze. I was waiting for
the rename patch to get merged to not need to rebase that so once that
lands I'll send a patch on top.
Regards,
BALATON Zoltan
> On 10/27/25 18:44, Peter Maydell wrote:
>> On Thu, 23 Oct 2025 at 13:22, Harsh Prateek Bora <harshpb@linux.ibm.com>
>> wrote:
>>>
>>> From: BALATON Zoltan <balaton@eik.bme.hu>
>>>
>>> We generate a flattened device tree programmatically for VOF. Change
>>> this to load the static parts from a device tree blob and only
>>> generate the parts that depend on run time conditions such as CPU
>>> type, memory size and PCI devices. Moving the static parts in a dts
>>> makes the board code simpler and more generic.
>>>
>>> Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>
>>> Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
>>> Link:
>>> https://lore.kernel.org/qemu-devel/383891fc2696609b27d2de9773efe1b4f493e333.1761176219.git.balaton@eik.bme.hu
>>> Signed-off-by: Harsh Prateek Bora <harshpb@linux.ibm.com>
>>
>> Hi; Coverity points out (CID 1642027) that this change
>> accidentally introduces a memory leak:
>>
>>> @@ -780,7 +675,10 @@ 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]) ==
>>> + if (!strcmp(pn, "pci1106,8231")) {
>>> + return; /* ISA bridge and devices are included in dtb */
>>> + }
>>
>> In this function we define at the top:
>> GString *node = g_string_new(NULL);
>>
>> This change introduces an early-return which does not free
>> the GString.
>>
>> The simplest fix is probably to declare node as
>> g_autoptr(GString) node = g_string_new(NULL);
>>
>> and delete the now-superfluous g_string_free() from the
>> bottom of the function.
>>
>> thanks
>> -- PMM
>
>
^ permalink raw reply [flat|nested] 39+ messages in thread
end of thread, other threads:[~2025-10-30 10:20 UTC | newest]
Thread overview: 39+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-10-23 12:16 [PULL RESEND 00/32] ppc-for-10.2 queue Harsh Prateek Bora
2025-10-23 12:16 ` [PULL 01/32] ppc/spapr: remove deprecated machine pseries-3.0 Harsh Prateek Bora
2025-10-23 12:16 ` [PULL 02/32] hw/ppc/spapr: Remove SpaprMachineClass::nr_xirqs field Harsh Prateek Bora
2025-10-23 12:16 ` [PULL 03/32] ppc/spapr: remove deprecated machine pseries-3.1 Harsh Prateek Bora
2025-10-23 12:16 ` [PULL 04/32] hw/ppc/spapr: Inline spapr_dtb_needed() Harsh Prateek Bora
2025-10-23 12:16 ` [PULL 05/32] hw/ppc/spapr: Inline few SPAPR_IRQ_* uses Harsh Prateek Bora
2025-10-23 12:16 ` [PULL 06/32] target/ppc/kvm: Remove kvmppc_get_host_serial() as unused Harsh Prateek Bora
2025-10-23 12:16 ` [PULL 07/32] target/ppc/kvm: Remove kvmppc_get_host_model() " Harsh Prateek Bora
2025-10-23 12:16 ` [PULL 08/32] ppc/spapr: remove deprecated machine pseries-4.0 Harsh Prateek Bora
2025-10-23 12:16 ` [PULL 09/32] hw/ppc/spapr: Remove SpaprMachineClass::phb_placement callback Harsh Prateek Bora
2025-10-23 12:16 ` [PULL 10/32] ppc/spapr: remove deprecated machine pseries-4.1 Harsh Prateek Bora
2025-10-23 12:16 ` [PULL 11/32] ppc/spapr: remove deprecated machine pseries-4.2 Harsh Prateek Bora
2025-10-23 12:16 ` [PULL 12/32] ppc/amigaone: Free allocated struct Harsh Prateek Bora
2025-10-23 12:16 ` [PULL 13/32] ppc/vof: Make nextprop behave more like Open Firmware Harsh Prateek Bora
2025-10-23 12:16 ` [PULL 14/32] hw/ppc/pegasos2: Remove explicit name properties from device tree Harsh Prateek Bora
2025-10-23 12:16 ` [PULL 15/32] hw/ppc/pegasos2: Change device tree generation Harsh Prateek Bora
2025-10-27 13:14 ` Peter Maydell
2025-10-30 9:06 ` Harsh Prateek Bora
2025-10-30 10:18 ` BALATON Zoltan
2025-10-23 12:16 ` [PULL 16/32] hw/ppc/pegasos2: Remove fdt pointer from machine state Harsh Prateek Bora
2025-10-23 12:16 ` [PULL 17/32] hw/ppc/pegasos2: Rename mv field in " Harsh Prateek Bora
2025-10-23 12:16 ` [PULL 18/32] hw/ppc/pegasos2: Add south bridge pointer in the " Harsh Prateek Bora
2025-10-23 12:16 ` [PULL 19/32] hw/ppc/pegasos2: Move PCI IRQ routing setup to a function Harsh Prateek Bora
2025-10-23 12:16 ` [PULL 20/32] hw/ppc/pegasos2: Move hardware specific parts out of machine reset Harsh Prateek Bora
2025-10-23 12:16 ` [PULL 21/32] hw/ppc/pegasos2: Introduce abstract superclass Harsh Prateek Bora
2025-10-23 12:16 ` [PULL 22/32] hw/ppc/pegasos2: Add bus frequency to machine state Harsh Prateek Bora
2025-10-23 12:16 ` [PULL 23/32] hw/ppc/pegasos2: Add Pegasos I emulation Harsh Prateek Bora
2025-10-23 12:16 ` [PULL 24/32] hw/ppc/pegasos2: Add VOF support for pegasos1 Harsh Prateek Bora
2025-10-23 12:16 ` [PULL 25/32] hw/ppc: Implement fadump register command Harsh Prateek Bora
2025-10-23 12:16 ` [PULL 26/32] hw/ppc: Trigger Fadump boot if fadump is registered Harsh Prateek Bora
2025-10-23 12:16 ` [PULL 27/32] hw/ppc: Preserve memory regions registered for fadump Harsh Prateek Bora
2025-10-27 13:06 ` Peter Maydell
2025-10-23 12:16 ` [PULL 28/32] hw/ppc: Implement saving CPU state in Fadump Harsh Prateek Bora
2025-10-27 13:03 ` Peter Maydell
2025-10-23 12:16 ` [PULL 29/32] hw/ppc: Pass dump-sizes property for fadump in device tree Harsh Prateek Bora
2025-10-23 12:16 ` [PULL 30/32] hw/ppc: Enable fadump for PSeries Harsh Prateek Bora
2025-10-23 12:16 ` [PULL 31/32] tests/functional: Add test for fadump in PSeries Harsh Prateek Bora
2025-10-23 12:16 ` [PULL 32/32] MAINTAINERS: Add entry for FADump (pSeries) Harsh Prateek Bora
2025-10-23 19:33 ` [PULL RESEND 00/32] ppc-for-10.2 queue Richard Henderson
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).