Skip to contentSkip to conversation

ppc: add a IBM 40p machine (RS/6000, PReP)

PATCH Superseded Hervé Poussineau 7 participants 36 messages Dec 29, 2016 – May 8, 2017

v1 of 3 Superseded Latest is v3 →

lore
Share & tools
lore
#0 lore raw

cover ppc: add a IBM 40p machine (RS/6000, PReP)

Hi,

This patchset adds the emulation of the IBM RS/6000 7020 (40p). The real machine is able to run AIX (up to 4.3.3), Windows NT (up to 4.0 SP1), the beta of OS/2 PowerPC, Solaris, Linux, NetBSD/PReP ...

I've tested current emulation with Open Hack'Ware, OpenBIOS and official firmware.

Linux kernel starts, and freezes during boot (like with 'prep' machine). Windows NT starts up to the point where it wants to change endianness. Other OSes have not been tested.

This machine is a superset of the 'prep' one, because we know exactly what is/should emulated, and that operating system list running on it is quite wide. I hope that 'prep' machine can be deprecated soon and then later removed.

Patches 1 to 3 are cleanups, and can probably be committed first. Patches 4 to 6 are the real implementation of the IBM 40p.

Hervé Poussineau (6):
pci: add pci_vga_type(), giving the device name of the chosen VGA
device
vga: increase priority of 0xa0000 memory region
prep: do not use global variable to access nvram
prep: QOM'ify System I/O
prep: add IBM RS/6000 7020 (40p) memory controller
prep: add IBM RS/6000 7020 (40p) machine emulation

 default-configs/ppc-softmmu.mak |   2 +
 hw/display/vga.c                |   2 +-
 hw/pci/pci.c                    |  22 ++-
 hw/ppc/Makefile.objs            |   2 +
 hw/ppc/prep.c                   | 235 ++++++++++++++++++++++++++++++-
 hw/ppc/prep_systemio.c          | 302 ++++++++++++++++++++++++++++++++++++++++
 hw/ppc/rs6000_mc.c              | 232 ++++++++++++++++++++++++++++++
 hw/ppc/trace-events             |  11 ++
 include/hw/pci/pci.h            |   1 +
 9 files changed, 800 insertions(+), 9 deletions(-)
 create mode 100644 hw/ppc/prep_systemio.c
 create mode 100644 hw/ppc/rs6000_mc.c
Signature · 1 line
2.1.4
#1 lore raw

PATCH 1/6 pci: add pci_vga_type(), giving the device name of the chosen VGA device

This is in fact a split of pci_vga_init() function in two parts.

---
 hw/pci/pci.c         | 22 ++++++++++++++++------
 include/hw/pci/pci.h |  1 +
 2 files changed, 17 insertions(+), 6 deletions(-)
hw/pci/pci.c +16 -6
index 24fae16..0d5a862 100644
@@ -1816,19 +1816,19 @@ PCIDevice *pci_nic_init_nofail(NICInfo *nd, PCIBus *rootbus,
     return pci_dev;
 }
 
-PCIDevice *pci_vga_init(PCIBus *bus)
+const char *pci_vga_type(void)
 {
     switch (vga_interface_type) {
     case VGA_CIRRUS:
-        return pci_create_simple(bus, -1, "cirrus-vga");
+        return "cirrus-vga";
     case VGA_QXL:
-        return pci_create_simple(bus, -1, "qxl-vga");
+        return "qxl-vga";
     case VGA_STD:
-        return pci_create_simple(bus, -1, "VGA");
+        return "VGA";
     case VGA_VMWARE:
-        return pci_create_simple(bus, -1, "vmware-svga");
+        return "vmware-svga";
     case VGA_VIRTIO:
-        return pci_create_simple(bus, -1, "virtio-vga");
+        return "virtio-vga";
     case VGA_NONE:
     default: /* Other non-PCI types. Checking for unsupported types is already
                 done in vl.c. */
@@ -1836,6 +1836,16 @@ PCIDevice *pci_vga_init(PCIBus *bus)
     }
 }
 
+PCIDevice *pci_vga_init(PCIBus *bus)
+{
+    const char *vga_type = pci_vga_type();
+    if (vga_type) {
+        return pci_create_simple(bus, -1, vga_type);
+    } else {
+        return NULL;
+    }
+}
+
 /* Whether a given bus number is in range of the secondary
  * bus of the given bridge device. */
 static bool pci_secondary_bus_in_range(PCIDevice *dev, int bus_num)
include/hw/pci/pci.h +1 -0
index 772692f..aa8d014 100644
@@ -420,6 +420,7 @@ PCIDevice *pci_nic_init_nofail(NICInfo *nd, PCIBus *rootbus,
                                const char *default_model,
                                const char *default_devaddr);
 
+const char *pci_vga_type(void);
 PCIDevice *pci_vga_init(PCIBus *bus);
 
 int pci_bus_num(PCIBus *s);
Signature · 1 line
2.1.4
Reviewed-by on v1 1/6
#2 lore raw

Re: [Qemu-devel] [PATCH 1/6] pci: add pci_vga_type(), giving the device name of the chosen VGA device

Quoted 3 lines · Hervé Poussineau

This is in fact a split of pci_vga_init() function in two parts.

I think it needs Michael or someone to merge it though.

Quoted 64 lines
---
 hw/pci/pci.c         | 22 ++++++++++++++++------
 include/hw/pci/pci.h |  1 +
 2 files changed, 17 insertions(+), 6 deletions(-)
hw/pci/pci.c +16 -6
index 24fae16..0d5a862 100644
@@ -1816,19 +1816,19 @@ PCIDevice *pci_nic_init_nofail(NICInfo *nd, PCIBus *rootbus,
     return pci_dev;
 }
 
-PCIDevice *pci_vga_init(PCIBus *bus)
+const char *pci_vga_type(void)
 {
     switch (vga_interface_type) {
     case VGA_CIRRUS:
-        return pci_create_simple(bus, -1, "cirrus-vga");
+        return "cirrus-vga";
     case VGA_QXL:
-        return pci_create_simple(bus, -1, "qxl-vga");
+        return "qxl-vga";
     case VGA_STD:
-        return pci_create_simple(bus, -1, "VGA");
+        return "VGA";
     case VGA_VMWARE:
-        return pci_create_simple(bus, -1, "vmware-svga");
+        return "vmware-svga";
     case VGA_VIRTIO:
-        return pci_create_simple(bus, -1, "virtio-vga");
+        return "virtio-vga";
     case VGA_NONE:
     default: /* Other non-PCI types. Checking for unsupported types is already
                 done in vl.c. */
@@ -1836,6 +1836,16 @@ PCIDevice *pci_vga_init(PCIBus *bus)
     }
 }
 
+PCIDevice *pci_vga_init(PCIBus *bus)
+{
+    const char *vga_type = pci_vga_type();
+    if (vga_type) {
+        return pci_create_simple(bus, -1, vga_type);
+    } else {
+        return NULL;
+    }
+}
+
 /* Whether a given bus number is in range of the secondary
  * bus of the given bridge device. */
 static bool pci_secondary_bus_in_range(PCIDevice *dev, int bus_num)
include/hw/pci/pci.h +1 -0
index 772692f..aa8d014 100644
@@ -420,6 +420,7 @@ PCIDevice *pci_nic_init_nofail(NICInfo *nd, PCIBus *rootbus,
                                const char *default_model,
                                const char *default_devaddr);
 
+const char *pci_vga_type(void);
 PCIDevice *pci_vga_init(PCIBus *bus);
 
 int pci_bus_num(PCIBus *s);
Signature · 4 lines
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
#3 lore raw

Re: [Qemu-devel] [PATCH 1/6] pci: add pci_vga_type(), giving the device name of the chosen VGA device

Quoted 8 lines · David Gibson
Quoted 3 lines · Hervé Poussineau

This is in fact a split of pci_vga_init() function in two parts.

I think it needs Michael or someone to merge it though.

Do we have to keep poking at pci_vga_type? I'd rather people just used -device for everything.

Quoted 70 lines
Quoted 64 lines
---
 hw/pci/pci.c         | 22 ++++++++++++++++------
 include/hw/pci/pci.h |  1 +
 2 files changed, 17 insertions(+), 6 deletions(-)
hw/pci/pci.c +16 -6
index 24fae16..0d5a862 100644
@@ -1816,19 +1816,19 @@ PCIDevice *pci_nic_init_nofail(NICInfo *nd, PCIBus *rootbus,
     return pci_dev;
 }
 
-PCIDevice *pci_vga_init(PCIBus *bus)
+const char *pci_vga_type(void)
 {
     switch (vga_interface_type) {
     case VGA_CIRRUS:
-        return pci_create_simple(bus, -1, "cirrus-vga");
+        return "cirrus-vga";
     case VGA_QXL:
-        return pci_create_simple(bus, -1, "qxl-vga");
+        return "qxl-vga";
     case VGA_STD:
-        return pci_create_simple(bus, -1, "VGA");
+        return "VGA";
     case VGA_VMWARE:
-        return pci_create_simple(bus, -1, "vmware-svga");
+        return "vmware-svga";
     case VGA_VIRTIO:
-        return pci_create_simple(bus, -1, "virtio-vga");
+        return "virtio-vga";
     case VGA_NONE:
     default: /* Other non-PCI types. Checking for unsupported types is already
                 done in vl.c. */
@@ -1836,6 +1836,16 @@ PCIDevice *pci_vga_init(PCIBus *bus)
     }
 }
 
+PCIDevice *pci_vga_init(PCIBus *bus)
+{
+    const char *vga_type = pci_vga_type();
+    if (vga_type) {
+        return pci_create_simple(bus, -1, vga_type);
+    } else {
+        return NULL;
+    }
+}
+
 /* Whether a given bus number is in range of the secondary
  * bus of the given bridge device. */
 static bool pci_secondary_bus_in_range(PCIDevice *dev, int bus_num)
include/hw/pci/pci.h +1 -0
index 772692f..aa8d014 100644
@@ -420,6 +420,7 @@ PCIDevice *pci_nic_init_nofail(NICInfo *nd, PCIBus *rootbus,
                                const char *default_model,
                                const char *default_devaddr);
 
+const char *pci_vga_type(void);
 PCIDevice *pci_vga_init(PCIBus *bus);
 
 int pci_bus_num(PCIBus *s);
Signature · 4 lines
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
#4 lore raw

Re: [Qemu-devel] [PATCH 1/6] pci: add pci_vga_type(), giving the device name of the chosen VGA device

Quoted 4 lines · Michael S. Tsirkin
Quoted 3 lines · David Gibson
Quoted 2 lines · Hervé Poussineau

This is in fact a split of pci_vga_init() function in two parts.

Quoted 8 lines
Quoted 5 lines
Quoted 1 line

I think it needs Michael or someone to merge it though.

Do we have to keep poking at pci_vga_type? I'd rather people just used -device for everything.

On some machine, I want to be able to specify on which PCI slot is added the graphic card.
- Either the machine code is able to get the pci_vga_type, to be able to do itself a pci_create_simple(bus, PCI_DEVFN(...), vga_type) [this patch]
- Or we need to add a pci_vga_init_with_address(int devfn)

What do you prefer?

Hervé

Quoted 74 lines
Quoted 71 lines
Quoted 58 lines
---
 hw/pci/pci.c         | 22 ++++++++++++++++------
 include/hw/pci/pci.h |  1 +
 2 files changed, 17 insertions(+), 6 deletions(-)
hw/pci/pci.c +16 -6
index 24fae16..0d5a862 100644
@@ -1816,19 +1816,19 @@ PCIDevice *pci_nic_init_nofail(NICInfo *nd, PCIBus *rootbus,
     return pci_dev;
 }
 
-PCIDevice *pci_vga_init(PCIBus *bus)
+const char *pci_vga_type(void)
 {
     switch (vga_interface_type) {
     case VGA_CIRRUS:
-        return pci_create_simple(bus, -1, "cirrus-vga");
+        return "cirrus-vga";
     case VGA_QXL:
-        return pci_create_simple(bus, -1, "qxl-vga");
+        return "qxl-vga";
     case VGA_STD:
-        return pci_create_simple(bus, -1, "VGA");
+        return "VGA";
     case VGA_VMWARE:
-        return pci_create_simple(bus, -1, "vmware-svga");
+        return "vmware-svga";
     case VGA_VIRTIO:
-        return pci_create_simple(bus, -1, "virtio-vga");
+        return "virtio-vga";
     case VGA_NONE:
     default: /* Other non-PCI types. Checking for unsupported types is already
                 done in vl.c. */
@@ -1836,6 +1836,16 @@ PCIDevice *pci_vga_init(PCIBus *bus)
     }
 }
 
+PCIDevice *pci_vga_init(PCIBus *bus)
+{
+    const char *vga_type = pci_vga_type();
+    if (vga_type) {
+        return pci_create_simple(bus, -1, vga_type);
+    } else {
+        return NULL;
+    }
+}
+
 /* Whether a given bus number is in range of the secondary
  * bus of the given bridge device. */
 static bool pci_secondary_bus_in_range(PCIDevice *dev, int bus_num)
include/hw/pci/pci.h +0 -0
index 772692f..aa8d014 100644

