All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC PATCH 1/5] Misc VOF fixes
  2021-06-06 15:46 [RFC PATCH 0/5] ppc/Pegasos2 VOF BALATON Zoltan
                   ` (3 preceding siblings ...)
  2021-06-06 15:46 ` [RFC PATCH 2/5] ppc/pegasos2: Introduce Pegasos2MachineState structure BALATON Zoltan
@ 2021-06-06 15:46 ` BALATON Zoltan
  2021-06-09  7:39 ` [RFC PATCH 0/5] ppc/Pegasos2 VOF Alexey Kardashevskiy
  5 siblings, 0 replies; 20+ messages in thread
From: BALATON Zoltan @ 2021-06-06 15:46 UTC (permalink / raw)
  To: qemu-devel, qemu-ppc; +Cc: Alexey Kardashevskiy, David Gibson

Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>
---
 hw/ppc/vof.c        |  11 +++++++----
 pc-bios/vof.bin     | Bin 3784 -> 3784 bytes
 pc-bios/vof/entry.S |   2 +-
 3 files changed, 8 insertions(+), 5 deletions(-)

diff --git a/hw/ppc/vof.c b/hw/ppc/vof.c
index a283b7d251..ac95be9666 100644
--- a/hw/ppc/vof.c
+++ b/hw/ppc/vof.c
@@ -144,12 +144,15 @@ static uint32_t vof_finddevice(const void *fdt, uint32_t nodeaddr)
     char fullnode[VOF_MAX_PATH];
     uint32_t ret = -1;
     int offset;
+    gchar *p;
 
     if (readstr(nodeaddr, fullnode, sizeof(fullnode))) {
         return (uint32_t) ret;
     }
 
-    offset = fdt_path_offset(fdt, fullnode);
+    p = g_ascii_strdown(fullnode, -1);
+    offset = fdt_path_offset(fdt, p);
+    g_free(p);
     if (offset >= 0) {
         ret = fdt_get_phandle(fdt, offset);
     }
