qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 00/13] Pegasos2 clean up and pegasos1 emulation
@ 2025-07-02 22:38 BALATON Zoltan
  2025-07-02 22:38 ` [PATCH v2 01/13] ppc/vof: Make nextprop behave more like Open Firmware BALATON Zoltan
                   ` (12 more replies)
  0 siblings, 13 replies; 14+ messages in thread
From: BALATON Zoltan @ 2025-07-02 22:38 UTC (permalink / raw)
  To: qemu-devel, qemu-ppc; +Cc: Nicholas Piggin

This series changes how the fdt for VOF is generated in pegasos2 by
moving the static parts to a dtb and only generate the changing parts
such as memory size and PCI devices programmatically. This simplifies
the code and allows simply adding emulation of Pegasos I which has a
different north bridge and slightly different memory map but otherwise
very similar and can be emulated by reusing parts from the amigaone
machine. The machine was tested with a Pegasos I ROM image and MorphOS.

The first patch (submitted separetely before, the reviewed v3 is
included here) fixes handling the name property in VOF that cannot be
represented in a dts as that always takes the path as the name and
cannot accept an explicit name property but we need the name property
to appear when guest queries properties which previously was worked
around by adding it to every node.

The series also adds an extended DEFINE_MACHINE macro that is later
used for more easily define the abstract machine type and hide most of
the QOM boiler plate.

Regards,
BALATON Zoltan

v2:
- rebase on master
- added some R-b tags from Philippe
- move first patch later (was first to allow merging separately)
- clarify blurb above

BALATON Zoltan (13):
  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/boards: Extend DEFINE_MACHINE macro to cover more use cases
  hw/ppc/pegasos2: Add Pegasos I emulation
  hw/ppc/pegasos2: Add VOF support for pegasos1

 MAINTAINERS              |   1 +
 hw/ppc/pegasos2.c        | 770 +++++++++++++++++++--------------------
 hw/ppc/vof.c             |  50 ++-
 include/hw/boards.h      |  16 +-
 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 +++++++++
 9 files changed, 718 insertions(+), 413 deletions(-)
 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

-- 
2.41.3



^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH v2 01/13] ppc/vof: Make nextprop behave more like Open Firmware
  2025-07-02 22:38 [PATCH v2 00/13] Pegasos2 clean up and pegasos1 emulation BALATON Zoltan
@ 2025-07-02 22:38 ` BALATON Zoltan
  2025-07-02 22:38 ` [PATCH v2 02/13] hw/ppc/pegasos2: Remove explicit name properties from device tree BALATON Zoltan
                   ` (11 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: BALATON Zoltan @ 2025-07-02 22:38 UTC (permalink / raw)
  To: qemu-devel, qemu-ppc; +Cc: Nicholas Piggin

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>
---
 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.41.3



^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH v2 02/13] hw/ppc/pegasos2: Remove explicit name properties from device tree
  2025-07-02 22:38 [PATCH v2 00/13] Pegasos2 clean up and pegasos1 emulation BALATON Zoltan
  2025-07-02 22:38 ` [PATCH v2 01/13] ppc/vof: Make nextprop behave more like Open Firmware BALATON Zoltan
@ 2025-07-02 22:38 ` BALATON Zoltan
  2025-07-02 22:38 ` [PATCH v2 03/13] hw/ppc/pegasos2: Change device tree generation BALATON Zoltan
                   ` (10 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: BALATON Zoltan @ 2025-07-02 22:38 UTC (permalink / raw)
  To: qemu-devel, qemu-ppc; +Cc: Nicholas Piggin

These are not needed any more now that VOF can handle it.

Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>
---
 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.41.3



^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH v2 03/13] hw/ppc/pegasos2: Change device tree generation
  2025-07-02 22:38 [PATCH v2 00/13] Pegasos2 clean up and pegasos1 emulation BALATON Zoltan
  2025-07-02 22:38 ` [PATCH v2 01/13] ppc/vof: Make nextprop behave more like Open Firmware BALATON Zoltan
  2025-07-02 22:38 ` [PATCH v2 02/13] hw/ppc/pegasos2: Remove explicit name properties from device tree BALATON Zoltan
@ 2025-07-02 22:38 ` BALATON Zoltan
  2025-07-02 22:38 ` [PATCH v2 04/13] hw/ppc/pegasos2: Remove fdt pointer from machine state BALATON Zoltan
                   ` (9 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: BALATON Zoltan @ 2025-07-02 22:38 UTC (permalink / raw)
  To: qemu-devel, qemu-ppc; +Cc: Nicholas Piggin

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>
---
 hw/ppc/pegasos2.c        | 292 +++++++--------------------------------
 pc-bios/dtb/meson.build  |   1 +
 pc-bios/dtb/pegasos2.dtb | Bin 0 -> 1701 bytes
 pc-bios/dtb/pegasos2.dts | 167 ++++++++++++++++++++++
 4 files changed, 220 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..646755a3cc 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,44 @@ 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;
+    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);
+    }
+    g_free(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 +857,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.41.3



^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH v2 04/13] hw/ppc/pegasos2: Remove fdt pointer from machine state
  2025-07-02 22:38 [PATCH v2 00/13] Pegasos2 clean up and pegasos1 emulation BALATON Zoltan
                   ` (2 preceding siblings ...)
  2025-07-02 22:38 ` [PATCH v2 03/13] hw/ppc/pegasos2: Change device tree generation BALATON Zoltan