include/hw/pci/pci.h PCIDevice *pci_nic_init_nofail(NICInfo *nd, PCIBus *rootbus, · line 426

Quoted 7 lines
include/hw/pci/pci.h +1 -0
@@ -420,6 +420,7 @@ PCIDevice *pci_nic_init_nofail(NICInfo *nd, PCIBus *rootbus,
                                const char *default_model,
                                const char *default_devaddr);
 
+const char *pci_vga_type(void);
 PCIDevice *pci_vga_init(PCIBus *bus);
 
 int pci_bus_num(PCIBus *s);

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

#5 lore raw

PATCH 2/6 vga: increase priority of 0xa0000 memory region

In reply to Hervé Poussineau

VGA device registers vram as BAR 0. If this BAR is activated as a very low address which crosses 0xa0000-0xbffff, low memory region is not accessible anymore.

This fixes display on PReP machine if we enable PCI mapping at address 0.

---
 hw/display/vga.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
hw/display/vga.c +1 -1
index 2a88b3c..c573f35 100644
@@ -2265,7 +2265,7 @@ void vga_init(VGACommonState *s, Object *obj, MemoryRegion *address_space,
     memory_region_add_subregion_overlap(address_space,
                                         0x000a0000,
                                         vga_io_memory,
-                                        1);
+                                        2);
     memory_region_set_coalescing(vga_io_memory);
     if (init_vga_ports) {
         portio_list_init(&s->vga_port_list, obj, vga_ports, s, "vga");
Signature · 1 line
2.1.4
#6 lore raw

Re: [Qemu-devel] [PATCH 2/6] vga: increase priority of 0xa0000 memory region

Quoted 5 lines · Hervé Poussineau

VGA device registers vram as BAR 0. If this BAR is activated as a very low address which crosses 0xa0000-0xbffff, low memory region is not accessible anymore.

This fixes display on PReP machine if we enable PCI mapping at address 0.

This commit message needs more information. What exactly is the VGA BAR colliding with? Why does the other thing have higher priority? Why is it safe for the VGA BAR to override the other thing? Why is this safe on all platforms?

Quoted 18 lines
---
 hw/display/vga.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
hw/display/vga.c +1 -1
index 2a88b3c..c573f35 100644
@@ -2265,7 +2265,7 @@ void vga_init(VGACommonState *s, Object *obj, MemoryRegion *address_space,
     memory_region_add_subregion_overlap(address_space,
                                         0x000a0000,
                                         vga_io_memory,
-                                        1);
+                                        2);
     memory_region_set_coalescing(vga_io_memory);
     if (init_vga_ports) {
         portio_list_init(&s->vga_port_list, obj, vga_ports, s, "vga");
Signature · 4 lines
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
#7 lore raw

Re: [Qemu-devel] [PATCH 2/6] vga: increase priority of 0xa0000 memory region

Quoted 11 lines · David Gibson
Quoted 5 lines · Hervé Poussineau

VGA device registers vram as BAR 0. If this BAR is activated as a very low address which crosses 0xa0000-0xbffff, low memory region is not accessible anymore.

This fixes display on PReP machine if we enable PCI mapping at address 0.

This commit message needs more information. What exactly is the VGA BAR colliding with? Why does the other thing have higher priority? Why is it safe for the VGA BAR to override the other thing? Why is this safe on all platforms?

VGA has (basically) two memory regions:
- the legacy one, from 0xa0000 to 0xbffff
- a memory region describing the whole VRAM, configurable with PCI BAR 0.

In QEMU, mapping PCI at address 0 is not permitted (MachineClass->pci_allow_0_address is false by default), except on arm/virt and ppc/spapr. So, this is usually not a problem as all PCI BARs (including video PCI BAR 0) are not mapped at address 0, and so both memory regions can't collide.

When trying Linux on ppc/40p (introduced later in this patchset), I saw that Linux assigns PCI BAR addresses in the order of PCI devices detection, and VGA PCI BAR 0 ends up at address 0. However, Linux assumes that 0xa0000-0xbffff is still available to drive the VGA card in text mode. Without changing the region priority, VGA output is garbled (as writes directly go to VGA memory). When increasing the region priority, VGA output is restored (as writes go to legacy address space).

arm/virt by default doesn't have a PCI VGA card.
ppc/spapr may probably have the same problem as ppc/40p. However, as VGA PCI BAR 0 and VGA legacy space both have a priority of 1, it may probably have a problem. I only need to convince Linux to use address 0 for VGA PCI BAR.

Hervé

Quoted 20 lines
Quoted 19 lines
---
 hw/display/vga.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
hw/display/vga.c +1 -1
index 2a88b3c..c573f35 100644
@@ -2265,7 +2265,7 @@ void vga_init(VGACommonState *s, Object *obj, MemoryRegion *address_space,
     memory_region_add_subregion_overlap(address_space,
                                         0x000a0000,
                                         vga_io_memory,
-                                        1);
+                                        2);
     memory_region_set_coalescing(vga_io_memory);
     if (init_vga_ports) {
         portio_list_init(&s->vga_port_list, obj, vga_ports, s, "vga");
#8 lore raw

Re: [Qemu-devel] [PATCH 2/6] vga: increase priority of 0xa0000 memory region

Quoted 8 lines · Hervé Poussineau
Quoted 7 lines · David Gibson
Quoted 5 lines · Hervé Poussineau

VGA device registers vram as BAR 0. If this BAR is activated as a very low address which crosses 0xa0000-0xbffff, low memory region is not accessible anymore.

This fixes display on PReP machine if we enable PCI mapping at address 0.

Quoted 8 lines
Quoted 4 lines

This commit message needs more information. What exactly is the VGA BAR colliding with? Why does the other thing have higher priority? Why is it safe for the VGA BAR to override the other thing? Why is this safe on all platforms?

VGA has (basically) two memory regions:
- the legacy one, from 0xa0000 to 0xbffff
- a memory region describing the whole VRAM, configurable with PCI BAR 0.

Yes, that I know. Note that both the fixed 0xa0000 and the BAR value are offsets with *PCI* memory space, which may not be the same as addresses in system memory space. PCI memory space is identity mapped into system address space on x86, IIRC, but it's not on spapr. AFAICT it's not identity mapped on PReP either (see raven_pcihost_initfn()). So the VGA legacy window will actually be at 0xc00a0000 and BAR0 at (0xc0000000 + BAR value) in the _system_ address space if I'm reading the PReP PCI bridge code correctly.

Quoted 1 line

In QEMU, mapping PCI at address 0 is not permitted (MachineClass->pci_allow_0_address is false by default),

I believe this is because of the identity map of PCI memory space on x86 (well, PC, strictly speaking). Because that's not the case on PReP, it should probably set allow_0_address = true.

Quoted 5 lines

except on arm/virt and ppc/spapr. So, this is usually not a problem as all PCI BARs (including video PCI BAR 0) are not mapped at address 0, and so both memory regions can't collide.

When trying Linux on ppc/40p (introduced later in this patchset), I saw that Linux assigns PCI BAR addresses in the order of PCI devices detection, and VGA PCI BAR 0 ends up at address 0.

Hmm. You're saying that Linux is assigning BAR 0 so that it collides with the legacy memory region? That sounds like a Linux bug. Or.. does Linux always assign BARs on PReP, or only if the firmware doesn't? Maybe the guest firmware needs to assign the BARs properly to avoid this collision.

Quoted 3 lines

However, Linux assumes that 0xa0000-0xbffff is still available to drive the VGA card in text mode. Without changing the region priority, VGA output is garbled (as writes directly go to VGA memory). When increasing the region priority, VGA output is restored (as writes go to legacy address space).

Right. But by increasing the priority, you're effectively making a hole in BAR0. That sounds like it will cause chaos if after boot you load a "real" VGA driver which tries to use the full video RAM through BAR0 instead of via the legacy area.

Quoted 27 lines

arm/virt by default doesn't have a PCI VGA card.
ppc/spapr may probably have the same problem as ppc/40p. However, as VGA PCI BAR 0 and VGA legacy space both have a priority of 1, it may probably have a problem. I only need to convince Linux to use address 0 for VGA PCI BAR.

Hervé

Quoted 20 lines
Quoted 19 lines
---
 hw/display/vga.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
hw/display/vga.c +1 -1
index 2a88b3c..c573f35 100644
@@ -2265,7 +2265,7 @@ void vga_init(VGACommonState *s, Object *obj, MemoryRegion *address_space,
     memory_region_add_subregion_overlap(address_space,
                                         0x000a0000,
                                         vga_io_memory,
-                                        1);
+                                        2);
     memory_region_set_coalescing(vga_io_memory);
     if (init_vga_ports) {
         portio_list_init(&s->vga_port_list, obj, vga_ports, s, "vga");
Signature · 4 lines
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
#9 lore raw

PATCH 3/6 prep: do not use global variable to access nvram

In reply to Hervé Poussineau
---
 hw/ppc/prep.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
hw/ppc/prep.c +2 -2
index 054af1e..9fb89d3 100644
@@ -339,13 +339,13 @@ static PortioList prep_port_list;
 /* NVRAM helpers */
 static inline uint32_t nvram_read(Nvram *nvram, uint32_t addr)
 {
-    NvramClass *k = NVRAM_GET_CLASS(sysctrl->nvram);
+    NvramClass *k = NVRAM_GET_CLASS(nvram);
     return (k->read)(nvram, addr);
 }
 
 static inline void nvram_write(Nvram *nvram, uint32_t addr, uint32_t val)
 {
-    NvramClass *k = NVRAM_GET_CLASS(sysctrl->nvram);
+    NvramClass *k = NVRAM_GET_CLASS(nvram);
     (k->write)(nvram, addr, val);
 }
 
Signature · 1 line
2.1.4
#10 lore raw

Re: [Qemu-devel] [PATCH 3/6] prep: do not use global variable to access nvram

Quoted 1 line · Hervé Poussineau

This makes sense on its own, so I've applied it to ppc-for-2.9.

Quoted 24 lines
---
 hw/ppc/prep.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
hw/ppc/prep.c +2 -2
index 054af1e..9fb89d3 100644
@@ -339,13 +339,13 @@ static PortioList prep_port_list;
 /* NVRAM helpers */
 static inline uint32_t nvram_read(Nvram *nvram, uint32_t addr)
 {
-    NvramClass *k = NVRAM_GET_CLASS(sysctrl->nvram);
+    NvramClass *k = NVRAM_GET_CLASS(nvram);
     return (k->read)(nvram, addr);
 }
 
 static inline void nvram_write(Nvram *nvram, uint32_t addr, uint32_t val)
 {
-    NvramClass *k = NVRAM_GET_CLASS(sysctrl->nvram);
+    NvramClass *k = NVRAM_GET_CLASS(nvram);
     (k->write)(nvram, addr, val);
 }
 
Signature · 4 lines
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
#11 lore raw

PATCH 4/6 prep: QOM'ify System I/O

In reply to Hervé Poussineau

Part of the functionality is copied from hw/ppc/prep.c. Also add support for board identification/equipment registers.

---
 hw/ppc/Makefile.objs   |   1 +
 hw/ppc/prep_systemio.c | 302 +++++++++++++++++++++++++++++++++++++++++++++++++
 hw/ppc/trace-events    |   4 +
 3 files changed, 307 insertions(+)
 create mode 100644 hw/ppc/prep_systemio.c
hw/ppc/Makefile.objs +1 -0
index 8025129..db72297 100644
@@ -16,6 +16,7 @@ obj-y += ppc405_boards.o ppc4xx_devs.o ppc405_uc.o ppc440_bamboo.o
 obj-y += ppc4xx_pci.o
 # PReP
 obj-$(CONFIG_PREP) += prep.o
+obj-$(CONFIG_PREP) += prep_systemio.o
 # OldWorld PowerMac
 obj-$(CONFIG_MAC) += mac_oldworld.o
 # NewWorld PowerMac
hw/ppc/prep_systemio.c new file +302 -0

302 lines not on this page · raw message

hw/ppc/trace-events +4 -0
index 2297ead..2ba6166 100644
@@ -74,3 +74,7 @@ ppc_tb_adjust(uint64_t offs1, uint64_t offs2, int64_t diff, int64_t seconds) "ad
 # hw/ppc/prep.c
 prep_io_800_writeb(uint32_t addr, uint32_t val) "0x%08" PRIx32 " => 0x%02" PRIx32
 prep_io_800_readb(uint32_t addr, uint32_t retval) "0x%08" PRIx32 " <= 0x%02" PRIx32
+
+# hw/ppc/prep_systemio.c
+prep_systemio_read(uint32_t addr, uint32_t val) "read addr=%x val=%x"
+prep_systemio_write(uint32_t addr, uint32_t val) "write addr=%x val=%x"
Signature · 1 line
2.1.4
#12 lore raw

Re: [Qemu-devel] [PATCH 4/6] prep: QOM'ify System I/O

Quoted 2 lines · Hervé Poussineau

Part of the functionality is copied from hw/ppc/prep.c. Also add support for board identification/equipment registers.

Needs more detail in the commit message. What is system I/O? what is it for?

The 1-line summary is also misleading; "QOM'ify" suggests you are changing an existing device to use QOM conventions, but no existing device is removed here. Is this actually something new, or is it a duplicate QOMified version of something else? If so, what?

Quoted 341 lines
---
 hw/ppc/Makefile.objs   |   1 +
 hw/ppc/prep_systemio.c | 302 +++++++++++++++++++++++++++++++++++++++++++++++++
 hw/ppc/trace-events    |   4 +
 3 files changed, 307 insertions(+)
 create mode 100644 hw/ppc/prep_systemio.c
hw/ppc/Makefile.objs +1 -0
index 8025129..db72297 100644
@@ -16,6 +16,7 @@ obj-y += ppc405_boards.o ppc4xx_devs.o ppc405_uc.o ppc440_bamboo.o
 obj-y += ppc4xx_pci.o
 # PReP
 obj-$(CONFIG_PREP) += prep.o
+obj-$(CONFIG_PREP) += prep_systemio.o
 # OldWorld PowerMac
 obj-$(CONFIG_MAC) += mac_oldworld.o
 # NewWorld PowerMac
hw/ppc/prep_systemio.c new file +302 -0
new file mode 100644
index 0000000..449056c
@@ -0,0 +1,302 @@
+/*
+ * QEMU PReP System I/O emulation
+ *
+ * Copyright (c) 2016 Herve Poussineau
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "qemu/osdep.h"
+#include "hw/isa/isa.h"
+#include "exec/address-spaces.h"
+#include "qemu/error-report.h" /* for error_report() */
+#include "sysemu/sysemu.h" /* for vm_stop() */
+#include "cpu.h"
+#include "trace.h"
+
+#define TYPE_PREP_SYSTEMIO "prep-systemio"
+#define PREP_SYSTEMIO(obj) \
+    OBJECT_CHECK(PrepSystemIoState, (obj), TYPE_PREP_SYSTEMIO)
+
+/* Bit as defined in PowerPC Reference Plaform v1.1, sect. 6.1.5, p. 132 */
+#define PREP_BIT(n) (1 << (7 - (n)))
+
+typedef struct PrepSystemIoState {
+    ISADevice parent_obj;
+    MemoryRegion ppc_parity_mem;
+
+    qemu_irq non_contiguous_io_map_irq;
+    uint8_t sreset; /* 0x0092 */
+    uint8_t equipment; /* 0x080c */
+    uint8_t system_control; /* 0x081c */
+    uint8_t iomap_type; /* 0x0850 */
+    uint8_t ibm_planar_id; /* 0x0852 */
+    qemu_irq softreset_irq;
+    PortioList portio;
+} PrepSystemIoState;
+
+/* PORT 0092 -- Special Port 92 (Read/Write) */
+
+enum {
+    PORT0092_SOFTRESET  = PREP_BIT(7),
+    PORT0092_LE_MODE    = PREP_BIT(6),
+};
+
+static void prep_port0092_write(void *opaque, uint32_t addr, uint32_t val)
+{
+    PrepSystemIoState *s = opaque;
+
+    trace_prep_systemio_write(addr, val);
+
+    if ((val & PORT0092_SOFTRESET) != 0) {
+        qemu_irq_raise(s->softreset_irq);
+        s->sreset = 1;
+    } else {
+        qemu_irq_lower(s->softreset_irq);
+        s->sreset = 0;
+    }
+
+    if ((val & PORT0092_LE_MODE) != 0) {
+        /* XXX Not supported yet */
+        error_report("little-endian mode not supported");
+        vm_stop(RUN_STATE_PAUSED);
+    } else {
+        /* Nothing to do */
+    }
+}
+
+static uint32_t prep_port0092_read(void *opaque, uint32_t addr)
+{
+    PrepSystemIoState *s = opaque;
+    /* XXX LE mode unsupported */
+    trace_prep_systemio_read(addr, 0);
+    return s->sreset;
+}
+
+/* PORT 0808 -- Hardfile Light Register (Write Only) */
+
+enum {
+    PORT0808_HARDFILE_LIGHT_ON  = PREP_BIT(7),
+};
+
+static void prep_port0808_write(void *opaque, uint32_t addr, uint32_t val)
+{
+    trace_prep_systemio_write(addr, val);
+}
+
+/* PORT 0810 -- Password Protect 1 Register (Write Only) */
+
+/* reset by port 0x4D in the SIO */
+static void prep_port0810_write(void *opaque, uint32_t addr, uint32_t val)
+{
+    trace_prep_systemio_write(addr, val);
+}
+
+/* PORT 0812 -- Password Protect 2 Register (Write Only) */
+
+/* reset by port 0x4D in the SIO */
+static void prep_port0812_write(void *opaque, uint32_t addr, uint32_t val)
+{
+    trace_prep_systemio_write(addr, val);
+}
+
+/* PORT 0814 -- L2 Invalidate Register (Write Only) */
+
+static void prep_port0814_write(void *opaque, uint32_t addr, uint32_t val)
+{
+    trace_prep_systemio_write(addr, val);
+}
+
+/* PORT 0818 -- Reserved for Keylock (Read Only) */
+
+enum {
+    PORT0818_KEYLOCK_SIGNAL_HIGH    = PREP_BIT(7),
+};
+
+static uint32_t prep_port0818_read(void *opaque, uint32_t addr)
+{
+    uint32_t val = 0;
+    trace_prep_systemio_read(addr, val);
+    return val;
+}
+
+/* PORT 080C -- Equipment */
+
+enum {
+    PORT080C_SCSIFUSE               = PREP_BIT(1),
+    PORT080C_L2_COPYBACK            = PREP_BIT(4),
+    PORT080C_L2_256                 = PREP_BIT(5),
+    PORT080C_UPGRADE_CPU            = PREP_BIT(6),
+    PORT080C_L2                     = PREP_BIT(7),
+};
+
+static uint32_t prep_port080c_read(void *opaque, uint32_t addr)
+{
+    PrepSystemIoState *s = opaque;
+    trace_prep_systemio_read(addr, s->equipment);
+    return s->equipment;
+}
+
+/* PORT 081C -- System Control Register (Read/Write) */
+
+enum {
+    PORT081C_FLOPPY_MOTOR_INHIBIT   = PREP_BIT(3),
+    PORT081C_MASK_TEA               = PREP_BIT(2),
+    PORT081C_L2_UPDATE_INHIBIT      = PREP_BIT(1),
+    PORT081C_L2_CACHEMISS_INHIBIT   = PREP_BIT(0),
+};
+
+static void prep_port081c_write(void *opaque, uint32_t addr, uint32_t val)
+{
+    PrepSystemIoState *s = opaque;
+    trace_prep_systemio_write(addr, val);
+    s->system_control = val;
+}
+
+static uint32_t prep_port081c_read(void *opaque, uint32_t addr)
+{
+    PrepSystemIoState *s = opaque;
+    trace_prep_systemio_read(addr, s->system_control);
+    return s->system_control;
+}
+
+/* System Board Identification */
+
+static uint32_t prep_port0852_read(void *opaque, uint32_t addr)
+{
+    PrepSystemIoState *s = opaque;
+    trace_prep_systemio_read(addr, s->ibm_planar_id);
+    return s->ibm_planar_id;
+}
+
+/* PORT 0850 -- I/O Map Type Register (Read/Write) */
+
+enum {
+    PORT0850_IOMAP_NONCONTIGUOUS    = PREP_BIT(7),
+};
+
+static uint32_t prep_port0850_read(void *opaque, uint32_t addr)
+{
+    PrepSystemIoState *s = opaque;
+    trace_prep_systemio_read(addr, s->iomap_type);
+    return s->iomap_type;
+}
+
+static void prep_port0850_write(void *opaque, uint32_t addr, uint32_t val)
+{
+    PrepSystemIoState *s = opaque;
+
+    trace_prep_systemio_write(addr, val);
+    qemu_set_irq(s->non_contiguous_io_map_irq,
+                 val & PORT0850_IOMAP_NONCONTIGUOUS ? 1 : 0);
+    s->iomap_type = val;
+}
+
+static const MemoryRegionPortio ppc_io800_port_list[] = {
+    { 0x092, 1, 1, .read = prep_port0092_read,
+                   .write = prep_port0092_write, },
+    { 0x808, 1, 1, .write = prep_port0808_write, },
+    { 0x80c, 1, 1, .read = prep_port080c_read, },
+    { 0x810, 1, 1, .write = prep_port0810_write, },
+    { 0x812, 1, 1, .write = prep_port0812_write, },
+    { 0x814, 1, 1, .write = prep_port0814_write, },
+    { 0x818, 1, 1, .read = prep_port0818_read },
+    { 0x81c, 1, 1, .read = prep_port081c_read,
+                   .write = prep_port081c_write, },
+    { 0x850, 1, 1, .read = prep_port0850_read,
+                   .write = prep_port0850_write, },
+    { 0x852, 1, 1, .read = prep_port0852_read, },
+    PORTIO_END_OF_LIST()
+};
+
+static uint64_t ppc_parity_error_readl(void *opaque, hwaddr addr,
+                                       unsigned int size)
+{
+    uint32_t val = 0;
+    trace_prep_systemio_read((unsigned int)addr, val);
+    return val;
+}
+
+static const MemoryRegionOps ppc_parity_error_ops = {
+    .read = ppc_parity_error_readl,
+    .valid = {
+        .min_access_size = 4,
+        .max_access_size = 4,
+    },
+};
+
+static void prep_systemio_realize(DeviceState *dev, Error **errp)
+{
+    ISADevice *isa = ISA_DEVICE(dev);
+    PrepSystemIoState *s = PREP_SYSTEMIO(dev);
+    PowerPCCPU *cpu;
+
+    qdev_init_gpio_out(dev, &s->non_contiguous_io_map_irq, 1);
+    s->iomap_type = 0; /* contiguous mode XXX 0x1? */
+    cpu = POWERPC_CPU(first_cpu);
+    s->softreset_irq = cpu->env.irq_inputs[PPC6xx_INPUT_HRESET];
+
+    isa_register_portio_list(isa, &s->portio, 0x0, ppc_io800_port_list, s,
+                             "systemio800");
+
+    memory_region_init_io(&s->ppc_parity_mem, OBJECT(dev),
+                          &ppc_parity_error_ops, s, "ppc-parity", 0x4);
+    memory_region_add_subregion(get_system_memory(), 0xbfffeff0,
+                                &s->ppc_parity_mem);
+}
+
+static const VMStateDescription vmstate_prep_systemio = {
+    .name = "prep_systemio",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT8(system_control, PrepSystemIoState),
+        VMSTATE_UINT8(iomap_type, PrepSystemIoState),
+        VMSTATE_END_OF_LIST()
+    },
+};
+
+static Property prep_systemio_properties[] = {
+    DEFINE_PROP_UINT8("ibm-planar-id", PrepSystemIoState, ibm_planar_id, 0),
+    DEFINE_PROP_UINT8("equipment", PrepSystemIoState, equipment, 0),
+    DEFINE_PROP_END_OF_LIST()
+};
+
+static void prep_systemio_class_initfn(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
+    dc->realize = prep_systemio_realize;
+    dc->vmsd = &vmstate_prep_systemio;
+    dc->props = prep_systemio_properties;
+}
+
+static TypeInfo prep_systemio800_info = {
+    .name          = TYPE_PREP_SYSTEMIO,
+    .parent        = TYPE_ISA_DEVICE,
+    .instance_size = sizeof(PrepSystemIoState),
+    .class_init    = prep_systemio_class_initfn,
+};
+
+static void prep_systemio_register_types(void)
+{
+    type_register_static(&prep_systemio800_info);
+}
+
+type_init(prep_systemio_register_types)
hw/ppc/trace-events +4 -0
index 2297ead..2ba6166 100644
@@ -74,3 +74,7 @@ ppc_tb_adjust(uint64_t offs1, uint64_t offs2, int64_t diff, int64_t seconds) "ad
 # hw/ppc/prep.c
 prep_io_800_writeb(uint32_t addr, uint32_t val) "0x%08" PRIx32 " => 0x%02" PRIx32
 prep_io_800_readb(uint32_t addr, uint32_t retval) "0x%08" PRIx32 " <= 0x%02" PRIx32
+
+# hw/ppc/prep_systemio.c
+prep_systemio_read(uint32_t addr, uint32_t val) "read addr=%x val=%x"
+prep_systemio_write(uint32_t addr, uint32_t val) "write addr=%x val=%x"
Signature · 4 lines
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
#13 lore raw

Re: [Qemu-devel] [PATCH 4/6] prep: QOM'ify System I/O

Quoted 6 lines · David Gibson
Quoted 2 lines · Hervé Poussineau

Part of the functionality is copied from hw/ppc/prep.c. Also add support for board identification/equipment registers.

Needs more detail in the commit message. What is system I/O? what is it for?

System I/O is a PPC PReP device which allows access to motherboard devices, living in the 0x800-0x8ff memory range. It is described in "PowerPC Reference platform Specification", available at ftp://ftp.software.ibm.com/rs6000/technology/spec/ (files srp1*) in section 6.1.5: "I/O Device Mapping"

Quoted 5 lines

The 1-line summary is also misleading; "QOM'ify" suggests you are changing an existing device to use QOM conventions, but no existing device is removed here. Is this actually something new, or is it a duplicate QOMified version of something else? If so, what?

It is a partial duplicate of System I/O device available in hw/ppc/prep.c .
The new one I'm adding doesn't have all the Motorola-specific registers, and follows a known specification.

The existing one should be deprecated and removed with the 'prep' machine.

Hervé

Quoted 342 lines
Quoted 341 lines
---
 hw/ppc/Makefile.objs   |   1 +
 hw/ppc/prep_systemio.c | 302 +++++++++++++++++++++++++++++++++++++++++++++++++
 hw/ppc/trace-events    |   4 +
 3 files changed, 307 insertions(+)
 create mode 100644 hw/ppc/prep_systemio.c
hw/ppc/Makefile.objs +1 -0
index 8025129..db72297 100644
@@ -16,6 +16,7 @@ obj-y += ppc405_boards.o ppc4xx_devs.o ppc405_uc.o ppc440_bamboo.o
 obj-y += ppc4xx_pci.o
 # PReP
 obj-$(CONFIG_PREP) += prep.o
+obj-$(CONFIG_PREP) += prep_systemio.o
 # OldWorld PowerMac
 obj-$(CONFIG_MAC) += mac_oldworld.o
 # NewWorld PowerMac
hw/ppc/prep_systemio.c new file +302 -0
new file mode 100644
index 0000000..449056c
@@ -0,0 +1,302 @@
+/*
+ * QEMU PReP System I/O emulation
+ *
+ * Copyright (c) 2016 Herve Poussineau
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "qemu/osdep.h"
+#include "hw/isa/isa.h"
+#include "exec/address-spaces.h"
+#include "qemu/error-report.h" /* for error_report() */
+#include "sysemu/sysemu.h" /* for vm_stop() */
+#include "cpu.h"
+#include "trace.h"
+
+#define TYPE_PREP_SYSTEMIO "prep-systemio"
+#define PREP_SYSTEMIO(obj) \
+    OBJECT_CHECK(PrepSystemIoState, (obj), TYPE_PREP_SYSTEMIO)
+
+/* Bit as defined in PowerPC Reference Plaform v1.1, sect. 6.1.5, p. 132 */
+#define PREP_BIT(n) (1 << (7 - (n)))
+
+typedef struct PrepSystemIoState {
+    ISADevice parent_obj;
+    MemoryRegion ppc_parity_mem;
+
+    qemu_irq non_contiguous_io_map_irq;
+    uint8_t sreset; /* 0x0092 */
+    uint8_t equipment; /* 0x080c */
+    uint8_t system_control; /* 0x081c */
+    uint8_t iomap_type; /* 0x0850 */
+    uint8_t ibm_planar_id; /* 0x0852 */
+    qemu_irq softreset_irq;
+    PortioList portio;
+} PrepSystemIoState;
+
+/* PORT 0092 -- Special Port 92 (Read/Write) */
+
+enum {
+    PORT0092_SOFTRESET  = PREP_BIT(7),
+    PORT0092_LE_MODE    = PREP_BIT(6),
+};
+
+static void prep_port0092_write(void *opaque, uint32_t addr, uint32_t val)
+{
+    PrepSystemIoState *s = opaque;
+
+    trace_prep_systemio_write(addr, val);
+
+    if ((val & PORT0092_SOFTRESET) != 0) {
+        qemu_irq_raise(s->softreset_irq);
+        s->sreset = 1;
+    } else {
+        qemu_irq_lower(s->softreset_irq);
+        s->sreset = 0;
+    }
+
+    if ((val & PORT0092_LE_MODE) != 0) {
+        /* XXX Not supported yet */
+        error_report("little-endian mode not supported");
+        vm_stop(RUN_STATE_PAUSED);
+    } else {
+        /* Nothing to do */
+    }
+}
+
+static uint32_t prep_port0092_read(void *opaque, uint32_t addr)
+{
+    PrepSystemIoState *s = opaque;
+    /* XXX LE mode unsupported */
+    trace_prep_systemio_read(addr, 0);
+    return s->sreset;
+}
+
+/* PORT 0808 -- Hardfile Light Register (Write Only) */
+
+enum {
+    PORT0808_HARDFILE_LIGHT_ON  = PREP_BIT(7),
+};
+
+static void prep_port0808_write(void *opaque, uint32_t addr, uint32_t val)
+{
+    trace_prep_systemio_write(addr, val);
+}
+
+/* PORT 0810 -- Password Protect 1 Register (Write Only) */
+
+/* reset by port 0x4D in the SIO */
+static void prep_port0810_write(void *opaque, uint32_t addr, uint32_t val)
+{
+    trace_prep_systemio_write(addr, val);
+}
+
+/* PORT 0812 -- Password Protect 2 Register (Write Only) */
+
+/* reset by port 0x4D in the SIO */
+static void prep_port0812_write(void *opaque, uint32_t addr, uint32_t val)
+{
+    trace_prep_systemio_write(addr, val);
+}
+
+/* PORT 0814 -- L2 Invalidate Register (Write Only) */
+
+static void prep_port0814_write(void *opaque, uint32_t addr, uint32_t val)
+{
+    trace_prep_systemio_write(addr, val);
+}
+
+/* PORT 0818 -- Reserved for Keylock (Read Only) */
+
+enum {
+    PORT0818_KEYLOCK_SIGNAL_HIGH    = PREP_BIT(7),
+};
+
+static uint32_t prep_port0818_read(void *opaque, uint32_t addr)
+{
+    uint32_t val = 0;
+    trace_prep_systemio_read(addr, val);
+    return val;
+}
+
+/* PORT 080C -- Equipment */
+
+enum {
+    PORT080C_SCSIFUSE               = PREP_BIT(1),
+    PORT080C_L2_COPYBACK            = PREP_BIT(4),
+    PORT080C_L2_256                 = PREP_BIT(5),
+    PORT080C_UPGRADE_CPU            = PREP_BIT(6),
+    PORT080C_L2                     = PREP_BIT(7),
+};
+
+static uint32_t prep_port080c_read(void *opaque, uint32_t addr)
+{
+    PrepSystemIoState *s = opaque;
+    trace_prep_systemio_read(addr, s->equipment);
+    return s->equipment;
+}
+
+/* PORT 081C -- System Control Register (Read/Write) */
+
+enum {
+    PORT081C_FLOPPY_MOTOR_INHIBIT   = PREP_BIT(3),
+    PORT081C_MASK_TEA               = PREP_BIT(2),
+    PORT081C_L2_UPDATE_INHIBIT      = PREP_BIT(1),
+    PORT081C_L2_CACHEMISS_INHIBIT   = PREP_BIT(0),
+};
+
+static void prep_port081c_write(void *opaque, uint32_t addr, uint32_t val)
+{
+    PrepSystemIoState *s = opaque;
+    trace_prep_systemio_write(addr, val);
+    s->system_control = val;
+}
+
+static uint32_t prep_port081c_read(void *opaque, uint32_t addr)
+{
+    PrepSystemIoState *s = opaque;
+    trace_prep_systemio_read(addr, s->system_control);
+    return s->system_control;
+}
+
+/* System Board Identification */
+
+static uint32_t prep_port0852_read(void *opaque, uint32_t addr)
+{
+    PrepSystemIoState *s = opaque;
+    trace_prep_systemio_read(addr, s->ibm_planar_id);
+    return s->ibm_planar_id;
+}
+
+/* PORT 0850 -- I/O Map Type Register (Read/Write) */
+
+enum {
+    PORT0850_IOMAP_NONCONTIGUOUS    = PREP_BIT(7),
+};
+
+static uint32_t prep_port0850_read(void *opaque, uint32_t addr)
+{
+    PrepSystemIoState *s = opaque;
+    trace_prep_systemio_read(addr, s->iomap_type);
+    return s->iomap_type;
+}
+
+static void prep_port0850_write(void *opaque, uint32_t addr, uint32_t val)
+{
+    PrepSystemIoState *s = opaque;
+
+    trace_prep_systemio_write(addr, val);
+    qemu_set_irq(s->non_contiguous_io_map_irq,
+                 val & PORT0850_IOMAP_NONCONTIGUOUS ? 1 : 0);
+    s->iomap_type = val;
+}
+
+static const MemoryRegionPortio ppc_io800_port_list[] = {
+    { 0x092, 1, 1, .read = prep_port0092_read,
+                   .write = prep_port0092_write, },
+    { 0x808, 1, 1, .write = prep_port0808_write, },
+    { 0x80c, 1, 1, .read = prep_port080c_read, },
+    { 0x810, 1, 1, .write = prep_port0810_write, },
+    { 0x812, 1, 1, .write = prep_port0812_write, },
+    { 0x814, 1, 1, .write = prep_port0814_write, },
+    { 0x818, 1, 1, .read = prep_port0818_read },
+    { 0x81c, 1, 1, .read = prep_port081c_read,
+                   .write = prep_port081c_write, },
+    { 0x850, 1, 1, .read = prep_port0850_read,
+                   .write = prep_port0850_write, },
+    { 0x852, 1, 1, .read = prep_port0852_read, },
+    PORTIO_END_OF_LIST()
+};
+
+static uint64_t ppc_parity_error_readl(void *opaque, hwaddr addr,
+                                       unsigned int size)
+{
+    uint32_t val = 0;
+    trace_prep_systemio_read((unsigned int)addr, val);
+    return val;
+}
+
+static const MemoryRegionOps ppc_parity_error_ops = {
+    .read = ppc_parity_error_readl,
+    .valid = {
+        .min_access_size = 4,
+        .max_access_size = 4,
+    },
+};
+
+static void prep_systemio_realize(DeviceState *dev, Error **errp)
+{
+    ISADevice *isa = ISA_DEVICE(dev);
+    PrepSystemIoState *s = PREP_SYSTEMIO(dev);
+    PowerPCCPU *cpu;
+
+    qdev_init_gpio_out(dev, &s->non_contiguous_io_map_irq, 1);
+    s->iomap_type = 0; /* contiguous mode XXX 0x1? */
+    cpu = POWERPC_CPU(first_cpu);
+    s->softreset_irq = cpu->env.irq_inputs[PPC6xx_INPUT_HRESET];
+
+    isa_register_portio_list(isa, &s->portio, 0x0, ppc_io800_port_list, s,
+                             "systemio800");
+
+    memory_region_init_io(&s->ppc_parity_mem, OBJECT(dev),
+                          &ppc_parity_error_ops, s, "ppc-parity", 0x4);
+    memory_region_add_subregion(get_system_memory(), 0xbfffeff0,
+                                &s->ppc_parity_mem);
+}
+
+static const VMStateDescription vmstate_prep_systemio = {
+    .name = "prep_systemio",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT8(system_control, PrepSystemIoState),
+        VMSTATE_UINT8(iomap_type, PrepSystemIoState),
+        VMSTATE_END_OF_LIST()
+    },
+};
+
+static Property prep_systemio_properties[] = {
+    DEFINE_PROP_UINT8("ibm-planar-id", PrepSystemIoState, ibm_planar_id, 0),
+    DEFINE_PROP_UINT8("equipment", PrepSystemIoState, equipment, 0),
+    DEFINE_PROP_END_OF_LIST()
+};
+
+static void prep_systemio_class_initfn(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
+    dc->realize = prep_systemio_realize;
+    dc->vmsd = &vmstate_prep_systemio;
+    dc->props = prep_systemio_properties;
+}
+
+static TypeInfo prep_systemio800_info = {
+    .name          = TYPE_PREP_SYSTEMIO,
+    .parent        = TYPE_ISA_DEVICE,
+    .instance_size = sizeof(PrepSystemIoState),
+    .class_init    = prep_systemio_class_initfn,
+};
+
+static void prep_systemio_register_types(void)
+{
+    type_register_static(&prep_systemio800_info);
+}
+
+type_init(prep_systemio_register_types)
hw/ppc/trace-events +4 -0
index 2297ead..2ba6166 100644
@@ -74,3 +74,7 @@ ppc_tb_adjust(uint64_t offs1, uint64_t offs2, int64_t diff, int64_t seconds) "ad
 # hw/ppc/prep.c
 prep_io_800_writeb(uint32_t addr, uint32_t val) "0x%08" PRIx32 " => 0x%02" PRIx32
 prep_io_800_readb(uint32_t addr, uint32_t retval) "0x%08" PRIx32 " <= 0x%02" PRIx32
+
+# hw/ppc/prep_systemio.c
+prep_systemio_read(uint32_t addr, uint32_t val) "read addr=%x val=%x"
+prep_systemio_write(uint32_t addr, uint32_t val) "write addr=%x val=%x"
#14 lore raw

Re: [Qemu-devel] [PATCH 4/6] prep: QOM'ify System I/O

Quoted 18 lines · Hervé Poussineau
Quoted 6 lines · David Gibson
Quoted 2 lines · Hervé Poussineau

Part of the functionality is copied from hw/ppc/prep.c. Also add support for board identification/equipment registers.

Needs more detail in the commit message. What is system I/O? what is it for?

System I/O is a PPC PReP device which allows access to motherboard devices, living in the 0x800-0x8ff memory range. It is described in "PowerPC Reference platform Specification", available at ftp://ftp.software.ibm.com/rs6000/technology/spec/ (files srp1*) in section 6.1.5: "I/O Device Mapping"

Quoted 5 lines

The 1-line summary is also misleading; "QOM'ify" suggests you are changing an existing device to use QOM conventions, but no existing device is removed here. Is this actually something new, or is it a duplicate QOMified version of something else? If so, what?

Quoted 5 lines

It is a partial duplicate of System I/O device available in hw/ppc/prep.c .
The new one I'm adding doesn't have all the Motorola-specific registers, and follows a known specification.

The existing one should be deprecated and removed with the 'prep' machine.

Ok, so fold this information into the commit message and resend.

Quoted 346 lines

Hervé

Quoted 342 lines
Quoted 341 lines
---
 hw/ppc/Makefile.objs   |   1 +
 hw/ppc/prep_systemio.c | 302 +++++++++++++++++++++++++++++++++++++++++++++++++
 hw/ppc/trace-events    |   4 +
 3 files changed, 307 insertions(+)
 create mode 100644 hw/ppc/prep_systemio.c
hw/ppc/Makefile.objs +1 -0
index 8025129..db72297 100644
@@ -16,6 +16,7 @@ obj-y += ppc405_boards.o ppc4xx_devs.o ppc405_uc.o ppc440_bamboo.o
 obj-y += ppc4xx_pci.o
 # PReP
 obj-$(CONFIG_PREP) += prep.o
+obj-$(CONFIG_PREP) += prep_systemio.o
 # OldWorld PowerMac
 obj-$(CONFIG_MAC) += mac_oldworld.o
 # NewWorld PowerMac
hw/ppc/prep_systemio.c new file +302 -0
new file mode 100644
index 0000000..449056c
@@ -0,0 +1,302 @@
+/*
+ * QEMU PReP System I/O emulation
+ *
+ * Copyright (c) 2016 Herve Poussineau
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "qemu/osdep.h"
+#include "hw/isa/isa.h"
+#include "exec/address-spaces.h"
+#include "qemu/error-report.h" /* for error_report() */
+#include "sysemu/sysemu.h" /* for vm_stop() */
+#include "cpu.h"
+#include "trace.h"
+
+#define TYPE_PREP_SYSTEMIO "prep-systemio"
+#define PREP_SYSTEMIO(obj) \
+    OBJECT_CHECK(PrepSystemIoState, (obj), TYPE_PREP_SYSTEMIO)
+
+/* Bit as defined in PowerPC Reference Plaform v1.1, sect. 6.1.5, p. 132 */
+#define PREP_BIT(n) (1 << (7 - (n)))
+
+typedef struct PrepSystemIoState {
+    ISADevice parent_obj;
+    MemoryRegion ppc_parity_mem;
+
+    qemu_irq non_contiguous_io_map_irq;
+    uint8_t sreset; /* 0x0092 */
+    uint8_t equipment; /* 0x080c */
+    uint8_t system_control; /* 0x081c */
+    uint8_t iomap_type; /* 0x0850 */
+    uint8_t ibm_planar_id; /* 0x0852 */
+    qemu_irq softreset_irq;
+    PortioList portio;
+} PrepSystemIoState;
+
+/* PORT 0092 -- Special Port 92 (Read/Write) */
+
+enum {
+    PORT0092_SOFTRESET  = PREP_BIT(7),
+    PORT0092_LE_MODE    = PREP_BIT(6),
+};
+
+static void prep_port0092_write(void *opaque, uint32_t addr, uint32_t val)
+{
+    PrepSystemIoState *s = opaque;
+
+    trace_prep_systemio_write(addr, val);
+
+    if ((val & PORT0092_SOFTRESET) != 0) {
+        qemu_irq_raise(s->softreset_irq);
+        s->sreset = 1;
+    } else {
+        qemu_irq_lower(s->softreset_irq);
+        s->sreset = 0;
+    }
+
+    if ((val & PORT0092_LE_MODE) != 0) {
+        /* XXX Not supported yet */
+        error_report("little-endian mode not supported");
+        vm_stop(RUN_STATE_PAUSED);
+    } else {
+        /* Nothing to do */
+    }
+}
+
+static uint32_t prep_port0092_read(void *opaque, uint32_t addr)
+{
+    PrepSystemIoState *s = opaque;
+    /* XXX LE mode unsupported */
+    trace_prep_systemio_read(addr, 0);
+    return s->sreset;
+}
+
+/* PORT 0808 -- Hardfile Light Register (Write Only) */
+
+enum {
+    PORT0808_HARDFILE_LIGHT_ON  = PREP_BIT(7),
+};
+
+static void prep_port0808_write(void *opaque, uint32_t addr, uint32_t val)
+{
+    trace_prep_systemio_write(addr, val);
+}
+
+/* PORT 0810 -- Password Protect 1 Register (Write Only) */
+
+/* reset by port 0x4D in the SIO */
+static void prep_port0810_write(void *opaque, uint32_t addr, uint32_t val)
+{
+    trace_prep_systemio_write(addr, val);
+}
+
+/* PORT 0812 -- Password Protect 2 Register (Write Only) */
+
+/* reset by port 0x4D in the SIO */
+static void prep_port0812_write(void *opaque, uint32_t addr, uint32_t val)
+{
+    trace_prep_systemio_write(addr, val);
+}
+
+/* PORT 0814 -- L2 Invalidate Register (Write Only) */
+
+static void prep_port0814_write(void *opaque, uint32_t addr, uint32_t val)
+{
+    trace_prep_systemio_write(addr, val);
+}
+
+/* PORT 0818 -- Reserved for Keylock (Read Only) */
+
+enum {
+    PORT0818_KEYLOCK_SIGNAL_HIGH    = PREP_BIT(7),
+};
+
+static uint32_t prep_port0818_read(void *opaque, uint32_t addr)
+{
+    uint32_t val = 0;
+    trace_prep_systemio_read(addr, val);
+    return val;
+}
+
+/* PORT 080C -- Equipment */
+
+enum {
+    PORT080C_SCSIFUSE               = PREP_BIT(1),
+    PORT080C_L2_COPYBACK            = PREP_BIT(4),
+    PORT080C_L2_256                 = PREP_BIT(5),
+    PORT080C_UPGRADE_CPU            = PREP_BIT(6),
+    PORT080C_L2                     = PREP_BIT(7),
+};
+
+static uint32_t prep_port080c_read(void *opaque, uint32_t addr)
+{
+    PrepSystemIoState *s = opaque;
+    trace_prep_systemio_read(addr, s->equipment);
+    return s->equipment;
+}
+
+/* PORT 081C -- System Control Register (Read/Write) */
+
+enum {
+    PORT081C_FLOPPY_MOTOR_INHIBIT   = PREP_BIT(3),
+    PORT081C_MASK_TEA               = PREP_BIT(2),
+    PORT081C_L2_UPDATE_INHIBIT      = PREP_BIT(1),
+    PORT081C_L2_CACHEMISS_INHIBIT   = PREP_BIT(0),
+};
+
+static void prep_port081c_write(void *opaque, uint32_t addr, uint32_t val)
+{
+    PrepSystemIoState *s = opaque;
+    trace_prep_systemio_write(addr, val);
+    s->system_control = val;
+}
+
+static uint32_t prep_port081c_read(void *opaque, uint32_t addr)
+{
+    PrepSystemIoState *s = opaque;
+    trace_prep_systemio_read(addr, s->system_control);
+    return s->system_control;
+}
+
+/* System Board Identification */
+
+static uint32_t prep_port0852_read(void *opaque, uint32_t addr)
+{
+    PrepSystemIoState *s = opaque;
+    trace_prep_systemio_read(addr, s->ibm_planar_id);
+    return s->ibm_planar_id;
+}
+
+/* PORT 0850 -- I/O Map Type Register (Read/Write) */
+
+enum {
+    PORT0850_IOMAP_NONCONTIGUOUS    = PREP_BIT(7),
+};
+
+static uint32_t prep_port0850_read(void *opaque, uint32_t addr)
+{
+    PrepSystemIoState *s = opaque;
+    trace_prep_systemio_read(addr, s->iomap_type);
+    return s->iomap_type;
+}
+
+static void prep_port0850_write(void *opaque, uint32_t addr, uint32_t val)
+{
+    PrepSystemIoState *s = opaque;
+
+    trace_prep_systemio_write(addr, val);
+    qemu_set_irq(s->non_contiguous_io_map_irq,
+                 val & PORT0850_IOMAP_NONCONTIGUOUS ? 1 : 0);
+    s->iomap_type = val;
+}
+
+static const MemoryRegionPortio ppc_io800_port_list[] = {
+    { 0x092, 1, 1, .read = prep_port0092_read,
+                   .write = prep_port0092_write, },
+    { 0x808, 1, 1, .write = prep_port0808_write, },
+    { 0x80c, 1, 1, .read = prep_port080c_read, },
+    { 0x810, 1, 1, .write = prep_port0810_write, },
+    { 0x812, 1, 1, .write = prep_port0812_write, },
+    { 0x814, 1, 1, .write = prep_port0814_write, },
+    { 0x818, 1, 1, .read = prep_port0818_read },
+    { 0x81c, 1, 1, .read = prep_port081c_read,
+                   .write = prep_port081c_write, },
+    { 0x850, 1, 1, .read = prep_port0850_read,
+                   .write = prep_port0850_write, },
+    { 0x852, 1, 1, .read = prep_port0852_read, },
+    PORTIO_END_OF_LIST()
+};
+
+static uint64_t ppc_parity_error_readl(void *opaque, hwaddr addr,
+                                       unsigned int size)
+{
+    uint32_t val = 0;
+    trace_prep_systemio_read((unsigned int)addr, val);
+    return val;
+}
+
+static const MemoryRegionOps ppc_parity_error_ops = {
+    .read = ppc_parity_error_readl,
+    .valid = {
+        .min_access_size = 4,
+        .max_access_size = 4,
+    },
+};
+
+static void prep_systemio_realize(DeviceState *dev, Error **errp)
+{
+    ISADevice *isa = ISA_DEVICE(dev);
+    PrepSystemIoState *s = PREP_SYSTEMIO(dev);
+    PowerPCCPU *cpu;
+
+    qdev_init_gpio_out(dev, &s->non_contiguous_io_map_irq, 1);
+    s->iomap_type = 0; /* contiguous mode XXX 0x1? */
+    cpu = POWERPC_CPU(first_cpu);
+    s->softreset_irq = cpu->env.irq_inputs[PPC6xx_INPUT_HRESET];
+
+    isa_register_portio_list(isa, &s->portio, 0x0, ppc_io800_port_list, s,
+                             "systemio800");
+
+    memory_region_init_io(&s->ppc_parity_mem, OBJECT(dev),
+                          &ppc_parity_error_ops, s, "ppc-parity", 0x4);
+    memory_region_add_subregion(get_system_memory(), 0xbfffeff0,
+                                &s->ppc_parity_mem);
+}
+
+static const VMStateDescription vmstate_prep_systemio = {
+    .name = "prep_systemio",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT8(system_control, PrepSystemIoState),
+        VMSTATE_UINT8(iomap_type, PrepSystemIoState),
+        VMSTATE_END_OF_LIST()
+    },
+};
+
+static Property prep_systemio_properties[] = {
+    DEFINE_PROP_UINT8("ibm-planar-id", PrepSystemIoState, ibm_planar_id, 0),
+    DEFINE_PROP_UINT8("equipment", PrepSystemIoState, equipment, 0),
+    DEFINE_PROP_END_OF_LIST()
+};
+
+static void prep_systemio_class_initfn(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
+    dc->realize = prep_systemio_realize;
+    dc->vmsd = &vmstate_prep_systemio;
+    dc->props = prep_systemio_properties;
+}
+
+static TypeInfo prep_systemio800_info = {
+    .name          = TYPE_PREP_SYSTEMIO,
+    .parent        = TYPE_ISA_DEVICE,
+    .instance_size = sizeof(PrepSystemIoState),
+    .class_init    = prep_systemio_class_initfn,
+};
+
+static void prep_systemio_register_types(void)
+{
+    type_register_static(&prep_systemio800_info);
+}
+
+type_init(prep_systemio_register_types)
hw/ppc/trace-events +4 -0
index 2297ead..2ba6166 100644
@@ -74,3 +74,7 @@ ppc_tb_adjust(uint64_t offs1, uint64_t offs2, int64_t diff, int64_t seconds) "ad
 # hw/ppc/prep.c
 prep_io_800_writeb(uint32_t addr, uint32_t val) "0x%08" PRIx32 " => 0x%02" PRIx32
 prep_io_800_readb(uint32_t addr, uint32_t retval) "0x%08" PRIx32 " <= 0x%02" PRIx32
+
+# hw/ppc/prep_systemio.c
+prep_systemio_read(uint32_t addr, uint32_t val) "read addr=%x val=%x"
+prep_systemio_write(uint32_t addr, uint32_t val) "write addr=%x val=%x"
Signature · 4 lines
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
#15 lore raw

Re: [Qemu-devel] [PATCH 4/6] prep: QOM'ify System I/O

In reply to Hervé Poussineau
Quoted 91 lines · Hervé Poussineau

Part of the functionality is copied from hw/ppc/prep.c. Also add support for board identification/equipment registers.

---
 hw/ppc/Makefile.objs   |   1 +
 hw/ppc/prep_systemio.c | 302 +++++++++++++++++++++++++++++++++++++++++++++++++
 hw/ppc/trace-events    |   4 +
 3 files changed, 307 insertions(+)
 create mode 100644 hw/ppc/prep_systemio.c
hw/ppc/Makefile.objs +1 -0
index 8025129..db72297 100644
@@ -16,6 +16,7 @@ obj-y += ppc405_boards.o ppc4xx_devs.o ppc405_uc.o ppc440_bamboo.o
 obj-y += ppc4xx_pci.o
 # PReP
 obj-$(CONFIG_PREP) += prep.o
+obj-$(CONFIG_PREP) += prep_systemio.o
 # OldWorld PowerMac
 obj-$(CONFIG_MAC) += mac_oldworld.o
 # NewWorld PowerMac
hw/ppc/prep_systemio.c new file +62 -0
new file mode 100644
index 0000000..449056c
@@ -0,0 +1,302 @@
+/*
+ * QEMU PReP System I/O emulation
+ *
+ * Copyright (c) 2016 Herve Poussineau
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "qemu/osdep.h"
+#include "hw/isa/isa.h"
+#include "exec/address-spaces.h"
+#include "qemu/error-report.h" /* for error_report() */
+#include "sysemu/sysemu.h" /* for vm_stop() */
+#include "cpu.h"
+#include "trace.h"
+
+#define TYPE_PREP_SYSTEMIO "prep-systemio"
+#define PREP_SYSTEMIO(obj) \
+    OBJECT_CHECK(PrepSystemIoState, (obj), TYPE_PREP_SYSTEMIO)
+
+/* Bit as defined in PowerPC Reference Plaform v1.1, sect. 6.1.5, p. 132 */
+#define PREP_BIT(n) (1 << (7 - (n)))
+
+typedef struct PrepSystemIoState {
+    ISADevice parent_obj;
+    MemoryRegion ppc_parity_mem;
+
+    qemu_irq non_contiguous_io_map_irq;
+    uint8_t sreset; /* 0x0092 */
+    uint8_t equipment; /* 0x080c */
+    uint8_t system_control; /* 0x081c */
+    uint8_t iomap_type; /* 0x0850 */
+    uint8_t ibm_planar_id; /* 0x0852 */
+    qemu_irq softreset_irq;
+    PortioList portio;
+} PrepSystemIoState;
+
+/* PORT 0092 -- Special Port 92 (Read/Write) */
+
+enum {
+    PORT0092_SOFTRESET  = PREP_BIT(7),
+    PORT0092_LE_MODE    = PREP_BIT(6),
+};
+
+static void prep_port0092_write(void *opaque, uint32_t addr, uint32_t val)
+{

hw/ppc/prep_systemio.c line 72

Quoted 10 lines
hw/ppc/prep_systemio.c new file +10 -0
+    PrepSystemIoState *s = opaque;
+
+    trace_prep_systemio_write(addr, val);
+
+    if ((val & PORT0092_SOFTRESET) != 0) {
+        qemu_irq_raise(s->softreset_irq);
+        s->sreset = 1;
+    } else {
+        qemu_irq_lower(s->softreset_irq);
+        s->sreset = 0;

You could just use

	s->sreset = val & PORT0092_SOFTRESET;
	qemu_set_irq(irq, s->sreset);

here, rather than the if.

Quoted 7 lines
hw/ppc/prep_systemio.c new file +7 -0
+    }
+
+    if ((val & PORT0092_LE_MODE) != 0) {
+        /* XXX Not supported yet */
+        error_report("little-endian mode not supported");
+        vm_stop(RUN_STATE_PAUSED);
+    } else {

hw/ppc/prep_systemio.c line 89

Quoted 10 lines
hw/ppc/prep_systemio.c new file +10 -0
+        /* Nothing to do */
+    }
+}
+
+static uint32_t prep_port0092_read(void *opaque, uint32_t addr)
+{
+    PrepSystemIoState *s = opaque;
+    /* XXX LE mode unsupported */
+    trace_prep_systemio_read(addr, 0);
+    return s->sreset;

This doesn't seem to quite logically match the write side. On the write side you convert the PORT0092_SOFTRESET bit into an explicit 0/1, here you return the raw 0/1. It ends up being the same thing because PORT0092_SOFTRESET == 0x01, but that's not terribly obvious.

Quoted 70 lines
hw/ppc/prep_systemio.c new file +70 -0
+}
+
+/* PORT 0808 -- Hardfile Light Register (Write Only) */
+
+enum {
+    PORT0808_HARDFILE_LIGHT_ON  = PREP_BIT(7),
+};
+
+static void prep_port0808_write(void *opaque, uint32_t addr, uint32_t val)
+{
+    trace_prep_systemio_write(addr, val);
+}
+
+/* PORT 0810 -- Password Protect 1 Register (Write Only) */
+
+/* reset by port 0x4D in the SIO */
+static void prep_port0810_write(void *opaque, uint32_t addr, uint32_t val)
+{
+    trace_prep_systemio_write(addr, val);
+}
+
+/* PORT 0812 -- Password Protect 2 Register (Write Only) */
+
+/* reset by port 0x4D in the SIO */
+static void prep_port0812_write(void *opaque, uint32_t addr, uint32_t val)
+{
+    trace_prep_systemio_write(addr, val);
+}
+
+/* PORT 0814 -- L2 Invalidate Register (Write Only) */
+
+static void prep_port0814_write(void *opaque, uint32_t addr, uint32_t val)
+{
+    trace_prep_systemio_write(addr, val);
+}
+
+/* PORT 0818 -- Reserved for Keylock (Read Only) */
+
+enum {
+    PORT0818_KEYLOCK_SIGNAL_HIGH    = PREP_BIT(7),
+};
+
+static uint32_t prep_port0818_read(void *opaque, uint32_t addr)
+{
+    uint32_t val = 0;
+    trace_prep_systemio_read(addr, val);
+    return val;
+}
+
+/* PORT 080C -- Equipment */
+
+enum {
+    PORT080C_SCSIFUSE               = PREP_BIT(1),
+    PORT080C_L2_COPYBACK            = PREP_BIT(4),
+    PORT080C_L2_256                 = PREP_BIT(5),
+    PORT080C_UPGRADE_CPU            = PREP_BIT(6),
+    PORT080C_L2                     = PREP_BIT(7),
+};
+
+static uint32_t prep_port080c_read(void *opaque, uint32_t addr)
+{
+    PrepSystemIoState *s = opaque;
+    trace_prep_systemio_read(addr, s->equipment);
+    return s->equipment;
+}
+
+/* PORT 081C -- System Control Register (Read/Write) */
+
+enum {
+    PORT081C_FLOPPY_MOTOR_INHIBIT   = PREP_BIT(3),

hw/ppc/prep_systemio.c line 169

Quoted 10 lines
hw/ppc/prep_systemio.c new file +10 -0
+    PORT081C_MASK_TEA               = PREP_BIT(2),
+    PORT081C_L2_UPDATE_INHIBIT      = PREP_BIT(1),
+    PORT081C_L2_CACHEMISS_INHIBIT   = PREP_BIT(0),
+};
+
+static void prep_port081c_write(void *opaque, uint32_t addr, uint32_t val)
+{
+    PrepSystemIoState *s = opaque;
+    trace_prep_systemio_write(addr, val);
+    s->system_control = val;

Should this value be masked to restrict it to the valid bits?

Quoted 29 lines
hw/ppc/prep_systemio.c new file +29 -0
+}
+
+static uint32_t prep_port081c_read(void *opaque, uint32_t addr)
+{
+    PrepSystemIoState *s = opaque;
+    trace_prep_systemio_read(addr, s->system_control);
+    return s->system_control;
+}
+
+/* System Board Identification */
+
+static uint32_t prep_port0852_read(void *opaque, uint32_t addr)
+{
+    PrepSystemIoState *s = opaque;
+    trace_prep_systemio_read(addr, s->ibm_planar_id);
+    return s->ibm_planar_id;
+}
+
+/* PORT 0850 -- I/O Map Type Register (Read/Write) */
+
+enum {
+    PORT0850_IOMAP_NONCONTIGUOUS    = PREP_BIT(7),
+};
+
+static uint32_t prep_port0850_read(void *opaque, uint32_t addr)
+{
+    PrepSystemIoState *s = opaque;
+    trace_prep_systemio_read(addr, s->iomap_type);
+    return s->iomap_type;

hw/ppc/prep_systemio.c line 208

Quoted 10 lines
hw/ppc/prep_systemio.c new file +10 -0
+}
+
+static void prep_port0850_write(void *opaque, uint32_t addr, uint32_t val)
+{
+    PrepSystemIoState *s = opaque;
+
+    trace_prep_systemio_write(addr, val);
+    qemu_set_irq(s->non_contiguous_io_map_irq,
+                 val & PORT0850_IOMAP_NONCONTIGUOUS ? 1 : 0);
+    s->iomap_type = val;

Again, should this be masked?

Quoted 53 lines
hw/ppc/prep_systemio.c new file +53 -0
+}
+
+static const MemoryRegionPortio ppc_io800_port_list[] = {
+    { 0x092, 1, 1, .read = prep_port0092_read,
+                   .write = prep_port0092_write, },
+    { 0x808, 1, 1, .write = prep_port0808_write, },
+    { 0x80c, 1, 1, .read = prep_port080c_read, },
+    { 0x810, 1, 1, .write = prep_port0810_write, },
+    { 0x812, 1, 1, .write = prep_port0812_write, },
+    { 0x814, 1, 1, .write = prep_port0814_write, },
+    { 0x818, 1, 1, .read = prep_port0818_read },
+    { 0x81c, 1, 1, .read = prep_port081c_read,
+                   .write = prep_port081c_write, },
+    { 0x850, 1, 1, .read = prep_port0850_read,
+                   .write = prep_port0850_write, },
+    { 0x852, 1, 1, .read = prep_port0852_read, },
+    PORTIO_END_OF_LIST()
+};
+
+static uint64_t ppc_parity_error_readl(void *opaque, hwaddr addr,
+                                       unsigned int size)
+{
+    uint32_t val = 0;
+    trace_prep_systemio_read((unsigned int)addr, val);
+    return val;
+}
+
+static const MemoryRegionOps ppc_parity_error_ops = {
+    .read = ppc_parity_error_readl,
+    .valid = {
+        .min_access_size = 4,
+        .max_access_size = 4,
+    },
+};
+
+static void prep_systemio_realize(DeviceState *dev, Error **errp)
+{
+    ISADevice *isa = ISA_DEVICE(dev);
+    PrepSystemIoState *s = PREP_SYSTEMIO(dev);
+    PowerPCCPU *cpu;
+
+    qdev_init_gpio_out(dev, &s->non_contiguous_io_map_irq, 1);
+    s->iomap_type = 0; /* contiguous mode XXX 0x1? */
+    cpu = POWERPC_CPU(first_cpu);
+    s->softreset_irq = cpu->env.irq_inputs[PPC6xx_INPUT_HRESET];
+
+    isa_register_portio_list(isa, &s->portio, 0x0, ppc_io800_port_list, s,
+                             "systemio800");
+
+    memory_region_init_io(&s->ppc_parity_mem, OBJECT(dev),
+                          &ppc_parity_error_ops, s, "ppc-parity", 0x4);
+    memory_region_add_subregion(get_system_memory(), 0xbfffeff0,
+                                &s->ppc_parity_mem);

hw/ppc/prep_systemio.c line 271

Quoted 10 lines
hw/ppc/prep_systemio.c new file +10 -0
+}
+
+static const VMStateDescription vmstate_prep_systemio = {
+    .name = "prep_systemio",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT8(system_control, PrepSystemIoState),
+        VMSTATE_UINT8(iomap_type, PrepSystemIoState),
+        VMSTATE_END_OF_LIST()

I'm not sure how useful this will be given how much other stuff in PReP won't migrate properly.

Quoted 43 lines
hw/ppc/prep_systemio.c new file +31 -0
+    },
+};
+
+static Property prep_systemio_properties[] = {
+    DEFINE_PROP_UINT8("ibm-planar-id", PrepSystemIoState, ibm_planar_id, 0),
+    DEFINE_PROP_UINT8("equipment", PrepSystemIoState, equipment, 0),
+    DEFINE_PROP_END_OF_LIST()
+};
+
+static void prep_systemio_class_initfn(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
+    dc->realize = prep_systemio_realize;
+    dc->vmsd = &vmstate_prep_systemio;
+    dc->props = prep_systemio_properties;
+}
+
+static TypeInfo prep_systemio800_info = {
+    .name          = TYPE_PREP_SYSTEMIO,
+    .parent        = TYPE_ISA_DEVICE,
+    .instance_size = sizeof(PrepSystemIoState),
+    .class_init    = prep_systemio_class_initfn,
+};
+
+static void prep_systemio_register_types(void)
+{
+    type_register_static(&prep_systemio800_info);
+}
+
+type_init(prep_systemio_register_types)
hw/ppc/trace-events +4 -0
index 2297ead..2ba6166 100644
@@ -74,3 +74,7 @@ ppc_tb_adjust(uint64_t offs1, uint64_t offs2, int64_t diff, int64_t seconds) "ad
 # hw/ppc/prep.c
 prep_io_800_writeb(uint32_t addr, uint32_t val) "0x%08" PRIx32 " => 0x%02" PRIx32
 prep_io_800_readb(uint32_t addr, uint32_t retval) "0x%08" PRIx32 " <= 0x%02" PRIx32
+
+# hw/ppc/prep_systemio.c
+prep_systemio_read(uint32_t addr, uint32_t val) "read addr=%x val=%x"
+prep_systemio_write(uint32_t addr, uint32_t val) "write addr=%x val=%x"
Signature · 4 lines
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
#16 lore raw

Re: [Qemu-devel] [PATCH 4/6] prep: QOM'ify System I/O

Quoted 104 lines · David Gibson
Quoted 91 lines · Hervé Poussineau

Part of the functionality is copied from hw/ppc/prep.c. Also add support for board identification/equipment registers.

---
 hw/ppc/Makefile.objs   |   1 +
 hw/ppc/prep_systemio.c | 302 +++++++++++++++++++++++++++++++++++++++++++++++++
 hw/ppc/trace-events    |   4 +
 3 files changed, 307 insertions(+)
 create mode 100644 hw/ppc/prep_systemio.c
hw/ppc/Makefile.objs +1 -0
index 8025129..db72297 100644
@@ -16,6 +16,7 @@ obj-y += ppc405_boards.o ppc4xx_devs.o ppc405_uc.o ppc440_bamboo.o
 obj-y += ppc4xx_pci.o
 # PReP
 obj-$(CONFIG_PREP) += prep.o
+obj-$(CONFIG_PREP) += prep_systemio.o
 # OldWorld PowerMac
 obj-$(CONFIG_MAC) += mac_oldworld.o
 # NewWorld PowerMac
hw/ppc/prep_systemio.c new file +62 -0
new file mode 100644
index 0000000..449056c
@@ -0,0 +1,302 @@
+/*
+ * QEMU PReP System I/O emulation
+ *
+ * Copyright (c) 2016 Herve Poussineau
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "qemu/osdep.h"
+#include "hw/isa/isa.h"
+#include "exec/address-spaces.h"
+#include "qemu/error-report.h" /* for error_report() */
+#include "sysemu/sysemu.h" /* for vm_stop() */
+#include "cpu.h"
+#include "trace.h"
+
+#define TYPE_PREP_SYSTEMIO "prep-systemio"
+#define PREP_SYSTEMIO(obj) \
+    OBJECT_CHECK(PrepSystemIoState, (obj), TYPE_PREP_SYSTEMIO)
+
+/* Bit as defined in PowerPC Reference Plaform v1.1, sect. 6.1.5, p. 132 */
+#define PREP_BIT(n) (1 << (7 - (n)))
+
+typedef struct PrepSystemIoState {
+    ISADevice parent_obj;
+    MemoryRegion ppc_parity_mem;
+
+    qemu_irq non_contiguous_io_map_irq;
+    uint8_t sreset; /* 0x0092 */
+    uint8_t equipment; /* 0x080c */
+    uint8_t system_control; /* 0x081c */
+    uint8_t iomap_type; /* 0x0850 */
+    uint8_t ibm_planar_id; /* 0x0852 */
+    qemu_irq softreset_irq;
+    PortioList portio;
+} PrepSystemIoState;
+
+/* PORT 0092 -- Special Port 92 (Read/Write) */
+
+enum {
+    PORT0092_SOFTRESET  = PREP_BIT(7),
+    PORT0092_LE_MODE    = PREP_BIT(6),
+};
+
+static void prep_port0092_write(void *opaque, uint32_t addr, uint32_t val)
+{

hw/ppc/prep_systemio.c line 72

Quoted 10 lines
hw/ppc/prep_systemio.c new file +10 -0
+    PrepSystemIoState *s = opaque;
+
+    trace_prep_systemio_write(addr, val);
+
+    if ((val & PORT0092_SOFTRESET) != 0) {
+        qemu_irq_raise(s->softreset_irq);
+        s->sreset = 1;
+    } else {
+        qemu_irq_lower(s->softreset_irq);
+        s->sreset = 0;

You could just use

Quoted 3 lines
	s->sreset = val & PORT0092_SOFTRESET;
	qemu_set_irq(irq, s->sreset);

here, rather than the if.

OK

Quoted 15 lines
Quoted 15 lines
hw/ppc/prep_systemio.c new file +14 -0
+    }
+
+    if ((val & PORT0092_LE_MODE) != 0) {
+        /* XXX Not supported yet */
+        error_report("little-endian mode not supported");
+        vm_stop(RUN_STATE_PAUSED);
+    } else {
+        /* Nothing to do */
+    }
+}
+
+static uint32_t prep_port0092_read(void *opaque, uint32_t addr)
+{
+    PrepSystemIoState *s = opaque;
Quoted 8 lines

hw/ppc/prep_systemio.c line 89

Quoted 3 lines
hw/ppc/prep_systemio.c new file +3 -0
+    /* XXX LE mode unsupported */
+    trace_prep_systemio_read(addr, 0);
+    return s->sreset;

This doesn't seem to quite logically match the write side. On the write side you convert the PORT0092_SOFTRESET bit into an explicit 0/1, here you return the raw 0/1. It ends up being the same thing because PORT0092_SOFTRESET == 0x01, but that's not terribly obvious.

OK, will change that.

Quoted 75 lines
Quoted 75 lines
hw/ppc/prep_systemio.c new file +74 -0
+}
+
+/* PORT 0808 -- Hardfile Light Register (Write Only) */
+
+enum {
+    PORT0808_HARDFILE_LIGHT_ON  = PREP_BIT(7),
+};
+
+static void prep_port0808_write(void *opaque, uint32_t addr, uint32_t val)
+{
+    trace_prep_systemio_write(addr, val);
+}
+
+/* PORT 0810 -- Password Protect 1 Register (Write Only) */
+
+/* reset by port 0x4D in the SIO */
+static void prep_port0810_write(void *opaque, uint32_t addr, uint32_t val)
+{
+    trace_prep_systemio_write(addr, val);
+}
+
+/* PORT 0812 -- Password Protect 2 Register (Write Only) */
+
+/* reset by port 0x4D in the SIO */
+static void prep_port0812_write(void *opaque, uint32_t addr, uint32_t val)
+{
+    trace_prep_systemio_write(addr, val);
+}
+
+/* PORT 0814 -- L2 Invalidate Register (Write Only) */
+
+static void prep_port0814_write(void *opaque, uint32_t addr, uint32_t val)
+{
+    trace_prep_systemio_write(addr, val);
+}
+
+/* PORT 0818 -- Reserved for Keylock (Read Only) */
+
+enum {
+    PORT0818_KEYLOCK_SIGNAL_HIGH    = PREP_BIT(7),
+};
+
+static uint32_t prep_port0818_read(void *opaque, uint32_t addr)
+{
+    uint32_t val = 0;
+    trace_prep_systemio_read(addr, val);
+    return val;
+}
+
+/* PORT 080C -- Equipment */
+
+enum {
+    PORT080C_SCSIFUSE               = PREP_BIT(1),
+    PORT080C_L2_COPYBACK            = PREP_BIT(4),
+    PORT080C_L2_256                 = PREP_BIT(5),
+    PORT080C_UPGRADE_CPU            = PREP_BIT(6),
+    PORT080C_L2                     = PREP_BIT(7),
+};
+
+static uint32_t prep_port080c_read(void *opaque, uint32_t addr)
+{
+    PrepSystemIoState *s = opaque;
+    trace_prep_systemio_read(addr, s->equipment);
+    return s->equipment;
+}
+
+/* PORT 081C -- System Control Register (Read/Write) */
+
+enum {
+    PORT081C_FLOPPY_MOTOR_INHIBIT   = PREP_BIT(3),
+    PORT081C_MASK_TEA               = PREP_BIT(2),
+    PORT081C_L2_UPDATE_INHIBIT      = PREP_BIT(1),
+    PORT081C_L2_CACHEMISS_INHIBIT   = PREP_BIT(0),
+};
Quoted 8 lines

hw/ppc/prep_systemio.c line 169

Quoted 6 lines
hw/ppc/prep_systemio.c new file +6 -0
+
+static void prep_port081c_write(void *opaque, uint32_t addr, uint32_t val)
+{
+    PrepSystemIoState *s = opaque;
+    trace_prep_systemio_write(addr, val);
+    s->system_control = val;

Should this value be masked to restrict it to the valid bits?

Some bits are reserved according to specification, and must be written as 0. I think we can still take them unconditionally.
Note that we do nothing with the value, except giving it back in prep_port081c_read()

Quoted 34 lines
Quoted 34 lines
hw/ppc/prep_systemio.c new file +33 -0
+}
+
+static uint32_t prep_port081c_read(void *opaque, uint32_t addr)
+{
+    PrepSystemIoState *s = opaque;
+    trace_prep_systemio_read(addr, s->system_control);
+    return s->system_control;
+}
+
+/* System Board Identification */
+
+static uint32_t prep_port0852_read(void *opaque, uint32_t addr)
+{
+    PrepSystemIoState *s = opaque;
+    trace_prep_systemio_read(addr, s->ibm_planar_id);
+    return s->ibm_planar_id;
+}
+
+/* PORT 0850 -- I/O Map Type Register (Read/Write) */
+
+enum {
+    PORT0850_IOMAP_NONCONTIGUOUS    = PREP_BIT(7),
+};
+
+static uint32_t prep_port0850_read(void *opaque, uint32_t addr)
+{
+    PrepSystemIoState *s = opaque;
+    trace_prep_systemio_read(addr, s->iomap_type);
+    return s->iomap_type;
+}
+
+static void prep_port0850_write(void *opaque, uint32_t addr, uint32_t val)
+{
Quoted 8 lines

hw/ppc/prep_systemio.c line 208

Quoted 6 lines
hw/ppc/prep_systemio.c new file +6 -0
+    PrepSystemIoState *s = opaque;
+
+    trace_prep_systemio_write(addr, val);
+    qemu_set_irq(s->non_contiguous_io_map_irq,
+                 val & PORT0850_IOMAP_NONCONTIGUOUS ? 1 : 0);
+    s->iomap_type = val;

Again, should this be masked?

Again some reserved bits. Let's take them unconditionally.

Quoted 59 lines
Quoted 59 lines
hw/ppc/prep_systemio.c new file +58 -0
+}
+
+static const MemoryRegionPortio ppc_io800_port_list[] = {
+    { 0x092, 1, 1, .read = prep_port0092_read,
+                   .write = prep_port0092_write, },
+    { 0x808, 1, 1, .write = prep_port0808_write, },
+    { 0x80c, 1, 1, .read = prep_port080c_read, },
+    { 0x810, 1, 1, .write = prep_port0810_write, },
+    { 0x812, 1, 1, .write = prep_port0812_write, },
+    { 0x814, 1, 1, .write = prep_port0814_write, },
+    { 0x818, 1, 1, .read = prep_port0818_read },
+    { 0x81c, 1, 1, .read = prep_port081c_read,
+                   .write = prep_port081c_write, },
+    { 0x850, 1, 1, .read = prep_port0850_read,
+                   .write = prep_port0850_write, },
+    { 0x852, 1, 1, .read = prep_port0852_read, },
+    PORTIO_END_OF_LIST()
+};
+
+static uint64_t ppc_parity_error_readl(void *opaque, hwaddr addr,
+                                       unsigned int size)
+{
+    uint32_t val = 0;
+    trace_prep_systemio_read((unsigned int)addr, val);
+    return val;
+}
+
+static const MemoryRegionOps ppc_parity_error_ops = {
+    .read = ppc_parity_error_readl,
+    .valid = {
+        .min_access_size = 4,
+        .max_access_size = 4,
+    },
+};
+
+static void prep_systemio_realize(DeviceState *dev, Error **errp)
+{
+    ISADevice *isa = ISA_DEVICE(dev);
+    PrepSystemIoState *s = PREP_SYSTEMIO(dev);
+    PowerPCCPU *cpu;
+
+    qdev_init_gpio_out(dev, &s->non_contiguous_io_map_irq, 1);
+    s->iomap_type = 0; /* contiguous mode XXX 0x1? */
+    cpu = POWERPC_CPU(first_cpu);
+    s->softreset_irq = cpu->env.irq_inputs[PPC6xx_INPUT_HRESET];
+
+    isa_register_portio_list(isa, &s->portio, 0x0, ppc_io800_port_list, s,
+                             "systemio800");
+
+    memory_region_init_io(&s->ppc_parity_mem, OBJECT(dev),
+                          &ppc_parity_error_ops, s, "ppc-parity", 0x4);
+    memory_region_add_subregion(get_system_memory(), 0xbfffeff0,
+                                &s->ppc_parity_mem);
+}
+
+static const VMStateDescription vmstate_prep_systemio = {
+    .name = "prep_systemio",
+    .version_id = 1,
Quoted 8 lines

hw/ppc/prep_systemio.c line 271

Quoted 5 lines
hw/ppc/prep_systemio.c new file +5 -0
+    .minimum_version_id = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT8(system_control, PrepSystemIoState),
+        VMSTATE_UINT8(iomap_type, PrepSystemIoState),
+        VMSTATE_END_OF_LIST()

I'm not sure how useful this will be given how much other stuff in PReP won't migrate properly.

PReP is mostly a PC with a PowerPC CPU, so most devices are already migration-safe.

Quoted 45 lines
Quoted 44 lines
hw/ppc/prep_systemio.c new file +31 -0
+    },
+};
+
+static Property prep_systemio_properties[] = {
+    DEFINE_PROP_UINT8("ibm-planar-id", PrepSystemIoState, ibm_planar_id, 0),
+    DEFINE_PROP_UINT8("equipment", PrepSystemIoState, equipment, 0),
+    DEFINE_PROP_END_OF_LIST()
+};
+
+static void prep_systemio_class_initfn(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
+    dc->realize = prep_systemio_realize;
+    dc->vmsd = &vmstate_prep_systemio;
+    dc->props = prep_systemio_properties;
+}
+
+static TypeInfo prep_systemio800_info = {
+    .name          = TYPE_PREP_SYSTEMIO,
+    .parent        = TYPE_ISA_DEVICE,
+    .instance_size = sizeof(PrepSystemIoState),
+    .class_init    = prep_systemio_class_initfn,
+};
+
+static void prep_systemio_register_types(void)
+{
+    type_register_static(&prep_systemio800_info);
+}
+
+type_init(prep_systemio_register_types)
hw/ppc/trace-events +4 -0
index 2297ead..2ba6166 100644
@@ -74,3 +74,7 @@ ppc_tb_adjust(uint64_t offs1, uint64_t offs2, int64_t diff, int64_t seconds) "ad
 # hw/ppc/prep.c
 prep_io_800_writeb(uint32_t addr, uint32_t val) "0x%08" PRIx32 " => 0x%02" PRIx32
 prep_io_800_readb(uint32_t addr, uint32_t retval) "0x%08" PRIx32 " <= 0x%02" PRIx32