@@ -160,14 +163,14 @@ static uint32_t vof_finddevice(const void *fdt, uint32_t nodeaddr)
 static const void *getprop(const void *fdt, int nodeoff, const char *propname,
                            int *proplen, bool *write0)
 {
-    const char *unit, *prop;
+    const char *unit, *prop = fdt_getprop(fdt, nodeoff, propname, proplen);
 
     /*
      * The "name" property is not actually stored as a property in the FDT,
      * we emulate it by returning a pointer to the node's name and adjust
      * proplen to include only the name but not the unit.
      */
-    if (strcmp(propname, "name") == 0) {
+    if (!prop && strcmp(propname, "name") == 0) {
         prop = fdt_get_name(fdt, nodeoff, proplen);
         if (!prop) {
             *proplen = 0;
@@ -193,7 +196,7 @@ static const void *getprop(const void *fdt, int nodeoff, const char *propname,
     if (write0) {
         *write0 = false;
     }
-    return fdt_getprop(fdt, nodeoff, propname, proplen);
+    return prop;
 }
 
 static uint32_t vof_getprop(const void *fdt, uint32_t nodeph, uint32_t pname,
diff --git a/pc-bios/vof.bin b/pc-bios/vof.bin
index 7e4c3742deae3c1904f4b2bf03ef72576b12d532..1ec670be82134adcb5ae128732aff6e371281360 100755
GIT binary patch
delta 14
VcmX>hdqQ@D4kKgpW?jbFyZ|U11hoJF

delta 14
VcmX>hdqQ@D4kP31&AN=Uc>yYn1swnY

diff --git a/pc-bios/vof/entry.S b/pc-bios/vof/entry.S
index 569688714c..f8066775ec 100644
--- a/pc-bios/vof/entry.S
+++ b/pc-bios/vof/entry.S
@@ -30,7 +30,7 @@ ENTRY(_prom_entry)
 	bl prom_entry
 	nop
 	mtlr    %r31
-	ld      %r31,104(%r1)
+	lwz     %r31,104(%r1)
 	addi    %r1,%r1,112
 	blr
 
-- 
2.21.4



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

* [RFC PATCH 2/5] ppc/pegasos2: Introduce Pegasos2MachineState structure
  2021-06-06 15:46 [RFC PATCH 0/5] ppc/Pegasos2 VOF BALATON Zoltan
                   ` (2 preceding siblings ...)
  2021-06-06 15:46 ` [RFC PATCH 3/5] target/ppc: Allow virtual hypervisor on CPU without HV BALATON Zoltan
@ 2021-06-06 15:46 ` BALATON Zoltan
  2021-06-06 19:04   ` Philippe Mathieu-Daudé
  2021-06-06 15:46 ` [RFC PATCH 1/5] Misc VOF fixes BALATON Zoltan
  2021-06-09  7:39 ` [RFC PATCH 0/5] ppc/Pegasos2 VOF Alexey Kardashevskiy
  5 siblings, 1 reply; 20+ messages in thread
From: BALATON Zoltan @ 2021-06-06 15:46 UTC (permalink / raw)
  To: qemu-devel, qemu-ppc; +Cc: Alexey Kardashevskiy, David Gibson

Add own machine state structure which will be used to store state
needed for firmware emulation.

Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>
---
 hw/ppc/pegasos2.c | 50 +++++++++++++++++++++++++++++++++++------------
 1 file changed, 37 insertions(+), 13 deletions(-)

diff --git a/hw/ppc/pegasos2.c b/hw/ppc/pegasos2.c
index 0bfd0928aa..07971175c9 100644
--- a/hw/ppc/pegasos2.c
+++ b/hw/ppc/pegasos2.c
@@ -1,7 +1,7 @@
 /*
  * QEMU PowerPC CHRP (Genesi/bPlan Pegasos II) hardware System Emulator
  *
- * Copyright (c) 2018-2020 BALATON Zoltan
+ * Copyright (c) 2018-2021 BALATON Zoltan
  *
  * This work is licensed under the GNU GPL license version 2 or later.
  *
@@ -41,6 +41,15 @@
 
 #define BUS_FREQ_HZ 133333333
 
+#define TYPE_PEGASOS2_MACHINE  MACHINE_TYPE_NAME("pegasos2")
+OBJECT_DECLARE_TYPE(Pegasos2MachineState, MachineClass, PEGASOS2_MACHINE)
+
+struct Pegasos2MachineState {
+    MachineState parent_obj;
+    PowerPCCPU *cpu;
+    DeviceState *mv;
+};
+
 static void pegasos2_cpu_reset(void *opaque)
 {
     PowerPCCPU *cpu = opaque;
@@ -51,9 +60,9 @@ static void pegasos2_cpu_reset(void *opaque)
 
 static void pegasos2_init(MachineState *machine)
 {
-    PowerPCCPU *cpu = NULL;
+    Pegasos2MachineState *pm = PEGASOS2_MACHINE(machine);
+    CPUPPCState *env;
     MemoryRegion *rom = g_new(MemoryRegion, 1);
-    DeviceState *mv;
     PCIBus *pci_bus;
     PCIDevice *dev;
     I2CBus *i2c_bus;
@@ -63,15 +72,16 @@ static void pegasos2_init(MachineState *machine)
     uint8_t *spd_data;
 
     /* init CPU */
-    cpu = POWERPC_CPU(cpu_create(machine->cpu_type));
-    if (PPC_INPUT(&cpu->env) != PPC_FLAGS_INPUT_6xx) {
+    pm->cpu = POWERPC_CPU(cpu_create(machine->cpu_type));
+    env = &pm->cpu->env;
+    if (PPC_INPUT(env) != PPC_FLAGS_INPUT_6xx) {
         error_report("Incompatible CPU, only 6xx bus supported");
         exit(1);
     }
 
     /* Set time-base frequency */
-    cpu_ppc_tb_init(&cpu->env, BUS_FREQ_HZ / 4);
-    qemu_register_reset(pegasos2_cpu_reset, cpu);
+    cpu_ppc_tb_init(env, BUS_FREQ_HZ / 4);
+    qemu_register_reset(pegasos2_cpu_reset, pm->cpu);
 
     /* RAM */
     memory_region_add_subregion(get_system_memory(), 0, machine->ram);
@@ -96,16 +106,16 @@ static void pegasos2_init(MachineState *machine)
     g_free(filename);
 
     /* Marvell Discovery II system controller */
-    mv = DEVICE(sysbus_create_simple(TYPE_MV64361, -1,
-                        ((qemu_irq *)cpu->env.irq_inputs)[PPC6xx_INPUT_INT]));
-    pci_bus = mv64361_get_pci_bus(mv, 1);
+    pm->mv = DEVICE(sysbus_create_simple(TYPE_MV64361, -1,
+                             ((qemu_irq *)env->irq_inputs)[PPC6xx_INPUT_INT]));
+    pci_bus = mv64361_get_pci_bus(pm->mv, 1);
 
     /* VIA VT8231 South Bridge (multifunction PCI device) */
     /* VT8231 function 0: PCI-to-ISA Bridge */
     dev = pci_create_simple_multifunction(pci_bus, PCI_DEVFN(12, 0), true,
                                           TYPE_VT8231_ISA);
     qdev_connect_gpio_out(DEVICE(dev), 0,
-                          qdev_get_gpio_in_named(mv, "gpp", 31));
+                          qdev_get_gpio_in_named(pm->mv, "gpp", 31));
 
     /* VT8231 function 1: IDE Controller */
     dev = pci_create_simple(pci_bus, PCI_DEVFN(12, 1), "via-ide");
@@ -129,8 +139,10 @@ static void pegasos2_init(MachineState *machine)
     pci_vga_init(pci_bus);
 }
 
-static void pegasos2_machine(MachineClass *mc)
+static void pegasos2_machine_class_init(ObjectClass *oc, void *data)
 {
+    MachineClass *mc = MACHINE_CLASS(oc);
+
     mc->desc = "Genesi/bPlan Pegasos II";
     mc->init = pegasos2_init;
     mc->block_default_type = IF_IDE;
@@ -141,4 +153,16 @@ static void pegasos2_machine(MachineClass *mc)
     mc->default_ram_size = 512 * MiB;
 }
 
-DEFINE_MACHINE("pegasos2", pegasos2_machine)
+static const TypeInfo pegasos2_machine_info = {
+    .name          = TYPE_PEGASOS2_MACHINE,
+    .parent        = TYPE_MACHINE,
+    .class_init    = pegasos2_machine_class_init,
+    .instance_size = sizeof(Pegasos2MachineState),
+};
+
+static void pegasos2_machine_register_types(void)
+{
+    type_register_static(&pegasos2_machine_info);
+}
+
+type_init(pegasos2_machine_register_types)
-- 
2.21.4



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

* [RFC PATCH 3/5] target/ppc: Allow virtual hypervisor on CPU without HV
  2021-06-06 15:46 [RFC PATCH 0/5] ppc/Pegasos2 VOF BALATON Zoltan
  2021-06-06 15:46 ` [RFC PATCH 5/5] ppc/pegasos2: Implement some RTAS functions with VOF BALATON Zoltan
  2021-06-06 15:46 ` [RFC PATCH 4/5] ppc/pegasos2: Use Virtual Open Firmware as firmware replacement BALATON Zoltan
@ 2021-06-06 15:46 ` BALATON Zoltan
  2021-06-06 15:46 ` [RFC PATCH 2/5] ppc/pegasos2: Introduce Pegasos2MachineState structure BALATON Zoltan
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 20+ messages in thread
From: BALATON Zoltan @ 2021-06-06 15:46 UTC (permalink / raw)
  To: qemu-devel, qemu-ppc; +Cc: Alexey Kardashevskiy, David Gibson

Change the assert in ppc_store_sdr1() to allow vhyp to be set on CPUs
without HV bit. This allows using the vhyp interface for firmware
emulation on pegasos2.

Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>
---
 target/ppc/cpu.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/target/ppc/cpu.c b/target/ppc/cpu.c
index 19d67b5b07..a29299882a 100644
--- a/target/ppc/cpu.c
+++ b/target/ppc/cpu.c
@@ -72,7 +72,7 @@ void ppc_store_sdr1(CPUPPCState *env, target_ulong value)
 {
     PowerPCCPU *cpu = env_archcpu(env);
     qemu_log_mask(CPU_LOG_MMU, "%s: " TARGET_FMT_lx "\n", __func__, value);
-    assert(!cpu->vhyp);
+    assert(!cpu->env.has_hv_mode || !cpu->vhyp);
 #if defined(TARGET_PPC64)
     if (mmu_is_64bit(env->mmu_model)) {
         target_ulong sdr_mask = SDR_64_HTABORG | SDR_64_HTABSIZE;
-- 
2.21.4



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

* [RFC PATCH 5/5] ppc/pegasos2: Implement some RTAS functions with VOF
  2021-06-06 15:46 [RFC PATCH 0/5] ppc/Pegasos2 VOF BALATON Zoltan
@ 2021-06-06 15:46 ` BALATON Zoltan
  2021-06-06 15:46 ` [RFC PATCH 4/5] ppc/pegasos2: Use Virtual Open Firmware as firmware replacement BALATON Zoltan
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 20+ messages in thread
From: BALATON Zoltan @ 2021-06-06 15:46 UTC (permalink / raw)
  To: qemu-devel, qemu-ppc; +Cc: Alexey Kardashevskiy, David Gibson

Linux uses RTAS functions to access PCI devices so we need to provide
these with VOF. Implement some of the most important functions to
allow booting Linux with VOF. With this the board is now usable
without a binary ROM image and we can enable it by default as other
boards.

Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>
---
 default-configs/devices/ppc-softmmu.mak |   2 +-
 hw/ppc/pegasos2.c                       | 108 ++++++++++++++++++++++++
 2 files changed, 109 insertions(+), 1 deletion(-)

diff --git a/default-configs/devices/ppc-softmmu.mak b/default-configs/devices/ppc-softmmu.mak
index c2d41198cd..4535993d8d 100644
--- a/default-configs/devices/ppc-softmmu.mak
+++ b/default-configs/devices/ppc-softmmu.mak
@@ -14,7 +14,7 @@ CONFIG_SAM460EX=y
 CONFIG_MAC_OLDWORLD=y
 CONFIG_MAC_NEWWORLD=y
 
-CONFIG_PEGASOS2=n
+CONFIG_PEGASOS2=y
 
 # For PReP
 CONFIG_PREP=y
diff --git a/hw/ppc/pegasos2.c b/hw/ppc/pegasos2.c
index 91e5fa8fbe..cb2be27394 100644
--- a/hw/ppc/pegasos2.c
+++ b/hw/ppc/pegasos2.c
@@ -43,6 +43,7 @@
 #define PROM_SIZE     0x80000
 
 #define KVMPPC_HCALL_BASE    0xf000
+#define KVMPPC_H_RTAS        (KVMPPC_HCALL_BASE + 0x0)
 #define KVMPPC_H_VOF_CLIENT  (KVMPPC_HCALL_BASE + 0x5)
 
 /* Copied from SLOF, and 4K is definitely not enough for GRUB */
@@ -198,6 +199,30 @@ static void pegasos2_init(MachineState *machine)
     }
 }
 
+static uint32_t pegasos2_pci_config_read(AddressSpace *as, int bus,
+                                         uint32_t addr, uint32_t len)
+{
+    hwaddr pcicfg = (bus ? 0xf1000c78 : 0xf1000cf8);
+    uint32_t val = 0xffffffff;
+
+    stl_le_phys(as, pcicfg, addr | BIT(31));
+    switch (len) {
+    case 4:
+        val = ldl_le_phys(as, pcicfg + 4);
+        break;
+    case 2:
+        val = lduw_le_phys(as, pcicfg + 4);
+        break;
+    case 1:
+        val = ldub_phys(as, pcicfg + 4);
+        break;
+    default:
+        qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid length\n", __func__);
+        break;
+    }
+    return val;
+}
+
 static void pegasos2_pci_config_write(AddressSpace *as, int bus, uint32_t addr,
                                       uint32_t len, uint32_t val)
 {
@@ -307,6 +332,87 @@ static void pegasos2_machine_reset(MachineState *machine)
     pm->cpu->vhyp = PPC_VIRTUAL_HYPERVISOR(machine);
 }
 
+enum pegasos2_rtas_tokens {
+    RTAS_RESTART_RTAS = 0,
+    RTAS_NVRAM_FETCH = 1,
+    RTAS_NVRAM_STORE = 2,
+    RTAS_GET_TIME_OF_DAY = 3,
+    RTAS_SET_TIME_OF_DAY = 4,
+    RTAS_EVENT_SCAN = 6,
+    RTAS_CHECK_EXCEPTION = 7,
+    RTAS_READ_PCI_CONFIG = 8,
+    RTAS_WRITE_PCI_CONFIG = 9,
+    RTAS_DISPLAY_CHARACTER = 10,
+    RTAS_SET_INDICATOR = 11,
+    RTAS_POWER_OFF = 17,
+    RTAS_SUSPEND = 18,
+    RTAS_HIBERNATE = 19,
+    RTAS_SYSTEM_REBOOT = 20,
+};
+
+static target_ulong pegasos2_rtas(PowerPCCPU *cpu, Pegasos2MachineState *pm,
+                                  target_ulong args_real)
+{
+    AddressSpace *as = CPU(cpu)->as;
+    uint32_t token = ldl_be_phys(as, args_real);
+    uint32_t nargs = ldl_be_phys(as, args_real + 4);
+    uint32_t nrets = ldl_be_phys(as, args_real + 8);
+    uint32_t args = args_real + 12;
+    uint32_t rets = args_real + 12 + nargs * 4;
+
+    if (nrets < 1) {
+        qemu_log_mask(LOG_GUEST_ERROR, "Too few return values in RTAS call\n");
+        return H_PARAMETER;
+    }
+    switch (token) {
+    case RTAS_READ_PCI_CONFIG:
+    {
+        uint32_t addr, len, val;
+
+        if (nargs != 2 || nrets != 2) {
+            stl_be_phys(as, rets, -1);
+            return H_PARAMETER;
+        }
+        addr = ldl_be_phys(as, args);
+        len = ldl_be_phys(as, args + 4);
+        val = pegasos2_pci_config_read(as, !(addr >> 24),
+                                       addr & 0x0fffffff, len);
+        stl_be_phys(as, rets, 0);
+        stl_be_phys(as, rets + 4, val);
+        return H_SUCCESS;
+    }
+    case RTAS_WRITE_PCI_CONFIG:
+    {
+        uint32_t addr, len, val;
+
+        if (nargs != 3 || nrets != 1) {
+            stl_be_phys(as, rets, -1);
+            return H_PARAMETER;
+        }
+        addr = ldl_be_phys(as, args);
+        len = ldl_be_phys(as, args + 4);
+        val = ldl_be_phys(as, args + 8);
+        pegasos2_pci_config_write(as, !(addr >> 24),
+                                  addr & 0x0fffffff, len, val);
+        stl_be_phys(as, rets, 0);
+        return H_SUCCESS;
+    }
+    case RTAS_DISPLAY_CHARACTER:
+        if (nargs != 1 || nrets != 1) {
+            stl_be_phys(as, rets, -1);
+            return H_PARAMETER;
+        }
+        qemu_log_mask(LOG_UNIMP, "%c", ldl_be_phys(as, args));
+        stl_be_phys(as, rets, 0);
+        return H_SUCCESS;
+    default:
+        qemu_log_mask(LOG_UNIMP, "Unknown RTAS token %u (args=%u, rets=%u)\n",
+                      token, nargs, nrets);
+        stl_be_phys(as, rets, 0);
+        return H_SUCCESS;
+    }
+}
+
 static void pegasos2_hypercall(PPCVirtualHypervisor *vhyp, PowerPCCPU *cpu)
 {
     Pegasos2MachineState *pm = PEGASOS2_MACHINE(vhyp);
@@ -318,6 +424,8 @@ static void pegasos2_hypercall(PPCVirtualHypervisor *vhyp, PowerPCCPU *cpu)
     if (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) {
+        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,
                                   env->gpr[4]);
-- 
2.21.4



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

* [RFC PATCH 0/5] ppc/Pegasos2 VOF
@ 2021-06-06 15:46 BALATON Zoltan
  2021-06-06 15:46 ` [RFC PATCH 5/5] ppc/pegasos2: Implement some RTAS functions with VOF BALATON Zoltan
                   ` (5 more replies)
  0 siblings, 6 replies; 20+ messages in thread
From: BALATON Zoltan @ 2021-06-06 15:46 UTC (permalink / raw)
  To: qemu-devel, qemu-ppc; +Cc: Alexey Kardashevskiy, David Gibson


Based-on: <20210520090557.435689-1-aik@ozlabs.ru>
^ That is v20 of Alexey's VOF patch

Hello,

Posting these for early review now. I plan to rebase on the next VOF
patch that hopefully fixes those points that I had to circumvent in
patch 1 for now. I've reported these before but now all of those that
are needed for pegasos2 are in one place. Other points I've reported
could be clean ups but not sttictly needed.

With this series on top of VOF v20 I can now boot Linux and MorphOS on
pegasos2 without needing a firmware blob so I hope this is enough to
get this board in 6.1 and also have it enabled so users can start
using it. That means that VOF will also be merged by then. This now
gives VOF another use case that may help it getting finished.

I've also updated my development tree with this series here:

https://osdn.net/projects/qmiga/scm/git/qemu/tree/pegasos2/

Please review so I can do any needed changes together with the rebase
on next VOF patch so we don't miss 6.1 this time.

Regards,
BALATON Zoltan

BALATON Zoltan (5):
  Misc VOF fixes
  ppc/pegasos2: Introduce Pegasos2MachineState structure
  target/ppc: Allow virtual hypervisor on CPU without HV
  ppc/pegasos2: Use Virtual Open Firmware as firmware replacement
  ppc/pegasos2: Implement some RTAS functions with VOF

 default-configs/devices/ppc-softmmu.mak |   2 +-
 hw/ppc/Kconfig                          |   1 +
 hw/ppc/pegasos2.c                       | 780 +++++++++++++++++++++++-
 hw/ppc/vof.c                            |  11 +-
 pc-bios/vof.bin                         | Bin 3784 -> 3784 bytes
 pc-bios/vof/entry.S                     |   2 +-
 target/ppc/cpu.c                        |   2 +-
 7 files changed, 776 insertions(+), 22 deletions(-)

-- 
2.21.4



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

* [RFC PATCH 4/5] ppc/pegasos2: Use Virtual Open Firmware as firmware replacement
  2021-06-06 15:46 [RFC PATCH 0/5] ppc/Pegasos2 VOF BALATON Zoltan
  2021-06-06 15:46 ` [RFC PATCH 5/5] ppc/pegasos2: Implement some RTAS functions with VOF BALATON Zoltan
@ 2021-06-06 15:46 ` BALATON Zoltan
  2021-06-15  7:09   ` Alexey Kardashevskiy
  2021-06-06 15:46 ` [RFC PATCH 3/5] target/ppc: Allow virtual hypervisor on CPU without HV BALATON Zoltan
                   ` (3 subsequent siblings)
  5 siblings, 1 reply; 20+ messages in thread
From: BALATON Zoltan @ 2021-06-06 15:46 UTC (permalink / raw)
  To: qemu-devel, qemu-ppc; +Cc: Alexey Kardashevskiy, David Gibson

The pegasos2 board comes with an Open Firmware compliant ROM based on
SmartFirmware but it has some changes that are not open source
therefore the ROM binary cannot be included in QEMU. Guests running on
the board however depend on services provided by the firmware. The
Virtual Open Firmware recently added to QEMU imlements a minimal set
of these services to allow some guests to boot without the original
firmware. This patch adds VOF as the default firmware for pegasos2
which allows booting Linux and MorphOS via -kernel option while a ROM
image can still be used with -bios for guests that don't run with VOF.

Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>
---
 hw/ppc/Kconfig    |   1 +
 hw/ppc/pegasos2.c | 622 +++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 621 insertions(+), 2 deletions(-)

diff --git a/hw/ppc/Kconfig b/hw/ppc/Kconfig
index b895720b28..0eb48128fe 100644
--- a/hw/ppc/Kconfig
+++ b/hw/ppc/Kconfig
@@ -75,6 +75,7 @@ config PEGASOS2
     select VT82C686
     select IDE_VIA
     select SMBUS_EEPROM
+    select VOF
 # This should come with VT82C686
     select ACPI_X86
 
diff --git a/hw/ppc/pegasos2.c b/hw/ppc/pegasos2.c
index 07971175c9..91e5fa8fbe 100644
--- a/hw/ppc/pegasos2.c
+++ b/hw/ppc/pegasos2.c
@@ -34,13 +34,36 @@
 #include "trace.h"
 #include "qemu/datadir.h"
 #include "sysemu/device_tree.h"
+#include "hw/ppc/vof.h"
 
-#define PROM_FILENAME "pegasos2.rom"
+#include <libfdt.h>
+
+#define PROM_FILENAME "vof.bin"
 #define PROM_ADDR     0xfff00000
 #define PROM_SIZE     0x80000
 
+#define KVMPPC_HCALL_BASE    0xf000
+#define KVMPPC_H_VOF_CLIENT  (KVMPPC_HCALL_BASE + 0x5)
+
+/* Copied from SLOF, and 4K is definitely not enough for GRUB */
+#define OF_STACK_SIZE       0x8000
+
+#define H_SUCCESS     0
+#define H_PRIVILEGE  -3  /* Caller not privileged */
+#define H_PARAMETER  -4  /* Parameter invalid, out-of-range or conflicting */
+
 #define BUS_FREQ_HZ 133333333
 
+#define PCI0_MEM_BASE 0xc0000000
+#define PCI0_MEM_SIZE 0x20000000
+#define PCI0_IO_BASE  0xf8000000
+#define PCI0_IO_SIZE  0x10000
+
+#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)
 
@@ -48,14 +71,26 @@ struct Pegasos2MachineState {
     MachineState parent_obj;
     PowerPCCPU *cpu;
     DeviceState *mv;
+    Vof *vof;
+    void *fdt_blob;
+    uint64_t kernel_addr;
+    uint64_t kernel_entry;
+    uint64_t kernel_size;
 };
 
+static void *build_fdt(MachineState *machine, int *fdt_size);
+
 static void pegasos2_cpu_reset(void *opaque)
 {
     PowerPCCPU *cpu = opaque;
+    Pegasos2MachineState *pm = PEGASOS2_MACHINE(current_machine);
 
     cpu_reset(CPU(cpu));
     cpu->env.spr[SPR_HID1] = 7ULL << 28;
+    if (pm->vof) {
+        cpu->env.gpr[1] = 2 * OF_STACK_SIZE - 0x20;
+        cpu->env.nip = 0x100;
+    }
 }
 
 static void pegasos2_init(MachineState *machine)
@@ -92,18 +127,24 @@ static void pegasos2_init(MachineState *machine)
         error_report("Could not find firmware '%s'", fwname);
         exit(1);
     }
+    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);
     sz = load_elf(filename, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1,
                   PPC_ELF_MACHINE, 0, 0);
     if (sz <= 0) {
-        sz = load_image_targphys(filename, 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);
         exit(1);
     }
     g_free(filename);
+    if (pm->vof) {
+        pm->vof->fw_size = sz;
+    }
 
     /* Marvell Discovery II system controller */
     pm->mv = DEVICE(sysbus_create_simple(TYPE_MV64361, -1,
@@ -137,20 +178,179 @@ static void pegasos2_init(MachineState *machine)
 
     /* other PC hardware */
     pci_vga_init(pci_bus);
+
+    if (machine->kernel_filename) {
+        sz = load_elf(machine->kernel_filename, NULL, NULL, NULL,
+                      &pm->kernel_entry, &pm->kernel_addr, NULL, NULL, 1,
+                      PPC_ELF_MACHINE, 0, 0);
+        if (sz <= 0) {
+            error_report("Could not load kernel '%s'",
+                         machine->kernel_filename);
+            exit(1);
+        }
+        pm->kernel_size = sz;
+        if (!pm->vof) {
+            warn_report("Option -kernel may be ineffective with -bios.");
+        }
+    }
+    if (machine->kernel_cmdline && !pm->vof) {
+        warn_report("Option -append may be ineffective with -bios.");
+    }
+}
+
+static void pegasos2_pci_config_write(AddressSpace *as, int bus, uint32_t addr,
+                                      uint32_t len, uint32_t val)
+{
+    hwaddr pcicfg = (bus ? 0xf1000c78 : 0xf1000cf8);
+
+    stl_le_phys(as, pcicfg, addr | BIT(31));
+    switch (len) {
+    case 4:
+        stl_le_phys(as, pcicfg + 4, val);
+        break;
+    case 2:
+        stw_le_phys(as, pcicfg + 4, val);
+        break;
+    case 1:
+        stb_phys(as, pcicfg + 4, val);
+        break;
+    default:
+        qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid length\n", __func__);
+        break;
+    }
+}
+
+static void pegasos2_machine_reset(MachineState *machine)
+{
+    Pegasos2MachineState *pm = PEGASOS2_MACHINE(machine);
+    AddressSpace *as = CPU(pm->cpu)->as;
+    void *fdt;
+    uint64_t d[2];
+    int sz;
+
+    qemu_devices_reset();
+    if (!pm->vof) {
+        return; /* Firmware should set up machine so nothing to do */
+    }
+
+    /* Otherwise, set up devices that board firmware would normally do */
+    stl_le_phys(as, 0xf1000000, 0x28020ff);
+    stl_le_phys(as, 0xf1000278, 0xa31fc);
+    stl_le_phys(as, 0xf100f300, 0x11ff0400);
+    stl_le_phys(as, 0xf100f10c, 0x80000000);
+    stl_le_phys(as, 0xf100001c, 0x8000000);
+    pegasos2_pci_config_write(as, 0, PCI_COMMAND, 2, PCI_COMMAND_IO |
+                              PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
+    pegasos2_pci_config_write(as, 1, PCI_COMMAND, 2, PCI_COMMAND_IO |
+                              PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
+
+    pegasos2_pci_config_write(as, 1, (PCI_DEVFN(12, 0) << 8) |
+                              PCI_INTERRUPT_LINE, 2, 0x9);
+    pegasos2_pci_config_write(as, 1, (PCI_DEVFN(12, 0) << 8) |
+                              0x50, 1, 0x2);
+
+    pegasos2_pci_config_write(as, 1, (PCI_DEVFN(12, 1) << 8) |
+                              PCI_INTERRUPT_LINE, 2, 0x109);
+    pegasos2_pci_config_write(as, 1, (PCI_DEVFN(12, 1) << 8) |
+                              PCI_CLASS_PROG, 1, 0xf);
+    pegasos2_pci_config_write(as, 1, (PCI_DEVFN(12, 1) << 8) |
+                              0x40, 1, 0xb);
+    pegasos2_pci_config_write(as, 1, (PCI_DEVFN(12, 1) << 8) |
+                              0x50, 4, 0x17171717);
+    pegasos2_pci_config_write(as, 1, (PCI_DEVFN(12, 1) << 8) |
+                              PCI_COMMAND, 2, 0x87);
+
+    pegasos2_pci_config_write(as, 1, (PCI_DEVFN(12, 2) << 8) |
+                              PCI_INTERRUPT_LINE, 2, 0x409);
+
+    pegasos2_pci_config_write(as, 1, (PCI_DEVFN(12, 3) << 8) |
+                              PCI_INTERRUPT_LINE, 2, 0x409);
+
+    pegasos2_pci_config_write(as, 1, (PCI_DEVFN(12, 4) << 8) |
+                              PCI_INTERRUPT_LINE, 2, 0x9);
+    pegasos2_pci_config_write(as, 1, (PCI_DEVFN(12, 4) << 8) |
+                              0x48, 4, 0xf00);
+    pegasos2_pci_config_write(as, 1, (PCI_DEVFN(12, 4) << 8) |
+                              0x40, 4, 0x558020);
+    pegasos2_pci_config_write(as, 1, (PCI_DEVFN(12, 4) << 8) |
+                              0x90, 4, 0xd00);
+
+    pegasos2_pci_config_write(as, 1, (PCI_DEVFN(12, 5) << 8) |
+                              PCI_INTERRUPT_LINE, 2, 0x309);
+
+    pegasos2_pci_config_write(as, 1, (PCI_DEVFN(12, 6) << 8) |
+                              PCI_INTERRUPT_LINE, 2, 0x309);
+
+    /* Device tree and VOF set up */
+    vof_init(pm->vof, machine->ram_size, &error_fatal);
+    if (vof_claim(pm->vof, 0, OF_STACK_SIZE, OF_STACK_SIZE) == -1) {
+        error_report("Memory allocation for stack failed");
+        exit(1);
+    }
+    if (pm->kernel_size &&
+        vof_claim(pm->vof, pm->kernel_addr, pm->kernel_size, 0) == -1) {
+        error_report("Memory for kernel is in use");
+        exit(1);
+    }
+    fdt = build_fdt(machine, &sz);
+    /* 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));
+    qemu_fdt_setprop(fdt, "/chosen", "qemu,boot-kernel", d, sizeof(d));
+
+    qemu_fdt_dumpdtb(fdt, fdt_totalsize(fdt));
+    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");
+    pm->cpu->vhyp = PPC_VIRTUAL_HYPERVISOR(machine);
+}
+
+static void pegasos2_hypercall(PPCVirtualHypervisor *vhyp, PowerPCCPU *cpu)
+{
+    Pegasos2MachineState *pm = PEGASOS2_MACHINE(vhyp);
+    CPUPPCState *env = &cpu->env;
+
+    /* The TCG path should also be holding the BQL at this point */
+    g_assert(qemu_mutex_iothread_locked());
+
+    if (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_VOF_CLIENT) {
+        int ret = vof_client_call(MACHINE(pm), pm->vof, pm->fdt_blob,
+                                  env->gpr[4]);
+        env->gpr[3] = (ret ? H_PARAMETER : H_SUCCESS);
+    } else {
+        qemu_log_mask(LOG_GUEST_ERROR, "Unsupported hypercall " TARGET_FMT_lx
+                      "\n", env->gpr[3]);
+        env->gpr[3] = -1;
+    }
+}
+
+static void vhyp_nop(PPCVirtualHypervisor *vhyp, PowerPCCPU *cpu)
+{
 }
 
 static void pegasos2_machine_class_init(ObjectClass *oc, void *data)
 {
     MachineClass *mc = MACHINE_CLASS(oc);
+    PPCVirtualHypervisorClass *vhc = PPC_VIRTUAL_HYPERVISOR_CLASS(oc);
 
     mc->desc = "Genesi/bPlan Pegasos II";
     mc->init = pegasos2_init;
+    mc->reset = pegasos2_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("7400_v2.9");
     mc->default_ram_id = "pegasos2.ram";
     mc->default_ram_size = 512 * MiB;
+
+    vhc->hypercall = pegasos2_hypercall;
+    vhc->cpu_exec_enter = vhyp_nop;
+    vhc->cpu_exec_exit = vhyp_nop;
 }
 
 static const TypeInfo pegasos2_machine_info = {
@@ -158,6 +358,10 @@ static const TypeInfo pegasos2_machine_info = {
     .parent        = TYPE_MACHINE,
     .class_init    = pegasos2_machine_class_init,
     .instance_size = sizeof(Pegasos2MachineState),
+    .interfaces = (InterfaceInfo[]) {
+        { TYPE_PPC_VIRTUAL_HYPERVISOR },
+        { }
+    },
 };
 
 static void pegasos2_machine_register_types(void)
@@ -166,3 +370,417 @@ static void pegasos2_machine_register_types(void)
 }
 
 type_init(pegasos2_machine_register_types)
+
+/* FDT creation for passing to firmware */
+
+typedef struct {
+    void *fdt;
+    const char *path;
+} FDTInfo;
+
+/* We do everything in reverse order so it comes out right in the tree */
+
+static void dt_ide(PCIBus *bus, PCIDevice *d, FDTInfo *fi)
+{
+    qemu_fdt_setprop_string(fi->fdt, fi->path, "device_type", "spi");
+}
+
+static void dt_usb(PCIBus *bus, PCIDevice *d, FDTInfo *fi)
+{
+    qemu_fdt_setprop_cell(fi->fdt, fi->path, "#size-cells", 0);
+    qemu_fdt_setprop_cell(fi->fdt, fi->path, "#address-cells", 1);
+    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");
+    qemu_fdt_setprop_string(fi->fdt, fi->path, "name", "isa");
+
+    /* addional 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");
+    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);
+    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");
+    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);
+    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");
+    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);
+    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");
+    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);
+    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");
+    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);
+    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", "");
+    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);
+    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");
+    qemu_fdt_setprop_string(fi->fdt, name->str, "name", "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 },
+    { "pci1106,8235", "other", NULL },
+    { "pci1106,3058", "sound", NULL },
+    { NULL, NULL }
+};
+
+static void add_pci_device(PCIBus *bus, PCIDevice *d, void *opaque)
+{
+    FDTInfo *fi = opaque;
+    GString *node = g_string_new(NULL);
+    uint32_t cells[(PCI_NUM_REGIONS + 1) * 5];
+    int i, j;
+    const char *name = NULL;
+    g_autofree const gchar *pn = g_strdup_printf("pci%x,%x",
+                                     pci_get_word(&d->config[PCI_VENDOR_ID]),
+                                     pci_get_word(&d->config[PCI_DEVICE_ID]));
+
+    for (i = 0; device_map[i].id; i++) {
+        if (!strcmp(pn, device_map[i].id)) {
+            name = device_map[i].name;
+            break;
+        }
+    }
+    g_string_printf(node, "%s/%s@%x", fi->path, (name ?: pn),
+                    PCI_SLOT(d->devfn));
+    if (PCI_FUNC(d->devfn)) {
+        g_string_append_printf(node, ",%x", PCI_FUNC(d->devfn));
+    }
+
+    qemu_fdt_add_subnode(fi->fdt, node->str);
+    if (device_map[i].dtf) {
+        FDTInfo cfi = { fi->fdt, node->str };
+        device_map[i].dtf(bus, d, &cfi);
+    }
+    cells[0] = cpu_to_be32(d->devfn << 8);
+    cells[1] = 0;
+    cells[2] = 0;
+    cells[3] = 0;
+    cells[4] = 0;
+    j = 5;
+    for (i = 0; i < PCI_NUM_REGIONS; i++) {
+        if (!d->io_regions[i].size) {
+            continue;
+        }
+        cells[j] = cpu_to_be32(d->devfn << 8 | (PCI_BASE_ADDRESS_0 + i * 4));
+        if (d->io_regions[i].type & PCI_BASE_ADDRESS_SPACE_IO) {
+            cells[j] |= cpu_to_be32(1 << 24);
+        } else {
+            cells[j] |= cpu_to_be32(2 << 24);
+            if (d->io_regions[i].type & PCI_BASE_ADDRESS_MEM_PREFETCH) {
+                cells[j] |= cpu_to_be32(4 << 28);
+            }
+        }
+        cells[j + 1] = 0;
+        cells[j + 2] = 0;
+        cells[j + 3] = cpu_to_be32(d->io_regions[i].size >> 32);
+        cells[j + 4] = cpu_to_be32(d->io_regions[i].size);
+        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]));
+    }
+    /* Pegasos2 firmware has subsystem-id amd 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",
+                          pci_get_word(&d->config[PCI_SUBSYSTEM_VENDOR_ID]));
+    cells[0] = pci_get_long(&d->config[PCI_CLASS_REVISION]);
+    qemu_fdt_setprop_cell(fi->fdt, node->str, "class-code", cells[0] >> 8);
+    qemu_fdt_setprop_cell(fi->fdt, node->str, "revision-id", cells[0] && 0xff);
+    qemu_fdt_setprop_cell(fi->fdt, node->str, "device-id",
+                          pci_get_word(&d->config[PCI_DEVICE_ID]));
+    qemu_fdt_setprop_cell(fi->fdt, node->str, "vendor-id",
+                          pci_get_word(&d->config[PCI_VENDOR_ID]));
+
+    g_string_free(node, TRUE);
+}
+
+static void *build_fdt(MachineState *machine, int *fdt_size)
+{
+    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");
+    qemu_fdt_setprop_string(fdt, "/pci@c0000000", "name", "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");
+    qemu_fdt_setprop_string(fdt, "/pci@80000000", "name", "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_setprop_string(fdt, "/failsafe", "name", "failsafe");
+
+    qemu_fdt_add_subnode(fdt, "/rtas");
+    qemu_fdt_setprop_cell(fdt, "/rtas", "system-reboot", 20);
+    qemu_fdt_setprop_cell(fdt, "/rtas", "hibernate", 19);
+    qemu_fdt_setprop_cell(fdt, "/rtas", "suspend", 18);
+    qemu_fdt_setprop_cell(fdt, "/rtas", "power-off", 17);
+    qemu_fdt_setprop_cell(fdt, "/rtas", "set-indicator", 11);
+    qemu_fdt_setprop_cell(fdt, "/rtas", "display-character", 10);
+    qemu_fdt_setprop_cell(fdt, "/rtas", "write-pci-config", 9);
+    qemu_fdt_setprop_cell(fdt, "/rtas", "read-pci-config", 8);
+    /* Pegasos2 firmware misspells check-exception and guests use that */
+    qemu_fdt_setprop_cell(fdt, "/rtas", "check-execption", 7);
+    qemu_fdt_setprop_cell(fdt, "/rtas", "event-scan", 6);
+    qemu_fdt_setprop_cell(fdt, "/rtas", "set-time-of-day", 4);
+    qemu_fdt_setprop_cell(fdt, "/rtas", "get-time-of-day", 3);
+    qemu_fdt_setprop_cell(fdt, "/rtas", "nvram-store", 2);
+    qemu_fdt_setprop_cell(fdt, "/rtas", "nvram-fetch", 1);
+    qemu_fdt_setprop_cell(fdt, "/rtas", "restart-rtas", 0);
+    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);
+    qemu_fdt_setprop_string(fdt, "/cpus", "name", "cpus");
+
+    /* FIXME Get CPU name from CPU object */
+    const char *cp = "/cpus/PowerPC,G4";
+    qemu_fdt_add_subnode(fdt, cp);
+    qemu_fdt_setprop_cell(fdt, cp, "l2cr", 0);
+    qemu_fdt_setprop_cell(fdt, cp, "d-cache-size", 0x8000);
+    qemu_fdt_setprop_cell(fdt, cp, "d-cache-block-size",
+                          cpu->env.dcache_line_size);
+    qemu_fdt_setprop_cell(fdt, cp, "d-cache-line-size",
+                          cpu->env.dcache_line_size);
+    qemu_fdt_setprop_cell(fdt, cp, "i-cache-size", 0x8000);
+    qemu_fdt_setprop_cell(fdt, cp, "i-cache-block-size",
+                          cpu->env.icache_line_size);
+    qemu_fdt_setprop_cell(fdt, cp, "i-cache-line-size",
+                          cpu->env.icache_line_size);
+    if (cpu->env.id_tlbs) {
+        qemu_fdt_setprop_cell(fdt, cp, "i-tlb-sets", cpu->env.nb_ways);
+        qemu_fdt_setprop_cell(fdt, cp, "i-tlb-size", cpu->env.tlb_per_way);
+        qemu_fdt_setprop_cell(fdt, cp, "d-tlb-sets", cpu->env.nb_ways);
+        qemu_fdt_setprop_cell(fdt, cp, "d-tlb-size", cpu->env.tlb_per_way);
+        qemu_fdt_setprop_string(fdt, cp, "tlb-split", "");
+    }
+    qemu_fdt_setprop_cell(fdt, cp, "tlb-sets", cpu->env.nb_ways);
+    qemu_fdt_setprop_cell(fdt, cp, "tlb-size", cpu->env.nb_tlb);
+    qemu_fdt_setprop_string(fdt, cp, "state", "running");
+    if (cpu->env.insns_flags & PPC_ALTIVEC) {
+        qemu_fdt_setprop_string(fdt, cp, "altivec", "");
+        qemu_fdt_setprop_string(fdt, cp, "data-streams", "");
+    }
+    /*
+     * FIXME What flags do data-streams, external-control and
+     * performance-monitor depend on?
+     */
+    qemu_fdt_setprop_string(fdt, cp, "external-control", "");
+    if (cpu->env.insns_flags & PPC_FLOAT_FSQRT) {
+        qemu_fdt_setprop_string(fdt, cp, "general-purpose", "");
+    }
+    qemu_fdt_setprop_string(fdt, cp, "performance-monitor", "");
+    if (cpu->env.insns_flags & PPC_FLOAT_FRES) {
+        qemu_fdt_setprop_string(fdt, cp, "graphics", "");
+    }
+    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, "cpu-version", cpu->env.spr[SPR_PVR]);
+    cells[0] = 0;
+    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");
+    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_setprop_string(fdt, "/memory@0", "name", "memory");
+
+    qemu_fdt_add_subnode(fdt, "/chosen");
+    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");
+
+    return fdt;
+}
-- 
2.21.4



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

* Re: [RFC PATCH 2/5] ppc/pegasos2: Introduce Pegasos2MachineState structure
  2021-06-06 15:46 ` [RFC PATCH 2/5] ppc/pegasos2: Introduce Pegasos2MachineState structure BALATON Zoltan
@ 2021-06-06 19:04   ` Philippe Mathieu-Daudé
  2021-06-06 20:35     ` BALATON Zoltan
  0 siblings, 1 reply; 20+ messages in thread
From: Philippe Mathieu-Daudé @ 2021-06-06 19:04 UTC (permalink / raw)
  To: BALATON Zoltan, qemu-devel, qemu-ppc; +Cc: Alexey Kardashevskiy, David Gibson

On 6/6/21 5:46 PM, BALATON Zoltan wrote:
> Add own machine state structure which will be used to store state
> needed for firmware emulation.
> 
> Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>
> ---
>  hw/ppc/pegasos2.c | 50 +++++++++++++++++++++++++++++++++++------------
>  1 file changed, 37 insertions(+), 13 deletions(-)

> +struct Pegasos2MachineState {
> +    MachineState parent_obj;
> +    PowerPCCPU *cpu;
> +    DeviceState *mv;
> +};
> +
>  static void pegasos2_cpu_reset(void *opaque)
>  {
>      PowerPCCPU *cpu = opaque;
> @@ -51,9 +60,9 @@ static void pegasos2_cpu_reset(void *opaque)
>  
>  static void pegasos2_init(MachineState *machine)
>  {
> -    PowerPCCPU *cpu = NULL;
> +    Pegasos2MachineState *pm = PEGASOS2_MACHINE(machine);
> +    CPUPPCState *env;
>      MemoryRegion *rom = g_new(MemoryRegion, 1);

It would be nice to have the 'rom' variable also in the machine state.
Can be done later...

Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>


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

* Re: [RFC PATCH 2/5] ppc/pegasos2: Introduce Pegasos2MachineState structure
  2021-06-06 19:04   ` Philippe Mathieu-Daudé
@ 2021-06-06 20:35     ` BALATON Zoltan
  0 siblings, 0 replies; 20+ messages in thread
From: BALATON Zoltan @ 2021-06-06 20:35 UTC (permalink / raw)
  To: Philippe Mathieu-Daudé
  Cc: Alexey Kardashevskiy, qemu-ppc, qemu-devel, David Gibson

[-- Attachment #1: Type: text/plain, Size: 1692 bytes --]

On Sun, 6 Jun 2021, Philippe Mathieu-Daudé wrote:
> On 6/6/21 5:46 PM, BALATON Zoltan wrote:
>> Add own machine state structure which will be used to store state
>> needed for firmware emulation.
>>
>> Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>
>> ---
>>  hw/ppc/pegasos2.c | 50 +++++++++++++++++++++++++++++++++++------------
>>  1 file changed, 37 insertions(+), 13 deletions(-)
>
>> +struct Pegasos2MachineState {
>> +    MachineState parent_obj;
>> +    PowerPCCPU *cpu;
>> +    DeviceState *mv;
>> +};
>> +
>>  static void pegasos2_cpu_reset(void *opaque)
>>  {
>>      PowerPCCPU *cpu = opaque;
>> @@ -51,9 +60,9 @@ static void pegasos2_cpu_reset(void *opaque)
>>
>>  static void pegasos2_init(MachineState *machine)
>>  {
>> -    PowerPCCPU *cpu = NULL;
>> +    Pegasos2MachineState *pm = PEGASOS2_MACHINE(machine);
>> +    CPUPPCState *env;
>>      MemoryRegion *rom = g_new(MemoryRegion, 1);
>
> It would be nice to have the 'rom' variable also in the machine state.
> Can be done later...

I've only moved vars to the new machine state that will be needed outside 
of the init method for VOF and rom isn't so that's kept local. It could be 
put there for consistency but not really needed so I've left it here.

> Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>

Thanks. By the way, even though this series allows loading Linux and 
MorphOS without the board ROM I'd prefer to keep the test using the ROM as 
implemented in your series because that excercies the emulation more than 
booting without ROM as the firmware inits more devices and uses more 
facilities that VOF mostly bypasses so for a test the board firmware is 
more complete.

Regards,
BALATON Zoltan

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

* Re: [RFC PATCH 0/5] ppc/Pegasos2 VOF
  2021-06-06 15:46 [RFC PATCH 0/5] ppc/Pegasos2 VOF BALATON Zoltan
                   ` (4 preceding siblings ...)
  2021-06-06 15:46 ` [RFC PATCH 1/5] Misc VOF fixes BALATON Zoltan
@ 2021-06-09  7:39 ` Alexey Kardashevskiy
  2021-06-09 10:28   ` BALATON Zoltan
  5 siblings, 1 reply; 20+ messages in thread
From: Alexey Kardashevskiy @ 2021-06-09  7:39 UTC (permalink / raw)
  To: BALATON Zoltan, qemu-devel, qemu-ppc; +Cc: David Gibson



On 6/7/21 01:46, BALATON Zoltan wrote:
> 
> Based-on: <20210520090557.435689-1-aik@ozlabs.ru>
> ^ That is v20 of Alexey's VOF patch
> 
> Hello,
> 
> Posting these for early review now. I plan to rebase on the next VOF
> patch that hopefully fixes those points that I had to circumvent in
> patch 1 for now. I've reported these before but now all of those that
> are needed for pegasos2 are in one place. Other points I've reported
> could be clean ups but not sttictly needed.
> 
> With this series on top of VOF v20 I can now boot Linux and MorphOS on
> pegasos2 without needing a firmware blob so I hope this is enough to
> get this board in 6.1 and also have it enabled so users can start
> using it. That means that VOF will also be merged by then. This now
> gives VOF another use case that may help it getting finished.
> 
> I've also updated my development tree with this series here:
> 
> https://osdn.net/projects/qmiga/scm/git/qemu/tree/pegasos2/
> 
> Please review so I can do any needed changes together with the rebase
> on next VOF patch so we don't miss 6.1 this time.


It would help if you provided the disk or/and kernel or/and initramdisk 
images and the example command line to give this a try. And said a few 
words who is this Pegasos2 guy :) The series looks ok to me otherwise. 
Thanks,

> 
> Regards,
> BALATON Zoltan
> 
> BALATON Zoltan (5):
>    Misc VOF fixes
>    ppc/pegasos2: Introduce Pegasos2MachineState structure
>    target/ppc: Allow virtual hypervisor on CPU without HV
>    ppc/pegasos2: Use Virtual Open Firmware as firmware replacement
>    ppc/pegasos2: Implement some RTAS functions with VOF
> 
>   default-configs/devices/ppc-softmmu.mak |   2 +-
>   hw/ppc/Kconfig                          |   1 +
>   hw/ppc/pegasos2.c                       | 780 +++++++++++++++++++++++-
>   hw/ppc/vof.c                            |  11 +-
>   pc-bios/vof.bin                         | Bin 3784 -> 3784 bytes
>   pc-bios/vof/entry.S                     |   2 +-
>   target/ppc/cpu.c                        |   2 +-
>   7 files changed, 776 insertions(+), 22 deletions(-)
> 

-- 
Alexey


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

* Re: [RFC PATCH 0/5] ppc/Pegasos2 VOF
  2021-06-09  7:39 ` [RFC PATCH 0/5] ppc/Pegasos2 VOF Alexey Kardashevskiy
@ 2021-06-09 10:28   ` BALATON Zoltan
  2021-06-10  7:14     ` Alexey Kardashevskiy
  0 siblings, 1 reply; 20+ messages in thread
From: BALATON Zoltan @ 2021-06-09 10:28 UTC (permalink / raw)
  To: Alexey Kardashevskiy; +Cc: qemu-ppc, qemu-devel, David Gibson

On Wed, 9 Jun 2021, Alexey Kardashevskiy wrote:
> On 6/7/21 01:46, BALATON Zoltan wrote:
>> Based-on: <20210520090557.435689-1-aik@ozlabs.ru>
>> ^ That is v20 of Alexey's VOF patch
>> 
>> Hello,
>> 
>> Posting these for early review now. I plan to rebase on the next VOF
>> patch that hopefully fixes those points that I had to circumvent in
>> patch 1 for now. I've reported these before but now all of those that
>> are needed for pegasos2 are in one place. Other points I've reported
>> could be clean ups but not sttictly needed.
>> 
>> With this series on top of VOF v20 I can now boot Linux and MorphOS on
>> pegasos2 without needing a firmware blob so I hope this is enough to
>> get this board in 6.1 and also have it enabled so users can start
>> using it. That means that VOF will also be merged by then. This now
>> gives VOF another use case that may help it getting finished.
>> 
>> I've also updated my development tree with this series here:
>> 
>> https://osdn.net/projects/qmiga/scm/git/qemu/tree/pegasos2/
>> 
>> Please review so I can do any needed changes together with the rebase
>> on next VOF patch so we don't miss 6.1 this time.
>
>
> It would help if you provided the disk or/and kernel or/and initramdisk 
> images and the example command line to give this a try. And said a few words 
> who is this Pegasos2 guy :) The series looks ok to me otherwise. Thanks,

These were in the original series adding this board:

https://patchew.org/QEMU/cover.1616680239.git.balaton@eik.bme.hu/

For testing I've used the kernel from debian 8.11.0 powerpc iso which is 
known to work on real hardware and MorphOS demo iso available from 
www.morphos-team.net. For debian look into install/pegasos to find the 
right vmlinuz-chrp.initrd kernel, for MorphOS use the boot.img from root 
of the iso as -kernel.

What's still missing is some rtas functions like get-time-of-day. Are 
these any kind of standard and is there a doc about their parameters and 
returns or I'll heave to find out from kernel sources? I plan to add these 
later but not needed to get it boot.

Regards,
BALATON Zoltan


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

* Re: [RFC PATCH 0/5] ppc/Pegasos2 VOF
  2021-06-09 10:28   ` BALATON Zoltan
@ 2021-06-10  7:14     ` Alexey Kardashevskiy
  2021-06-10  8:25       ` David Gibson
  0 siblings, 1 reply; 20+ messages in thread
From: Alexey Kardashevskiy @ 2021-06-10  7:14 UTC (permalink / raw)
  To: BALATON Zoltan; +Cc: qemu-ppc, qemu-devel, David Gibson



On 6/9/21 20:28, BALATON Zoltan wrote:
> On Wed, 9 Jun 2021, Alexey Kardashevskiy wrote:
>> On 6/7/21 01:46, BALATON Zoltan wrote:
>>> Based-on: <20210520090557.435689-1-aik@ozlabs.ru>
>>> ^ That is v20 of Alexey's VOF patch
>>>
>>> Hello,
>>>
>>> Posting these for early review now. I plan to rebase on the next VOF
>>> patch that hopefully fixes those points that I had to circumvent in
>>> patch 1 for now. I've reported these before but now all of those that
>>> are needed for pegasos2 are in one place. Other points I've reported
>>> could be clean ups but not sttictly needed.
>>>
>>> With this series on top of VOF v20 I can now boot Linux and MorphOS on
>>> pegasos2 without needing a firmware blob so I hope this is enough to
>>> get this board in 6.1 and also have it enabled so users can start
>>> using it. That means that VOF will also be merged by then. This now
>>> gives VOF another use case that may help it getting finished.
>>>
>>> I've also updated my development tree with this series here:
>>>
>>> https://osdn.net/projects/qmiga/scm/git/qemu/tree/pegasos2/
>>>
>>> Please review so I can do any needed changes together with the rebase
>>> on next VOF patch so we don't miss 6.1 this time.
>>
>>
>> It would help if you provided the disk or/and kernel or/and 
>> initramdisk images and the example command line to give this a try. 
>> And said a few words who is this Pegasos2 guy :) The series looks ok 
>> to me otherwise. Thanks,
> 
> These were in the original series adding this board:
> 
> https://patchew.org/QEMU/cover.1616680239.git.balaton@eik.bme.hu/


Ah ok. Thanks!


> For testing I've used the kernel from debian 8.11.0 powerpc iso which is 
> known to work on real hardware and MorphOS demo iso available from 
> www.morphos-team.net. For debian look into install/pegasos to find the 
> right vmlinuz-chrp.initrd kernel, for MorphOS use the boot.img from root 
> of the iso as -kernel.
> 
> What's still missing is some rtas functions like get-time-of-day. Are 
> these any kind of standard and is there a doc about their parameters and 
> returns or I'll heave to find out from kernel sources? I plan to add 
> these later but not needed to get it boot.

pseries guests use what the LoPAPR spec (derived from sPAPR - "server 
PAPR") describes:

https://openpowerfoundation.org/?resource_lib=linux-on-power-architecture-platform-reference


-- 
Alexey


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

* Re: [RFC PATCH 0/5] ppc/Pegasos2 VOF
  2021-06-10  7:14     ` Alexey Kardashevskiy
@ 2021-06-10  8:25       ` David Gibson
  2021-06-10 10:04         ` BALATON Zoltan
  0 siblings, 1 reply; 20+ messages in thread
From: David Gibson @ 2021-06-10  8:25 UTC (permalink / raw)
  To: Alexey Kardashevskiy; +Cc: qemu-ppc, qemu-devel

[-- Attachment #1: Type: text/plain, Size: 3158 bytes --]

On Thu, Jun 10, 2021 at 05:14:45PM +1000, Alexey Kardashevskiy wrote:
> 
> 
> On 6/9/21 20:28, BALATON Zoltan wrote:
> > On Wed, 9 Jun 2021, Alexey Kardashevskiy wrote:
> > > On 6/7/21 01:46, BALATON Zoltan wrote:
> > > > Based-on: <20210520090557.435689-1-aik@ozlabs.ru>
> > > > ^ That is v20 of Alexey's VOF patch
> > > > 
> > > > Hello,
> > > > 
> > > > Posting these for early review now. I plan to rebase on the next VOF
> > > > patch that hopefully fixes those points that I had to circumvent in
> > > > patch 1 for now. I've reported these before but now all of those that
> > > > are needed for pegasos2 are in one place. Other points I've reported
> > > > could be clean ups but not sttictly needed.
> > > > 
> > > > With this series on top of VOF v20 I can now boot Linux and MorphOS on
> > > > pegasos2 without needing a firmware blob so I hope this is enough to
> > > > get this board in 6.1 and also have it enabled so users can start
> > > > using it. That means that VOF will also be merged by then. This now
> > > > gives VOF another use case that may help it getting finished.
> > > > 
> > > > I've also updated my development tree with this series here:
> > > > 
> > > > https://osdn.net/projects/qmiga/scm/git/qemu/tree/pegasos2/
> > > > 
> > > > Please review so I can do any needed changes together with the rebase
> > > > on next VOF patch so we don't miss 6.1 this time.
> > > 
> > > 
> > > It would help if you provided the disk or/and kernel or/and
> > > initramdisk images and the example command line to give this a try.
> > > And said a few words who is this Pegasos2 guy :) The series looks ok
> > > to me otherwise. Thanks,
> > 
> > These were in the original series adding this board:
> > 
> > https://patchew.org/QEMU/cover.1616680239.git.balaton@eik.bme.hu/
> 
> 
> Ah ok. Thanks!
> 
> 
> > For testing I've used the kernel from debian 8.11.0 powerpc iso which is
> > known to work on real hardware and MorphOS demo iso available from
> > www.morphos-team.net. For debian look into install/pegasos to find the
> > right vmlinuz-chrp.initrd kernel, for MorphOS use the boot.img from root
> > of the iso as -kernel.
> > 
> > What's still missing is some rtas functions like get-time-of-day. Are
> > these any kind of standard and is there a doc about their parameters and
> > returns or I'll heave to find out from kernel sources? I plan to add
> > these later but not needed to get it boot.
> 
> pseries guests use what the LoPAPR spec (derived from sPAPR - "server PAPR")
> describes:
> 
> https://openpowerfoundation.org/?resource_lib=linux-on-power-architecture-platform-reference

Of course pegasos won't remotely be PAPR, but you could look at how
the RTAS functions are defined there.

I'm not really sure of the origins of RTAS.  It's not in plain
IEEE1275 (the original OF spec), but the fact pegasos uses it suggests
it's not purely a PAPR thing, either.

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

* Re: [RFC PATCH 0/5] ppc/Pegasos2 VOF
  2021-06-10  8:25       ` David Gibson
@ 2021-06-10 10:04         ` BALATON Zoltan
  2021-06-10 10:37           ` David Gibson
  2021-06-10 12:33           ` R: " luigi burdo
  0 siblings, 2 replies; 20+ messages in thread
From: BALATON Zoltan @ 2021-06-10 10:04 UTC (permalink / raw)
  To: David Gibson; +Cc: Alexey Kardashevskiy, qemu-ppc, qemu-devel



On Thu, 10 Jun 2021, David Gibson wrote:

> On Thu, Jun 10, 2021 at 05:14:45PM +1000, Alexey Kardashevskiy wrote:
>>
>>
>> On 6/9/21 20:28, BALATON Zoltan wrote:
>>> On Wed, 9 Jun 2021, Alexey Kardashevskiy wrote:
>>>> On 6/7/21 01:46, BALATON Zoltan wrote:
>>>>> Based-on: <20210520090557.435689-1-aik@ozlabs.ru>
>>>>> ^ That is v20 of Alexey's VOF patch
>>>>>
>>>>> Hello,
>>>>>
>>>>> Posting these for early review now. I plan to rebase on the next VOF
>>>>> patch that hopefully fixes those points that I had to circumvent in
>>>>> patch 1 for now. I've reported these before but now all of those that
>>>>> are needed for pegasos2 are in one place. Other points I've reported
>>>>> could be clean ups but not sttictly needed.
>>>>>
>>>>> With this series on top of VOF v20 I can now boot Linux and MorphOS on
>>>>> pegasos2 without needing a firmware blob so I hope this is enough to
>>>>> get this board in 6.1 and also have it enabled so users can start
>>>>> using it. That means that VOF will also be merged by then. This now
>>>>> gives VOF another use case that may help it getting finished.
>>>>>
>>>>> I've also updated my development tree with this series here:
>>>>>
>>>>> https://osdn.net/projects/qmiga/scm/git/qemu/tree/pegasos2/
>>>>>
>>>>> Please review so I can do any needed changes together with the rebase
>>>>> on next VOF patch so we don't miss 6.1 this time.
>>>>
>>>>
>>>> It would help if you provided the disk or/and kernel or/and
>>>> initramdisk images and the example command line to give this a try.
>>>> And said a few words who is this Pegasos2 guy :) The series looks ok
>>>> to me otherwise. Thanks,
>>>
>>> These were in the original series adding this board:
>>>
>>> https://patchew.org/QEMU/cover.1616680239.git.balaton@eik.bme.hu/
>>
>>
>> Ah ok. Thanks!
>>
>>
>>> For testing I've used the kernel from debian 8.11.0 powerpc iso which is
>>> known to work on real hardware and MorphOS demo iso available from
>>> www.morphos-team.net. For debian look into install/pegasos to find the
>>> right vmlinuz-chrp.initrd kernel, for MorphOS use the boot.img from root
>>> of the iso as -kernel.
>>>
>>> What's still missing is some rtas functions like get-time-of-day. Are
>>> these any kind of standard and is there a doc about their parameters and
>>> returns or I'll heave to find out from kernel sources? I plan to add
>>> these later but not needed to get it boot.
>>
>> pseries guests use what the LoPAPR spec (derived from sPAPR - "server PAPR")
>> describes:
>>
>> https://openpowerfoundation.org/?resource_lib=linux-on-power-architecture-platform-reference
>
> Of course pegasos won't remotely be PAPR, but you could look at how
> the RTAS functions are defined there.
>
> I'm not really sure of the origins of RTAS.  It's not in plain
> IEEE1275 (the original OF spec), but the fact pegasos uses it suggests
> it's not purely a PAPR thing, either.

Pegasos is supposed to be a CHRP platform so maybe there's something on it 
in that doc, I haven't checked yet but now you mentioned these I should 
probably look there.

Thenks,
BALATON Zoltan


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

* Re: [RFC PATCH 0/5] ppc/Pegasos2 VOF
  2021-06-10 10:04         ` BALATON Zoltan
@ 2021-06-10 10:37           ` David Gibson
  2021-06-10 12:33           ` R: " luigi burdo
  1 sibling, 0 replies; 20+ messages in thread
From: David Gibson @ 2021-06-10 10:37 UTC (permalink / raw)
  To: BALATON Zoltan; +Cc: Alexey Kardashevskiy, qemu-ppc, qemu-devel

[-- Attachment #1: Type: text/plain, Size: 3830 bytes --]

On Thu, Jun 10, 2021 at 12:04:59PM +0200, BALATON Zoltan wrote:
> 
> 
> On Thu, 10 Jun 2021, David Gibson wrote:
> 
> > On Thu, Jun 10, 2021 at 05:14:45PM +1000, Alexey Kardashevskiy wrote:
> > > 
> > > 
> > > On 6/9/21 20:28, BALATON Zoltan wrote:
> > > > On Wed, 9 Jun 2021, Alexey Kardashevskiy wrote:
> > > > > On 6/7/21 01:46, BALATON Zoltan wrote:
> > > > > > Based-on: <20210520090557.435689-1-aik@ozlabs.ru>
> > > > > > ^ That is v20 of Alexey's VOF patch
> > > > > > 
> > > > > > Hello,
> > > > > > 
> > > > > > Posting these for early review now. I plan to rebase on the next VOF
> > > > > > patch that hopefully fixes those points that I had to circumvent in
> > > > > > patch 1 for now. I've reported these before but now all of those that
> > > > > > are needed for pegasos2 are in one place. Other points I've reported
> > > > > > could be clean ups but not sttictly needed.
> > > > > > 
> > > > > > With this series on top of VOF v20 I can now boot Linux and MorphOS on
> > > > > > pegasos2 without needing a firmware blob so I hope this is enough to
> > > > > > get this board in 6.1 and also have it enabled so users can start
> > > > > > using it. That means that VOF will also be merged by then. This now
> > > > > > gives VOF another use case that may help it getting finished.
> > > > > > 
> > > > > > I've also updated my development tree with this series here:
> > > > > > 
> > > > > > https://osdn.net/projects/qmiga/scm/git/qemu/tree/pegasos2/
> > > > > > 
> > > > > > Please review so I can do any needed changes together with the rebase
> > > > > > on next VOF patch so we don't miss 6.1 this time.
> > > > > 
> > > > > 
> > > > > It would help if you provided the disk or/and kernel or/and
> > > > > initramdisk images and the example command line to give this a try.
> > > > > And said a few words who is this Pegasos2 guy :) The series looks ok
> > > > > to me otherwise. Thanks,
> > > > 
> > > > These were in the original series adding this board:
> > > > 
> > > > https://patchew.org/QEMU/cover.1616680239.git.balaton@eik.bme.hu/
> > > 
> > > 
> > > Ah ok. Thanks!
> > > 
> > > 
> > > > For testing I've used the kernel from debian 8.11.0 powerpc iso which is
> > > > known to work on real hardware and MorphOS demo iso available from
> > > > www.morphos-team.net. For debian look into install/pegasos to find the
> > > > right vmlinuz-chrp.initrd kernel, for MorphOS use the boot.img from root
> > > > of the iso as -kernel.
> > > > 
> > > > What's still missing is some rtas functions like get-time-of-day. Are
> > > > these any kind of standard and is there a doc about their parameters and
> > > > returns or I'll heave to find out from kernel sources? I plan to add
> > > > these later but not needed to get it boot.
> > > 
> > > pseries guests use what the LoPAPR spec (derived from sPAPR - "server PAPR")
> > > describes:
> > > 
> > > https://openpowerfoundation.org/?resource_lib=linux-on-power-architecture-platform-reference
> > 
> > Of course pegasos won't remotely be PAPR, but you could look at how
> > the RTAS functions are defined there.
> > 
> > I'm not really sure of the origins of RTAS.  It's not in plain
> > IEEE1275 (the original OF spec), but the fact pegasos uses it suggests
> > it's not purely a PAPR thing, either.
> 
> Pegasos is supposed to be a CHRP platform so maybe there's something on it
> in that doc, I haven't checked yet but now you mentioned these I should
> probably look there.

Sounds like a good bet.  I believe PAPR is a distant descendent of
CHRP, so that seems pretty likely.

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

* R: [RFC PATCH 0/5] ppc/Pegasos2 VOF
  2021-06-10 10:04         ` BALATON Zoltan
  2021-06-10 10:37           ` David Gibson
@ 2021-06-10 12:33           ` luigi burdo
  2021-06-10 12:52             ` BALATON Zoltan
  1 sibling, 1 reply; 20+ messages in thread
From: luigi burdo @ 2021-06-10 12:33 UTC (permalink / raw)
  To: BALATON Zoltan; +Cc: qemu-ppc, qemu-devel, David Gibson

[-- Attachment #1: Type: text/plain, Size: 3979 bytes --]

Hi Zoltan,
i dont know if you know and if in the docs is described the pegasos II can support smp dual G4 cpu.
Here some hystorical info about this great machine from the past Phase 5 A\BOX (kosmoplovci.net)<https://www.kosmoplovci.net/hc/hc4/tech/phase5-abox.html>.
i remember really good that period (when i was young man)... the  caipirinha become one of my best cocktail 🙂

Ciao
Luigi

________________________________
Da: Qemu-ppc <qemu-ppc-bounces+intermediadc=hotmail.com@nongnu.org> per conto di BALATON Zoltan <balaton@eik.bme.hu>
Inviato: giovedì 10 giugno 2021 12:04
A: David Gibson <david@gibson.dropbear.id.au>
Cc: qemu-ppc@nongnu.org <qemu-ppc@nongnu.org>; qemu-devel@nongnu.org <qemu-devel@nongnu.org>
Oggetto: Re: [RFC PATCH 0/5] ppc/Pegasos2 VOF



On Thu, 10 Jun 2021, David Gibson wrote:

> On Thu, Jun 10, 2021 at 05:14:45PM +1000, Alexey Kardashevskiy wrote:
>>
>>
>> On 6/9/21 20:28, BALATON Zoltan wrote:
>>> On Wed, 9 Jun 2021, Alexey Kardashevskiy wrote:
>>>> On 6/7/21 01:46, BALATON Zoltan wrote:
>>>>> Based-on: <20210520090557.435689-1-aik@ozlabs.ru>
>>>>> ^ That is v20 of Alexey's VOF patch
>>>>>
>>>>> Hello,
>>>>>
>>>>> Posting these for early review now. I plan to rebase on the next VOF
>>>>> patch that hopefully fixes those points that I had to circumvent in
>>>>> patch 1 for now. I've reported these before but now all of those that
>>>>> are needed for pegasos2 are in one place. Other points I've reported
>>>>> could be clean ups but not sttictly needed.
>>>>>
>>>>> With this series on top of VOF v20 I can now boot Linux and MorphOS on
>>>>> pegasos2 without needing a firmware blob so I hope this is enough to
>>>>> get this board in 6.1 and also have it enabled so users can start
>>>>> using it. That means that VOF will also be merged by then. This now
>>>>> gives VOF another use case that may help it getting finished.
>>>>>
>>>>> I've also updated my development tree with this series here:
>>>>>
>>>>> https://osdn.net/projects/qmiga/scm/git/qemu/tree/pegasos2/
>>>>>
>>>>> Please review so I can do any needed changes together with the rebase
>>>>> on next VOF patch so we don't miss 6.1 this time.
>>>>
>>>>
>>>> It would help if you provided the disk or/and kernel or/and
>>>> initramdisk images and the example command line to give this a try.
>>>> And said a few words who is this Pegasos2 guy :) The series looks ok
>>>> to me otherwise. Thanks,
>>>
>>> These were in the original series adding this board:
>>>
>>> https://patchew.org/QEMU/cover.1616680239.git.balaton@eik.bme.hu/
>>
>>
>> Ah ok. Thanks!
>>
>>
>>> For testing I've used the kernel from debian 8.11.0 powerpc iso which is
>>> known to work on real hardware and MorphOS demo iso available from
>>> www.morphos-team.net<http://www.morphos-team.net>. For debian look into install/pegasos to find the
>>> right vmlinuz-chrp.initrd kernel, for MorphOS use the boot.img from root
>>> of the iso as -kernel.
>>>
>>> What's still missing is some rtas functions like get-time-of-day. Are
>>> these any kind of standard and is there a doc about their parameters and
>>> returns or I'll heave to find out from kernel sources? I plan to add
>>> these later but not needed to get it boot.
>>
>> pseries guests use what the LoPAPR spec (derived from sPAPR - "server PAPR")
>> describes:
>>
>> https://openpowerfoundation.org/?resource_lib=linux-on-power-architecture-platform-reference
>
> Of course pegasos won't remotely be PAPR, but you could look at how
> the RTAS functions are defined there.
>
> I'm not really sure of the origins of RTAS.  It's not in plain
> IEEE1275 (the original OF spec), but the fact pegasos uses it suggests
> it's not purely a PAPR thing, either.

Pegasos is supposed to be a CHRP platform so maybe there's something on it
in that doc, I haven't checked yet but now you mentioned these I should
probably look there.

Thenks,
BALATON Zoltan


[-- Attachment #2: Type: text/html, Size: 6885 bytes --]

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

* Re: R: [RFC PATCH 0/5] ppc/Pegasos2 VOF
  2021-06-10 12:33           ` R: " luigi burdo
@ 2021-06-10 12:52             ` BALATON Zoltan
  0 siblings, 0 replies; 20+ messages in thread
From: BALATON Zoltan @ 2021-06-10 12:52 UTC (permalink / raw)
  To: luigi burdo; +Cc: qemu-ppc, qemu-devel, David Gibson

[-- Attachment #1: Type: text/plain, Size: 1488 bytes --]

On Thu, 10 Jun 2021, luigi burdo wrote:
> i dont know if you know and if in the docs is described the pegasos II can support smp dual G4 cpu.

I think theoretically the Marvell Discovery II chip can support dual CPU 
and meybe even a G5, this is described in its docs. However in practice 
this was never implemented for Pegasos2 and there was only either a G3 or 
G4 single CPU card available for it. It probably does not make much sense 
to emulate anything else than the G4 version as that's what has the most 
features that guest OSes can use. The current emulation is just enough for 
that and I don't plan to implement more of the MV64361 chip to emulate non 
existent SMP configs as probably nothing would run on it anyway so it does 
not worth the extra effort.

> Here some hystorical info about this great machine from the past Phase 5 A\BOX (kosmoplovci.net)<https://www.kosmoplovci.net/hc/hc4/tech/phase5-abox.html>.
> i remember really good that period (when i was young man)... the  caipirinha become one of my best cocktail 🙂

Maybe interesting for history behind Pegasos2 only but otherwise probably 
not too relevant to how it was actually implemented at the end which is 
what counts if you want to run existing guests OSes. This doc seems to 
describe a system that wasn't implemented but instead a similar system was 
made from off the shelf components available at the time so for emulation 
a better reference are the docs of those chips.

Regards.
BALATON Zoltan

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

* Re: [RFC PATCH 4/5] ppc/pegasos2: Use Virtual Open Firmware as firmware replacement
  2021-06-06 15:46 ` [RFC PATCH 4/5] ppc/pegasos2: Use Virtual Open Firmware as firmware replacement BALATON Zoltan
@ 2021-06-15  7:09   ` Alexey Kardashevskiy
  2021-06-15  9:44     ` BALATON Zoltan
  0 siblings, 1 reply; 20+ messages in thread
From: Alexey Kardashevskiy @ 2021-06-15  7:09 UTC (permalink / raw)
  To: BALATON Zoltan; +Cc: qemu-ppc, qemu-devel, David Gibson



On 6/7/21 01:46, BALATON Zoltan wrote:
> The pegasos2 board comes with an Open Firmware compliant ROM based on
> SmartFirmware but it has some changes that are not open source
> therefore the ROM binary cannot be included in QEMU. Guests running on
> the board however depend on services provided by the firmware. The
> Virtual Open Firmware recently added to QEMU imlements a minimal set
> of these services to allow some guests to boot without the original
> firmware. This patch adds VOF as the default firmware for pegasos2
> which allows booting Linux and MorphOS via -kernel option while a ROM
> image can still be used with -bios for guests that don't run with VOF.
> 
> Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>
> ---
>   hw/ppc/Kconfig    |   1 +
>   hw/ppc/pegasos2.c | 622 +++++++++++++++++++++++++++++++++++++++++++++-
>   2 files changed, 621 insertions(+), 2 deletions(-)
> 
> diff --git a/hw/ppc/Kconfig b/hw/ppc/Kconfig
> index b895720b28..0eb48128fe 100644
> --- a/hw/ppc/Kconfig
> +++ b/hw/ppc/Kconfig
> @@ -75,6 +75,7 @@ config PEGASOS2
>       select VT82C686
>       select IDE_VIA
>       select SMBUS_EEPROM
> +    select VOF
>   # This should come with VT82C686
>       select ACPI_X86
>   
> diff --git a/hw/ppc/pegasos2.c b/hw/ppc/pegasos2.c
> index 07971175c9..91e5fa8fbe 100644
> --- a/hw/ppc/pegasos2.c
> +++ b/hw/ppc/pegasos2.c
> @@ -34,13 +34,36 @@
>   #include "trace.h"
>   #include "qemu/datadir.h"
>   #include "sysemu/device_tree.h"
> +#include "hw/ppc/vof.h"
>   
> -#define PROM_FILENAME "pegasos2.rom"
> +#include <libfdt.h>
> +
> +#define PROM_FILENAME "vof.bin"
>   #define PROM_ADDR     0xfff00000
>   #define PROM_SIZE     0x80000
>   
> +#define KVMPPC_HCALL_BASE    0xf000
> +#define KVMPPC_H_VOF_CLIENT  (KVMPPC_HCALL_BASE + 0x5)
> +
> +/* Copied from SLOF, and 4K is definitely not enough for GRUB */
> +#define OF_STACK_SIZE       0x8000
> +
> +#define H_SUCCESS     0
> +#define H_PRIVILEGE  -3  /* Caller not privileged */
> +#define H_PARAMETER  -4  /* Parameter invalid, out-of-range or conflicting */
> +
>   #define BUS_FREQ_HZ 133333333
>   
> +#define PCI0_MEM_BASE 0xc0000000
> +#define PCI0_MEM_SIZE 0x20000000
> +#define PCI0_IO_BASE  0xf8000000
> +#define PCI0_IO_SIZE  0x10000
> +
> +#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)
>   
> @@ -48,14 +71,26 @@ struct Pegasos2MachineState {
>       MachineState parent_obj;
>       PowerPCCPU *cpu;
>       DeviceState *mv;
> +    Vof *vof;
> +    void *fdt_blob;
> +    uint64_t kernel_addr;
> +    uint64_t kernel_entry;
> +    uint64_t kernel_size;
>   };
>   
> +static void *build_fdt(MachineState *machine, int *fdt_size);
> +
>   static void pegasos2_cpu_reset(void *opaque)
>   {
>       PowerPCCPU *cpu = opaque;
> +    Pegasos2MachineState *pm = PEGASOS2_MACHINE(current_machine);
>   
>       cpu_reset(CPU(cpu));
>       cpu->env.spr[SPR_HID1] = 7ULL << 28;
> +    if (pm->vof) {
> +        cpu->env.gpr[1] = 2 * OF_STACK_SIZE - 0x20;
> +        cpu->env.nip = 0x100;
> +    }
>   }
>   
>   static void pegasos2_init(MachineState *machine)
> @@ -92,18 +127,24 @@ static void pegasos2_init(MachineState *machine)
>           error_report("Could not find firmware '%s'", fwname);
>           exit(1);
>       }
> +    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);
>       sz = load_elf(filename, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1,
>                     PPC_ELF_MACHINE, 0, 0);
>       if (sz <= 0) {
> -        sz = load_image_targphys(filename, 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);
>           exit(1);
>       }
>       g_free(filename);
> +    if (pm->vof) {
> +        pm->vof->fw_size = sz;
> +    }
>   
>       /* Marvell Discovery II system controller */
>       pm->mv = DEVICE(sysbus_create_simple(TYPE_MV64361, -1,
> @@ -137,20 +178,179 @@ static void pegasos2_init(MachineState *machine)
>   
>       /* other PC hardware */
>       pci_vga_init(pci_bus);
> +
> +    if (machine->kernel_filename) {
> +        sz = load_elf(machine->kernel_filename, NULL, NULL, NULL,
> +                      &pm->kernel_entry, &pm->kernel_addr, NULL, NULL, 1,
> +                      PPC_ELF_MACHINE, 0, 0);
> +        if (sz <= 0) {
> +            error_report("Could not load kernel '%s'",
> +                         machine->kernel_filename);
> +            exit(1);
> +        }
> +        pm->kernel_size = sz;
> +        if (!pm->vof) {
> +            warn_report("Option -kernel may be ineffective with -bios.");
> +        }
> +    }
> +    if (machine->kernel_cmdline && !pm->vof) {
> +        warn_report("Option -append may be ineffective with -bios.");
> +    }
> +}
> +
> +static void pegasos2_pci_config_write(AddressSpace *as, int bus, uint32_t addr,
> +                                      uint32_t len, uint32_t val)
> +{
> +    hwaddr pcicfg = (bus ? 0xf1000c78 : 0xf1000cf8);
> +
> +    stl_le_phys(as, pcicfg, addr | BIT(31));
> +    switch (len) {
> +    case 4:
> +        stl_le_phys(as, pcicfg + 4, val);
> +        break;
> +    case 2:
> +        stw_le_phys(as, pcicfg + 4, val);
> +        break;
> +    case 1:
> +        stb_phys(as, pcicfg + 4, val);
> +        break;
> +    default:
> +        qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid length\n", __func__);
> +        break;
> +    }
> +}
> +
> +static void pegasos2_machine_reset(MachineState *machine)
> +{
> +    Pegasos2MachineState *pm = PEGASOS2_MACHINE(machine);
> +    AddressSpace *as = CPU(pm->cpu)->as;
> +    void *fdt;
> +    uint64_t d[2];
> +    int sz;
> +
> +    qemu_devices_reset();
> +    if (!pm->vof) {
> +        return; /* Firmware should set up machine so nothing to do */
> +    }
> +
> +    /* Otherwise, set up devices that board firmware would normally do */
> +    stl_le_phys(as, 0xf1000000, 0x28020ff);
> +    stl_le_phys(as, 0xf1000278, 0xa31fc);
> +    stl_le_phys(as, 0xf100f300, 0x11ff0400);
> +    stl_le_phys(as, 0xf100f10c, 0x80000000);
> +    stl_le_phys(as, 0xf100001c, 0x8000000);
> +    pegasos2_pci_config_write(as, 0, PCI_COMMAND, 2, PCI_COMMAND_IO |
> +                              PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
> +    pegasos2_pci_config_write(as, 1, PCI_COMMAND, 2, PCI_COMMAND_IO |
> +                              PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
> +
> +    pegasos2_pci_config_write(as, 1, (PCI_DEVFN(12, 0) << 8) |
> +                              PCI_INTERRUPT_LINE, 2, 0x9);
> +    pegasos2_pci_config_write(as, 1, (PCI_DEVFN(12, 0) << 8) |
> +                              0x50, 1, 0x2);
> +
> +    pegasos2_pci_config_write(as, 1, (PCI_DEVFN(12, 1) << 8) |
> +                              PCI_INTERRUPT_LINE, 2, 0x109);
> +    pegasos2_pci_config_write(as, 1, (PCI_DEVFN(12, 1) << 8) |
> +                              PCI_CLASS_PROG, 1, 0xf);
> +    pegasos2_pci_config_write(as, 1, (PCI_DEVFN(12, 1) << 8) |
> +                              0x40, 1, 0xb);
> +    pegasos2_pci_config_write(as, 1, (PCI_DEVFN(12, 1) << 8) |
> +                              0x50, 4, 0x17171717);
> +    pegasos2_pci_config_write(as, 1, (PCI_DEVFN(12, 1) << 8) |
> +                              PCI_COMMAND, 2, 0x87);
> +
> +    pegasos2_pci_config_write(as, 1, (PCI_DEVFN(12, 2) << 8) |
> +                              PCI_INTERRUPT_LINE, 2, 0x409);
> +
> +    pegasos2_pci_config_write(as, 1, (PCI_DEVFN(12, 3) << 8) |
> +                              PCI_INTERRUPT_LINE, 2, 0x409);
> +
> +    pegasos2_pci_config_write(as, 1, (PCI_DEVFN(12, 4) << 8) |
> +                              PCI_INTERRUPT_LINE, 2, 0x9);
> +    pegasos2_pci_config_write(as, 1, (PCI_DEVFN(12, 4) << 8) |
> +                              0x48, 4, 0xf00);
> +    pegasos2_pci_config_write(as, 1, (PCI_DEVFN(12, 4) << 8) |
> +                              0x40, 4, 0x558020);
> +    pegasos2_pci_config_write(as, 1, (PCI_DEVFN(12, 4) << 8) |
> +                              0x90, 4, 0xd00);
> +
> +    pegasos2_pci_config_write(as, 1, (PCI_DEVFN(12, 5) << 8) |
> +                              PCI_INTERRUPT_LINE, 2, 0x309);
> +
> +    pegasos2_pci_config_write(as, 1, (PCI_DEVFN(12, 6) << 8) |
> +                              PCI_INTERRUPT_LINE, 2, 0x309);
> +
> +    /* Device tree and VOF set up */
> +    vof_init(pm->vof, machine->ram_size, &error_fatal);
> +    if (vof_claim(pm->vof, 0, OF_STACK_SIZE, OF_STACK_SIZE) == -1) {
> +        error_report("Memory allocation for stack failed");
> +        exit(1);
> +    }
> +    if (pm->kernel_size &&
> +        vof_claim(pm->vof, pm->kernel_addr, pm->kernel_size, 0) == -1) {
> +        error_report("Memory for kernel is in use");
> +        exit(1);
> +    }
> +    fdt = build_fdt(machine, &sz);
> +    /* 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));
> +    qemu_fdt_setprop(fdt, "/chosen", "qemu,boot-kernel", d, sizeof(d));
> +
> +    qemu_fdt_dumpdtb(fdt, fdt_totalsize(fdt));
> +    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");
> +    pm->cpu->vhyp = PPC_VIRTUAL_HYPERVISOR(machine);
> +}
> +
> +static void pegasos2_hypercall(PPCVirtualHypervisor *vhyp, PowerPCCPU *cpu)
> +{
> +    Pegasos2MachineState *pm = PEGASOS2_MACHINE(vhyp);
> +    CPUPPCState *env = &cpu->env;
> +
> +    /* The TCG path should also be holding the BQL at this point */
> +    g_assert(qemu_mutex_iothread_locked());
> +
> +    if (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_VOF_CLIENT) {
> +        int ret = vof_client_call(MACHINE(pm), pm->vof, pm->fdt_blob,
> +                                  env->gpr[4]);
> +        env->gpr[3] = (ret ? H_PARAMETER : H_SUCCESS);
> +    } else {
> +        qemu_log_mask(LOG_GUEST_ERROR, "Unsupported hypercall " TARGET_FMT_lx
> +                      "\n", env->gpr[3]);
> +        env->gpr[3] = -1;
> +    }
> +}
> +
> +static void vhyp_nop(PPCVirtualHypervisor *vhyp, PowerPCCPU *cpu)
> +{
>   }
>   
>   static void pegasos2_machine_class_init(ObjectClass *oc, void *data)
>   {
>       MachineClass *mc = MACHINE_CLASS(oc);
> +    PPCVirtualHypervisorClass *vhc = PPC_VIRTUAL_HYPERVISOR_CLASS(oc);
>   
>       mc->desc = "Genesi/bPlan Pegasos II";
>       mc->init = pegasos2_init;
> +    mc->reset = pegasos2_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("7400_v2.9");
>       mc->default_ram_id = "pegasos2.ram";
>       mc->default_ram_size = 512 * MiB;
> +
> +    vhc->hypercall = pegasos2_hypercall;
> +    vhc->cpu_exec_enter = vhyp_nop;
> +    vhc->cpu_exec_exit = vhyp_nop;
>   }
>   
>   static const TypeInfo pegasos2_machine_info = {
> @@ -158,6 +358,10 @@ static const TypeInfo pegasos2_machine_info = {
>       .parent        = TYPE_MACHINE,
>       .class_init    = pegasos2_machine_class_init,
>       .instance_size = sizeof(Pegasos2MachineState),
> +    .interfaces = (InterfaceInfo[]) {
> +        { TYPE_PPC_VIRTUAL_HYPERVISOR },
> +        { }
> +    },
>   };
>   
>   static void pegasos2_machine_register_types(void)
> @@ -166,3 +370,417 @@ static void pegasos2_machine_register_types(void)
>   }
>   
>   type_init(pegasos2_machine_register_types)
> +
> +/* FDT creation for passing to firmware */
> +
> +typedef struct {
> +    void *fdt;
> +    const char *path;
> +} FDTInfo;
> +
> +/* We do everything in reverse order so it comes out right in the tree */
> +
> +static void dt_ide(PCIBus *bus, PCIDevice *d, FDTInfo *fi)
> +{
> +    qemu_fdt_setprop_string(fi->fdt, fi->path, "device_type", "spi");
> +}
> +
> +static void dt_usb(PCIBus *bus, PCIDevice *d, FDTInfo *fi)
> +{
> +    qemu_fdt_setprop_cell(fi->fdt, fi->path, "#size-cells", 0);
> +    qemu_fdt_setprop_cell(fi->fdt, fi->path, "#address-cells", 1);
> +    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");
> +    qemu_fdt_setprop_string(fi->fdt, fi->path, "name", "isa");
> +
> +    /* addional 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");
> +    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);
> +    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");
> +    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);
> +    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");
> +    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);
> +    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");
> +    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);
> +    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");
> +    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);
> +    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", "");
> +    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);
> +    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");
> +    qemu_fdt_setprop_string(fi->fdt, name->str, "name", "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 },
> +    { "pci1106,8235", "other", NULL },
> +    { "pci1106,3058", "sound", NULL },
> +    { NULL, NULL }
> +};
> +
> +static void add_pci_device(PCIBus *bus, PCIDevice *d, void *opaque)
> +{
> +    FDTInfo *fi = opaque;
> +    GString *node = g_string_new(NULL);
> +    uint32_t cells[(PCI_NUM_REGIONS + 1) * 5];
> +    int i, j;
> +    const char *name = NULL;
> +    g_autofree const gchar *pn = g_strdup_printf("pci%x,%x",
> +                                     pci_get_word(&d->config[PCI_VENDOR_ID]),
> +                                     pci_get_word(&d->config[PCI_DEVICE_ID]));
> +
> +    for (i = 0; device_map[i].id; i++) {
> +        if (!strcmp(pn, device_map[i].id)) {
> +            name = device_map[i].name;
> +            break;
> +        }
> +    }
> +    g_string_printf(node, "%s/%s@%x", fi->path, (name ?: pn),
> +                    PCI_SLOT(d->devfn));
> +    if (PCI_FUNC(d->devfn)) {
> +        g_string_append_printf(node, ",%x", PCI_FUNC(d->devfn));
> +    }
> +
> +    qemu_fdt_add_subnode(fi->fdt, node->str);
> +    if (device_map[i].dtf) {
> +        FDTInfo cfi = { fi->fdt, node->str };
> +        device_map[i].dtf(bus, d, &cfi);
> +    }
> +    cells[0] = cpu_to_be32(d->devfn << 8);
> +    cells[1] = 0;
> +    cells[2] = 0;
> +    cells[3] = 0;
> +    cells[4] = 0;
> +    j = 5;
> +    for (i = 0; i < PCI_NUM_REGIONS; i++) {
> +        if (!d->io_regions[i].size) {
> +            continue;
> +        }
> +        cells[j] = cpu_to_be32(d->devfn << 8 | (PCI_BASE_ADDRESS_0 + i * 4));
> +        if (d->io_regions[i].type & PCI_BASE_ADDRESS_SPACE_IO) {
> +            cells[j] |= cpu_to_be32(1 << 24);
> +        } else {
> +            cells[j] |= cpu_to_be32(2 << 24);
> +            if (d->io_regions[i].type & PCI_BASE_ADDRESS_MEM_PREFETCH) {
> +                cells[j] |= cpu_to_be32(4 << 28);
> +            }
> +        }
> +        cells[j + 1] = 0;
> +        cells[j + 2] = 0;
> +        cells[j + 3] = cpu_to_be32(d->io_regions[i].size >> 32);
> +        cells[j + 4] = cpu_to_be32(d->io_regions[i].size);
> +        j += 5;
> +    }


btw I was wondering if Linux on pegasos2 could assign resources when 
/chosen/linux,pci-probe-only is in the FDT, could not it? Or the serial 
device does not probe and Linux does not boot?



-- 
Alexey


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

* Re: [RFC PATCH 4/5] ppc/pegasos2: Use Virtual Open Firmware as firmware replacement
  2021-06-15  7:09   ` Alexey Kardashevskiy
@ 2021-06-15  9:44     ` BALATON Zoltan
  2021-06-16  4:58       ` Alexey Kardashevskiy
  0 siblings, 1 reply; 20+ messages in thread
From: BALATON Zoltan @ 2021-06-15  9:44 UTC (permalink / raw)
  To: Alexey Kardashevskiy; +Cc: qemu-ppc, qemu-devel, David Gibson

On Tue, 15 Jun 2021, Alexey Kardashevskiy wrote:
> On 6/7/21 01:46, BALATON Zoltan wrote:
>> The pegasos2 board comes with an Open Firmware compliant ROM based on
>> SmartFirmware but it has some changes that are not open source
>> therefore the ROM binary cannot be included in QEMU. Guests running on
>> the board however depend on services provided by the firmware. The
>> Virtual Open Firmware recently added to QEMU imlements a minimal set
>> of these services to allow some guests to boot without the original
>> firmware. This patch adds VOF as the default firmware for pegasos2
>> which allows booting Linux and MorphOS via -kernel option while a ROM
>> image can still be used with -bios for guests that don't run with VOF.
>> 
>> Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>
>> ---
>>   hw/ppc/Kconfig    |   1 +
>>   hw/ppc/pegasos2.c | 622 +++++++++++++++++++++++++++++++++++++++++++++-
>>   2 files changed, 621 insertions(+), 2 deletions(-)
>> 
>> diff --git a/hw/ppc/Kconfig b/hw/ppc/Kconfig
>> index b895720b28..0eb48128fe 100644
>> --- a/hw/ppc/Kconfig
>> +++ b/hw/ppc/Kconfig
>> @@ -75,6 +75,7 @@ config PEGASOS2
>>       select VT82C686
>>       select IDE_VIA
>>       select SMBUS_EEPROM
>> +    select VOF
>>   # This should come with VT82C686
>>       select ACPI_X86
>>   diff --git a/hw/ppc/pegasos2.c b/hw/ppc/pegasos2.c
>> index 07971175c9..91e5fa8fbe 100644
>> --- a/hw/ppc/pegasos2.c
>> +++ b/hw/ppc/pegasos2.c
[...]
>> +static void add_pci_device(PCIBus *bus, PCIDevice *d, void *opaque)
>> +{
>> +    FDTInfo *fi = opaque;
>> +    GString *node = g_string_new(NULL);
>> +    uint32_t cells[(PCI_NUM_REGIONS + 1) * 5];
>> +    int i, j;
>> +    const char *name = NULL;
>> +    g_autofree const gchar *pn = g_strdup_printf("pci%x,%x",
>> + 
>> pci_get_word(&d->config[PCI_VENDOR_ID]),
>> + 
>> pci_get_word(&d->config[PCI_DEVICE_ID]));
>> +
>> +    for (i = 0; device_map[i].id; i++) {
>> +        if (!strcmp(pn, device_map[i].id)) {
>> +            name = device_map[i].name;
>> +            break;
>> +        }
>> +    }
>> +    g_string_printf(node, "%s/%s@%x", fi->path, (name ?: pn),
>> +                    PCI_SLOT(d->devfn));
>> +    if (PCI_FUNC(d->devfn)) {
>> +        g_string_append_printf(node, ",%x", PCI_FUNC(d->devfn));
>> +    }
>> +
>> +    qemu_fdt_add_subnode(fi->fdt, node->str);
>> +    if (device_map[i].dtf) {
>> +        FDTInfo cfi = { fi->fdt, node->str };
>> +        device_map[i].dtf(bus, d, &cfi);
>> +    }
>> +    cells[0] = cpu_to_be32(d->devfn << 8);
>> +    cells[1] = 0;
>> +    cells[2] = 0;
>> +    cells[3] = 0;
>> +    cells[4] = 0;
>> +    j = 5;
>> +    for (i = 0; i < PCI_NUM_REGIONS; i++) {
>> +        if (!d->io_regions[i].size) {
>> +            continue;
>> +        }
>> +        cells[j] = cpu_to_be32(d->devfn << 8 | (PCI_BASE_ADDRESS_0 + i * 
>> 4));
>> +        if (d->io_regions[i].type & PCI_BASE_ADDRESS_SPACE_IO) {
>> +            cells[j] |= cpu_to_be32(1 << 24);
>> +        } else {
>> +            cells[j] |= cpu_to_be32(2 << 24);
>> +            if (d->io_regions[i].type & PCI_BASE_ADDRESS_MEM_PREFETCH) {
>> +                cells[j] |= cpu_to_be32(4 << 28);
>> +            }
>> +        }
>> +        cells[j + 1] = 0;
>> +        cells[j + 2] = 0;
>> +        cells[j + 3] = cpu_to_be32(d->io_regions[i].size >> 32);
>> +        cells[j + 4] = cpu_to_be32(d->io_regions[i].size);
>> +        j += 5;
>> +    }
>
>
> btw I was wondering if Linux on pegasos2 could assign resources when 
> /chosen/linux,pci-probe-only is in the FDT, could not it? Or the serial 
> device does not probe and Linux does not boot?

Linux probes PCI devices by itself but MorphOS relies on the device tree 
entries so I need at least the reg properties for that then it will map 
the BARs but I think it won't scan the bus otherwise. You still seem to 
add PCI devices in spapr too, at least I think I've got the idea for this 
function above from there.

Regards,
BALATON Zoltan


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

* Re: [RFC PATCH 4/5] ppc/pegasos2: Use Virtual Open Firmware as firmware replacement
  2021-06-15  9:44     ` BALATON Zoltan
@ 2021-06-16  4:58       ` Alexey Kardashevskiy
  2021-06-16 10:38         ` BALATON Zoltan
  0 siblings, 1 reply; 20+ messages in thread
From: Alexey Kardashevskiy @ 2021-06-16  4:58 UTC (permalink / raw)
  To: BALATON Zoltan; +Cc: qemu-ppc, qemu-devel, David Gibson



On 6/15/21 19:44, BALATON Zoltan wrote:
> On Tue, 15 Jun 2021, Alexey Kardashevskiy wrote:
>> On 6/7/21 01:46, BALATON Zoltan wrote:
>>> The pegasos2 board comes with an Open Firmware compliant ROM based on
>>> SmartFirmware but it has some changes that are not open source
>>> therefore the ROM binary cannot be included in QEMU. Guests running on
>>> the board however depend on services provided by the firmware. The
>>> Virtual Open Firmware recently added to QEMU imlements a minimal set
>>> of these services to allow some guests to boot without the original
>>> firmware. This patch adds VOF as the default firmware for pegasos2
>>> which allows booting Linux and MorphOS via -kernel option while a ROM
>>> image can still be used with -bios for guests that don't run with VOF.
>>>
>>> Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>
>>> ---
>>>   hw/ppc/Kconfig    |   1 +
>>>   hw/ppc/pegasos2.c | 622 +++++++++++++++++++++++++++++++++++++++++++++-
>>>   2 files changed, 621 insertions(+), 2 deletions(-)
>>>
>>> diff --git a/hw/ppc/Kconfig b/hw/ppc/Kconfig
>>> index b895720b28..0eb48128fe 100644
>>> --- a/hw/ppc/Kconfig
>>> +++ b/hw/ppc/Kconfig
>>> @@ -75,6 +75,7 @@ config PEGASOS2
>>>       select VT82C686
>>>       select IDE_VIA
>>>       select SMBUS_EEPROM
>>> +    select VOF
>>>   # This should come with VT82C686
>>>       select ACPI_X86
>>>   diff --git a/hw/ppc/pegasos2.c b/hw/ppc/pegasos2.c
>>> index 07971175c9..91e5fa8fbe 100644
>>> --- a/hw/ppc/pegasos2.c
>>> +++ b/hw/ppc/pegasos2.c
> [...]
>>> +static void add_pci_device(PCIBus *bus, PCIDevice *d, void *opaque)
>>> +{
>>> +    FDTInfo *fi = opaque;
>>> +    GString *node = g_string_new(NULL);
>>> +    uint32_t cells[(PCI_NUM_REGIONS + 1) * 5];
>>> +    int i, j;
>>> +    const char *name = NULL;
>>> +    g_autofree const gchar *pn = g_strdup_printf("pci%x,%x",
>>> + pci_get_word(&d->config[PCI_VENDOR_ID]),
>>> + pci_get_word(&d->config[PCI_DEVICE_ID]));
>>> +
>>> +    for (i = 0; device_map[i].id; i++) {
>>> +        if (!strcmp(pn, device_map[i].id)) {
>>> +            name = device_map[i].name;
>>> +            break;
>>> +        }
>>> +    }
>>> +    g_string_printf(node, "%s/%s@%x", fi->path, (name ?: pn),
>>> +                    PCI_SLOT(d->devfn));
>>> +    if (PCI_FUNC(d->devfn)) {
>>> +        g_string_append_printf(node, ",%x", PCI_FUNC(d->devfn));
>>> +    }
>>> +
>>> +    qemu_fdt_add_subnode(fi->fdt, node->str);
>>> +    if (device_map[i].dtf) {
>>> +        FDTInfo cfi = { fi->fdt, node->str };
>>> +        device_map[i].dtf(bus, d, &cfi);
>>> +    }
>>> +    cells[0] = cpu_to_be32(d->devfn << 8);
>>> +    cells[1] = 0;
>>> +    cells[2] = 0;
>>> +    cells[3] = 0;
>>> +    cells[4] = 0;
>>> +    j = 5;
>>> +    for (i = 0; i < PCI_NUM_REGIONS; i++) {
>>> +        if (!d->io_regions[i].size) {
>>> +            continue;
>>> +        }
>>> +        cells[j] = cpu_to_be32(d->devfn << 8 | (PCI_BASE_ADDRESS_0 + 
>>> i * 4));
>>> +        if (d->io_regions[i].type & PCI_BASE_ADDRESS_SPACE_IO) {
>>> +            cells[j] |= cpu_to_be32(1 << 24);
>>> +        } else {
>>> +            cells[j] |= cpu_to_be32(2 << 24);
>>> +            if (d->io_regions[i].type & 
>>> PCI_BASE_ADDRESS_MEM_PREFETCH) {
>>> +                cells[j] |= cpu_to_be32(4 << 28);
>>> +            }
>>> +        }
>>> +        cells[j + 1] = 0;
>>> +        cells[j + 2] = 0;
>>> +        cells[j + 3] = cpu_to_be32(d->io_regions[i].size >> 32);
>>> +        cells[j + 4] = cpu_to_be32(d->io_regions[i].size);
>>> +        j += 5;
>>> +    }
>>
>>
>> btw I was wondering if Linux on pegasos2 could assign resources when 
>> /chosen/linux,pci-probe-only is in the FDT, could not it? Or the 
>> serial device does not probe and Linux does not boot?
> 
> Linux probes PCI devices by itself but MorphOS relies on the device tree 
> entries so I need at least the reg properties for that then it will map 
> the BARs but I think it won't scan the bus otherwise. You still seem to 
> add PCI devices in spapr too, at least I think I've got the idea for 
> this function above from there.


Linux does not scan, this is why we are adding devices in the FDT for 
pseries (and likely so should you) but Linux does reassign resources if 
something is wrong.

Does MorphOS boot with this patchset? If it does not, and Linux 
reassigns resources, we are probably better off with a minimalist 
approach and skip resource assignment.


-- 
Alexey


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

* Re: [RFC PATCH 4/5] ppc/pegasos2: Use Virtual Open Firmware as firmware replacement
  2021-06-16  4:58       ` Alexey Kardashevskiy
@ 2021-06-16 10:38         ` BALATON Zoltan
  0 siblings, 0 replies; 20+ messages in thread
From: BALATON Zoltan @ 2021-06-16 10:38 UTC (permalink / raw)
  To: Alexey Kardashevskiy; +Cc: qemu-ppc, qemu-devel, David Gibson

[-- Attachment #1: Type: text/plain, Size: 5368 bytes --]

On Wed, 16 Jun 2021, Alexey Kardashevskiy wrote:
> On 6/15/21 19:44, BALATON Zoltan wrote:
>> On Tue, 15 Jun 2021, Alexey Kardashevskiy wrote:
>>> On 6/7/21 01:46, BALATON Zoltan wrote:
>>>> The pegasos2 board comes with an Open Firmware compliant ROM based on
>>>> SmartFirmware but it has some changes that are not open source
>>>> therefore the ROM binary cannot be included in QEMU. Guests running on
>>>> the board however depend on services provided by the firmware. The
>>>> Virtual Open Firmware recently added to QEMU imlements a minimal set
>>>> of these services to allow some guests to boot without the original
>>>> firmware. This patch adds VOF as the default firmware for pegasos2
>>>> which allows booting Linux and MorphOS via -kernel option while a ROM
>>>> image can still be used with -bios for guests that don't run with VOF.
>>>> 
>>>> Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>
>>>> ---
>>>>   hw/ppc/Kconfig    |   1 +
>>>>   hw/ppc/pegasos2.c | 622 +++++++++++++++++++++++++++++++++++++++++++++-
>>>>   2 files changed, 621 insertions(+), 2 deletions(-)
>>>> 
>>>> diff --git a/hw/ppc/Kconfig b/hw/ppc/Kconfig
>>>> index b895720b28..0eb48128fe 100644
>>>> --- a/hw/ppc/Kconfig
>>>> +++ b/hw/ppc/Kconfig
>>>> @@ -75,6 +75,7 @@ config PEGASOS2
>>>>       select VT82C686
>>>>       select IDE_VIA
>>>>       select SMBUS_EEPROM
>>>> +    select VOF
>>>>   # This should come with VT82C686
>>>>       select ACPI_X86
>>>>   diff --git a/hw/ppc/pegasos2.c b/hw/ppc/pegasos2.c
>>>> index 07971175c9..91e5fa8fbe 100644
>>>> --- a/hw/ppc/pegasos2.c
>>>> +++ b/hw/ppc/pegasos2.c
>> [...]
>>>> +static void add_pci_device(PCIBus *bus, PCIDevice *d, void *opaque)
>>>> +{
>>>> +    FDTInfo *fi = opaque;
>>>> +    GString *node = g_string_new(NULL);
>>>> +    uint32_t cells[(PCI_NUM_REGIONS + 1) * 5];
>>>> +    int i, j;
>>>> +    const char *name = NULL;
>>>> +    g_autofree const gchar *pn = g_strdup_printf("pci%x,%x",
>>>> + pci_get_word(&d->config[PCI_VENDOR_ID]),
>>>> + pci_get_word(&d->config[PCI_DEVICE_ID]));
>>>> +
>>>> +    for (i = 0; device_map[i].id; i++) {
>>>> +        if (!strcmp(pn, device_map[i].id)) {
>>>> +            name = device_map[i].name;
>>>> +            break;
>>>> +        }
>>>> +    }
>>>> +    g_string_printf(node, "%s/%s@%x", fi->path, (name ?: pn),
>>>> +                    PCI_SLOT(d->devfn));
>>>> +    if (PCI_FUNC(d->devfn)) {
>>>> +        g_string_append_printf(node, ",%x", PCI_FUNC(d->devfn));
>>>> +    }
>>>> +
>>>> +    qemu_fdt_add_subnode(fi->fdt, node->str);
>>>> +    if (device_map[i].dtf) {
>>>> +        FDTInfo cfi = { fi->fdt, node->str };
>>>> +        device_map[i].dtf(bus, d, &cfi);
>>>> +    }
>>>> +    cells[0] = cpu_to_be32(d->devfn << 8);
>>>> +    cells[1] = 0;
>>>> +    cells[2] = 0;
>>>> +    cells[3] = 0;
>>>> +    cells[4] = 0;
>>>> +    j = 5;
>>>> +    for (i = 0; i < PCI_NUM_REGIONS; i++) {
>>>> +        if (!d->io_regions[i].size) {
>>>> +            continue;
>>>> +        }
>>>> +        cells[j] = cpu_to_be32(d->devfn << 8 | (PCI_BASE_ADDRESS_0 + i * 
>>>> 4));
>>>> +        if (d->io_regions[i].type & PCI_BASE_ADDRESS_SPACE_IO) {
>>>> +            cells[j] |= cpu_to_be32(1 << 24);
>>>> +        } else {
>>>> +            cells[j] |= cpu_to_be32(2 << 24);
>>>> +            if (d->io_regions[i].type & PCI_BASE_ADDRESS_MEM_PREFETCH) {
>>>> +                cells[j] |= cpu_to_be32(4 << 28);
>>>> +            }
>>>> +        }
>>>> +        cells[j + 1] = 0;
>>>> +        cells[j + 2] = 0;
>>>> +        cells[j + 3] = cpu_to_be32(d->io_regions[i].size >> 32);
>>>> +        cells[j + 4] = cpu_to_be32(d->io_regions[i].size);
>>>> +        j += 5;
>>>> +    }
>>> 
>>> 
>>> btw I was wondering if Linux on pegasos2 could assign resources when 
>>> /chosen/linux,pci-probe-only is in the FDT, could not it? Or the serial 
>>> device does not probe and Linux does not boot?
>> 
>> Linux probes PCI devices by itself but MorphOS relies on the device tree 
>> entries so I need at least the reg properties for that then it will map the 
>> BARs but I think it won't scan the bus otherwise. You still seem to add PCI 
>> devices in spapr too, at least I think I've got the idea for this function 
>> above from there.
>
>
> Linux does not scan, this is why we are adding devices in the FDT for pseries 
> (and likely so should you) but Linux does reassign resources if something is 
> wrong.
>
> Does MorphOS boot with this patchset? If it does not, and Linux reassigns 
> resources, we are probably better off with a minimalist approach and skip 
> resource assignment.

MorphOS and Linux boot with this and I don't understand what you mean by 
resource assingment. I'm not setting BARs just adding info about them in 
the reg property but the address is 0, it's still the guest OS (Linux or 
MorphOS) that maps these where it wants. (The board firmware does map some 
devices such as USB or IDE it uses itself but fortunately no guest depends 
on that and they enable devices if they aren't yet enabled.)

Regards,
BALATON Zoltan

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

end of thread, other threads:[~2021-06-16 10:39 UTC | newest]

Thread overview: 20+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-06-06 15:46 [RFC PATCH 0/5] ppc/Pegasos2 VOF BALATON Zoltan
2021-06-06 15:46 ` [RFC PATCH 5/5] ppc/pegasos2: Implement some RTAS functions with VOF BALATON Zoltan
2021-06-06 15:46 ` [RFC PATCH 4/5] ppc/pegasos2: Use Virtual Open Firmware as firmware replacement BALATON Zoltan
2021-06-15  7:09   ` Alexey Kardashevskiy
2021-06-15  9:44     ` BALATON Zoltan
2021-06-16  4:58       ` Alexey Kardashevskiy
2021-06-16 10:38         ` BALATON Zoltan
2021-06-06 15:46 ` [RFC PATCH 3/5] target/ppc: Allow virtual hypervisor on CPU without HV BALATON Zoltan
2021-06-06 15:46 ` [RFC PATCH 2/5] ppc/pegasos2: Introduce Pegasos2MachineState structure BALATON Zoltan
2021-06-06 19:04   ` Philippe Mathieu-Daudé
2021-06-06 20:35     ` BALATON Zoltan
2021-06-06 15:46 ` [RFC PATCH 1/5] Misc VOF fixes BALATON Zoltan
2021-06-09  7:39 ` [RFC PATCH 0/5] ppc/Pegasos2 VOF Alexey Kardashevskiy
2021-06-09 10:28   ` BALATON Zoltan
2021-06-10  7:14     ` Alexey Kardashevskiy
2021-06-10  8:25       ` David Gibson
2021-06-10 10:04         ` BALATON Zoltan
2021-06-10 10:37           ` David Gibson
2021-06-10 12:33           ` R: " luigi burdo
2021-06-10 12:52             ` BALATON Zoltan

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.