@ 2025-07-02 22:38 ` BALATON Zoltan
  2025-07-02 22:38 ` [PATCH v2 05/13] hw/ppc/pegasos2: Rename mv field in " BALATON Zoltan
                   ` (8 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: BALATON Zoltan @ 2025-07-02 22:38 UTC (permalink / raw)
  To: qemu-devel, qemu-ppc; +Cc: Nicholas Piggin

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>
---
 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 646755a3cc..7dc7803c64 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.41.3



^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH v2 05/13] hw/ppc/pegasos2: Rename mv field in machine state
  2025-07-02 22:38 [PATCH v2 00/13] Pegasos2 clean up and pegasos1 emulation BALATON Zoltan
                   ` (3 preceding siblings ...)
  2025-07-02 22:38 ` [PATCH v2 04/13] hw/ppc/pegasos2: Remove fdt pointer from machine state BALATON Zoltan
@ 2025-07-02 22:38 ` BALATON Zoltan
  2025-07-02 22:38 ` [PATCH v2 06/13] hw/ppc/pegasos2: Add south bridge pointer in the " BALATON Zoltan
                   ` (7 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: BALATON Zoltan @ 2025-07-02 22:38 UTC (permalink / raw)
  To: qemu-devel, qemu-ppc; +Cc: Nicholas Piggin

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>
---
 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 7dc7803c64..9b50cd3dab 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);
 }
@@ -858,10 +858,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.41.3



^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH v2 06/13] hw/ppc/pegasos2: Add south bridge pointer in the machine state
  2025-07-02 22:38 [PATCH v2 00/13] Pegasos2 clean up and pegasos1 emulation BALATON Zoltan
                   ` (4 preceding siblings ...)
  2025-07-02 22:38 ` [PATCH v2 05/13] hw/ppc/pegasos2: Rename mv field in " BALATON Zoltan
@ 2025-07-02 22:38 ` BALATON Zoltan
  2025-07-02 22:38 ` [PATCH v2 07/13] hw/ppc/pegasos2: Move PCI IRQ routing setup to a function BALATON Zoltan
                   ` (6 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: BALATON Zoltan @ 2025-07-02 22:38 UTC (permalink / raw)
  To: qemu-devel, qemu-ppc; +Cc: Nicholas Piggin

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>
---
 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 9b50cd3dab..66bceec5ef 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.41.3



^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH v2 07/13] hw/ppc/pegasos2: Move PCI IRQ routing setup to a function
  2025-07-02 22:38 [PATCH v2 00/13] Pegasos2 clean up and pegasos1 emulation BALATON Zoltan
                   ` (5 preceding siblings ...)
  2025-07-02 22:38 ` [PATCH v2 06/13] hw/ppc/pegasos2: Add south bridge pointer in the " BALATON Zoltan
@ 2025-07-02 22:38 ` BALATON Zoltan
  2025-07-02 22:38 ` [PATCH v2 08/13] hw/ppc/pegasos2: Move hardware specific parts out of machine reset BALATON Zoltan
                   ` (5 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: BALATON Zoltan @ 2025-07-02 22:38 UTC (permalink / raw)
  To: qemu-devel, qemu-ppc; +Cc: Nicholas Piggin

Collect steps of setting up PCI IRQ routing in one function.

Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>
---
 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 66bceec5ef..26a571f82e 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.41.3



^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH v2 08/13] hw/ppc/pegasos2: Move hardware specific parts out of machine reset
  2025-07-02 22:38 [PATCH v2 00/13] Pegasos2 clean up and pegasos1 emulation BALATON Zoltan
                   ` (6 preceding siblings ...)
  2025-07-02 22:38 ` [PATCH v2 07/13] hw/ppc/pegasos2: Move PCI IRQ routing setup to a function BALATON Zoltan