+
+# hw/ppc/prep_systemio.c
+prep_systemio_read(uint32_t addr, uint32_t val) "read addr=%x val=%x"
+prep_systemio_write(uint32_t addr, uint32_t val) "write addr=%x val=%x"
#17 lore raw

Re: [Qemu-devel] [PATCH 4/6] prep: QOM'ify System I/O

Quoted 221 lines · Hervé Poussineau
Quoted 104 lines · David Gibson
Quoted 91 lines · Hervé Poussineau

Part of the functionality is copied from hw/ppc/prep.c. Also add support for board identification/equipment registers.

---
 hw/ppc/Makefile.objs   |   1 +
 hw/ppc/prep_systemio.c | 302 +++++++++++++++++++++++++++++++++++++++++++++++++
 hw/ppc/trace-events    |   4 +
 3 files changed, 307 insertions(+)
 create mode 100644 hw/ppc/prep_systemio.c
hw/ppc/Makefile.objs +1 -0
index 8025129..db72297 100644
@@ -16,6 +16,7 @@ obj-y += ppc405_boards.o ppc4xx_devs.o ppc405_uc.o ppc440_bamboo.o
 obj-y += ppc4xx_pci.o
 # PReP
 obj-$(CONFIG_PREP) += prep.o
+obj-$(CONFIG_PREP) += prep_systemio.o
 # OldWorld PowerMac
 obj-$(CONFIG_MAC) += mac_oldworld.o
 # NewWorld PowerMac
hw/ppc/prep_systemio.c new file +62 -0
new file mode 100644
index 0000000..449056c
@@ -0,0 +1,302 @@
+/*
+ * QEMU PReP System I/O emulation
+ *
+ * Copyright (c) 2016 Herve Poussineau
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "qemu/osdep.h"
+#include "hw/isa/isa.h"
+#include "exec/address-spaces.h"
+#include "qemu/error-report.h" /* for error_report() */
+#include "sysemu/sysemu.h" /* for vm_stop() */
+#include "cpu.h"
+#include "trace.h"
+
+#define TYPE_PREP_SYSTEMIO "prep-systemio"
+#define PREP_SYSTEMIO(obj) \
+    OBJECT_CHECK(PrepSystemIoState, (obj), TYPE_PREP_SYSTEMIO)
+
+/* Bit as defined in PowerPC Reference Plaform v1.1, sect. 6.1.5, p. 132 */
+#define PREP_BIT(n) (1 << (7 - (n)))
+
+typedef struct PrepSystemIoState {
+    ISADevice parent_obj;
+    MemoryRegion ppc_parity_mem;
+
+    qemu_irq non_contiguous_io_map_irq;
+    uint8_t sreset; /* 0x0092 */
+    uint8_t equipment; /* 0x080c */
+    uint8_t system_control; /* 0x081c */
+    uint8_t iomap_type; /* 0x0850 */
+    uint8_t ibm_planar_id; /* 0x0852 */
+    qemu_irq softreset_irq;
+    PortioList portio;
+} PrepSystemIoState;
+
+/* PORT 0092 -- Special Port 92 (Read/Write) */
+
+enum {
+    PORT0092_SOFTRESET  = PREP_BIT(7),
+    PORT0092_LE_MODE    = PREP_BIT(6),
+};
+
+static void prep_port0092_write(void *opaque, uint32_t addr, uint32_t val)
+{

hw/ppc/prep_systemio.c line 72

Quoted 10 lines
hw/ppc/prep_systemio.c new file +10 -0
+    PrepSystemIoState *s = opaque;
+
+    trace_prep_systemio_write(addr, val);
+
+    if ((val & PORT0092_SOFTRESET) != 0) {
+        qemu_irq_raise(s->softreset_irq);
+        s->sreset = 1;
+    } else {
+        qemu_irq_lower(s->softreset_irq);
+        s->sreset = 0;

You could just use

Quoted 3 lines
	s->sreset = val & PORT0092_SOFTRESET;
	qemu_set_irq(irq, s->sreset);

here, rather than the if.

OK

Quoted 15 lines
Quoted 15 lines
hw/ppc/prep_systemio.c new file +14 -0
+    }
+
+    if ((val & PORT0092_LE_MODE) != 0) {
+        /* XXX Not supported yet */
+        error_report("little-endian mode not supported");
+        vm_stop(RUN_STATE_PAUSED);
+    } else {
+        /* Nothing to do */
+    }
+}
+
+static uint32_t prep_port0092_read(void *opaque, uint32_t addr)
+{
+    PrepSystemIoState *s = opaque;
Quoted 8 lines

hw/ppc/prep_systemio.c line 89

Quoted 3 lines
hw/ppc/prep_systemio.c new file +3 -0
+    /* XXX LE mode unsupported */
+    trace_prep_systemio_read(addr, 0);
+    return s->sreset;

This doesn't seem to quite logically match the write side. On the write side you convert the PORT0092_SOFTRESET bit into an explicit 0/1, here you return the raw 0/1. It ends up being the same thing because PORT0092_SOFTRESET == 0x01, but that's not terribly obvious.

OK, will change that.

Quoted 75 lines
Quoted 75 lines
hw/ppc/prep_systemio.c new file +74 -0
+}
+
+/* PORT 0808 -- Hardfile Light Register (Write Only) */
+
+enum {
+    PORT0808_HARDFILE_LIGHT_ON  = PREP_BIT(7),
+};
+
+static void prep_port0808_write(void *opaque, uint32_t addr, uint32_t val)
+{
+    trace_prep_systemio_write(addr, val);
+}
+
+/* PORT 0810 -- Password Protect 1 Register (Write Only) */
+
+/* reset by port 0x4D in the SIO */
+static void prep_port0810_write(void *opaque, uint32_t addr, uint32_t val)
+{
+    trace_prep_systemio_write(addr, val);
+}
+
+/* PORT 0812 -- Password Protect 2 Register (Write Only) */
+
+/* reset by port 0x4D in the SIO */
+static void prep_port0812_write(void *opaque, uint32_t addr, uint32_t val)
+{
+    trace_prep_systemio_write(addr, val);
+}
+
+/* PORT 0814 -- L2 Invalidate Register (Write Only) */
+
+static void prep_port0814_write(void *opaque, uint32_t addr, uint32_t val)
+{
+    trace_prep_systemio_write(addr, val);
+}
+
+/* PORT 0818 -- Reserved for Keylock (Read Only) */
+
+enum {
+    PORT0818_KEYLOCK_SIGNAL_HIGH    = PREP_BIT(7),
+};
+
+static uint32_t prep_port0818_read(void *opaque, uint32_t addr)
+{
+    uint32_t val = 0;
+    trace_prep_systemio_read(addr, val);
+    return val;
+}
+
+/* PORT 080C -- Equipment */
+
+enum {
+    PORT080C_SCSIFUSE               = PREP_BIT(1),
+    PORT080C_L2_COPYBACK            = PREP_BIT(4),
+    PORT080C_L2_256                 = PREP_BIT(5),
+    PORT080C_UPGRADE_CPU            = PREP_BIT(6),
+    PORT080C_L2                     = PREP_BIT(7),
+};
+
+static uint32_t prep_port080c_read(void *opaque, uint32_t addr)
+{
+    PrepSystemIoState *s = opaque;
+    trace_prep_systemio_read(addr, s->equipment);
+    return s->equipment;
+}
+
+/* PORT 081C -- System Control Register (Read/Write) */
+
+enum {
+    PORT081C_FLOPPY_MOTOR_INHIBIT   = PREP_BIT(3),
+    PORT081C_MASK_TEA               = PREP_BIT(2),
+    PORT081C_L2_UPDATE_INHIBIT      = PREP_BIT(1),
+    PORT081C_L2_CACHEMISS_INHIBIT   = PREP_BIT(0),
+};
Quoted 8 lines

hw/ppc/prep_systemio.c line 169