@ 2025-07-02 22:38 ` BALATON Zoltan
  2025-07-02 22:38 ` [PATCH v2 09/13] hw/ppc/pegasos2: Introduce abstract superclass BALATON Zoltan
                   ` (4 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: BALATON Zoltan @ 2025-07-02 22:38 UTC (permalink / raw)
  To: qemu-devel, qemu-ppc; +Cc: Nicholas Piggin

Move the chipset reset which is pegasos2 specific out from machine
reset to a separate function and move parts not specific to pegasos2
form build_fdt in machine reset so now build_fdt contains pegasos2
specific parts and renamed accordingly.

Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>
---
 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 26a571f82e..e3c1ee9347 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));
@@ -828,12 +848,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) {
@@ -841,21 +859,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.41.3



^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH v2 09/13] hw/ppc/pegasos2: Introduce abstract superclass
  2025-07-02 22:38 [PATCH v2 00/13] Pegasos2 clean up and pegasos1 emulation BALATON Zoltan
                   ` (7 preceding siblings ...)
  2025-07-02 22:38 ` [PATCH v2 08/13] hw/ppc/pegasos2: Move hardware specific parts out of machine reset BALATON Zoltan
@ 2025-07-02 22:38 ` BALATON Zoltan
  2025-07-02 22:38 ` [PATCH v2 10/13] hw/ppc/pegasos2: Add bus frequency to machine state BALATON Zoltan
                   ` (3 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: BALATON Zoltan @ 2025-07-02 22:38 UTC (permalink / raw)
  To: qemu-devel, qemu-ppc; +Cc: Nicholas Piggin

Rename machine state struct to PegasosMachineState as it will be used
for pegasos1 too.

Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>
---
 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 e3c1ee9347..f7999520e4 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,
+    },
+    {
+        .name          = MACHINE_TYPE_NAME("pegasos2"),
+        .parent        = TYPE_PEGASOS_MACHINE,
+        .class_init    = pegasos2_machine_class_init,
+        .interfaces = (const InterfaceInfo[]) {
+              { TYPE_PPC_VIRTUAL_HYPERVISOR },
+              { TYPE_VOF_MACHINE_IF },
+              { }
+        },
     },
 };
 
-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 */
 
@@ -848,7 +850,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.41.3



^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH v2 10/13] hw/ppc/pegasos2: Add bus frequency to machine state
  2025-07-02 22:38 [PATCH v2 00/13] Pegasos2 clean up and pegasos1 emulation BALATON Zoltan
                   ` (8 preceding siblings ...)
  2025-07-02 22:38 ` [PATCH v2 09/13] hw/ppc/pegasos2: Introduce abstract superclass BALATON Zoltan
@ 2025-07-02 22:38 ` BALATON Zoltan
  2025-07-02 22:38 ` [PATCH v2 11/13] hw/boards: Extend DEFINE_MACHINE macro to cover more use cases BALATON Zoltan
                   ` (2 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: BALATON Zoltan @ 2025-07-02 22:38 UTC (permalink / raw)
  To: qemu-devel, qemu-ppc; +Cc: Nicholas Piggin

Store the bus frequency in the machine state and set it from instance
init method.

Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>
---
 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 f7999520e4..ae3f01231d 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 */
@@ -603,6 +602,13 @@ static bool pegasos2_setprop(MachineState *ms, const char *path,
     return true;
 }
 
+static void pegasos2_init(Object *obj)
+{
+    PegasosMachineState *pm = PEGASOS_MACHINE(obj);
+
+    pm->bus_freq_hz = 133333333;
+}
+
 static void pegasos2_machine_class_init(ObjectClass *oc, const void *data)
 {
     MachineClass *mc = MACHINE_CLASS(oc);
@@ -610,7 +616,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";
@@ -640,6 +646,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,
         .interfaces = (const InterfaceInfo[]) {
               { TYPE_PPC_VIRTUAL_HYPERVISOR },
               { TYPE_VOF_MACHINE_IF },
@@ -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;
@@ -861,7 +868,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.41.3



^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH v2 11/13] hw/boards: Extend DEFINE_MACHINE macro to cover more use cases
  2025-07-02 22:38 [PATCH v2 00/13] Pegasos2 clean up and pegasos1 emulation BALATON Zoltan
                   ` (9 preceding siblings ...)
  2025-07-02 22:38 ` [PATCH v2 10/13] hw/ppc/pegasos2: Add bus frequency to machine state BALATON Zoltan
@ 2025-07-02 22:38 ` BALATON Zoltan
  2025-07-02 22:38 ` [PATCH v2 12/13] hw/ppc/pegasos2: Add Pegasos I emulation BALATON Zoltan
  2025-07-02 22:38 ` [PATCH v2 13/13] hw/ppc/pegasos2: Add VOF support for pegasos1 BALATON Zoltan
  12 siblings, 0 replies; 14+ messages in thread