Quoted 6 lines
hw/ppc/prep_systemio.c new file +6 -0
+
+static void prep_port081c_write(void *opaque, uint32_t addr, uint32_t val)
+{
+    PrepSystemIoState *s = opaque;
+    trace_prep_systemio_write(addr, val);
+    s->system_control = val;

Should this value be masked to restrict it to the valid bits?

Quoted 2 lines

Some bits are reserved according to specification, and must be written as 0.

Right, so I assumed.

Quoted 1 line

I think we can still take them unconditionally.

Hrm.. allowing reserved bits to be set and retrieved is usually a bad idea. Do you have a particular reason to allow this?

Quoted 163 lines

Note that we do nothing with the value, except giving it back in prep_port081c_read()

Quoted 34 lines
Quoted 34 lines
hw/ppc/prep_systemio.c new file +33 -0
+}
+
+static uint32_t prep_port081c_read(void *opaque, uint32_t addr)
+{
+    PrepSystemIoState *s = opaque;
+    trace_prep_systemio_read(addr, s->system_control);
+    return s->system_control;
+}
+
+/* System Board Identification */
+
+static uint32_t prep_port0852_read(void *opaque, uint32_t addr)
+{
+    PrepSystemIoState *s = opaque;
+    trace_prep_systemio_read(addr, s->ibm_planar_id);
+    return s->ibm_planar_id;
+}
+
+/* PORT 0850 -- I/O Map Type Register (Read/Write) */
+
+enum {
+    PORT0850_IOMAP_NONCONTIGUOUS    = PREP_BIT(7),
+};
+
+static uint32_t prep_port0850_read(void *opaque, uint32_t addr)
+{
+    PrepSystemIoState *s = opaque;
+    trace_prep_systemio_read(addr, s->iomap_type);
+    return s->iomap_type;
+}
+
+static void prep_port0850_write(void *opaque, uint32_t addr, uint32_t val)
+{
Quoted 8 lines

hw/ppc/prep_systemio.c line 208

Quoted 6 lines
hw/ppc/prep_systemio.c new file +6 -0
+    PrepSystemIoState *s = opaque;
+
+    trace_prep_systemio_write(addr, val);
+    qemu_set_irq(s->non_contiguous_io_map_irq,
+                 val & PORT0850_IOMAP_NONCONTIGUOUS ? 1 : 0);
+    s->iomap_type = val;

Again, should this be masked?

Again some reserved bits. Let's take them unconditionally.

Quoted 59 lines
Quoted 59 lines
hw/ppc/prep_systemio.c new file +58 -0
+}
+
+static const MemoryRegionPortio ppc_io800_port_list[] = {
+    { 0x092, 1, 1, .read = prep_port0092_read,
+                   .write = prep_port0092_write, },
+    { 0x808, 1, 1, .write = prep_port0808_write, },
+    { 0x80c, 1, 1, .read = prep_port080c_read, },
+    { 0x810, 1, 1, .write = prep_port0810_write, },
+    { 0x812, 1, 1, .write = prep_port0812_write, },
+    { 0x814, 1, 1, .write = prep_port0814_write, },
+    { 0x818, 1, 1, .read = prep_port0818_read },
+    { 0x81c, 1, 1, .read = prep_port081c_read,
+                   .write = prep_port081c_write, },
+    { 0x850, 1, 1, .read = prep_port0850_read,
+                   .write = prep_port0850_write, },
+    { 0x852, 1, 1, .read = prep_port0852_read, },
+    PORTIO_END_OF_LIST()
+};
+
+static uint64_t ppc_parity_error_readl(void *opaque, hwaddr addr,
+                                       unsigned int size)
+{
+    uint32_t val = 0;
+    trace_prep_systemio_read((unsigned int)addr, val);
+    return val;
+}
+
+static const MemoryRegionOps ppc_parity_error_ops = {
+    .read = ppc_parity_error_readl,
+    .valid = {
+        .min_access_size = 4,
+        .max_access_size = 4,
+    },
+};
+
+static void prep_systemio_realize(DeviceState *dev, Error **errp)
+{
+    ISADevice *isa = ISA_DEVICE(dev);
+    PrepSystemIoState *s = PREP_SYSTEMIO(dev);
+    PowerPCCPU *cpu;
+
+    qdev_init_gpio_out(dev, &s->non_contiguous_io_map_irq, 1);
+    s->iomap_type = 0; /* contiguous mode XXX 0x1? */
+    cpu = POWERPC_CPU(first_cpu);
+    s->softreset_irq = cpu->env.irq_inputs[PPC6xx_INPUT_HRESET];
+
+    isa_register_portio_list(isa, &s->portio, 0x0, ppc_io800_port_list, s,
+                             "systemio800");
+
+    memory_region_init_io(&s->ppc_parity_mem, OBJECT(dev),
+                          &ppc_parity_error_ops, s, "ppc-parity", 0x4);
+    memory_region_add_subregion(get_system_memory(), 0xbfffeff0,
+                                &s->ppc_parity_mem);
+}
+
+static const VMStateDescription vmstate_prep_systemio = {
+    .name = "prep_systemio",
+    .version_id = 1,
Quoted 8 lines

hw/ppc/prep_systemio.c line 271

Quoted 5 lines
hw/ppc/prep_systemio.c new file +5 -0
+    .minimum_version_id = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT8(system_control, PrepSystemIoState),
+        VMSTATE_UINT8(iomap_type, PrepSystemIoState),
+        VMSTATE_END_OF_LIST()

I'm not sure how useful this will be given how much other stuff in PReP won't migrate properly.

PReP is mostly a PC with a PowerPC CPU, so most devices are already migration-safe.

Quoted 45 lines
Quoted 44 lines
hw/ppc/prep_systemio.c new file +31 -0
+    },
+};
+
+static Property prep_systemio_properties[] = {
+    DEFINE_PROP_UINT8("ibm-planar-id", PrepSystemIoState, ibm_planar_id, 0),
+    DEFINE_PROP_UINT8("equipment", PrepSystemIoState, equipment, 0),
+    DEFINE_PROP_END_OF_LIST()
+};
+
+static void prep_systemio_class_initfn(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
+    dc->realize = prep_systemio_realize;
+    dc->vmsd = &vmstate_prep_systemio;
+    dc->props = prep_systemio_properties;
+}
+
+static TypeInfo prep_systemio800_info = {
+    .name          = TYPE_PREP_SYSTEMIO,
+    .parent        = TYPE_ISA_DEVICE,
+    .instance_size = sizeof(PrepSystemIoState),
+    .class_init    = prep_systemio_class_initfn,
+};
+
+static void prep_systemio_register_types(void)
+{
+    type_register_static(&prep_systemio800_info);
+}
+
+type_init(prep_systemio_register_types)
hw/ppc/trace-events +4 -0
index 2297ead..2ba6166 100644
@@ -74,3 +74,7 @@ ppc_tb_adjust(uint64_t offs1, uint64_t offs2, int64_t diff, int64_t seconds) "ad
 # hw/ppc/prep.c
 prep_io_800_writeb(uint32_t addr, uint32_t val) "0x%08" PRIx32 " => 0x%02" PRIx32
 prep_io_800_readb(uint32_t addr, uint32_t retval) "0x%08" PRIx32 " <= 0x%02" PRIx32
+
+# hw/ppc/prep_systemio.c
+prep_systemio_read(uint32_t addr, uint32_t val) "read addr=%x val=%x"
+prep_systemio_write(uint32_t addr, uint32_t val) "write addr=%x val=%x"
Signature · 4 lines
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
#18 lore raw

Re: [Qemu-devel] [PATCH 4/6] prep: QOM'ify System I/O

Quoted 225 lines · David Gibson
Quoted 221 lines · Hervé Poussineau
Quoted 104 lines · David Gibson
Quoted 91 lines · Hervé Poussineau

Part of the functionality is copied from hw/ppc/prep.c. Also add support for board identification/equipment registers.

---
 hw/ppc/Makefile.objs   |   1 +
 hw/ppc/prep_systemio.c | 302 +++++++++++++++++++++++++++++++++++++++++++++++++
 hw/ppc/trace-events    |   4 +
 3 files changed, 307 insertions(+)
 create mode 100644 hw/ppc/prep_systemio.c
hw/ppc/Makefile.objs +1 -0
index 8025129..db72297 100644
@@ -16,6 +16,7 @@ obj-y += ppc405_boards.o ppc4xx_devs.o ppc405_uc.o ppc440_bamboo.o
 obj-y += ppc4xx_pci.o
 # PReP
 obj-$(CONFIG_PREP) += prep.o
+obj-$(CONFIG_PREP) += prep_systemio.o
 # OldWorld PowerMac
 obj-$(CONFIG_MAC) += mac_oldworld.o
 # NewWorld PowerMac
hw/ppc/prep_systemio.c new file +62 -0
new file mode 100644
index 0000000..449056c
@@ -0,0 +1,302 @@
+/*
+ * QEMU PReP System I/O emulation
+ *
+ * Copyright (c) 2016 Herve Poussineau
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "qemu/osdep.h"
+#include "hw/isa/isa.h"
+#include "exec/address-spaces.h"
+#include "qemu/error-report.h" /* for error_report() */
+#include "sysemu/sysemu.h" /* for vm_stop() */
+#include "cpu.h"
+#include "trace.h"
+
+#define TYPE_PREP_SYSTEMIO "prep-systemio"
+#define PREP_SYSTEMIO(obj) \
+    OBJECT_CHECK(PrepSystemIoState, (obj), TYPE_PREP_SYSTEMIO)
+
+/* Bit as defined in PowerPC Reference Plaform v1.1, sect. 6.1.5, p. 132 */
+#define PREP_BIT(n) (1 << (7 - (n)))
+
+typedef struct PrepSystemIoState {
+    ISADevice parent_obj;
+    MemoryRegion ppc_parity_mem;
+
+    qemu_irq non_contiguous_io_map_irq;
+    uint8_t sreset; /* 0x0092 */
+    uint8_t equipment; /* 0x080c */
+    uint8_t system_control; /* 0x081c */
+    uint8_t iomap_type; /* 0x0850 */
+    uint8_t ibm_planar_id; /* 0x0852 */
+    qemu_irq softreset_irq;
+    PortioList portio;
+} PrepSystemIoState;
+
+/* PORT 0092 -- Special Port 92 (Read/Write) */
+
+enum {
+    PORT0092_SOFTRESET  = PREP_BIT(7),
+    PORT0092_LE_MODE    = PREP_BIT(6),
+};
+
+static void prep_port0092_write(void *opaque, uint32_t addr, uint32_t val)
+{

hw/ppc/prep_systemio.c line 72

Quoted 10 lines
hw/ppc/prep_systemio.c new file +10 -0
+    PrepSystemIoState *s = opaque;
+
+    trace_prep_systemio_write(addr, val);
+
+    if ((val & PORT0092_SOFTRESET) != 0) {
+        qemu_irq_raise(s->softreset_irq);
+        s->sreset = 1;
+    } else {
+        qemu_irq_lower(s->softreset_irq);
+        s->sreset = 0;

You could just use

Quoted 3 lines
	s->sreset = val & PORT0092_SOFTRESET;
	qemu_set_irq(irq, s->sreset);

here, rather than the if.

OK

Quoted 15 lines
Quoted 15 lines
hw/ppc/prep_systemio.c new file +14 -0
+    }
+
+    if ((val & PORT0092_LE_MODE) != 0) {
+        /* XXX Not supported yet */
+        error_report("little-endian mode not supported");
+        vm_stop(RUN_STATE_PAUSED);
+    } else {
+        /* Nothing to do */
+    }
+}
+
+static uint32_t prep_port0092_read(void *opaque, uint32_t addr)
+{
+    PrepSystemIoState *s = opaque;
Quoted 8 lines

hw/ppc/prep_systemio.c line 89

Quoted 3 lines
hw/ppc/prep_systemio.c new file +3 -0
+    /* XXX LE mode unsupported */
+    trace_prep_systemio_read(addr, 0);
+    return s->sreset;

This doesn't seem to quite logically match the write side. On the write side you convert the PORT0092_SOFTRESET bit into an explicit 0/1, here you return the raw 0/1. It ends up being the same thing because PORT0092_SOFTRESET == 0x01, but that's not terribly obvious.

OK, will change that.

Quoted 75 lines
Quoted 75 lines
hw/ppc/prep_systemio.c new file +74 -0
+}
+
+/* PORT 0808 -- Hardfile Light Register (Write Only) */
+
+enum {
+    PORT0808_HARDFILE_LIGHT_ON  = PREP_BIT(7),
+};
+
+static void prep_port0808_write(void *opaque, uint32_t addr, uint32_t val)
+{
+    trace_prep_systemio_write(addr, val);
+}
+
+/* PORT 0810 -- Password Protect 1 Register (Write Only) */
+
+/* reset by port 0x4D in the SIO */
+static void prep_port0810_write(void *opaque, uint32_t addr, uint32_t val)
+{
+    trace_prep_systemio_write(addr, val);
+}
+
+/* PORT 0812 -- Password Protect 2 Register (Write Only) */
+
+/* reset by port 0x4D in the SIO */
+static void prep_port0812_write(void *opaque, uint32_t addr, uint32_t val)
+{
+    trace_prep_systemio_write(addr, val);
+}
+
+/* PORT 0814 -- L2 Invalidate Register (Write Only) */
+
+static void prep_port0814_write(void *opaque, uint32_t addr, uint32_t val)
+{
+    trace_prep_systemio_write(addr, val);
+}
+
+/* PORT 0818 -- Reserved for Keylock (Read Only) */
+
+enum {
+    PORT0818_KEYLOCK_SIGNAL_HIGH    = PREP_BIT(7),
+};
+
+static uint32_t prep_port0818_read(void *opaque, uint32_t addr)
+{
+    uint32_t val = 0;
+    trace_prep_systemio_read(addr, val);
+    return val;
+}
+
+/* PORT 080C -- Equipment */
+
+enum {
+    PORT080C_SCSIFUSE               = PREP_BIT(1),
+    PORT080C_L2_COPYBACK            = PREP_BIT(4),
+    PORT080C_L2_256                 = PREP_BIT(5),
+    PORT080C_UPGRADE_CPU            = PREP_BIT(6),
+    PORT080C_L2                     = PREP_BIT(7),
+};
+
+static uint32_t prep_port080c_read(void *opaque, uint32_t addr)
+{
+    PrepSystemIoState *s = opaque;
+    trace_prep_systemio_read(addr, s->equipment);
+    return s->equipment;
+}
+
+/* PORT 081C -- System Control Register (Read/Write) */
+
+enum {
+    PORT081C_FLOPPY_MOTOR_INHIBIT   = PREP_BIT(3),
+    PORT081C_MASK_TEA               = PREP_BIT(2),
+    PORT081C_L2_UPDATE_INHIBIT      = PREP_BIT(1),
+    PORT081C_L2_CACHEMISS_INHIBIT   = PREP_BIT(0),
+};
Quoted 8 lines

hw/ppc/prep_systemio.c line 169

Quoted 6 lines
hw/ppc/prep_systemio.c new file +6 -0
+
+static void prep_port081c_write(void *opaque, uint32_t addr, uint32_t val)
+{
+    PrepSystemIoState *s = opaque;
+    trace_prep_systemio_write(addr, val);
+    s->system_control = val;

Should this value be masked to restrict it to the valid bits?

Quoted 2 lines

Some bits are reserved according to specification, and must be written as 0.

Quoted 6 lines

Right, so I assumed.

Quoted 1 line

I think we can still take them unconditionally.

Hrm.. allowing reserved bits to be set and retrieved is usually a bad idea. Do you have a particular reason to allow this?

Not much. I've changed it to ignore reserved bits in write handler, so they are read back as 0.

Hervé

#19 lore raw

PATCH 5/6 prep: add IBM RS/6000 7020 (40p) memory controller

In reply to Hervé Poussineau
---
 default-configs/ppc-softmmu.mak |   1 +
 hw/ppc/Makefile.objs            |   1 +
 hw/ppc/rs6000_mc.c              | 232 ++++++++++++++++++++++++++++++++++++++++
 hw/ppc/trace-events             |   7 ++
 4 files changed, 241 insertions(+)
 create mode 100644 hw/ppc/rs6000_mc.c
default-configs/ppc-softmmu.mak +1 -0
index d4d0f9b..e567658 100644
@@ -47,3 +47,4 @@ CONFIG_LIBDECNUMBER=y
 # For PReP
 CONFIG_MC146818RTC=y
 CONFIG_ISA_TESTDEV=y
+CONFIG_RS6000_MC=y
hw/ppc/Makefile.objs +1 -0
index db72297..0012934 100644
@@ -17,6 +17,7 @@ obj-y += ppc4xx_pci.o
 # PReP
 obj-$(CONFIG_PREP) += prep.o
 obj-$(CONFIG_PREP) += prep_systemio.o
+obj-${CONFIG_RS6000_MC} += rs6000_mc.o
 # OldWorld PowerMac
 obj-$(CONFIG_MAC) += mac_oldworld.o
 # NewWorld PowerMac
hw/ppc/rs6000_mc.c new file +232 -0

232 lines not on this page · raw message

hw/ppc/trace-events +7 -0
index 2ba6166..42b8ec0 100644
@@ -78,3 +78,10 @@ prep_io_800_readb(uint32_t addr, uint32_t retval) "0x%08" PRIx32 " <= 0x%02" PRI
 # hw/ppc/prep_systemio.c
 prep_systemio_read(uint32_t addr, uint32_t val) "read addr=%x val=%x"
 prep_systemio_write(uint32_t addr, uint32_t val) "write addr=%x val=%x"
+
+# hw/ppc/rs6000_mc.c
+rs6000mc_id_read(uint32_t addr, uint32_t val) "read addr=%x val=%x"
+rs6000mc_presence_read(uint32_t addr, uint32_t val) "read addr=%x val=%x"
+rs6000mc_size_read(uint32_t addr, uint32_t val) "read addr=%x val=%x"
+rs6000mc_size_write(uint32_t addr, uint32_t val) "write addr=%x val=%x"
+rs6000mc_parity_read(uint32_t addr, uint32_t val) "read addr=%x val=%x"
Signature · 1 line
2.1.4
#20 lore raw

Re: [Qemu-devel] [PATCH 5/6] prep: add IBM RS/6000 7020 (40p) memory controller

Quoted 185 lines · Hervé Poussineau
---
 default-configs/ppc-softmmu.mak |   1 +
 hw/ppc/Makefile.objs            |   1 +
 hw/ppc/rs6000_mc.c              | 232 ++++++++++++++++++++++++++++++++++++++++
 hw/ppc/trace-events             |   7 ++
 4 files changed, 241 insertions(+)
 create mode 100644 hw/ppc/rs6000_mc.c
default-configs/ppc-softmmu.mak +1 -0
index d4d0f9b..e567658 100644
@@ -47,3 +47,4 @@ CONFIG_LIBDECNUMBER=y
 # For PReP
 CONFIG_MC146818RTC=y
 CONFIG_ISA_TESTDEV=y
+CONFIG_RS6000_MC=y
hw/ppc/Makefile.objs +1 -0
index db72297..0012934 100644
@@ -17,6 +17,7 @@ obj-y += ppc4xx_pci.o
 # PReP
 obj-$(CONFIG_PREP) += prep.o
 obj-$(CONFIG_PREP) += prep_systemio.o
+obj-${CONFIG_RS6000_MC} += rs6000_mc.o
 # OldWorld PowerMac
 obj-$(CONFIG_MAC) += mac_oldworld.o
 # NewWorld PowerMac
hw/ppc/rs6000_mc.c new file +149 -0
new file mode 100644
index 0000000..c684421
@@ -0,0 +1,232 @@
+/*
+ * QEMU RS/6000 memory controller
+ *
+ * Copyright (c) 2016 Hervé Poussineau
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) version 3 or any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "qemu/osdep.h"
+#include "hw/isa/isa.h"
+#include "exec/address-spaces.h"
+#include "hw/boards.h"
+#include "qapi/error.h"
+#include "trace.h"
+
+#define TYPE_RS6000MC "rs6000-mc"
+#define RS6000MC_DEVICE(obj) \
+    OBJECT_CHECK(RS6000MCState, (obj), TYPE_RS6000MC)
+
+typedef struct RS6000MCState {
+    ISADevice parent_obj;
+    /* see US patent 5,684,979 for details (expired 2001-11-04) */
+    uint32_t ram_size;
+    bool autoconfigure;
+    MemoryRegion simm[6];
+    unsigned int simm_size[6];
+    uint32_t end_address[8];
+    uint8_t port0820_index;
+    PortioList portio;
+} RS6000MCState;
+
+/* P0RT 0803 -- SIMM ID Register (32/8 MB) (Read Only) */
+
+static uint32_t rs6000mc_port0803_read(void *opaque, uint32_t addr)
+{
+    RS6000MCState *s = opaque;
+    uint32_t val = 0;
+    int socket;
+
+    /* (1 << socket) indicates 32 MB SIMM at given socket */
+    for (socket = 0; socket < 6; socket++) {
+        if (s->simm_size[socket] == 32) {
+            val |= (1 << socket);
+        }
+    }
+
+    trace_rs6000mc_id_read(addr, val);
+    return val;
+}
+
+/* PORT 0804 -- SIMM Presence Register (Read Only) */
+
+static uint32_t rs6000mc_port0804_read(void *opaque, uint32_t addr)
+{
+    RS6000MCState *s = opaque;
+    uint32_t val = 0xff;
+    int socket;
+
+    /* (1 << socket) indicates SIMM absence at given socket */
+    for (socket = 0; socket < 6; socket++) {
+        if (s->simm_size[socket]) {
+            val &= ~(1 << socket);
+        }
+    }
+    s->port0820_index = 0;
+
+    trace_rs6000mc_presence_read(addr, val);
+    return val;
+}
+
+/* Memory Controller Size Programming Register */
+
+static uint32_t rs6000mc_port0820_read(void *opaque, uint32_t addr)
+{
+    RS6000MCState *s = opaque;
+    uint32_t val = s->end_address[s->port0820_index] & 0x1f;
+    s->port0820_index = (s->port0820_index + 1) & 7;
+    trace_rs6000mc_size_read(addr, val);
+    return val;
+}
+
+static void rs6000mc_port0820_write(void *opaque, uint32_t addr, uint32_t val)
+{
+    RS6000MCState *s = opaque;
+    uint8_t socket = val >> 5;
+    uint32_t end_address = val & 0x1f;
+
+    trace_rs6000mc_size_write(addr, val);
+    s->end_address[socket] = end_address;
+    if (socket > 0 && socket < 7) {
+        if (s->simm_size[socket - 1]) {
+            uint32_t size;
+            uint32_t start_address = 0;
+            if (socket > 1) {
+                start_address = s->end_address[socket - 1];
+            }
+
+            size = end_address - start_address;
+            memory_region_set_enabled(&s->simm[socket - 1], size != 0);
+            memory_region_set_address(&s->simm[socket - 1],
+                                      start_address * 8 * 1024 * 1024);
+        }
+    }
+}
+
+/* Read Memory Parity Error */
+
+enum {
+    PORT0841_NO_ERROR_DETECTED = 0x01,
+};
+
+static uint32_t rs6000mc_port0841_read(void *opaque, uint32_t addr)
+{
+    uint32_t val = PORT0841_NO_ERROR_DETECTED;
+    trace_rs6000mc_parity_read(addr, val);
+    return val;
+}
+
+static const MemoryRegionPortio rs6000mc_port_list[] = {
+    { 0x803, 1, 1, .read = rs6000mc_port0803_read },
+    { 0x804, 1, 1, .read = rs6000mc_port0804_read },
+    { 0x820, 1, 1, .read = rs6000mc_port0820_read,
+                   .write = rs6000mc_port0820_write, },
+    { 0x841, 1, 1, .read = rs6000mc_port0841_read },
+    PORTIO_END_OF_LIST()
+};
+
+static void rs6000mc_realize(DeviceState *dev, Error **errp)
+{
+    RS6000MCState *s = RS6000MC_DEVICE(dev);
+    int socket = 0;
+    unsigned int ram_size = s->ram_size / (1024 * 1024);
+
+    while (socket < 6) {
+        if (ram_size >= 64) {
+            s->simm_size[socket] = 32;
+            s->simm_size[socket + 1] = 32;
+            ram_size -= 64;

hw/ppc/rs6000_mc.c line 159

Quoted 10 lines
hw/ppc/rs6000_mc.c new file +10 -0
+        } else if (ram_size >= 16) {
+            s->simm_size[socket] = 8;
+            s->simm_size[socket + 1] = 8;
+            ram_size -= 16;
+        } else {
+            /* Not enough memory */
+            break;
+        }
+        socket += 2;
+    }

Surely this needs some warning if you try to set ram-size greater than the hardware can support (192MiB, IIUC).

Quoted 87 lines
hw/ppc/rs6000_mc.c new file +72 -0
+    for (socket = 0; socket < 6; socket++) {
+        if (s->simm_size[socket]) {
+            char name[] = "simm.?";
+            name[5] = socket + '0';
+            memory_region_allocate_system_memory(&s->simm[socket], OBJECT(dev),
+                                                 name, s->simm_size[socket]
+                                                 * 1024 * 1024);
+            memory_region_add_subregion_overlap(get_system_memory(), 0,
+                                                &s->simm[socket], socket);
+        }
+    }
+    if (ram_size) {
+        /* unable to push all requested RAM in SIMMs */
+        error_setg(errp, "RAM size incompatible with this board. "
+                   "Try again with something else, like %d MB",
+                   s->ram_size / 1024 / 1024 - ram_size);
+        return;
+    }
+
+    if (s->autoconfigure) {
+        uint32_t start_address = 0;
+        for (socket = 0; socket < 6; socket++) {
+            if (s->simm_size[socket]) {
+                memory_region_set_enabled(&s->simm[socket], true);
+                memory_region_set_address(&s->simm[socket], start_address);
+                start_address += memory_region_size(&s->simm[socket]);
+            }
+        }
+    }
+
+    isa_register_portio_list(ISA_DEVICE(dev), &s->portio, 0x0,
+                             rs6000mc_port_list, s, "rs6000mc");
+}
+
+static const VMStateDescription vmstate_rs6000mc = {
+    .name = "rs6000-mc",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT8(port0820_index, RS6000MCState),
+        VMSTATE_END_OF_LIST()
+    },
+};
+
+static Property rs6000mc_properties[] = {
+    DEFINE_PROP_UINT32("ram-size", RS6000MCState, ram_size, 0),
+    DEFINE_PROP_BOOL("auto-configure", RS6000MCState, autoconfigure, true),
+    DEFINE_PROP_END_OF_LIST()
+};
+
+static void rs6000mc_class_initfn(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
+    dc->realize = rs6000mc_realize;
+    dc->vmsd = &vmstate_rs6000mc;
+    dc->props = rs6000mc_properties;
+}
+
+static const TypeInfo rs6000mc_info = {
+    .name          = TYPE_RS6000MC,
+    .parent        = TYPE_ISA_DEVICE,
+    .instance_size = sizeof(RS6000MCState),
+    .class_init    = rs6000mc_class_initfn,
+};
+
+static void rs6000mc_types(void)
+{
+    type_register_static(&rs6000mc_info);
+}
+
+type_init(rs6000mc_types)
hw/ppc/trace-events +7 -0
index 2ba6166..42b8ec0 100644
@@ -78,3 +78,10 @@ prep_io_800_readb(uint32_t addr, uint32_t retval) "0x%08" PRIx32 " <= 0x%02" PRI
 # hw/ppc/prep_systemio.c
 prep_systemio_read(uint32_t addr, uint32_t val) "read addr=%x val=%x"
 prep_systemio_write(uint32_t addr, uint32_t val) "write addr=%x val=%x"
+
+# hw/ppc/rs6000_mc.c
+rs6000mc_id_read(uint32_t addr, uint32_t val) "read addr=%x val=%x"
+rs6000mc_presence_read(uint32_t addr, uint32_t val) "read addr=%x val=%x"
+rs6000mc_size_read(uint32_t addr, uint32_t val) "read addr=%x val=%x"
+rs6000mc_size_write(uint32_t addr, uint32_t val) "write addr=%x val=%x"
+rs6000mc_parity_read(uint32_t addr, uint32_t val) "read addr=%x val=%x"
Signature · 4 lines
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
#21 lore raw

Re: [Qemu-devel] [PATCH 5/6] prep: add IBM RS/6000 7020 (40p) memory controller

Quoted 191 lines · David Gibson
Quoted 190 lines · Hervé Poussineau
---
 default-configs/ppc-softmmu.mak |   1 +
 hw/ppc/Makefile.objs            |   1 +
 hw/ppc/rs6000_mc.c              | 232 ++++++++++++++++++++++++++++++++++++++++
 hw/ppc/trace-events             |   7 ++
 4 files changed, 241 insertions(+)
 create mode 100644 hw/ppc/rs6000_mc.c
default-configs/ppc-softmmu.mak +1 -0
index d4d0f9b..e567658 100644
@@ -47,3 +47,4 @@ CONFIG_LIBDECNUMBER=y
 # For PReP
 CONFIG_MC146818RTC=y
 CONFIG_ISA_TESTDEV=y
+CONFIG_RS6000_MC=y
hw/ppc/Makefile.objs +1 -0
index db72297..0012934 100644
@@ -17,6 +17,7 @@ obj-y += ppc4xx_pci.o
 # PReP
 obj-$(CONFIG_PREP) += prep.o
 obj-$(CONFIG_PREP) += prep_systemio.o
+obj-${CONFIG_RS6000_MC} += rs6000_mc.o
 # OldWorld PowerMac
 obj-$(CONFIG_MAC) += mac_oldworld.o
 # NewWorld PowerMac
hw/ppc/rs6000_mc.c new file +154 -0
new file mode 100644
index 0000000..c684421
@@ -0,0 +1,232 @@
+/*
+ * QEMU RS/6000 memory controller
+ *
+ * Copyright (c) 2016 Hervé Poussineau
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) version 3 or any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "qemu/osdep.h"
+#include "hw/isa/isa.h"
+#include "exec/address-spaces.h"
+#include "hw/boards.h"
+#include "qapi/error.h"
+#include "trace.h"
+
+#define TYPE_RS6000MC "rs6000-mc"
+#define RS6000MC_DEVICE(obj) \
+    OBJECT_CHECK(RS6000MCState, (obj), TYPE_RS6000MC)
+
+typedef struct RS6000MCState {
+    ISADevice parent_obj;
+    /* see US patent 5,684,979 for details (expired 2001-11-04) */
+    uint32_t ram_size;
+    bool autoconfigure;
+    MemoryRegion simm[6];
+    unsigned int simm_size[6];
+    uint32_t end_address[8];
+    uint8_t port0820_index;
+    PortioList portio;
+} RS6000MCState;
+
+/* P0RT 0803 -- SIMM ID Register (32/8 MB) (Read Only) */
+
+static uint32_t rs6000mc_port0803_read(void *opaque, uint32_t addr)
+{
+    RS6000MCState *s = opaque;
+    uint32_t val = 0;
+    int socket;
+
+    /* (1 << socket) indicates 32 MB SIMM at given socket */
+    for (socket = 0; socket < 6; socket++) {
+        if (s->simm_size[socket] == 32) {
+            val |= (1 << socket);
+        }
+    }
+
+    trace_rs6000mc_id_read(addr, val);
+    return val;
+}
+
+/* PORT 0804 -- SIMM Presence Register (Read Only) */
+
+static uint32_t rs6000mc_port0804_read(void *opaque, uint32_t addr)
+{
+    RS6000MCState *s = opaque;
+    uint32_t val = 0xff;
+    int socket;
+
+    /* (1 << socket) indicates SIMM absence at given socket */
+    for (socket = 0; socket < 6; socket++) {
+        if (s->simm_size[socket]) {
+            val &= ~(1 << socket);
+        }
+    }
+    s->port0820_index = 0;
+
+    trace_rs6000mc_presence_read(addr, val);
+    return val;
+}
+
+/* Memory Controller Size Programming Register */
+
+static uint32_t rs6000mc_port0820_read(void *opaque, uint32_t addr)
+{
+    RS6000MCState *s = opaque;
+    uint32_t val = s->end_address[s->port0820_index] & 0x1f;
+    s->port0820_index = (s->port0820_index + 1) & 7;
+    trace_rs6000mc_size_read(addr, val);
+    return val;
+}
+
+static void rs6000mc_port0820_write(void *opaque, uint32_t addr, uint32_t val)
+{
+    RS6000MCState *s = opaque;
+    uint8_t socket = val >> 5;
+    uint32_t end_address = val & 0x1f;
+
+    trace_rs6000mc_size_write(addr, val);
+    s->end_address[socket] = end_address;
+    if (socket > 0 && socket < 7) {
+        if (s->simm_size[socket - 1]) {
+            uint32_t size;
+            uint32_t start_address = 0;
+            if (socket > 1) {
+                start_address = s->end_address[socket - 1];
+            }
+
+            size = end_address - start_address;
+            memory_region_set_enabled(&s->simm[socket - 1], size != 0);
+            memory_region_set_address(&s->simm[socket - 1],
+                                      start_address * 8 * 1024 * 1024);
+        }
+    }
+}
+
+/* Read Memory Parity Error */
+
+enum {
+    PORT0841_NO_ERROR_DETECTED = 0x01,
+};
+
+static uint32_t rs6000mc_port0841_read(void *opaque, uint32_t addr)
+{
+    uint32_t val = PORT0841_NO_ERROR_DETECTED;
+    trace_rs6000mc_parity_read(addr, val);
+    return val;
+}
+
+static const MemoryRegionPortio rs6000mc_port_list[] = {
+    { 0x803, 1, 1, .read = rs6000mc_port0803_read },
+    { 0x804, 1, 1, .read = rs6000mc_port0804_read },
+    { 0x820, 1, 1, .read = rs6000mc_port0820_read,
+                   .write = rs6000mc_port0820_write, },
+    { 0x841, 1, 1, .read = rs6000mc_port0841_read },
+    PORTIO_END_OF_LIST()
+};
+
+static void rs6000mc_realize(DeviceState *dev, Error **errp)
+{
+    RS6000MCState *s = RS6000MC_DEVICE(dev);
+    int socket = 0;
+    unsigned int ram_size = s->ram_size / (1024 * 1024);
+
+    while (socket < 6) {
+        if (ram_size >= 64) {
+            s->simm_size[socket] = 32;
+            s->simm_size[socket + 1] = 32;
+            ram_size -= 64;
+        } else if (ram_size >= 16) {
+            s->simm_size[socket] = 8;
+            s->simm_size[socket + 1] = 8;
+            ram_size -= 16;
+        } else {
Quoted 8 lines

hw/ppc/rs6000_mc.c line 159

Quoted 5 lines
hw/ppc/rs6000_mc.c new file +5 -0
+            /* Not enough memory */
+            break;
+        }
+        socket += 2;
+    }

Surely this needs some warning if you try to set ram-size greater than the hardware can support (192MiB, IIUC).

10 lines later, if you were unable to map the whole requested RAM, you'll get an error.

Quoted 7 lines

hw/ppc/rs6000_mc.c line 178

Quoted 7 lines
hw/ppc/rs6000_mc.c new file +7 -0
+    if (ram_size) {
+        /* unable to push all requested RAM in SIMMs */
+        error_setg(errp, "RAM size incompatible with this board. "
+                   "Try again with something else, like %d MB",
+                   s->ram_size / 1024 / 1024 - ram_size);
+        return;
+    }

Is it enough?

Quoted 89 lines
Quoted 88 lines
hw/ppc/rs6000_mc.c new file +72 -0
+    for (socket = 0; socket < 6; socket++) {
+        if (s->simm_size[socket]) {
+            char name[] = "simm.?";
+            name[5] = socket + '0';
+            memory_region_allocate_system_memory(&s->simm[socket], OBJECT(dev),
+                                                 name, s->simm_size[socket]
+                                                 * 1024 * 1024);
+            memory_region_add_subregion_overlap(get_system_memory(), 0,
+                                                &s->simm[socket], socket);
+        }
+    }
+    if (ram_size) {
+        /* unable to push all requested RAM in SIMMs */
+        error_setg(errp, "RAM size incompatible with this board. "
+                   "Try again with something else, like %d MB",
+                   s->ram_size / 1024 / 1024 - ram_size);
+        return;
+    }
+
+    if (s->autoconfigure) {
+        uint32_t start_address = 0;
+        for (socket = 0; socket < 6; socket++) {
+            if (s->simm_size[socket]) {
+                memory_region_set_enabled(&s->simm[socket], true);
+                memory_region_set_address(&s->simm[socket], start_address);
+                start_address += memory_region_size(&s->simm[socket]);
+            }
+        }
+    }
+
+    isa_register_portio_list(ISA_DEVICE(dev), &s->portio, 0x0,
+                             rs6000mc_port_list, s, "rs6000mc");
+}
+
+static const VMStateDescription vmstate_rs6000mc = {
+    .name = "rs6000-mc",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT8(port0820_index, RS6000MCState),
+        VMSTATE_END_OF_LIST()
+    },
+};
+
+static Property rs6000mc_properties[] = {
+    DEFINE_PROP_UINT32("ram-size", RS6000MCState, ram_size, 0),
+    DEFINE_PROP_BOOL("auto-configure", RS6000MCState, autoconfigure, true),
+    DEFINE_PROP_END_OF_LIST()
+};
+
+static void rs6000mc_class_initfn(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
+    dc->realize = rs6000mc_realize;
+    dc->vmsd = &vmstate_rs6000mc;
+    dc->props = rs6000mc_properties;
+}
+
+static const TypeInfo rs6000mc_info = {
+    .name          = TYPE_RS6000MC,
+    .parent        = TYPE_ISA_DEVICE,
+    .instance_size = sizeof(RS6000MCState),
+    .class_init    = rs6000mc_class_initfn,
+};
+
+static void rs6000mc_types(void)
+{
+    type_register_static(&rs6000mc_info);
+}
+
+type_init(rs6000mc_types)
hw/ppc/trace-events +7 -0
index 2ba6166..42b8ec0 100644
@@ -78,3 +78,10 @@ prep_io_800_readb(uint32_t addr, uint32_t retval) "0x%08" PRIx32 " <= 0x%02" PRI
 # hw/ppc/prep_systemio.c
 prep_systemio_read(uint32_t addr, uint32_t val) "read addr=%x val=%x"
 prep_systemio_write(uint32_t addr, uint32_t val) "write addr=%x val=%x"
+
+# hw/ppc/rs6000_mc.c
+rs6000mc_id_read(uint32_t addr, uint32_t val) "read addr=%x val=%x"
+rs6000mc_presence_read(uint32_t addr, uint32_t val) "read addr=%x val=%x"
+rs6000mc_size_read(uint32_t addr, uint32_t val) "read addr=%x val=%x"
+rs6000mc_size_write(uint32_t addr, uint32_t val) "write addr=%x val=%x"
+rs6000mc_parity_read(uint32_t addr, uint32_t val) "read addr=%x val=%x"
#22 lore raw

Re: [Qemu-devel] [PATCH 5/6] prep: add IBM RS/6000 7020 (40p) memory controller

Quoted 201 lines · Hervé Poussineau
Quoted 191 lines · David Gibson
Quoted 190 lines · Hervé Poussineau
---
 default-configs/ppc-softmmu.mak |   1 +
 hw/ppc/Makefile.objs            |   1 +
 hw/ppc/rs6000_mc.c              | 232 ++++++++++++++++++++++++++++++++++++++++
 hw/ppc/trace-events             |   7 ++
 4 files changed, 241 insertions(+)
 create mode 100644 hw/ppc/rs6000_mc.c
default-configs/ppc-softmmu.mak +1 -0
index d4d0f9b..e567658 100644
@@ -47,3 +47,4 @@ CONFIG_LIBDECNUMBER=y
 # For PReP
 CONFIG_MC146818RTC=y
 CONFIG_ISA_TESTDEV=y
+CONFIG_RS6000_MC=y
hw/ppc/Makefile.objs +1 -0
index db72297..0012934 100644
@@ -17,6 +17,7 @@ obj-y += ppc4xx_pci.o
 # PReP
 obj-$(CONFIG_PREP) += prep.o
 obj-$(CONFIG_PREP) += prep_systemio.o
+obj-${CONFIG_RS6000_MC} += rs6000_mc.o
 # OldWorld PowerMac
 obj-$(CONFIG_MAC) += mac_oldworld.o
 # NewWorld PowerMac
hw/ppc/rs6000_mc.c new file +154 -0
new file mode 100644
index 0000000..c684421
@@ -0,0 +1,232 @@
+/*
+ * QEMU RS/6000 memory controller
+ *
+ * Copyright (c) 2016 Hervé Poussineau
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) version 3 or any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "qemu/osdep.h"
+#include "hw/isa/isa.h"
+#include "exec/address-spaces.h"
+#include "hw/boards.h"
+#include "qapi/error.h"
+#include "trace.h"
+
+#define TYPE_RS6000MC "rs6000-mc"
+#define RS6000MC_DEVICE(obj) \
+    OBJECT_CHECK(RS6000MCState, (obj), TYPE_RS6000MC)
+
+typedef struct RS6000MCState {
+    ISADevice parent_obj;
+    /* see US patent 5,684,979 for details (expired 2001-11-04) */
+    uint32_t ram_size;
+    bool autoconfigure;
+    MemoryRegion simm[6];
+    unsigned int simm_size[6];
+    uint32_t end_address[8];
+    uint8_t port0820_index;
+    PortioList portio;
+} RS6000MCState;
+
+/* P0RT 0803 -- SIMM ID Register (32/8 MB) (Read Only) */
+
+static uint32_t rs6000mc_port0803_read(void *opaque, uint32_t addr)
+{
+    RS6000MCState *s = opaque;
+    uint32_t val = 0;
+    int socket;
+
+    /* (1 << socket) indicates 32 MB SIMM at given socket */
+    for (socket = 0; socket < 6; socket++) {
+        if (s->simm_size[socket] == 32) {
+            val |= (1 << socket);
+        }
+    }
+
+    trace_rs6000mc_id_read(addr, val);
+    return val;
+}
+
+/* PORT 0804 -- SIMM Presence Register (Read Only) */
+
+static uint32_t rs6000mc_port0804_read(void *opaque, uint32_t addr)
+{
+    RS6000MCState *s = opaque;
+    uint32_t val = 0xff;
+    int socket;
+
+    /* (1 << socket) indicates SIMM absence at given socket */
+    for (socket = 0; socket < 6; socket++) {
+        if (s->simm_size[socket]) {
+            val &= ~(1 << socket);
+        }
+    }
+    s->port0820_index = 0;
+
+    trace_rs6000mc_presence_read(addr, val);
+    return val;
+}
+
+/* Memory Controller Size Programming Register */
+
+static uint32_t rs6000mc_port0820_read(void *opaque, uint32_t addr)
+{
+    RS6000MCState *s = opaque;
+    uint32_t val = s->end_address[s->port0820_index] & 0x1f;
+    s->port0820_index = (s->port0820_index + 1) & 7;
+    trace_rs6000mc_size_read(addr, val);
+    return val;
+}
+
+static void rs6000mc_port0820_write(void *opaque, uint32_t addr, uint32_t val)
+{
+    RS6000MCState *s = opaque;
+    uint8_t socket = val >> 5;
+    uint32_t end_address = val & 0x1f;
+
+    trace_rs6000mc_size_write(addr, val);
+    s->end_address[socket] = end_address;
+    if (socket > 0 && socket < 7) {
+        if (s->simm_size[socket - 1]) {
+            uint32_t size;
+            uint32_t start_address = 0;
+            if (socket > 1) {
+                start_address = s->end_address[socket - 1];
+            }
+
+            size = end_address - start_address;
+            memory_region_set_enabled(&s->simm[socket - 1], size != 0);
+            memory_region_set_address(&s->simm[socket - 1],
+                                      start_address * 8 * 1024 * 1024);
+        }
+    }
+}
+
+/* Read Memory Parity Error */
+
+enum {
+    PORT0841_NO_ERROR_DETECTED = 0x01,
+};
+
+static uint32_t rs6000mc_port0841_read(void *opaque, uint32_t addr)
+{
+    uint32_t val = PORT0841_NO_ERROR_DETECTED;
+    trace_rs6000mc_parity_read(addr, val);
+    return val;
+}
+
+static const MemoryRegionPortio rs6000mc_port_list[] = {
+    { 0x803, 1, 1, .read = rs6000mc_port0803_read },
+    { 0x804, 1, 1, .read = rs6000mc_port0804_read },
+    { 0x820, 1, 1, .read = rs6000mc_port0820_read,
+                   .write = rs6000mc_port0820_write, },
+    { 0x841, 1, 1, .read = rs6000mc_port0841_read },
+    PORTIO_END_OF_LIST()
+};
+
+static void rs6000mc_realize(DeviceState *dev, Error **errp)
+{
+    RS6000MCState *s = RS6000MC_DEVICE(dev);
+    int socket = 0;
+    unsigned int ram_size = s->ram_size / (1024 * 1024);
+
+    while (socket < 6) {
+        if (ram_size >= 64) {
+            s->simm_size[socket] = 32;
+            s->simm_size[socket + 1] = 32;
+            ram_size -= 64;
+        } else if (ram_size >= 16) {
+            s->simm_size[socket] = 8;
+            s->simm_size[socket + 1] = 8;
+            ram_size -= 16;
+        } else {
Quoted 8 lines

hw/ppc/rs6000_mc.c line 159

Quoted 5 lines
hw/ppc/rs6000_mc.c new file +5 -0
+            /* Not enough memory */
+            break;
+        }
+        socket += 2;
+    }

Surely this needs some warning if you try to set ram-size greater than the hardware can support (192MiB, IIUC).

Quoted 1 line

10 lines later, if you were unable to map the whole requested RAM, you'll get an error.

Sorry, missed that.

Quoted 9 lines
Quoted 7 lines

hw/ppc/rs6000_mc.c line 178

Quoted 7 lines
hw/ppc/rs6000_mc.c new file +7 -0
+    if (ram_size) {
+        /* unable to push all requested RAM in SIMMs */
+        error_setg(errp, "RAM size incompatible with this board. "
+                   "Try again with something else, like %d MB",
+                   s->ram_size / 1024 / 1024 - ram_size);
+        return;
+    }

Is it enough?

Yes, that should be fine.

Quoted 89 lines
Quoted 88 lines
Quoted 87 lines
hw/ppc/rs6000_mc.c new file +72 -0
+    for (socket = 0; socket < 6; socket++) {
+        if (s->simm_size[socket]) {
+            char name[] = "simm.?";
+            name[5] = socket + '0';
+            memory_region_allocate_system_memory(&s->simm[socket], OBJECT(dev),
+                                                 name, s->simm_size[socket]
+                                                 * 1024 * 1024);
+            memory_region_add_subregion_overlap(get_system_memory(), 0,
+                                                &s->simm[socket], socket);
+        }
+    }
+    if (ram_size) {
+        /* unable to push all requested RAM in SIMMs */
+        error_setg(errp, "RAM size incompatible with this board. "
+                   "Try again with something else, like %d MB",
+                   s->ram_size / 1024 / 1024 - ram_size);
+        return;
+    }
+
+    if (s->autoconfigure) {
+        uint32_t start_address = 0;
+        for (socket = 0; socket < 6; socket++) {
+            if (s->simm_size[socket]) {
+                memory_region_set_enabled(&s->simm[socket], true);
+                memory_region_set_address(&s->simm[socket], start_address);
+                start_address += memory_region_size(&s->simm[socket]);
+            }
+        }
+    }
+
+    isa_register_portio_list(ISA_DEVICE(dev), &s->portio, 0x0,
+                             rs6000mc_port_list, s, "rs6000mc");
+}
+
+static const VMStateDescription vmstate_rs6000mc = {
+    .name = "rs6000-mc",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT8(port0820_index, RS6000MCState),
+        VMSTATE_END_OF_LIST()
+    },
+};
+
+static Property rs6000mc_properties[] = {
+    DEFINE_PROP_UINT32("ram-size", RS6000MCState, ram_size, 0),
+    DEFINE_PROP_BOOL("auto-configure", RS6000MCState, autoconfigure, true),
+    DEFINE_PROP_END_OF_LIST()
+};
+
+static void rs6000mc_class_initfn(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
+    dc->realize = rs6000mc_realize;
+    dc->vmsd = &vmstate_rs6000mc;
+    dc->props = rs6000mc_properties;
+}
+
+static const TypeInfo rs6000mc_info = {
+    .name          = TYPE_RS6000MC,
+    .parent        = TYPE_ISA_DEVICE,
+    .instance_size = sizeof(RS6000MCState),
+    .class_init    = rs6000mc_class_initfn,
+};
+
+static void rs6000mc_types(void)
+{
+    type_register_static(&rs6000mc_info);
+}
+
+type_init(rs6000mc_types)
hw/ppc/trace-events +7 -0
index 2ba6166..42b8ec0 100644
@@ -78,3 +78,10 @@ prep_io_800_readb(uint32_t addr, uint32_t retval) "0x%08" PRIx32 " <= 0x%02" PRI
 # hw/ppc/prep_systemio.c
 prep_systemio_read(uint32_t addr, uint32_t val) "read addr=%x val=%x"
 prep_systemio_write(uint32_t addr, uint32_t val) "write addr=%x val=%x"
+
+# hw/ppc/rs6000_mc.c
+rs6000mc_id_read(uint32_t addr, uint32_t val) "read addr=%x val=%x"
+rs6000mc_presence_read(uint32_t addr, uint32_t val) "read addr=%x val=%x"
+rs6000mc_size_read(uint32_t addr, uint32_t val) "read addr=%x val=%x"
+rs6000mc_size_write(uint32_t addr, uint32_t val) "write addr=%x val=%x"
+rs6000mc_parity_read(uint32_t addr, uint32_t val) "read addr=%x val=%x"
Signature · 4 lines
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
#23 lore raw

PATCH 6/6 prep: add IBM RS/6000 7020 (40p) machine emulation

In reply to Hervé Poussineau

Machine supports both Open Hack'Ware and OpenBIOS.
Open Hack'Ware is the default because OpenBIOS is currently unable to boot PReP boot partitions or PReP kernels.

---
 default-configs/ppc-softmmu.mak |   1 +
 hw/ppc/prep.c                   | 231 ++++++++++++++++++++++++++++++++++++++++
 2 files changed, 232 insertions(+)
default-configs/ppc-softmmu.mak +1 -0
index e567658..7dd004e 100644
@@ -18,6 +18,7 @@ CONFIG_I82378=y
 CONFIG_PC87312=y
 CONFIG_MACIO=y
 CONFIG_PCSPK=y
+CONFIG_CS4231A=y
 CONFIG_CUDA=y
 CONFIG_ADB=y
 CONFIG_MAC_NVRAM=y
hw/ppc/prep.c +231 -0

259 lines not on this page · raw message

Signature · 1 line
2.1.4
#24 lore raw

Re: [Qemu-devel] [PATCH 6/6] prep: add IBM RS/6000 7020 (40p) machine emulation

Quoted 65 lines · Hervé Poussineau

Machine supports both Open Hack'Ware and OpenBIOS.
Open Hack'Ware is the default because OpenBIOS is currently unable to boot PReP boot partitions or PReP kernels.

---
 default-configs/ppc-softmmu.mak |   1 +
 hw/ppc/prep.c                   | 231 ++++++++++++++++++++++++++++++++++++++++
 2 files changed, 232 insertions(+)
default-configs/ppc-softmmu.mak +1 -0
index e567658..7dd004e 100644
@@ -18,6 +18,7 @@ CONFIG_I82378=y
 CONFIG_PC87312=y
 CONFIG_MACIO=y
 CONFIG_PCSPK=y
+CONFIG_CS4231A=y
 CONFIG_CUDA=y
 CONFIG_ADB=y
 CONFIG_MAC_NVRAM=y
hw/ppc/prep.c +10 -0
index 9fb89d3..c0373d1 100644
@@ -2,6 +2,7 @@
  * QEMU PPC PREP hardware System Emulator
  *
  * Copyright (c) 2003-2007 Jocelyn Mayer
+ * Copyright (c) 2016 Hervé Poussineau
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to deal
@@ -43,6 +44,7 @@
 #include "hw/isa/pc87312.h"
 #include "sysemu/block-backend.h"
 #include "sysemu/arch_init.h"
+#include "sysemu/kvm.h"
 #include "sysemu/qtest.h"
 #include "exec/address-spaces.h"
 #include "trace.h"
@@ -54,6 +56,8 @@
 
 #define MAX_IDE_BUS 2
 
+#define CFG_ADDR 0xf0000510
+
 #define BIOS_SIZE (1024 * 1024)
 #define BIOS_FILENAME "ppc_rom.bin"
 #define KERNEL_LOAD_ADDR 0x01000000
@@ -316,6 +320,12 @@ static uint32_t PREP_io_800_readb (void *opaque, uint32_t addr)
 
 #define NVRAM_SIZE        0x2000
 
+static void fw_cfg_boot_set(void *opaque, const char *boot_device,
+                            Error **errp)
+{
+    fw_cfg_add_i16(opaque, FW_CFG_BOOT_DEVICE, boot_device[0]);
+}
+
 static void ppc_prep_reset(void *opaque)
 {
     PowerPCCPU *cpu = opaque;

hw/ppc/prep.c static void prep_machine_init(MachineClass *mc) · line 696

Quoted 10 lines
hw/ppc/prep.c +7 -0
@@ -677,4 +687,225 @@ static void prep_machine_init(MachineClass *mc)
     mc->default_boot_order = "cad";
 }
 