From: BALATON Zoltan @ 2025-07-02 22:38 UTC (permalink / raw)
  To: qemu-devel, qemu-ppc; +Cc: Nicholas Piggin

Add a more general DEFINE_MACHINE_EXTENDED macro and define simpler
versions with less parameters based on that. This is inspired by how
the OBJECT_DEFINE macros do this in a similar way to allow using the
shortened definition in more complex cases too.

Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>
---
 include/hw/boards.h | 16 ++++++++++++++--
 1 file changed, 14 insertions(+), 2 deletions(-)

diff --git a/include/hw/boards.h b/include/hw/boards.h
index f424b2b505..8e8eff2f6d 100644
--- a/include/hw/boards.h
+++ b/include/hw/boards.h
@@ -761,7 +761,8 @@ struct MachineState {
         } \
     } while (0)
 
-#define DEFINE_MACHINE(namestr, machine_initfn) \
+#define DEFINE_MACHINE_EXTENDED(namestr, PARENT_NAME, InstanceName, \
+                                machine_initfn, ABSTRACT, ...) \
     static void machine_initfn##_class_init(ObjectClass *oc, const void *data) \
     { \
         MachineClass *mc = MACHINE_CLASS(oc); \
@@ -769,8 +770,11 @@ struct MachineState {
     } \
     static const TypeInfo machine_initfn##_typeinfo = { \
         .name       = MACHINE_TYPE_NAME(namestr), \
-        .parent     = TYPE_MACHINE, \
+        .parent     = TYPE_##PARENT_NAME, \
         .class_init = machine_initfn##_class_init, \
+        .instance_size = sizeof(InstanceName), \
+        .abstract = ABSTRACT, \
+        .interfaces = (const InterfaceInfo[]) { __VA_ARGS__ } , \
     }; \
     static void machine_initfn##_register_types(void) \
     { \
@@ -778,6 +782,14 @@ struct MachineState {
     } \
     type_init(machine_initfn##_register_types)
 
+#define DEFINE_MACHINE(namestr, machine_initfn) \
+    DEFINE_MACHINE_EXTENDED(namestr, MACHINE, MachineState, machine_initfn, \
+                            false, { })
+
+#define DEFINE_MACHINE_WITH_INTERFACES(namestr, machine_initfn, ...) \
+    DEFINE_MACHINE_EXTENDED(namestr, MACHINE, MachineState, machine_initfn, \
+                            false, __VA_ARGS__)
+
 extern GlobalProperty hw_compat_10_0[];
 extern const size_t hw_compat_10_0_len;
 
-- 
2.41.3



^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH v2 12/13] hw/ppc/pegasos2: Add Pegasos I emulation
  2025-07-02 22:38 [PATCH v2 00/13] Pegasos2 clean up and pegasos1 emulation BALATON Zoltan
                   ` (10 preceding siblings ...)
  2025-07-02 22:38 ` [PATCH v2 11/13] hw/boards: Extend DEFINE_MACHINE macro to cover more use cases BALATON Zoltan
@ 2025-07-02 22:38 ` BALATON Zoltan
  2025-07-02 22:38 ` [PATCH v2 13/13] hw/ppc/pegasos2: Add VOF support for pegasos1 BALATON Zoltan
  12 siblings, 0 replies; 14+ messages in thread
From: BALATON Zoltan @ 2025-07-02 22:38 UTC (permalink / raw)
  To: qemu-devel, qemu-ppc; +Cc: Nicholas Piggin

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>
---
 hw/ppc/pegasos2.c | 170 +++++++++++++++++++++++++++++++++-------------
 1 file changed, 124 insertions(+), 46 deletions(-)

diff --git a/hw/ppc/pegasos2.c b/hw/ppc/pegasos2.c
index ae3f01231d..a88d93ae04 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,62 +652,84 @@ 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_init(Object *obj)
-{
-    PegasosMachineState *pm = PEGASOS_MACHINE(obj);
-
-    pm->bus_freq_hz = 133333333;
-}
-
-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,
+                        { 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,
+        .name          = MACHINE_TYPE_NAME("pegasos1"),
+        .parent        = TYPE_PEGASOS_MACHINE,
+        .class_init    = pegasos1_machine_class_init,
+        .instance_init = pegasos1_init,
     },
     {
         .name          = MACHINE_TYPE_NAME("pegasos2"),
         .parent        = TYPE_PEGASOS_MACHINE,
         .class_init    = pegasos2_machine_class_init,
         .instance_init = pegasos2_init,
-        .interfaces = (const InterfaceInfo[]) {
-              { TYPE_PPC_VIRTUAL_HYPERVISOR },
-              { TYPE_VOF_MACHINE_IF },
-              { }
-        },
     },
 };
 