+static int prep_set_cmos_checksum(DeviceState *dev, void *opaque)
+{
+    uint16_t checksum = *(uint16_t *)opaque;
+    ISADevice *rtc;
+
+    rtc = ISA_DEVICE(object_dynamic_cast(OBJECT(dev), "mc146818rtc"));
+    if (rtc) {

I don't think this is strictly safe though you'll probably get away with it. You need to test the result of object_dynamic_cast() against NULL *before* you upcast it to the IsaDevice.

Quoted 215 lines
hw/ppc/prep.c +214 -0
+        rtc_set_memory(rtc, 0x2e, checksum & 0xff);
+        rtc_set_memory(rtc, 0x3e, checksum & 0xff);
+        rtc_set_memory(rtc, 0x2f, checksum >> 8);
+        rtc_set_memory(rtc, 0x3f, checksum >> 8);
+    }
+    return 0;
+}
+
+static void ibm_40p_init(MachineState *machine)
+{
+    CPUPPCState *env = NULL;
+    uint16_t cmos_checksum;
+    PowerPCCPU *cpu;
+    DeviceState *dev;
+    SysBusDevice *pcihost;
+    Nvram *m48t59 = NULL;
+    PCIBus *pci_bus;
+    ISABus *isa_bus;
+    void *fw_cfg;
+    const char *vga_type;
+    int i;
+    uint32_t kernel_base = 0, initrd_base = 0;
+    long kernel_size = 0, initrd_size = 0;
+    char boot_device;
+
+    /* init CPU */
+    if (!machine->cpu_model) {
+        machine->cpu_model = "604";
+    }
+    cpu = cpu_ppc_init(machine->cpu_model);
+    if (cpu == NULL) {
+        fprintf(stderr, "Unable to find PowerPC CPU definition\n");
+        exit(1);
+    }
+    env = &cpu->env;
+
+    if (env->flags & POWERPC_FLAG_RTC_CLK) {
+        /* POWER / PowerPC 601 RTC clock frequency is 7.8125 MHz */
+        cpu_ppc_tb_init(env, 7812500UL);
+    } else {
+        /* Set time-base frequency to 100 Mhz */
+        cpu_ppc_tb_init(env, 100UL * 1000UL * 1000UL);
+    }
+    qemu_register_reset(ppc_prep_reset, cpu);
+    if (PPC_INPUT(env) != PPC_FLAGS_INPUT_6xx) {
+        hw_error("Only 6xx bus is supported on PREP machine\n");
+    }
+
+    /* PCI host */
+    dev = qdev_create(NULL, "raven-pcihost");
+    if (!bios_name) {
+        bios_name = BIOS_FILENAME;
+    }
+    qdev_prop_set_string(dev, "bios-name", bios_name);
+    qdev_prop_set_uint32(dev, "elf-machine", PPC_ELF_MACHINE);
+    pcihost = SYS_BUS_DEVICE(dev);
+    object_property_add_child(qdev_get_machine(), "raven", OBJECT(dev), NULL);
+    qdev_init_nofail(dev);
+    pci_bus = PCI_BUS(qdev_get_child_bus(dev, "pci.0"));
+    if (pci_bus == NULL) {
+        fprintf(stderr, "Couldn't create PCI host controller.\n");
+        exit(1);
+    }
+
+    /* PCI -> ISA bridge */
+    dev = DEVICE(pci_create_simple(pci_bus, PCI_DEVFN(11, 0), "i82378"));
+    qdev_connect_gpio_out(dev, 0,
+                          cpu->env.irq_inputs[PPC6xx_INPUT_INT]);
+    sysbus_connect_irq(pcihost, 0, qdev_get_gpio_in(dev, 15));
+    sysbus_connect_irq(pcihost, 1, qdev_get_gpio_in(dev, 13));
+    sysbus_connect_irq(pcihost, 2, qdev_get_gpio_in(dev, 15));
+    sysbus_connect_irq(pcihost, 3, qdev_get_gpio_in(dev, 13));
+    isa_bus = ISA_BUS(qdev_get_child_bus(dev, "isa.0"));
+
+    /* Memory controller */
+    dev = DEVICE(isa_create(isa_bus, "rs6000-mc"));
+    qdev_prop_set_uint32(dev, "ram-size", machine->ram_size);
+    qdev_init_nofail(dev);
+
+    /* initialize CMOS checksums */
+    cmos_checksum = 0x6aa9;
+    qbus_walk_children(BUS(isa_bus), prep_set_cmos_checksum, NULL, NULL, NULL,
+                       &cmos_checksum);
+
+    /* initialize audio subsystem */
+    audio_init();
+
+    /* add some more devices */
+    if (defaults_enabled()) {
+        isa_create_simple(isa_bus, "i8042");
+        m48t59 = NVRAM(isa_create_simple(isa_bus, "isa-m48t59"));
+
+        dev = DEVICE(isa_create(isa_bus, "cs4231a"));
+        qdev_prop_set_uint32(dev, "iobase", 0x830);
+        qdev_prop_set_uint32(dev, "irq", 10);
+        qdev_init_nofail(dev);
+
+        dev = DEVICE(isa_create(isa_bus, "pc87312"));
+        qdev_prop_set_uint32(dev, "config", 12);
+        qdev_init_nofail(dev);
+
+        dev = DEVICE(isa_create(isa_bus, "prep-systemio"));
+        qdev_prop_set_uint32(dev, "ibm-planar-id", 0xfc);
+        qdev_prop_set_uint32(dev, "equipment", 0xc0);
+        qdev_init_nofail(dev);
+
+        pci_create_simple(pci_bus, PCI_DEVFN(1, 0), "lsi53c810");
+
+        vga_type = pci_vga_type();
+        if (vga_type) {
+            pci_create_simple(pci_bus, PCI_DEVFN(2, 0), pci_vga_type());
+        }
+
+        for (i = 0; i < nb_nics; i++) {
+            pci_nic_init_nofail(&nd_table[i], pci_bus, "pcnet",
+                                i == 0 ? "3" : NULL);
+        }
+    }
+
+    /* Prepare firmware configuration for OpenBIOS */
+    fw_cfg = fw_cfg_init_mem(CFG_ADDR, CFG_ADDR + 2);
+
+    if (machine->kernel_filename) {
+        /* load kernel */
+        kernel_base = KERNEL_LOAD_ADDR;
+        kernel_size = load_image_targphys(machine->kernel_filename,
+                                          kernel_base,
+                                          machine->ram_size - kernel_base);
+        if (kernel_size < 0) {
+            error_report("could not load kernel '%s'",
+                          machine->kernel_filename);
+            exit(1);
+        }
+        fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_ADDR, kernel_base);
+        fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_SIZE, kernel_size);
+        /* load initrd */
+        if (machine->initrd_filename) {
+            initrd_base = INITRD_LOAD_ADDR;
+            initrd_size = load_image_targphys(machine->initrd_filename,
+                                              initrd_base,
+                                              machine->ram_size - initrd_base);
+            if (initrd_size < 0) {
+                error_report("could not load initial ram disk '%s'",
+                             machine->initrd_filename);
+                exit(1);
+            }
+            fw_cfg_add_i32(fw_cfg, FW_CFG_INITRD_ADDR, initrd_base);
+            fw_cfg_add_i32(fw_cfg, FW_CFG_INITRD_SIZE, initrd_size);
+        }
+        if (machine->kernel_cmdline && *machine->kernel_cmdline) {
+            fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_CMDLINE, CMDLINE_ADDR);
+            pstrcpy_targphys("cmdline", CMDLINE_ADDR, TARGET_PAGE_SIZE,
+                             machine->kernel_cmdline);
+            fw_cfg_add_string(fw_cfg, FW_CFG_CMDLINE_DATA,
+                              machine->kernel_cmdline);
+            fw_cfg_add_i32(fw_cfg, FW_CFG_CMDLINE_SIZE,
+                           strlen(machine->kernel_cmdline) + 1);
+        }
+        boot_device = 'm';
+    } else {
+        boot_device = machine->boot_order[0];
+    }
+
+    fw_cfg_add_i16(fw_cfg, FW_CFG_MAX_CPUS, (uint16_t)max_cpus);
+    fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, (uint64_t)machine->ram_size);
+    fw_cfg_add_i16(fw_cfg, FW_CFG_MACHINE_ID, ARCH_PREP);
+
+    fw_cfg_add_i16(fw_cfg, FW_CFG_PPC_WIDTH, graphic_width);
+    fw_cfg_add_i16(fw_cfg, FW_CFG_PPC_HEIGHT, graphic_height);
+    fw_cfg_add_i16(fw_cfg, FW_CFG_PPC_DEPTH, graphic_depth);
+
+    fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_IS_KVM, kvm_enabled());
+    if (kvm_enabled()) {
+#ifdef CONFIG_KVM
+        uint8_t *hypercall;
+
+        fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_TBFREQ, kvmppc_get_tbfreq());
+        hypercall = g_malloc(16);
+        kvmppc_get_hypercall(env, hypercall, 16);
+        fw_cfg_add_bytes(fw_cfg, FW_CFG_PPC_KVM_HC, hypercall, 16);
+        fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_KVM_PID, getpid());
+#endif
+    } else {
+        fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_TBFREQ, NANOSECONDS_PER_SECOND);
+    }
+    fw_cfg_add_i16(fw_cfg, FW_CFG_BOOT_DEVICE, boot_device);
+    qemu_register_boot_set(fw_cfg_boot_set, fw_cfg);
+
+    /* Prepare firmware configuration for Open Hack'Ware */
+    if (m48t59) {
+        PPC_NVRAM_set_params(m48t59, NVRAM_SIZE, "PREP", ram_size,
+                             boot_device,
+                             kernel_base, kernel_size,
+                             machine->kernel_cmdline,
+                             initrd_base, initrd_size,
+                             /* XXX: need an option to load a NVRAM image */
+                             0,
+                             graphic_width, graphic_height, graphic_depth);
+    }
+}
+
+static void ibm_40p_machine_init(MachineClass *mc)
+{
+    mc->desc = "IBM RS/6000 7020 (40p)",
+    mc->init = ibm_40p_init;
+    mc->max_cpus = 1;
+    mc->pci_allow_0_address = true;
+    mc->default_ram_size = 128 * M_BYTE;
+    mc->block_default_type = IF_SCSI;
+    mc->default_display = "std"; /* FIXME: should be S3 Trio */
+    mc->default_boot_order = "c";
+}
+
+DEFINE_MACHINE("40p", ibm_40p_machine_init)
 DEFINE_MACHINE("prep", prep_machine_init)
Signature · 4 lines
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
#25 lore raw

Re: [Qemu-devel] [PATCH 6/6] prep: add IBM RS/6000 7020 (40p) machine emulation

In reply to Hervé Poussineau

Hi,

I stumbled upon this code while working on arch_init.c cleanups:

On Thu, Dec 29, 2016 at 11:12:16PM +0100, Hervé Poussineau wrote:
[...]

Quoted 2 lines
hw/ppc/prep.c +2 -0
+static void ibm_40p_init(MachineState *machine)
+{

[...]

hw/ppc/prep.c static void prep_machine_init(MachineClass *mc) · line 782

Quoted 2 lines
hw/ppc/prep.c +2 -0
+    /* initialize audio subsystem */
+    audio_init();

Why exactly did you need this, if main() already calls audio_init()?

[...]

Quoted 18 lines
hw/ppc/prep.c +13 -0
+static void ibm_40p_machine_init(MachineClass *mc)
+{
+    mc->desc = "IBM RS/6000 7020 (40p)",
+    mc->init = ibm_40p_init;
+    mc->max_cpus = 1;
+    mc->pci_allow_0_address = true;
+    mc->default_ram_size = 128 * M_BYTE;
+    mc->block_default_type = IF_SCSI;
+    mc->default_display = "std"; /* FIXME: should be S3 Trio */
+    mc->default_boot_order = "c";
+}
+
+DEFINE_MACHINE("40p", ibm_40p_machine_init)
 DEFINE_MACHINE("prep", prep_machine_init)
Signature · 1 line
2.1.4
Signature · 1 line
Eduardo
#26 lore raw

Re: [Qemu-devel] [PATCH 6/6] prep: add IBM RS/6000 7020 (40p) machine emulation

Quoted 6 lines · Eduardo Habkost

Hi,

I stumbled upon this code while working on arch_init.c cleanups:

On Thu, Dec 29, 2016 at 11:12:16PM +0100, Hervé Poussineau wrote:
[...]

Quoted 8 lines
Quoted 2 lines
hw/ppc/prep.c +2 -0
+static void ibm_40p_init(MachineState *machine)
+{

[...]

hw/ppc/prep.c static void prep_machine_init(MachineClass *mc) · line 782

Quoted 2 lines
hw/ppc/prep.c +2 -0
+    /* initialize audio subsystem */
+    audio_init();

Why exactly did you need this, if main() already calls audio_init()?

Because prep machine was doing it?
Anyway, it also works without it.

Quoted 21 lines

[...]

Quoted 18 lines
hw/ppc/prep.c +13 -1
+static void ibm_40p_machine_init(MachineClass *mc)
+{
+    mc->desc = "IBM RS/6000 7020 (40p)",
+    mc->init = ibm_40p_init;
+    mc->max_cpus = 1;
+    mc->pci_allow_0_address = true;
+    mc->default_ram_size = 128 * M_BYTE;
+    mc->block_default_type = IF_SCSI;
+    mc->default_display = "std"; /* FIXME: should be S3 Trio */
+    mc->default_boot_order = "c";
+}
+
+DEFINE_MACHINE("40p", ibm_40p_machine_init)
 DEFINE_MACHINE("prep", prep_machine_init)
--

2.1.4

#27 lore raw
In reply to Hervé Poussineau

Hi Hervé,

nice work!

Quoted 9 lines · Hervé Poussineau

Hi,

This patchset adds the emulation of the IBM RS/6000 7020 (40p). The real machine is able to run AIX (up to 4.3.3), Windows NT (up to 4.0 SP1), the beta of OS/2 PowerPC, Solaris, Linux, NetBSD/PReP ...

I've tested current emulation with Open Hack'Ware, OpenBIOS and official firmware.

Linux kernel starts, and freezes during boot (like with 'prep' machine).

If prep can't do it anymore, it looks like a regression. I definitely remember seen a sitting penguin and a login prompt ~ 2 years ago. At least with OFW.

Quoted 1 line

Windows NT starts up to the point where it wants to change endianness.

I hit that with Solaris/PPC a few years back as you published your previous attempt. Do you know what is missing? I guess CPU endianness switch emulation is working because it is used in the newer POWER CPUs. Is it just the systemIO which has to be improved, or is it more?

Quoted 5 lines

Other OSes have not been tested.

This machine is a superset of the 'prep' one, because we know exactly what is/should emulated, and that operating system list running on it is quite wide. I hope that 'prep' machine can be deprecated soon and then later removed.

Would be nice to keep 'prep' until the 40p can boot Linux and NetBSD 6.1.3 (this version used to work with -M prep last time I checked).

Artyom

Quoted 29 lines

Patches 1 to 3 are cleanups, and can probably be committed first. Patches 4 to 6 are the real implementation of the IBM 40p.

Hervé Poussineau (6):
pci: add pci_vga_type(), giving the device name of the chosen VGA
device
vga: increase priority of 0xa0000 memory region
prep: do not use global variable to access nvram
prep: QOM'ify System I/O
prep: add IBM RS/6000 7020 (40p) memory controller
prep: add IBM RS/6000 7020 (40p) machine emulation

 default-configs/ppc-softmmu.mak |   2 +
 hw/display/vga.c                |   2 +-
 hw/pci/pci.c                    |  22 ++-
 hw/ppc/Makefile.objs            |   2 +
 hw/ppc/prep.c                   | 235 ++++++++++++++++++++++++++++++-
 hw/ppc/prep_systemio.c          | 302 ++++++++++++++++++++++++++++++++++++++++
 hw/ppc/rs6000_mc.c              | 232 ++++++++++++++++++++++++++++++
 hw/ppc/trace-events             |  11 ++
 include/hw/pci/pci.h            |   1 +
 9 files changed, 800 insertions(+), 9 deletions(-)
 create mode 100644 hw/ppc/prep_systemio.c
 create mode 100644 hw/ppc/rs6000_mc.c

--
2.1.4

Signature · 4 lines
Regards,
Artyom Tarasenko

SPARC and PPC PReP under qemu blog: http://tyom.blogspot.com/search/label/qemu
#28 lore raw
Quoted 19 lines · Artyom Tarasenko

Hi Hervé,

nice work!

Quoted 9 lines · Hervé Poussineau

Hi,

This patchset adds the emulation of the IBM RS/6000 7020 (40p). The real machine is able to run AIX (up to 4.3.3), Windows NT (up to 4.0 SP1), the beta of OS/2 PowerPC, Solaris, Linux, NetBSD/PReP ...

I've tested current emulation with Open Hack'Ware, OpenBIOS and official firmware.

Linux kernel starts, and freezes during boot (like with 'prep' machine).

If prep can't do it anymore, it looks like a regression. I definitely remember seen a sitting penguin and a login prompt ~ 2 years ago. At least with OFW.

Quoted 6 lines
Quoted 1 line

Windows NT starts up to the point where it wants to change endianness.

I hit that with Solaris/PPC a few years back as you published your previous attempt. Do you know what is missing? I guess CPU endianness switch emulation is working because it is used in the newer POWER CPUs. Is it just the systemIO which has to be improved, or is it more?

It could be the system peripherals. On the other hand, I think the endian switch mechanism is a bit different on those older CPUs compared to the new ones which PAPR uses, so it's possible that's not properly implemented.

Quoted 41 lines
Quoted 5 lines

Other OSes have not been tested.

This machine is a superset of the 'prep' one, because we know exactly what is/should emulated, and that operating system list running on it is quite wide. I hope that 'prep' machine can be deprecated soon and then later removed.

Would be nice to keep 'prep' until the 40p can boot Linux and NetBSD 6.1.3 (this version used to work with -M prep last time I checked).

Artyom

Quoted 27 lines

Patches 1 to 3 are cleanups, and can probably be committed first. Patches 4 to 6 are the real implementation of the IBM 40p.

Hervé Poussineau (6):
pci: add pci_vga_type(), giving the device name of the chosen VGA
device
vga: increase priority of 0xa0000 memory region
prep: do not use global variable to access nvram
prep: QOM'ify System I/O
prep: add IBM RS/6000 7020 (40p) memory controller
prep: add IBM RS/6000 7020 (40p) machine emulation

 default-configs/ppc-softmmu.mak |   2 +
 hw/display/vga.c                |   2 +-
 hw/pci/pci.c                    |  22 ++-
 hw/ppc/Makefile.objs            |   2 +
 hw/ppc/prep.c                   | 235 ++++++++++++++++++++++++++++++-
 hw/ppc/prep_systemio.c          | 302 ++++++++++++++++++++++++++++++++++++++++
 hw/ppc/rs6000_mc.c              | 232 ++++++++++++++++++++++++++++++
 hw/ppc/trace-events             |  11 ++
 include/hw/pci/pci.h            |   1 +
 9 files changed, 800 insertions(+), 9 deletions(-)
 create mode 100644 hw/ppc/prep_systemio.c
 create mode 100644 hw/ppc/rs6000_mc.c
Signature · 4 lines
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
#29 lore raw
In reply to Artyom Tarasenko
Quoted 14 lines · Artyom Tarasenko

Hi Hervé,

nice work!

Quoted 9 lines · Hervé Poussineau

Hi,

This patchset adds the emulation of the IBM RS/6000 7020 (40p). The real machine is able to run AIX (up to 4.3.3), Windows NT (up to 4.0 SP1), the beta of OS/2 PowerPC, Solaris, Linux, NetBSD/PReP ...

I've tested current emulation with Open Hack'Ware, OpenBIOS and official firmware.

Linux kernel starts, and freezes during boot (like with 'prep' machine).

I already saw a regression during 2.7.0 cycle with 603 CPU. However, I was unable to provide kernel source, so Benjamin was unable to find the problem.
http://lists.gnu.org/archive/html/qemu-devel/2016-08/msg03760.html

Quoted 11 lines

If prep can't do it anymore, it looks like a regression. I definitely remember seen a sitting penguin and a login prompt ~ 2 years ago. At least with OFW.

Quoted 1 line

Windows NT starts up to the point where it wants to change endianness.

I hit that with Solaris/PPC a few years back as you published your previous attempt. Do you know what is missing? I guess CPU endianness switch emulation is working because it is used in the newer POWER CPUs. Is it just the systemIO which has to be improved, or is it more?

Yes, PReP System I/O has LE flag which is not implemented.
You may be interested by ftp://ftp.software.ibm.com/rs6000/technology/spec/endian.ps which deals about endianness switching, with some code from Windows NT/PPC

Quoted 9 lines
Quoted 6 lines

Other OSes have not been tested.

This machine is a superset of the 'prep' one, because we know exactly what is/should emulated, and that operating system list running on it is quite wide. I hope that 'prep' machine can be deprecated soon and then later removed.

Would be nice to keep 'prep' until the 40p can boot Linux and NetBSD 6.1.3 (this version used to work with -M prep last time I checked).

Some Linux kernels seem to work, some other ones seem to not work (hang while booting) I've not searched why.

I tried NetBSD 6.1.3/PReP.
cdroms/harddisks don't boot anymore with Open Hack'Ware since some changes in IDE core Kernel boots better with 40p than with prep

====================================================
prep:

Copyright (c) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
2006, 2007, 2008, 2009, 2010, 2011, 2012
The NetBSD Foundation, Inc. All rights reserved.
Copyright (c) 1982, 1986, 1989, 1991, 1993
The Regents of the University of California. All rights reserved.

NetBSD 6.1.3 (INSTALL)
Model: Qemu
total memory = 128 MB
avail memory = 119 MB
panic: call to null-ptr from 0x0

The operating system has halted.
Please press any key to reboot.

====================================================
40p/Open Hack'Ware:

Copyright (c) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
2006, 2007, 2008, 2009, 2010, 2011, 2012
The NetBSD Foundation, Inc. All rights reserved.
Copyright (c) 1982, 1986, 1989, 1991, 1993
The Regents of the University of California. All rights reserved.

NetBSD 6.1.3 (INSTALL)
Model: Qemu
total memory = 128 MB
avail memory = 119 MB
mainbus0 (root)
cpu0 at mainbus0: 604 (Revision 1.3), ID 0 (primary)
cpu0: HID0 0xc084<ICE,DCE,SGE,BHT>, powersave: 1
cpu0: 0.00 MHz
Couldn't find PNP data for bus 0 devfunc 0x0
pnpbus0 at mainbus0
pci0 at mainbus0 bus 0: indirect configuration space access pchb0 at pci0 dev 0 function 0
pchb0: vendor 0x1057 product 0x4801 (rev. 0x00)
siop0 at pci0 dev 1 function 0: Symbios Logic 53c810 (fast scsi)
siop0: couldn't map interrupt
vga0 at pci0 dev 2 function 0: vendor 0x1234 product 0x1111 (rev. 0x02) wsdisplay0 at vga0 (kbdmux ignored)
drm at vga0 not configured
pcn0 at pci0 dev 3 function 0: AMD PCnet-PCI Ethernet
pcn0: Am79c970A PCnet-PCI II rev 0, Ethernet address 52:54:00:12:34:56
pcn0: unable to map interrupt
pcib0 at pci0 dev 11 function 0: vendor 0x8086 product 0x0484 (rev. 0x03) isa0 at pcib0
com0 at isa0 port 0x3f8-0x3ff irq 4: ns16550a, working fifo
com0: console
com1 at isa0 port 0x2f8-0x2ff irq 3: ns16550a, working fifo pckbc0 at isa0 port 0x60-0x64
pckbd0 at pckbc0 (kbd slot)
pckbc0: using irq 1 for kbd slot
wskbd0 at pckbd0 (mux ignored)
vmmask 10000000 schedmask 10000000 highmask 70000000
boot device: mainbus0
root on md0a dumps on md0b
root file system type: ffs
WARNING: no TOD clock present
WARNING: using filesystem time
WARNING: CHECK AND RESET THE DATE!
erase ^H, werase ^W, kill ^U, intr ^C, status ^T
Terminal type? [vt100]

====================================================
40p/official firmware with cdrom boot:

Copyright (c) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
2006, 2007, 2008, 2009, 2010, 2011, 2012
The NetBSD Foundation, Inc. All rights reserved.
Copyright (c) 1982, 1986, 1989, 1991, 1993
The Regents of the University of California. All rights reserved.

NetBSD 6.1.3 (INSTALL)
Model: IBM PPS Model 6015
total memory = 128 MB
avail memory = 119 MB
trap: kernel read DSI trap @ 0x481b4cae by 0x2a4f50 (DSISR 0x40000000, err=14), lr 0x140e84
panic: trap

The operating system has halted.
Please press any key to reboot.
====================================================

OpenBIOS doesn't support PReP boot partitions (type 0x41) nor PReP kernels so this is a no-go yet.

Regards,

Hervé

#30 lore raw
Quoted 55 lines · Hervé Poussineau
Quoted 20 lines · Artyom Tarasenko

Hi Hervé,

nice work!

Quoted 13 lines · Hervé Poussineau

Hi,

This patchset adds the emulation of the IBM RS/6000 7020 (40p). The real machine is
able to run AIX (up to 4.3.3), Windows NT (up to 4.0 SP1), the beta of OS/2 PowerPC,
Solaris, Linux, NetBSD/PReP ...

I've tested current emulation with Open Hack'Ware, OpenBIOS and official firmware.

Linux kernel starts, and freezes during boot (like with 'prep' machine).

I already saw a regression during 2.7.0 cycle with 603 CPU. However, I was unable to provide kernel source, so Benjamin was unable to find the problem.
http://lists.gnu.org/archive/html/qemu-devel/2016-08/msg03760.html

Quoted 5 lines

If prep can't do it anymore, it looks like a regression. I definitely remember seen a sitting penguin and a login prompt ~ 2 years ago. At least with OFW.

Quoted 7 lines
Quoted 1 line

Windows NT starts up to the point where it wants to change endianness.

I hit that with Solaris/PPC a few years back as you published your previous attempt. Do you know what is missing? I guess CPU endianness switch emulation is working because it is used in the newer POWER CPUs. Is it just the systemIO which has to be improved, or is it more?

Yes, PReP System I/O has LE flag which is not implemented.
You may be interested by ftp://ftp.software.ibm.com/rs6000/technology/spec/endian.ps which deals about endianness switching, with some code from Windows NT/PPC

Quoted 9 lines
Quoted 7 lines

Other OSes have not been tested.

This machine is a superset of the 'prep' one, because we know exactly what is/should
emulated, and that operating system list running on it is quite wide. I hope that 'prep' machine can be deprecated soon and then later removed.

Quoted 7 lines
Quoted 2 lines

Would be nice to keep 'prep' until the 40p can boot Linux and NetBSD 6.1.3 (this version used to work with -M prep last time I checked).

Some Linux kernels seem to work, some other ones seem to not work (hang while booting)
I've not searched why.

I should have somewhere the Debian Woody Image I used. Will test it tonight.

Quoted 89 lines

I tried NetBSD 6.1.3/PReP.
cdroms/harddisks don't boot anymore with Open Hack'Ware since some changes in IDE core
Kernel boots better with 40p than with prep

====================================================
prep:

Copyright (c) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
2006, 2007, 2008, 2009, 2010, 2011, 2012
The NetBSD Foundation, Inc. All rights reserved.
Copyright (c) 1982, 1986, 1989, 1991, 1993
The Regents of the University of California. All rights reserved.

NetBSD 6.1.3 (INSTALL)
Model: Qemu
total memory = 128 MB
avail memory = 119 MB
panic: call to null-ptr from 0x0

The operating system has halted.
Please press any key to reboot.

====================================================
40p/Open Hack'Ware:

Copyright (c) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
2006, 2007, 2008, 2009, 2010, 2011, 2012
The NetBSD Foundation, Inc. All rights reserved.
Copyright (c) 1982, 1986, 1989, 1991, 1993
The Regents of the University of California. All rights reserved.

NetBSD 6.1.3 (INSTALL)
Model: Qemu
total memory = 128 MB
avail memory = 119 MB
mainbus0 (root)
cpu0 at mainbus0: 604 (Revision 1.3), ID 0 (primary)
cpu0: HID0 0xc084<ICE,DCE,SGE,BHT>, powersave: 1
cpu0: 0.00 MHz
Couldn't find PNP data for bus 0 devfunc 0x0
pnpbus0 at mainbus0
pci0 at mainbus0 bus 0: indirect configuration space access pchb0 at pci0 dev 0 function 0
pchb0: vendor 0x1057 product 0x4801 (rev. 0x00)
siop0 at pci0 dev 1 function 0: Symbios Logic 53c810 (fast scsi)
siop0: couldn't map interrupt
vga0 at pci0 dev 2 function 0: vendor 0x1234 product 0x1111 (rev. 0x02) wsdisplay0 at vga0 (kbdmux ignored)
drm at vga0 not configured
pcn0 at pci0 dev 3 function 0: AMD PCnet-PCI Ethernet
pcn0: Am79c970A PCnet-PCI II rev 0, Ethernet address 52:54:00:12:34:56
pcn0: unable to map interrupt
pcib0 at pci0 dev 11 function 0: vendor 0x8086 product 0x0484 (rev. 0x03) isa0 at pcib0
com0 at isa0 port 0x3f8-0x3ff irq 4: ns16550a, working fifo
com0: console
com1 at isa0 port 0x2f8-0x2ff irq 3: ns16550a, working fifo pckbc0 at isa0 port 0x60-0x64
pckbd0 at pckbc0 (kbd slot)
pckbc0: using irq 1 for kbd slot
wskbd0 at pckbd0 (mux ignored)
vmmask 10000000 schedmask 10000000 highmask 70000000
boot device: mainbus0
root on md0a dumps on md0b
root file system type: ffs
WARNING: no TOD clock present
WARNING: using filesystem time
WARNING: CHECK AND RESET THE DATE!
erase ^H, werase ^W, kill ^U, intr ^C, status ^T
Terminal type? [vt100]

====================================================
40p/official firmware with cdrom boot:

Copyright (c) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
2006, 2007, 2008, 2009, 2010, 2011, 2012
The NetBSD Foundation, Inc. All rights reserved.
Copyright (c) 1982, 1986, 1989, 1991, 1993
The Regents of the University of California. All rights reserved.

NetBSD 6.1.3 (INSTALL)
Model: IBM PPS Model 6015
total memory = 128 MB
avail memory = 119 MB
trap: kernel read DSI trap @ 0x481b4cae by 0x2a4f50 (DSISR 0x40000000, err=14), lr 0x140e84
panic: trap

Quoted 6 lines

The operating system has halted.
Please press any key to reboot.
====================================================

OpenBIOS doesn't support PReP boot partitions (type 0x41) nor PReP kernels so this is a no-go yet.

OpenBIOS doesn't, but OFW does. It has just occurred to me that I haven't build a LSI Version for you.
It should be easy, because OFW seems to have the LSI driver. Will try building it this weekend.

Signature · 4 lines
Regards,
Artyom Tarasenko

SPARC and PPC PReP under qemu blog: http://tyom.blogspot.com/search/label/qemu
#31 lore raw
In reply to Hervé Poussineau
Quoted 147 lines · Hervé Poussineau
Quoted 18 lines · Artyom Tarasenko

Hi Hervé,

nice work!

Quoted 12 lines · Hervé Poussineau

Hi,

This patchset adds the emulation of the IBM RS/6000 7020 (40p). The real machine is
able to run AIX (up to 4.3.3), Windows NT (up to 4.0 SP1), the beta of OS/2 PowerPC,
Solaris, Linux, NetBSD/PReP ...

I've tested current emulation with Open Hack'Ware, OpenBIOS and official firmware.

Linux kernel starts, and freezes during boot (like with 'prep' machine).

I already saw a regression during 2.7.0 cycle with 603 CPU. However, I was unable to provide kernel source, so Benjamin was unable to find the problem.
http://lists.gnu.org/archive/html/qemu-devel/2016-08/msg03760.html

Quoted 11 lines

If prep can't do it anymore, it looks like a regression. I definitely remember seen a sitting penguin and a login prompt ~ 2 years ago. At least with OFW.

Quoted 1 line

Windows NT starts up to the point where it wants to change endianness.

I hit that with Solaris/PPC a few years back as you published your previous attempt. Do you know what is missing? I guess CPU endianness switch emulation is working because it is used in the newer POWER CPUs. Is it just the systemIO which has to be improved, or is it more?

Yes, PReP System I/O has LE flag which is not implemented.
You may be interested by ftp://ftp.software.ibm.com/rs6000/technology/spec/endian.ps which deals about endianness switching, with some code from Windows NT/PPC

Quoted 11 lines
Quoted 8 lines

Other OSes have not been tested.

This machine is a superset of the 'prep' one, because we know exactly what is/should
emulated, and that operating system list running on it is quite wide. I hope that 'prep' machine can be deprecated soon and then later removed.

Would be nice to keep 'prep' until the 40p can boot Linux and NetBSD 6.1.3 (this version used to work with -M prep last time I checked).

Some Linux kernels seem to work, some other ones seem to not work (hang while booting)
I've not searched why.

I tried NetBSD 6.1.3/PReP.
cdroms/harddisks don't boot anymore with Open Hack'Ware since some changes in IDE core
Kernel boots better with 40p than with prep

====================================================
prep:

Copyright (c) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
2006, 2007, 2008, 2009, 2010, 2011, 2012
The NetBSD Foundation, Inc. All rights reserved.
Copyright (c) 1982, 1986, 1989, 1991, 1993
The Regents of the University of California. All rights reserved.

NetBSD 6.1.3 (INSTALL)
Model: Qemu
total memory = 128 MB
avail memory = 119 MB
panic: call to null-ptr from 0x0

The operating system has halted.
Please press any key to reboot.

====================================================
40p/Open Hack'Ware:

Copyright (c) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
2006, 2007, 2008, 2009, 2010, 2011, 2012
The NetBSD Foundation, Inc. All rights reserved.
Copyright (c) 1982, 1986, 1989, 1991, 1993
The Regents of the University of California. All rights reserved.

NetBSD 6.1.3 (INSTALL)
Model: Qemu
total memory = 128 MB
avail memory = 119 MB
mainbus0 (root)
cpu0 at mainbus0: 604 (Revision 1.3), ID 0 (primary)
cpu0: HID0 0xc084<ICE,DCE,SGE,BHT>, powersave: 1
cpu0: 0.00 MHz
Couldn't find PNP data for bus 0 devfunc 0x0
pnpbus0 at mainbus0
pci0 at mainbus0 bus 0: indirect configuration space access pchb0 at pci0 dev 0 function 0
pchb0: vendor 0x1057 product 0x4801 (rev. 0x00)
siop0 at pci0 dev 1 function 0: Symbios Logic 53c810 (fast scsi)
siop0: couldn't map interrupt
vga0 at pci0 dev 2 function 0: vendor 0x1234 product 0x1111 (rev. 0x02) wsdisplay0 at vga0 (kbdmux ignored)
drm at vga0 not configured
pcn0 at pci0 dev 3 function 0: AMD PCnet-PCI Ethernet
pcn0: Am79c970A PCnet-PCI II rev 0, Ethernet address 52:54:00:12:34:56
pcn0: unable to map interrupt
pcib0 at pci0 dev 11 function 0: vendor 0x8086 product 0x0484 (rev. 0x03) isa0 at pcib0
com0 at isa0 port 0x3f8-0x3ff irq 4: ns16550a, working fifo
com0: console
com1 at isa0 port 0x2f8-0x2ff irq 3: ns16550a, working fifo pckbc0 at isa0 port 0x60-0x64
pckbd0 at pckbc0 (kbd slot)
pckbc0: using irq 1 for kbd slot
wskbd0 at pckbd0 (mux ignored)
vmmask 10000000 schedmask 10000000 highmask 70000000
boot device: mainbus0
root on md0a dumps on md0b
root file system type: ffs
WARNING: no TOD clock present
WARNING: using filesystem time
WARNING: CHECK AND RESET THE DATE!
erase ^H, werase ^W, kill ^U, intr ^C, status ^T
Terminal type? [vt100]

====================================================
40p/official firmware with cdrom boot:

Copyright (c) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
2006, 2007, 2008, 2009, 2010, 2011, 2012
The NetBSD Foundation, Inc. All rights reserved.
Copyright (c) 1982, 1986, 1989, 1991, 1993
The Regents of the University of California. All rights reserved.

NetBSD 6.1.3 (INSTALL)
Model: IBM PPS Model 6015
total memory = 128 MB
avail memory = 119 MB
trap: kernel read DSI trap @ 0x481b4cae by 0x2a4f50 (DSISR 0x40000000, err=14), lr 0x140e84
panic: trap

Quoted 6 lines

The operating system has halted.
Please press any key to reboot.
====================================================

OpenBIOS doesn't support PReP boot partitions (type 0x41) nor PReP kernels so this is a no-go yet.

Just out of interest, is it just the PReP boot partition support that is missing from OpenBIOS? If so, that should be fairly easy to implement if there's a spec lying around somewhere.

It would be great if we could finally remove OHW from QEMU :)

ATB,

Mark.

#32 lore raw
Quoted 153 lines · Mark Cave-Ayland
Quoted 151 lines · Hervé Poussineau
Quoted 18 lines · Artyom Tarasenko

Hi Hervé,

nice work!

Quoted 12 lines · Hervé Poussineau

Hi,

This patchset adds the emulation of the IBM RS/6000 7020 (40p). The real machine is
able to run AIX (up to 4.3.3), Windows NT (up to 4.0 SP1), the beta of OS/2 PowerPC,
Solaris, Linux, NetBSD/PReP ...

I've tested current emulation with Open Hack'Ware, OpenBIOS and official firmware.

Linux kernel starts, and freezes during boot (like with 'prep' machine).

I already saw a regression during 2.7.0 cycle with 603 CPU. However, I was unable to provide kernel source, so Benjamin was unable to find the problem.
http://lists.gnu.org/archive/html/qemu-devel/2016-08/msg03760.html

Quoted 11 lines

If prep can't do it anymore, it looks like a regression. I definitely remember seen a sitting penguin and a login prompt ~ 2 years ago. At least with OFW.

Quoted 1 line

Windows NT starts up to the point where it wants to change endianness.

I hit that with Solaris/PPC a few years back as you published your previous attempt. Do you know what is missing? I guess CPU endianness switch emulation is working because it is used in the newer POWER CPUs. Is it just the systemIO which has to be improved, or is it more?

Yes, PReP System I/O has LE flag which is not implemented.
You may be interested by ftp://ftp.software.ibm.com/rs6000/technology/spec/endian.ps which deals about endianness switching, with some code from Windows NT/PPC

Quoted 11 lines
Quoted 8 lines

Other OSes have not been tested.

This machine is a superset of the 'prep' one, because we know exactly what is/should
emulated, and that operating system list running on it is quite wide. I hope that 'prep' machine can be deprecated soon and then later removed.

Would be nice to keep 'prep' until the 40p can boot Linux and NetBSD 6.1.3 (this version used to work with -M prep last time I checked).

Some Linux kernels seem to work, some other ones seem to not work (hang while booting)
I've not searched why.

I tried NetBSD 6.1.3/PReP.
cdroms/harddisks don't boot anymore with Open Hack'Ware since some changes in IDE core
Kernel boots better with 40p than with prep

====================================================
prep:

Copyright (c) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
2006, 2007, 2008, 2009, 2010, 2011, 2012
The NetBSD Foundation, Inc. All rights reserved.
Copyright (c) 1982, 1986, 1989, 1991, 1993
The Regents of the University of California. All rights reserved.

NetBSD 6.1.3 (INSTALL)
Model: Qemu
total memory = 128 MB
avail memory = 119 MB
panic: call to null-ptr from 0x0

The operating system has halted.
Please press any key to reboot.

====================================================
40p/Open Hack'Ware:

Copyright (c) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
2006, 2007, 2008, 2009, 2010, 2011, 2012
The NetBSD Foundation, Inc. All rights reserved.
Copyright (c) 1982, 1986, 1989, 1991, 1993
The Regents of the University of California. All rights reserved.

NetBSD 6.1.3 (INSTALL)
Model: Qemu
total memory = 128 MB
avail memory = 119 MB
mainbus0 (root)
cpu0 at mainbus0: 604 (Revision 1.3), ID 0 (primary)
cpu0: HID0 0xc084<ICE,DCE,SGE,BHT>, powersave: 1
cpu0: 0.00 MHz
Couldn't find PNP data for bus 0 devfunc 0x0
pnpbus0 at mainbus0
pci0 at mainbus0 bus 0: indirect configuration space access pchb0 at pci0 dev 0 function 0
pchb0: vendor 0x1057 product 0x4801 (rev. 0x00)
siop0 at pci0 dev 1 function 0: Symbios Logic 53c810 (fast scsi)
siop0: couldn't map interrupt
vga0 at pci0 dev 2 function 0: vendor 0x1234 product 0x1111 (rev. 0x02) wsdisplay0 at vga0 (kbdmux ignored)
drm at vga0 not configured
pcn0 at pci0 dev 3 function 0: AMD PCnet-PCI Ethernet
pcn0: Am79c970A PCnet-PCI II rev 0, Ethernet address 52:54:00:12:34:56
pcn0: unable to map interrupt
pcib0 at pci0 dev 11 function 0: vendor 0x8086 product 0x0484 (rev. 0x03) isa0 at pcib0
com0 at isa0 port 0x3f8-0x3ff irq 4: ns16550a, working fifo
com0: console
com1 at isa0 port 0x2f8-0x2ff irq 3: ns16550a, working fifo pckbc0 at isa0 port 0x60-0x64
pckbd0 at pckbc0 (kbd slot)
pckbc0: using irq 1 for kbd slot
wskbd0 at pckbd0 (mux ignored)
vmmask 10000000 schedmask 10000000 highmask 70000000
boot device: mainbus0
root on md0a dumps on md0b
root file system type: ffs
WARNING: no TOD clock present
WARNING: using filesystem time
WARNING: CHECK AND RESET THE DATE!
erase ^H, werase ^W, kill ^U, intr ^C, status ^T
Terminal type? [vt100]

====================================================
40p/official firmware with cdrom boot:

Copyright (c) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
2006, 2007, 2008, 2009, 2010, 2011, 2012
The NetBSD Foundation, Inc. All rights reserved.
Copyright (c) 1982, 1986, 1989, 1991, 1993
The Regents of the University of California. All rights reserved.

NetBSD 6.1.3 (INSTALL)
Model: IBM PPS Model 6015
total memory = 128 MB
avail memory = 119 MB
trap: kernel read DSI trap @ 0x481b4cae by 0x2a4f50 (DSISR 0x40000000, err=14), lr 0x140e84
panic: trap

The operating system has halted.
Please press any key to reboot.
====================================================

Quoted 6 lines
Quoted 2 lines

OpenBIOS doesn't support PReP boot partitions (type 0x41) nor PReP kernels so this is a no-go yet.

Just out of interest, is it just the PReP boot partition support that is missing from OpenBIOS? If so, that should be fairly easy to implement if there's a spec lying around somewhere.

Not much magic required here - look for a partition with ID 0x41 and if it's there, load its contents and treat it as an ELF file.

It's at least mentioned in the LoPAPR spec, see chapter B.11.1 ("disk-label" support package).

Thomas

#33 lore raw
In reply to Mark Cave-Ayland
Quoted 153 lines · Mark Cave-Ayland
Quoted 151 lines · Hervé Poussineau
Quoted 18 lines · Artyom Tarasenko

Hi Hervé,

nice work!

Quoted 12 lines · Hervé Poussineau

Hi,

This patchset adds the emulation of the IBM RS/6000 7020 (40p). The real machine is
able to run AIX (up to 4.3.3), Windows NT (up to 4.0 SP1), the beta of OS/2 PowerPC,
Solaris, Linux, NetBSD/PReP ...

I've tested current emulation with Open Hack'Ware, OpenBIOS and official firmware.

Linux kernel starts, and freezes during boot (like with 'prep' machine).

I already saw a regression during 2.7.0 cycle with 603 CPU. However, I was unable to provide kernel source, so Benjamin was unable to find the problem.
http://lists.gnu.org/archive/html/qemu-devel/2016-08/msg03760.html

Quoted 11 lines

If prep can't do it anymore, it looks like a regression. I definitely remember seen a sitting penguin and a login prompt ~ 2 years ago. At least with OFW.

Quoted 1 line

Windows NT starts up to the point where it wants to change endianness.

I hit that with Solaris/PPC a few years back as you published your previous attempt. Do you know what is missing? I guess CPU endianness switch emulation is working because it is used in the newer POWER CPUs. Is it just the systemIO which has to be improved, or is it more?

Yes, PReP System I/O has LE flag which is not implemented.
You may be interested by ftp://ftp.software.ibm.com/rs6000/technology/spec/endian.ps which deals about endianness switching, with some code from Windows NT/PPC

Quoted 11 lines
Quoted 8 lines

Other OSes have not been tested.

This machine is a superset of the 'prep' one, because we know exactly what is/should
emulated, and that operating system list running on it is quite wide. I hope that 'prep' machine can be deprecated soon and then later removed.

Would be nice to keep 'prep' until the 40p can boot Linux and NetBSD 6.1.3 (this version used to work with -M prep last time I checked).

Some Linux kernels seem to work, some other ones seem to not work (hang while booting)
I've not searched why.

I tried NetBSD 6.1.3/PReP.
cdroms/harddisks don't boot anymore with Open Hack'Ware since some changes in IDE core
Kernel boots better with 40p than with prep

====================================================
prep:

Copyright (c) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
2006, 2007, 2008, 2009, 2010, 2011, 2012
The NetBSD Foundation, Inc. All rights reserved.
Copyright (c) 1982, 1986, 1989, 1991, 1993
The Regents of the University of California. All rights reserved.

NetBSD 6.1.3 (INSTALL)
Model: Qemu
total memory = 128 MB
avail memory = 119 MB
panic: call to null-ptr from 0x0

The operating system has halted.
Please press any key to reboot.

====================================================
40p/Open Hack'Ware:

Copyright (c) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
2006, 2007, 2008, 2009, 2010, 2011, 2012
The NetBSD Foundation, Inc. All rights reserved.
Copyright (c) 1982, 1986, 1989, 1991, 1993
The Regents of the University of California. All rights reserved.

NetBSD 6.1.3 (INSTALL)
Model: Qemu
total memory = 128 MB
avail memory = 119 MB
mainbus0 (root)
cpu0 at mainbus0: 604 (Revision 1.3), ID 0 (primary)
cpu0: HID0 0xc084<ICE,DCE,SGE,BHT>, powersave: 1
cpu0: 0.00 MHz
Couldn't find PNP data for bus 0 devfunc 0x0
pnpbus0 at mainbus0
pci0 at mainbus0 bus 0: indirect configuration space access pchb0 at pci0 dev 0 function 0
pchb0: vendor 0x1057 product 0x4801 (rev. 0x00)
siop0 at pci0 dev 1 function 0: Symbios Logic 53c810 (fast scsi)
siop0: couldn't map interrupt
vga0 at pci0 dev 2 function 0: vendor 0x1234 product 0x1111 (rev. 0x02) wsdisplay0 at vga0 (kbdmux ignored)
drm at vga0 not configured
pcn0 at pci0 dev 3 function 0: AMD PCnet-PCI Ethernet
pcn0: Am79c970A PCnet-PCI II rev 0, Ethernet address 52:54:00:12:34:56
pcn0: unable to map interrupt
pcib0 at pci0 dev 11 function 0: vendor 0x8086 product 0x0484 (rev. 0x03) isa0 at pcib0
com0 at isa0 port 0x3f8-0x3ff irq 4: ns16550a, working fifo
com0: console
com1 at isa0 port 0x2f8-0x2ff irq 3: ns16550a, working fifo pckbc0 at isa0 port 0x60-0x64
pckbd0 at pckbc0 (kbd slot)
pckbc0: using irq 1 for kbd slot
wskbd0 at pckbd0 (mux ignored)
vmmask 10000000 schedmask 10000000 highmask 70000000
boot device: mainbus0
root on md0a dumps on md0b
root file system type: ffs
WARNING: no TOD clock present
WARNING: using filesystem time
WARNING: CHECK AND RESET THE DATE!
erase ^H, werase ^W, kill ^U, intr ^C, status ^T
Terminal type? [vt100]

====================================================
40p/official firmware with cdrom boot:

Copyright (c) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
2006, 2007, 2008, 2009, 2010, 2011, 2012
The NetBSD Foundation, Inc. All rights reserved.
Copyright (c) 1982, 1986, 1989, 1991, 1993
The Regents of the University of California. All rights reserved.

NetBSD 6.1.3 (INSTALL)
Model: IBM PPS Model 6015
total memory = 128 MB
avail memory = 119 MB
trap: kernel read DSI trap @ 0x481b4cae by 0x2a4f50 (DSISR 0x40000000, err=14), lr 0x140e84
panic: trap

The operating system has halted.
Please press any key to reboot.
====================================================

Quoted 8 lines
Quoted 2 lines

OpenBIOS doesn't support PReP boot partitions (type 0x41) nor PReP kernels so this is a no-go yet.

Just out of interest, is it just the PReP boot partition support that is missing from OpenBIOS? If so, that should be fairly easy to implement if there's a spec lying around somewhere.

It would be great if we could finally remove OHW from QEMU :)

I think it can be easily replaced with OFW. I was not able to find any image where OHW would perform better than OFW.

Artyom

Signature · 4 lines
Regards,
Artyom Tarasenko

SPARC and PPC PReP under qemu blog: http://tyom.blogspot.com/search/label/qemu
#34 lore raw
In reply to Mark Cave-Ayland
Quoted 7 lines · Mark Cave-Ayland
Quoted 3 lines

OpenBIOS doesn't support PReP boot partitions (type 0x41) nor PReP kernels so this is a no-go yet.

Just out of interest, is it just the PReP boot partition support that is missing from OpenBIOS? If so, that should be fairly easy to implement if there's a spec lying around somewhere.

2 things are missing to boot from hard disk/cdrom:
- support for LSI SCSI adapter
- support for PReP boot partition support

However, if you want to boot with -kernel, you only need to have support for PReP boot partition. Partial specification is available at:
ftp://ftp.software.ibm.com/rs6000/technology/spec/srp1_1.exe
section 5.3 (Loading the Load Image)
and
section 5.4 (Transferring System Control to Load Image)

Quoted 1 line

It would be great if we could finally remove OHW from QEMU :)

I fully agree on that!

Hervé

#35 lore raw
Quoted 25 lines · Hervé Poussineau
Quoted 9 lines · Mark Cave-Ayland
Quoted 4 lines

OpenBIOS doesn't support PReP boot partitions (type 0x41) nor PReP kernels so this is a no-go yet.

Just out of interest, is it just the PReP boot partition support that is missing from OpenBIOS? If so, that should be fairly easy to implement if there's a spec lying around somewhere.

2 things are missing to boot from hard disk/cdrom:
- support for LSI SCSI adapter
- support for PReP boot partition support

However, if you want to boot with -kernel, you only need to have support for PReP boot partition.
Partial specification is available at:
ftp://ftp.software.ibm.com/rs6000/technology/spec/srp1_1.exe section 5.3 (Loading the Load Image)
and
section 5.4 (Transferring System Control to Load Image)

Quoted 4 lines
Quoted 1 line

It would be great if we could finally remove OHW from QEMU :)

I fully agree on that!

Attached an OFW build with LSI support.
To boot from the LSI disk type
boot /scsi/disk

In theory OFW should support the S3-Trio too, but my first attempt failed on DAC initialisation. Will get back to it later. This build it supports -vga std and -vga cirrus and uses serial console by default.

Artyom

Signature · 4 lines
Regards,
Artyom Tarasenko

SPARC and PPC PReP under qemu blog: http://tyom.blogspot.com/search/label/qemu