-- 
2.41.3



^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH v2 13/13] hw/ppc/pegasos2: Add VOF support for pegasos1
  2025-07-02 22:38 [PATCH v2 00/13] Pegasos2 clean up and pegasos1 emulation BALATON Zoltan
                   ` (11 preceding siblings ...)
  2025-07-02 22:38 ` [PATCH v2 12/13] hw/ppc/pegasos2: Add Pegasos I emulation BALATON Zoltan
@ 2025-07-02 22:38 ` BALATON Zoltan
  12 siblings, 0 replies; 14+ messages in thread
From: BALATON Zoltan @ 2025-07-02 22:38 UTC (permalink / raw)
  To: qemu-devel, qemu-ppc; +Cc: Nicholas Piggin

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>
---
 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 7128e0bc98..5db5f8e97e 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1626,6 +1626,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 a88d93ae04..c9a35198e9 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",
@@ -935,6 +1012,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.41.3



^ permalink raw reply related	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2025-07-02 22:41 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-07-02 22:38 [PATCH v2 00/13] Pegasos2 clean up and pegasos1 emulation BALATON Zoltan
2025-07-02 22:38 ` [PATCH v2 01/13] ppc/vof: Make nextprop behave more like Open Firmware BALATON Zoltan
2025-07-02 22:38 ` [PATCH v2 02/13] hw/ppc/pegasos2: Remove explicit name properties from device tree BALATON Zoltan
2025-07-02 22:38 ` [PATCH v2 03/13] hw/ppc/pegasos2: Change device tree generation BALATON Zoltan
2025-07-02 22:38 ` [PATCH v2 04/13] hw/ppc/pegasos2: Remove fdt pointer from machine state BALATON Zoltan
2025-07-02 22:38 ` [PATCH v2 05/13] hw/ppc/pegasos2: Rename mv field in " BALATON Zoltan
2025-07-02 22:38 ` [PATCH v2 06/13] hw/ppc/pegasos2: Add south bridge pointer in the " BALATON Zoltan
2025-07-02 22:38 ` [PATCH v2 07/13] hw/ppc/pegasos2: Move PCI IRQ routing setup to a function BALATON Zoltan
2025-07-02 22:38 ` [PATCH v2 08/13] hw/ppc/pegasos2: Move hardware specific parts out of machine reset BALATON Zoltan
2025-07-02 22:38 ` [PATCH v2 09/13] hw/ppc/pegasos2: Introduce abstract superclass BALATON Zoltan
2025-07-02 22:38 ` [PATCH v2 10/13] hw/ppc/pegasos2: Add bus frequency to machine state BALATON Zoltan
2025-07-02 22:38 ` [PATCH v2 11/13] hw/boards: Extend DEFINE_MACHINE macro to cover more use cases BALATON Zoltan
2025-07-02 22:38 ` [PATCH v2 12/13] hw/ppc/pegasos2: Add Pegasos I emulation BALATON Zoltan
2025-07-02 22:38 ` [PATCH v2 13/13] hw/ppc/pegasos2: Add VOF support for pegasos1 BALATON Zoltan

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).