All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH 0/6] ppc: add a IBM 40p machine (RS/6000, PReP)
@ 2016-12-29 22:12 Hervé Poussineau
  2016-12-29 22:12 ` [Qemu-devel] [PATCH 1/6] pci: add pci_vga_type(), giving the device name of the chosen VGA device Hervé Poussineau
                   ` (6 more replies)
  0 siblings, 7 replies; 36+ messages in thread
From: Hervé Poussineau @ 2016-12-29 22:12 UTC (permalink / raw)
  To: qemu-devel
  Cc: David Gibson, Alexander Graf, qemu-ppc, Thomas Huth,
	Giancarlo Teodori, 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).
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

-- 
2.1.4

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

* [Qemu-devel] [PATCH 1/6] pci: add pci_vga_type(), giving the device name of the chosen VGA device
  2016-12-29 22:12 [Qemu-devel] [PATCH 0/6] ppc: add a IBM 40p machine (RS/6000, PReP) Hervé Poussineau
@ 2016-12-29 22:12 ` Hervé Poussineau
  2017-01-02 23:01   ` David Gibson
  2016-12-29 22:12 ` [Qemu-devel] [PATCH 2/6] vga: increase priority of 0xa0000 memory region Hervé Poussineau
                   ` (5 subsequent siblings)
  6 siblings, 1 reply; 36+ messages in thread
From: Hervé Poussineau @ 2016-12-29 22:12 UTC (permalink / raw)
  To: qemu-devel
  Cc: David Gibson, Alexander Graf, qemu-ppc, Thomas Huth,
	Giancarlo Teodori, Hervé Poussineau, Michael S. Tsirkin,
	Marcel Apfelbaum

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

Signed-off-by: Hervé Poussineau <hpoussin@reactos.org>
---
 hw/pci/pci.c         | 22 ++++++++++++++++------
 include/hw/pci/pci.h |  1 +
 2 files changed, 17 insertions(+), 6 deletions(-)

diff --git a/hw/pci/pci.c b/hw/pci/pci.c
index 24fae16..0d5a862 100644
--- a/hw/pci/pci.c
+++ b/hw/pci/pci.c
@@ -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)
diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h
index 772692f..aa8d014 100644
--- a/include/hw/pci/pci.h
+++ b/include/hw/pci/pci.h
@@ -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);
-- 
2.1.4

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

* [Qemu-devel] [PATCH 2/6] vga: increase priority of 0xa0000 memory region
  2016-12-29 22:12 [Qemu-devel] [PATCH 0/6] ppc: add a IBM 40p machine (RS/6000, PReP) Hervé Poussineau
  2016-12-29 22:12 ` [Qemu-devel] [PATCH 1/6] pci: add pci_vga_type(), giving the device name of the chosen VGA device Hervé Poussineau
@ 2016-12-29 22:12 ` Hervé Poussineau
  2017-01-02 23:02   ` David Gibson
  2016-12-29 22:12 ` [Qemu-devel] [PATCH 3/6] prep: do not use global variable to access nvram Hervé Poussineau
                   ` (4 subsequent siblings)
  6 siblings, 1 reply; 36+ messages in thread
From: Hervé Poussineau @ 2016-12-29 22:12 UTC (permalink / raw)
  To: qemu-devel
  Cc: David Gibson, Alexander Graf, qemu-ppc, Thomas Huth,
	Giancarlo Teodori, 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.

Signed-off-by: Hervé Poussineau <hpoussin@reactos.org>
---
 hw/display/vga.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/display/vga.c b/hw/display/vga.c
index 2a88b3c..c573f35 100644
--- a/hw/display/vga.c
+++ b/hw/display/vga.c
@@ -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");
-- 
2.1.4

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

* [Qemu-devel] [PATCH 3/6] prep: do not use global variable to access nvram
  2016-12-29 22:12 [Qemu-devel] [PATCH 0/6] ppc: add a IBM 40p machine (RS/6000, PReP) Hervé Poussineau
  2016-12-29 22:12 ` [Qemu-devel] [PATCH 1/6] pci: add pci_vga_type(), giving the device name of the chosen VGA device Hervé Poussineau
  2016-12-29 22:12 ` [Qemu-devel] [PATCH 2/6] vga: increase priority of 0xa0000 memory region Hervé Poussineau
@ 2016-12-29 22:12 ` Hervé Poussineau
  2017-01-03  3:51   ` David Gibson
  2016-12-29 22:12 ` [Qemu-devel] [PATCH 4/6] prep: QOM'ify System I/O Hervé Poussineau
                   ` (3 subsequent siblings)
  6 siblings, 1 reply; 36+ messages in thread
From: Hervé Poussineau @ 2016-12-29 22:12 UTC (permalink / raw)
  To: qemu-devel
  Cc: David Gibson, Alexander Graf, qemu-ppc, Thomas Huth,
	Giancarlo Teodori, Hervé Poussineau

Signed-off-by: Hervé Poussineau <hpoussin@reactos.org>
---
 hw/ppc/prep.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/hw/ppc/prep.c b/hw/ppc/prep.c
index 054af1e..9fb89d3 100644
--- a/hw/ppc/prep.c
+++ b/hw/ppc/prep.c
@@ -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);
 }
 
-- 
2.1.4

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

* [Qemu-devel] [PATCH 4/6] prep: QOM'ify System I/O
  2016-12-29 22:12 [Qemu-devel] [PATCH 0/6] ppc: add a IBM 40p machine (RS/6000, PReP) Hervé Poussineau
                   ` (2 preceding siblings ...)
  2016-12-29 22:12 ` [Qemu-devel] [PATCH 3/6] prep: do not use global variable to access nvram Hervé Poussineau
@ 2016-12-29 22:12 ` Hervé Poussineau
  2017-01-02 23:03   ` David Gibson
  2017-01-03  4:45   ` David Gibson
  2016-12-29 22:12 ` [Qemu-devel] [PATCH 5/6] prep: add IBM RS/6000 7020 (40p) memory controller Hervé Poussineau
                   ` (2 subsequent siblings)
  6 siblings, 2 replies; 36+ messages in thread
From: Hervé Poussineau @ 2016-12-29 22:12 UTC (permalink / raw)
  To: qemu-devel
  Cc: David Gibson, Alexander Graf, qemu-ppc, Thomas Huth,
	Giancarlo Teodori, Hervé Poussineau

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

Signed-off-by: Hervé Poussineau <hpoussin@reactos.org>
---
 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

diff --git a/hw/ppc/Makefile.objs b/hw/ppc/Makefile.objs
index 8025129..db72297 100644
--- a/hw/ppc/Makefile.objs
+++ b/hw/ppc/Makefile.objs
@@ -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
diff --git a/hw/ppc/prep_systemio.c b/hw/ppc/prep_systemio.c
new file mode 100644
index 0000000..449056c
--- /dev/null
+++ b/hw/ppc/prep_systemio.c
@@ -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)
diff --git a/hw/ppc/trace-events b/hw/ppc/trace-events
index 2297ead..2ba6166 100644
--- a/hw/ppc/trace-events
+++ b/hw/ppc/trace-events
@@ -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"
-- 
2.1.4

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

* [Qemu-devel] [PATCH 5/6] prep: add IBM RS/6000 7020 (40p) memory controller
  2016-12-29 22:12 [Qemu-devel] [PATCH 0/6] ppc: add a IBM 40p machine (RS/6000, PReP) Hervé Poussineau
                   ` (3 preceding siblings ...)
  2016-12-29 22:12 ` [Qemu-devel] [PATCH 4/6] prep: QOM'ify System I/O Hervé Poussineau
@ 2016-12-29 22:12 ` Hervé Poussineau
  2017-01-03  4:57   ` David Gibson
  2016-12-29 22:12 ` [Qemu-devel] [PATCH 6/6] prep: add IBM RS/6000 7020 (40p) machine emulation Hervé Poussineau
  2017-01-11 16:58 ` [Qemu-devel] [PATCH 0/6] ppc: add a IBM 40p machine (RS/6000, PReP) Artyom Tarasenko
  6 siblings, 1 reply; 36+ messages in thread
From: Hervé Poussineau @ 2016-12-29 22:12 UTC (permalink / raw)
  To: qemu-devel
  Cc: David Gibson, Alexander Graf, qemu-ppc, Thomas Huth,
	Giancarlo Teodori, Hervé Poussineau

Signed-off-by: Hervé Poussineau <hpoussin@reactos.org>
---
 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

diff --git a/default-configs/ppc-softmmu.mak b/default-configs/ppc-softmmu.mak
index d4d0f9b..e567658 100644
--- a/default-configs/ppc-softmmu.mak
+++ b/default-configs/ppc-softmmu.mak
@@ -47,3 +47,4 @@ CONFIG_LIBDECNUMBER=y
 # For PReP
 CONFIG_MC146818RTC=y
 CONFIG_ISA_TESTDEV=y
+CONFIG_RS6000_MC=y
diff --git a/hw/ppc/Makefile.objs b/hw/ppc/Makefile.objs
index db72297..0012934 100644
--- a/hw/ppc/Makefile.objs
+++ b/hw/ppc/Makefile.objs
@@ -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
diff --git a/hw/ppc/rs6000_mc.c b/hw/ppc/rs6000_mc.c
new file mode 100644
index 0000000..c684421
--- /dev/null
+++ b/hw/ppc/rs6000_mc.c
@@ -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 {
+            /* Not enough memory */
+            break;
+        }
+        socket += 2;
+    }
+
+    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)
diff --git a/hw/ppc/trace-events b/hw/ppc/trace-events
index 2ba6166..42b8ec0 100644
--- a/hw/ppc/trace-events
+++ b/hw/ppc/trace-events
@@ -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"
-- 
2.1.4

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

* [Qemu-devel] [PATCH 6/6] prep: add IBM RS/6000 7020 (40p) machine emulation
  2016-12-29 22:12 [Qemu-devel] [PATCH 0/6] ppc: add a IBM 40p machine (RS/6000, PReP) Hervé Poussineau
                   ` (4 preceding siblings ...)
  2016-12-29 22:12 ` [Qemu-devel] [PATCH 5/6] prep: add IBM RS/6000 7020 (40p) memory controller Hervé Poussineau
@ 2016-12-29 22:12 ` Hervé Poussineau
  2017-01-03  5:02   ` David Gibson
  2017-05-08 20:49   ` Eduardo Habkost
  2017-01-11 16:58 ` [Qemu-devel] [PATCH 0/6] ppc: add a IBM 40p machine (RS/6000, PReP) Artyom Tarasenko
  6 siblings, 2 replies; 36+ messages in thread
From: Hervé Poussineau @ 2016-12-29 22:12 UTC (permalink / raw)
  To: qemu-devel
  Cc: David Gibson, Alexander Graf, qemu-ppc, Thomas Huth,
	Giancarlo Teodori, 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.

Signed-off-by: Hervé Poussineau <hpoussin@reactos.org>
---
 default-configs/ppc-softmmu.mak |   1 +
 hw/ppc/prep.c                   | 231 ++++++++++++++++++++++++++++++++++++++++
 2 files changed, 232 insertions(+)

diff --git a/default-configs/ppc-softmmu.mak b/default-configs/ppc-softmmu.mak
index e567658..7dd004e 100644
--- a/default-configs/ppc-softmmu.mak
+++ b/default-configs/ppc-softmmu.mak
@@ -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
diff --git a/hw/ppc/prep.c b/hw/ppc/prep.c
index 9fb89d3..c0373d1 100644
--- a/hw/ppc/prep.c
+++ b/hw/ppc/prep.c
@@ -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;
@@ -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) {
+        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)
-- 
2.1.4

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

* Re: [Qemu-devel] [PATCH 1/6] pci: add pci_vga_type(), giving the device name of the chosen VGA device
  2016-12-29 22:12 ` [Qemu-devel] [PATCH 1/6] pci: add pci_vga_type(), giving the device name of the chosen VGA device Hervé Poussineau
@ 2017-01-02 23:01   ` David Gibson
  2017-01-10  3:14     ` Michael S. Tsirkin
  0 siblings, 1 reply; 36+ messages in thread
From: David Gibson @ 2017-01-02 23:01 UTC (permalink / raw)
  To: Hervé Poussineau
  Cc: qemu-devel, Alexander Graf, qemu-ppc, Thomas Huth,
	Giancarlo Teodori, Michael S. Tsirkin, Marcel Apfelbaum

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

On Thu, Dec 29, 2016 at 11:12:11PM +0100, Hervé Poussineau wrote:
> This is in fact a split of pci_vga_init() function in two parts.
> 
> Signed-off-by: Hervé Poussineau <hpoussin@reactos.org>

Reviewed-by: David Gibson <david@gibson.dropbear.id.au>

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

> ---
>  hw/pci/pci.c         | 22 ++++++++++++++++------
>  include/hw/pci/pci.h |  1 +
>  2 files changed, 17 insertions(+), 6 deletions(-)
> 
> diff --git a/hw/pci/pci.c b/hw/pci/pci.c
> index 24fae16..0d5a862 100644
> --- a/hw/pci/pci.c
> +++ b/hw/pci/pci.c
> @@ -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)
> diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h
> index 772692f..aa8d014 100644
> --- a/include/hw/pci/pci.h
> +++ b/include/hw/pci/pci.h
> @@ -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

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

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

* Re: [Qemu-devel] [PATCH 2/6] vga: increase priority of 0xa0000 memory region
  2016-12-29 22:12 ` [Qemu-devel] [PATCH 2/6] vga: increase priority of 0xa0000 memory region Hervé Poussineau
@ 2017-01-02 23:02   ` David Gibson
  2017-01-03 22:37     ` Hervé Poussineau
  0 siblings, 1 reply; 36+ messages in thread
From: David Gibson @ 2017-01-02 23:02 UTC (permalink / raw)
  To: Hervé Poussineau
  Cc: qemu-devel, Alexander Graf, qemu-ppc, Thomas Huth, Giancarlo Teodori

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

On Thu, Dec 29, 2016 at 11:12:12PM +0100, Hervé Poussineau wrote:
> 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?

> Signed-off-by: Hervé Poussineau <hpoussin@reactos.org>
> ---
>  hw/display/vga.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/hw/display/vga.c b/hw/display/vga.c
> index 2a88b3c..c573f35 100644
> --- a/hw/display/vga.c
> +++ b/hw/display/vga.c
> @@ -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");

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

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

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

* Re: [Qemu-devel] [PATCH 4/6] prep: QOM'ify System I/O
  2016-12-29 22:12 ` [Qemu-devel] [PATCH 4/6] prep: QOM'ify System I/O Hervé Poussineau
@ 2017-01-02 23:03   ` David Gibson
  2017-01-03 22:51     ` Hervé Poussineau
  2017-01-03  4:45   ` David Gibson
  1 sibling, 1 reply; 36+ messages in thread
From: David Gibson @ 2017-01-02 23:03 UTC (permalink / raw)
  To: Hervé Poussineau
  Cc: qemu-devel, Alexander Graf, qemu-ppc, Thomas Huth, Giancarlo Teodori

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

On Thu, Dec 29, 2016 at 11:12:14PM +0100, Hervé Poussineau wrote:
> 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?
> 
> Signed-off-by: Hervé Poussineau <hpoussin@reactos.org>
> ---
>  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
> 
> diff --git a/hw/ppc/Makefile.objs b/hw/ppc/Makefile.objs
> index 8025129..db72297 100644
> --- a/hw/ppc/Makefile.objs
> +++ b/hw/ppc/Makefile.objs
> @@ -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
> diff --git a/hw/ppc/prep_systemio.c b/hw/ppc/prep_systemio.c
> new file mode 100644
> index 0000000..449056c
> --- /dev/null
> +++ b/hw/ppc/prep_systemio.c
> @@ -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)
> diff --git a/hw/ppc/trace-events b/hw/ppc/trace-events
> index 2297ead..2ba6166 100644
> --- a/hw/ppc/trace-events
> +++ b/hw/ppc/trace-events
> @@ -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"

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

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

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

* Re: [Qemu-devel] [PATCH 3/6] prep: do not use global variable to access nvram
  2016-12-29 22:12 ` [Qemu-devel] [PATCH 3/6] prep: do not use global variable to access nvram Hervé Poussineau
@ 2017-01-03  3:51   ` David Gibson
  0 siblings, 0 replies; 36+ messages in thread
From: David Gibson @ 2017-01-03  3:51 UTC (permalink / raw)
  To: Hervé Poussineau
  Cc: qemu-devel, Alexander Graf, qemu-ppc, Thomas Huth, Giancarlo Teodori

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

On Thu, Dec 29, 2016 at 11:12:13PM +0100, Hervé Poussineau wrote:
> Signed-off-by: Hervé Poussineau <hpoussin@reactos.org>

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

> ---
>  hw/ppc/prep.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/hw/ppc/prep.c b/hw/ppc/prep.c
> index 054af1e..9fb89d3 100644
> --- a/hw/ppc/prep.c
> +++ b/hw/ppc/prep.c
> @@ -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);
>  }
>  

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

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

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

* Re: [Qemu-devel] [PATCH 4/6] prep: QOM'ify System I/O
  2016-12-29 22:12 ` [Qemu-devel] [PATCH 4/6] prep: QOM'ify System I/O Hervé Poussineau
  2017-01-02 23:03   ` David Gibson
@ 2017-01-03  4:45   ` David Gibson
  2017-01-04 21:17     ` Hervé Poussineau
  1 sibling, 1 reply; 36+ messages in thread
From: David Gibson @ 2017-01-03  4:45 UTC (permalink / raw)
  To: Hervé Poussineau
  Cc: qemu-devel, Alexander Graf, qemu-ppc, Thomas Huth, Giancarlo Teodori

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

On Thu, Dec 29, 2016 at 11:12:14PM +0100, Hervé Poussineau wrote:
> Part of the functionality is copied from hw/ppc/prep.c.
> Also add support for board identification/equipment registers.
> 
> Signed-off-by: Hervé Poussineau <hpoussin@reactos.org>
> ---
>  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
> 
> diff --git a/hw/ppc/Makefile.objs b/hw/ppc/Makefile.objs
> index 8025129..db72297 100644
> --- a/hw/ppc/Makefile.objs
> +++ b/hw/ppc/Makefile.objs
> @@ -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
> diff --git a/hw/ppc/prep_systemio.c b/hw/ppc/prep_systemio.c
> new file mode 100644
> index 0000000..449056c
> --- /dev/null
> +++ b/hw/ppc/prep_systemio.c
> @@ -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;

You could just use
	s->sreset = val & PORT0092_SOFTRESET;
	qemu_set_irq(irq, s->sreset);
here, rather than the if.

> +    }
> +
> +    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;

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.

> +}
> +
> +/* 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;

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

> +}
> +
> +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;

Again, should this be masked?

> +}
> +
> +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()

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

> +    },
> +};
> +
> +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)
> diff --git a/hw/ppc/trace-events b/hw/ppc/trace-events
> index 2297ead..2ba6166 100644
> --- a/hw/ppc/trace-events
> +++ b/hw/ppc/trace-events
> @@ -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"

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

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

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

* Re: [Qemu-devel] [PATCH 5/6] prep: add IBM RS/6000 7020 (40p) memory controller
  2016-12-29 22:12 ` [Qemu-devel] [PATCH 5/6] prep: add IBM RS/6000 7020 (40p) memory controller Hervé Poussineau
@ 2017-01-03  4:57   ` David Gibson
  2017-01-03 22:55     ` Hervé Poussineau
  0 siblings, 1 reply; 36+ messages in thread
From: David Gibson @ 2017-01-03  4:57 UTC (permalink / raw)
  To: Hervé Poussineau
  Cc: qemu-devel, Alexander Graf, qemu-ppc, Thomas Huth, Giancarlo Teodori

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

On Thu, Dec 29, 2016 at 11:12:15PM +0100, Hervé Poussineau wrote:
> Signed-off-by: Hervé Poussineau <hpoussin@reactos.org>
> ---
>  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
> 
> diff --git a/default-configs/ppc-softmmu.mak b/default-configs/ppc-softmmu.mak
> index d4d0f9b..e567658 100644
> --- a/default-configs/ppc-softmmu.mak
> +++ b/default-configs/ppc-softmmu.mak
> @@ -47,3 +47,4 @@ CONFIG_LIBDECNUMBER=y
>  # For PReP
>  CONFIG_MC146818RTC=y
>  CONFIG_ISA_TESTDEV=y
> +CONFIG_RS6000_MC=y
> diff --git a/hw/ppc/Makefile.objs b/hw/ppc/Makefile.objs
> index db72297..0012934 100644
> --- a/hw/ppc/Makefile.objs
> +++ b/hw/ppc/Makefile.objs
> @@ -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
> diff --git a/hw/ppc/rs6000_mc.c b/hw/ppc/rs6000_mc.c
> new file mode 100644
> index 0000000..c684421
> --- /dev/null
> +++ b/hw/ppc/rs6000_mc.c
> @@ -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 {
> +            /* 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).

> +    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)
> diff --git a/hw/ppc/trace-events b/hw/ppc/trace-events
> index 2ba6166..42b8ec0 100644
> --- a/hw/ppc/trace-events
> +++ b/hw/ppc/trace-events
> @@ -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"

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

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

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

* Re: [Qemu-devel] [PATCH 6/6] prep: add IBM RS/6000 7020 (40p) machine emulation
  2016-12-29 22:12 ` [Qemu-devel] [PATCH 6/6] prep: add IBM RS/6000 7020 (40p) machine emulation Hervé Poussineau
@ 2017-01-03  5:02   ` David Gibson
  2017-05-08 20:49   ` Eduardo Habkost
  1 sibling, 0 replies; 36+ messages in thread
From: David Gibson @ 2017-01-03  5:02 UTC (permalink / raw)
  To: Hervé Poussineau
  Cc: qemu-devel, Alexander Graf, qemu-ppc, Thomas Huth, Giancarlo Teodori

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

On Thu, Dec 29, 2016 at 11:12:16PM +0100, Hervé Poussineau wrote:
> 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.
> 
> Signed-off-by: Hervé Poussineau <hpoussin@reactos.org>
> ---
>  default-configs/ppc-softmmu.mak |   1 +
>  hw/ppc/prep.c                   | 231 ++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 232 insertions(+)
> 
> diff --git a/default-configs/ppc-softmmu.mak b/default-configs/ppc-softmmu.mak
> index e567658..7dd004e 100644
> --- a/default-configs/ppc-softmmu.mak
> +++ b/default-configs/ppc-softmmu.mak
> @@ -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
> diff --git a/hw/ppc/prep.c b/hw/ppc/prep.c
> index 9fb89d3..c0373d1 100644
> --- a/hw/ppc/prep.c
> +++ b/hw/ppc/prep.c
> @@ -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;
> @@ -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.

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

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

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

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

* Re: [Qemu-devel] [PATCH 2/6] vga: increase priority of 0xa0000 memory region
  2017-01-02 23:02   ` David Gibson
@ 2017-01-03 22:37     ` Hervé Poussineau
  2017-01-04  0:05       ` David Gibson
  0 siblings, 1 reply; 36+ messages in thread
From: Hervé Poussineau @ 2017-01-03 22:37 UTC (permalink / raw)
  To: David Gibson
  Cc: qemu-devel, Alexander Graf, qemu-ppc, Thomas Huth, Giancarlo Teodori

Le 03/01/2017 à 00:02, David Gibson a écrit :
> On Thu, Dec 29, 2016 at 11:12:12PM +0100, Hervé Poussineau wrote:
>> 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é

>
>> Signed-off-by: Hervé Poussineau <hpoussin@reactos.org>
>> ---
>>  hw/display/vga.c | 2 +-
>>  1 file changed, 1 insertion(+), 1 deletion(-)
>>
>> diff --git a/hw/display/vga.c b/hw/display/vga.c
>> index 2a88b3c..c573f35 100644
>> --- a/hw/display/vga.c
>> +++ b/hw/display/vga.c
>> @@ -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");
>

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

* Re: [Qemu-devel] [PATCH 4/6] prep: QOM'ify System I/O
  2017-01-02 23:03   ` David Gibson
@ 2017-01-03 22:51     ` Hervé Poussineau
  2017-01-03 23:39       ` David Gibson
  0 siblings, 1 reply; 36+ messages in thread
From: Hervé Poussineau @ 2017-01-03 22:51 UTC (permalink / raw)
  To: David Gibson
  Cc: qemu-devel, Alexander Graf, qemu-ppc, Thomas Huth, Giancarlo Teodori

Le 03/01/2017 à 00:03, David Gibson a écrit :
> On Thu, Dec 29, 2016 at 11:12:14PM +0100, Hervé Poussineau wrote:
>> 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"

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

>>
>> Signed-off-by: Hervé Poussineau <hpoussin@reactos.org>
>> ---
>>  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
>>
>> diff --git a/hw/ppc/Makefile.objs b/hw/ppc/Makefile.objs
>> index 8025129..db72297 100644
>> --- a/hw/ppc/Makefile.objs
>> +++ b/hw/ppc/Makefile.objs
>> @@ -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
>> diff --git a/hw/ppc/prep_systemio.c b/hw/ppc/prep_systemio.c
>> new file mode 100644
>> index 0000000..449056c
>> --- /dev/null
>> +++ b/hw/ppc/prep_systemio.c
>> @@ -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)
>> diff --git a/hw/ppc/trace-events b/hw/ppc/trace-events
>> index 2297ead..2ba6166 100644
>> --- a/hw/ppc/trace-events
>> +++ b/hw/ppc/trace-events
>> @@ -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"
>

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

* Re: [Qemu-devel] [PATCH 5/6] prep: add IBM RS/6000 7020 (40p) memory controller
  2017-01-03  4:57   ` David Gibson
@ 2017-01-03 22:55     ` Hervé Poussineau
  2017-01-03 23:39       ` David Gibson
  0 siblings, 1 reply; 36+ messages in thread
From: Hervé Poussineau @ 2017-01-03 22:55 UTC (permalink / raw)
  To: David Gibson
  Cc: qemu-devel, Alexander Graf, qemu-ppc, Thomas Huth, Giancarlo Teodori

Le 03/01/2017 à 05:57, David Gibson a écrit :
> On Thu, Dec 29, 2016 at 11:12:15PM +0100, Hervé Poussineau wrote:
>> Signed-off-by: Hervé Poussineau <hpoussin@reactos.org>
>> ---
>>  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
>>
>> diff --git a/default-configs/ppc-softmmu.mak b/default-configs/ppc-softmmu.mak
>> index d4d0f9b..e567658 100644
>> --- a/default-configs/ppc-softmmu.mak
>> +++ b/default-configs/ppc-softmmu.mak
>> @@ -47,3 +47,4 @@ CONFIG_LIBDECNUMBER=y
>>  # For PReP
>>  CONFIG_MC146818RTC=y
>>  CONFIG_ISA_TESTDEV=y
>> +CONFIG_RS6000_MC=y
>> diff --git a/hw/ppc/Makefile.objs b/hw/ppc/Makefile.objs
>> index db72297..0012934 100644
>> --- a/hw/ppc/Makefile.objs
>> +++ b/hw/ppc/Makefile.objs
>> @@ -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
>> diff --git a/hw/ppc/rs6000_mc.c b/hw/ppc/rs6000_mc.c
>> new file mode 100644
>> index 0000000..c684421
>> --- /dev/null
>> +++ b/hw/ppc/rs6000_mc.c
>> @@ -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 {
>> +            /* 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.
 >> +    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?


>
>> +    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)
>> diff --git a/hw/ppc/trace-events b/hw/ppc/trace-events
>> index 2ba6166..42b8ec0 100644
>> --- a/hw/ppc/trace-events
>> +++ b/hw/ppc/trace-events
>> @@ -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"
>

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

* Re: [Qemu-devel] [PATCH 5/6] prep: add IBM RS/6000 7020 (40p) memory controller
  2017-01-03 22:55     ` Hervé Poussineau
@ 2017-01-03 23:39       ` David Gibson
  0 siblings, 0 replies; 36+ messages in thread
From: David Gibson @ 2017-01-03 23:39 UTC (permalink / raw)
  To: Hervé Poussineau
  Cc: qemu-devel, Alexander Graf, qemu-ppc, Thomas Huth, Giancarlo Teodori

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

On Tue, Jan 03, 2017 at 11:55:10PM +0100, Hervé Poussineau wrote:
> Le 03/01/2017 à 05:57, David Gibson a écrit :
> > On Thu, Dec 29, 2016 at 11:12:15PM +0100, Hervé Poussineau wrote:
> > > Signed-off-by: Hervé Poussineau <hpoussin@reactos.org>
> > > ---
> > >  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
> > > 
> > > diff --git a/default-configs/ppc-softmmu.mak b/default-configs/ppc-softmmu.mak
> > > index d4d0f9b..e567658 100644
> > > --- a/default-configs/ppc-softmmu.mak
> > > +++ b/default-configs/ppc-softmmu.mak
> > > @@ -47,3 +47,4 @@ CONFIG_LIBDECNUMBER=y
> > >  # For PReP
> > >  CONFIG_MC146818RTC=y
> > >  CONFIG_ISA_TESTDEV=y
> > > +CONFIG_RS6000_MC=y
> > > diff --git a/hw/ppc/Makefile.objs b/hw/ppc/Makefile.objs
> > > index db72297..0012934 100644
> > > --- a/hw/ppc/Makefile.objs
> > > +++ b/hw/ppc/Makefile.objs
> > > @@ -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
> > > diff --git a/hw/ppc/rs6000_mc.c b/hw/ppc/rs6000_mc.c
> > > new file mode 100644
> > > index 0000000..c684421
> > > --- /dev/null
> > > +++ b/hw/ppc/rs6000_mc.c
> > > @@ -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 {
> > > +            /* 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.

Sorry, missed that.

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

> > > +    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)
> > > diff --git a/hw/ppc/trace-events b/hw/ppc/trace-events
> > > index 2ba6166..42b8ec0 100644
> > > --- a/hw/ppc/trace-events
> > > +++ b/hw/ppc/trace-events
> > > @@ -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"
> > 
> 

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

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

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

* Re: [Qemu-devel] [PATCH 4/6] prep: QOM'ify System I/O
  2017-01-03 22:51     ` Hervé Poussineau
@ 2017-01-03 23:39       ` David Gibson
  0 siblings, 0 replies; 36+ messages in thread
From: David Gibson @ 2017-01-03 23:39 UTC (permalink / raw)
  To: Hervé Poussineau
  Cc: qemu-devel, Alexander Graf, qemu-ppc, Thomas Huth, Giancarlo Teodori

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

On Tue, Jan 03, 2017 at 11:51:27PM +0100, Hervé Poussineau wrote:
> Le 03/01/2017 à 00:03, David Gibson a écrit :
> > On Thu, Dec 29, 2016 at 11:12:14PM +0100, Hervé Poussineau wrote:
> > > 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"
> 
> > 
> > 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.


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

> 
> Hervé
> 
> > > 
> > > Signed-off-by: Hervé Poussineau <hpoussin@reactos.org>
> > > ---
> > >  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
> > > 
> > > diff --git a/hw/ppc/Makefile.objs b/hw/ppc/Makefile.objs
> > > index 8025129..db72297 100644
> > > --- a/hw/ppc/Makefile.objs
> > > +++ b/hw/ppc/Makefile.objs
> > > @@ -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
> > > diff --git a/hw/ppc/prep_systemio.c b/hw/ppc/prep_systemio.c
> > > new file mode 100644
> > > index 0000000..449056c
> > > --- /dev/null
> > > +++ b/hw/ppc/prep_systemio.c
> > > @@ -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)
> > > diff --git a/hw/ppc/trace-events b/hw/ppc/trace-events
> > > index 2297ead..2ba6166 100644
> > > --- a/hw/ppc/trace-events
> > > +++ b/hw/ppc/trace-events
> > > @@ -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"
> > 
> 

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

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

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

* Re: [Qemu-devel] [PATCH 2/6] vga: increase priority of 0xa0000 memory region
  2017-01-03 22:37     ` Hervé Poussineau
@ 2017-01-04  0:05       ` David Gibson
  0 siblings, 0 replies; 36+ messages in thread
From: David Gibson @ 2017-01-04  0:05 UTC (permalink / raw)
  To: Hervé Poussineau
  Cc: qemu-devel, Alexander Graf, qemu-ppc, Thomas Huth, Giancarlo Teodori

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

On Tue, Jan 03, 2017 at 11:37:20PM +0100, Hervé Poussineau wrote:
> Le 03/01/2017 à 00:02, David Gibson a écrit :
> > On Thu, Dec 29, 2016 at 11:12:12PM +0100, Hervé Poussineau wrote:
> > > 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.

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.

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

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

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

> 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é
> 
> > 
> > > Signed-off-by: Hervé Poussineau <hpoussin@reactos.org>
> > > ---
> > >  hw/display/vga.c | 2 +-
> > >  1 file changed, 1 insertion(+), 1 deletion(-)
> > > 
> > > diff --git a/hw/display/vga.c b/hw/display/vga.c
> > > index 2a88b3c..c573f35 100644
> > > --- a/hw/display/vga.c
> > > +++ b/hw/display/vga.c
> > > @@ -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");
> > 
> 

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

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

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

* Re: [Qemu-devel] [PATCH 4/6] prep: QOM'ify System I/O
  2017-01-03  4:45   ` David Gibson
@ 2017-01-04 21:17     ` Hervé Poussineau
  2017-01-05  0:41       ` David Gibson
  0 siblings, 1 reply; 36+ messages in thread
From: Hervé Poussineau @ 2017-01-04 21:17 UTC (permalink / raw)
  To: David Gibson
  Cc: qemu-devel, Alexander Graf, qemu-ppc, Thomas Huth, Giancarlo Teodori

Le 03/01/2017 à 05:45, David Gibson a écrit :
> On Thu, Dec 29, 2016 at 11:12:14PM +0100, Hervé Poussineau wrote:
>> Part of the functionality is copied from hw/ppc/prep.c.
>> Also add support for board identification/equipment registers.
>>
>> Signed-off-by: Hervé Poussineau <hpoussin@reactos.org>
>> ---
>>  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
>>
>> diff --git a/hw/ppc/Makefile.objs b/hw/ppc/Makefile.objs
>> index 8025129..db72297 100644
>> --- a/hw/ppc/Makefile.objs
>> +++ b/hw/ppc/Makefile.objs
>> @@ -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
>> diff --git a/hw/ppc/prep_systemio.c b/hw/ppc/prep_systemio.c
>> new file mode 100644
>> index 0000000..449056c
>> --- /dev/null
>> +++ b/hw/ppc/prep_systemio.c
>> @@ -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;
>
> You could just use
> 	s->sreset = val & PORT0092_SOFTRESET;
> 	qemu_set_irq(irq, s->sreset);
> here, rather than the if.

OK

>
>> +    }
>> +
>> +    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;
>
> 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.

>
>> +}
>> +
>> +/* 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;
>
> 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()

>
>> +}
>> +
>> +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;
>
> Again, should this be masked?

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

>
>> +}
>> +
>> +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()
>
> 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.

>
>> +    },
>> +};
>> +
>> +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)
>> diff --git a/hw/ppc/trace-events b/hw/ppc/trace-events
>> index 2297ead..2ba6166 100644
>> --- a/hw/ppc/trace-events
>> +++ b/hw/ppc/trace-events
>> @@ -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"
>

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

* Re: [Qemu-devel] [PATCH 4/6] prep: QOM'ify System I/O
  2017-01-04 21:17     ` Hervé Poussineau
@ 2017-01-05  0:41       ` David Gibson
  2017-01-05 20:57         ` Hervé Poussineau
  0 siblings, 1 reply; 36+ messages in thread
From: David Gibson @ 2017-01-05  0:41 UTC (permalink / raw)
  To: Hervé Poussineau
  Cc: qemu-devel, Alexander Graf, qemu-ppc, Thomas Huth, Giancarlo Teodori

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

On Wed, Jan 04, 2017 at 10:17:10PM +0100, Hervé Poussineau wrote:
> Le 03/01/2017 à 05:45, David Gibson a écrit :
> > On Thu, Dec 29, 2016 at 11:12:14PM +0100, Hervé Poussineau wrote:
> > > Part of the functionality is copied from hw/ppc/prep.c.
> > > Also add support for board identification/equipment registers.
> > > 
> > > Signed-off-by: Hervé Poussineau <hpoussin@reactos.org>
> > > ---
> > >  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
> > > 
> > > diff --git a/hw/ppc/Makefile.objs b/hw/ppc/Makefile.objs
> > > index 8025129..db72297 100644
> > > --- a/hw/ppc/Makefile.objs
> > > +++ b/hw/ppc/Makefile.objs
> > > @@ -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
> > > diff --git a/hw/ppc/prep_systemio.c b/hw/ppc/prep_systemio.c
> > > new file mode 100644
> > > index 0000000..449056c
> > > --- /dev/null
> > > +++ b/hw/ppc/prep_systemio.c
> > > @@ -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;
> > 
> > You could just use
> > 	s->sreset = val & PORT0092_SOFTRESET;
> > 	qemu_set_irq(irq, s->sreset);
> > here, rather than the if.
> 
> OK
> 
> > 
> > > +    }
> > > +
> > > +    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;
> > 
> > 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.
> 
> > 
> > > +}
> > > +
> > > +/* 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;
> > 
> > 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.

Right, so I assumed.

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

> Note that we do nothing with the value, except giving it back in prep_port081c_read()
> 
> > 
> > > +}
> > > +
> > > +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;
> > 
> > Again, should this be masked?
> 
> Again some reserved bits. Let's take them unconditionally.
> 
> > 
> > > +}
> > > +
> > > +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()
> > 
> > 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.
> 
> > 
> > > +    },
> > > +};
> > > +
> > > +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)
> > > diff --git a/hw/ppc/trace-events b/hw/ppc/trace-events
> > > index 2297ead..2ba6166 100644
> > > --- a/hw/ppc/trace-events
> > > +++ b/hw/ppc/trace-events
> > > @@ -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"
> > 
> 

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

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

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

* Re: [Qemu-devel] [PATCH 4/6] prep: QOM'ify System I/O
  2017-01-05  0:41       ` David Gibson
@ 2017-01-05 20:57         ` Hervé Poussineau
  0 siblings, 0 replies; 36+ messages in thread
From: Hervé Poussineau @ 2017-01-05 20:57 UTC (permalink / raw)
  To: David Gibson
  Cc: qemu-devel, Alexander Graf, qemu-ppc, Thomas Huth, Giancarlo Teodori

Le 05/01/2017 à 01:41, David Gibson a écrit :
> On Wed, Jan 04, 2017 at 10:17:10PM +0100, Hervé Poussineau wrote:
>> Le 03/01/2017 à 05:45, David Gibson a écrit :
>>> On Thu, Dec 29, 2016 at 11:12:14PM +0100, Hervé Poussineau wrote:
>>>> Part of the functionality is copied from hw/ppc/prep.c.
>>>> Also add support for board identification/equipment registers.
>>>>
>>>> Signed-off-by: Hervé Poussineau <hpoussin@reactos.org>
>>>> ---
>>>>  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
>>>>
>>>> diff --git a/hw/ppc/Makefile.objs b/hw/ppc/Makefile.objs
>>>> index 8025129..db72297 100644
>>>> --- a/hw/ppc/Makefile.objs
>>>> +++ b/hw/ppc/Makefile.objs
>>>> @@ -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
>>>> diff --git a/hw/ppc/prep_systemio.c b/hw/ppc/prep_systemio.c
>>>> new file mode 100644
>>>> index 0000000..449056c
>>>> --- /dev/null
>>>> +++ b/hw/ppc/prep_systemio.c
>>>> @@ -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;
>>>
>>> You could just use
>>> 	s->sreset = val & PORT0092_SOFTRESET;
>>> 	qemu_set_irq(irq, s->sreset);
>>> here, rather than the if.
>>
>> OK
>>
>>>
>>>> +    }
>>>> +
>>>> +    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;
>>>
>>> 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.
>>
>>>
>>>> +}
>>>> +
>>>> +/* 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;
>>>
>>> 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.
>
> Right, so I assumed.
>
>> 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é

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

* Re: [Qemu-devel] [PATCH 1/6] pci: add pci_vga_type(), giving the device name of the chosen VGA device
  2017-01-02 23:01   ` David Gibson
@ 2017-01-10  3:14     ` Michael S. Tsirkin
  2017-01-10 21:00       ` Hervé Poussineau
  0 siblings, 1 reply; 36+ messages in thread
From: Michael S. Tsirkin @ 2017-01-10  3:14 UTC (permalink / raw)
  To: David Gibson
  Cc: Hervé Poussineau, qemu-devel, Alexander Graf, qemu-ppc,
	Thomas Huth, Giancarlo Teodori, Marcel Apfelbaum

On Tue, Jan 03, 2017 at 10:01:25AM +1100, David Gibson wrote:
> On Thu, Dec 29, 2016 at 11:12:11PM +0100, Hervé Poussineau wrote:
> > This is in fact a split of pci_vga_init() function in two parts.
> > 
> > Signed-off-by: Hervé Poussineau <hpoussin@reactos.org>
> 
> Reviewed-by: David Gibson <david@gibson.dropbear.id.au>
> 
> 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.

> > ---
> >  hw/pci/pci.c         | 22 ++++++++++++++++------
> >  include/hw/pci/pci.h |  1 +
> >  2 files changed, 17 insertions(+), 6 deletions(-)
> > 
> > diff --git a/hw/pci/pci.c b/hw/pci/pci.c
> > index 24fae16..0d5a862 100644
> > --- a/hw/pci/pci.c
> > +++ b/hw/pci/pci.c
> > @@ -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)
> > diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h
> > index 772692f..aa8d014 100644
> > --- a/include/hw/pci/pci.h
> > +++ b/include/hw/pci/pci.h
> > @@ -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

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

* Re: [Qemu-devel] [PATCH 1/6] pci: add pci_vga_type(), giving the device name of the chosen VGA device
  2017-01-10  3:14     ` Michael S. Tsirkin
@ 2017-01-10 21:00       ` Hervé Poussineau
  0 siblings, 0 replies; 36+ messages in thread
From: Hervé Poussineau @ 2017-01-10 21:00 UTC (permalink / raw)
  To: Michael S. Tsirkin, David Gibson
  Cc: qemu-devel, Alexander Graf, qemu-ppc, Thomas Huth,
	Giancarlo Teodori, Marcel Apfelbaum

Le 10/01/2017 à 04:14, Michael S. Tsirkin a écrit :
> On Tue, Jan 03, 2017 at 10:01:25AM +1100, David Gibson wrote:
>> On Thu, Dec 29, 2016 at 11:12:11PM +0100, Hervé Poussineau wrote:
>>> This is in fact a split of pci_vga_init() function in two parts.
>>>
>>> Signed-off-by: Hervé Poussineau <hpoussin@reactos.org>
>>
>> Reviewed-by: David Gibson <david@gibson.dropbear.id.au>
>>
>> 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é

>
>>> ---
>>>  hw/pci/pci.c         | 22 ++++++++++++++++------
>>>  include/hw/pci/pci.h |  1 +
>>>  2 files changed, 17 insertions(+), 6 deletions(-)
>>>
>>> diff --git a/hw/pci/pci.c b/hw/pci/pci.c
>>> index 24fae16..0d5a862 100644
>>> --- a/hw/pci/pci.c
>>> +++ b/hw/pci/pci.c
>>> @@ -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)
>>> diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h
>>> index 772692f..aa8d014 100644
>>> --- a/include/hw/pci/pci.h
>>> +++ b/include/hw/pci/pci.h
>>> @@ -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
>
>
>

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

* Re: [Qemu-devel] [PATCH 0/6] ppc: add a IBM 40p machine (RS/6000, PReP)
  2016-12-29 22:12 [Qemu-devel] [PATCH 0/6] ppc: add a IBM 40p machine (RS/6000, PReP) Hervé Poussineau
                   ` (5 preceding siblings ...)
  2016-12-29 22:12 ` [Qemu-devel] [PATCH 6/6] prep: add IBM RS/6000 7020 (40p) machine emulation Hervé Poussineau
@ 2017-01-11 16:58 ` Artyom Tarasenko
  2017-01-11 23:18   ` David Gibson
  2017-01-12 12:57   ` Hervé Poussineau
  6 siblings, 2 replies; 36+ messages in thread
From: Artyom Tarasenko @ 2017-01-11 16:58 UTC (permalink / raw)
  To: Hervé Poussineau
  Cc: qemu-devel, Giancarlo Teodori, Thomas Huth, Alexander Graf,
	qemu-ppc, David Gibson

Hi Hervé,

nice work!

On Thu, Dec 29, 2016 at 11:12 PM, Hervé Poussineau <hpoussin@reactos.org> wrote:
> 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.

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

> 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

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



-- 
Regards,
Artyom Tarasenko

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

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

* Re: [Qemu-devel] [PATCH 0/6] ppc: add a IBM 40p machine (RS/6000, PReP)
  2017-01-11 16:58 ` [Qemu-devel] [PATCH 0/6] ppc: add a IBM 40p machine (RS/6000, PReP) Artyom Tarasenko
@ 2017-01-11 23:18   ` David Gibson
  2017-01-12 12:57   ` Hervé Poussineau
  1 sibling, 0 replies; 36+ messages in thread
From: David Gibson @ 2017-01-11 23:18 UTC (permalink / raw)
  To: Artyom Tarasenko
  Cc: Hervé Poussineau, qemu-devel, Giancarlo Teodori,
	Thomas Huth, Alexander Graf, qemu-ppc

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

On Wed, Jan 11, 2017 at 05:58:40PM +0100, Artyom Tarasenko wrote:
> Hi Hervé,
> 
> nice work!
> 
> On Thu, Dec 29, 2016 at 11:12 PM, Hervé Poussineau <hpoussin@reactos.org> wrote:
> > 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.
> 
> > 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.

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

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

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

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

* Re: [Qemu-devel] [PATCH 0/6] ppc: add a IBM 40p machine (RS/6000, PReP)
  2017-01-11 16:58 ` [Qemu-devel] [PATCH 0/6] ppc: add a IBM 40p machine (RS/6000, PReP) Artyom Tarasenko
  2017-01-11 23:18   ` David Gibson
@ 2017-01-12 12:57   ` Hervé Poussineau
  2017-01-12 13:46     ` Artyom Tarasenko
  2017-01-13 12:23     ` Mark Cave-Ayland
  1 sibling, 2 replies; 36+ messages in thread
From: Hervé Poussineau @ 2017-01-12 12:57 UTC (permalink / raw)
  To: Artyom Tarasenko
  Cc: qemu-devel, Giancarlo Teodori, Thomas Huth, Alexander Graf,
	qemu-ppc, David Gibson

Le 11/01/2017 à 17:58, Artyom Tarasenko a écrit :
> Hi Hervé,
>
> nice work!
>
> On Thu, Dec 29, 2016 at 11:12 PM, Hervé Poussineau <hpoussin@reactos.org> wrote:
>> 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

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

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

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

* Re: [Qemu-devel] [PATCH 0/6] ppc: add a IBM 40p machine (RS/6000, PReP)
  2017-01-12 12:57   ` Hervé Poussineau
@ 2017-01-12 13:46     ` Artyom Tarasenko
  2017-01-13 12:23     ` Mark Cave-Ayland
  1 sibling, 0 replies; 36+ messages in thread
From: Artyom Tarasenko @ 2017-01-12 13:46 UTC (permalink / raw)
  To: Hervé Poussineau
  Cc: qemu-devel, Giancarlo Teodori, Thomas Huth, Alexander Graf,
	qemu-ppc, David Gibson

On Thu, Jan 12, 2017 at 1:57 PM, Hervé Poussineau <hpoussin@reactos.org> wrote:
> Le 11/01/2017 à 17:58, Artyom Tarasenko a écrit :
>>
>> Hi Hervé,
>>
>> nice work!
>>
>> On Thu, Dec 29, 2016 at 11:12 PM, Hervé Poussineau <hpoussin@reactos.org>
>> wrote:
>>>
>>> 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
>
>>
>> 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.
>>
>>> 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
>
>>
>>> 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 should have somewhere the Debian Woody Image I used. Will test it tonight.

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

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.

-- 
Regards,
Artyom Tarasenko

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

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

* Re: [Qemu-devel] [PATCH 0/6] ppc: add a IBM 40p machine (RS/6000, PReP)
  2017-01-12 12:57   ` Hervé Poussineau
  2017-01-12 13:46     ` Artyom Tarasenko
@ 2017-01-13 12:23     ` Mark Cave-Ayland
  2017-01-13 13:26       ` Thomas Huth
                         ` (2 more replies)
  1 sibling, 3 replies; 36+ messages in thread
From: Mark Cave-Ayland @ 2017-01-13 12:23 UTC (permalink / raw)
  To: Hervé Poussineau, Artyom Tarasenko
  Cc: Giancarlo Teodori, Thomas Huth, qemu-devel, qemu-ppc, David Gibson

On 12/01/17 12:57, Hervé Poussineau wrote:

> Le 11/01/2017 à 17:58, Artyom Tarasenko a écrit :
>> Hi Hervé,
>>
>> nice work!
>>
>> On Thu, Dec 29, 2016 at 11:12 PM, Hervé Poussineau
>> <hpoussin@reactos.org> wrote:
>>> 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
> 
>>
>> 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.
>>
>>> 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
> 
>>
>>> 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.

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.

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

* Re: [Qemu-devel] [PATCH 0/6] ppc: add a IBM 40p machine (RS/6000, PReP)
  2017-01-13 12:23     ` Mark Cave-Ayland
@ 2017-01-13 13:26       ` Thomas Huth
  2017-01-13 13:30       ` Artyom Tarasenko
  2017-01-14 13:11       ` Hervé Poussineau
  2 siblings, 0 replies; 36+ messages in thread
From: Thomas Huth @ 2017-01-13 13:26 UTC (permalink / raw)
  To: Mark Cave-Ayland, Hervé Poussineau, Artyom Tarasenko
  Cc: Giancarlo Teodori, qemu-devel, qemu-ppc, David Gibson

On 13.01.2017 13:23, Mark Cave-Ayland wrote:
> On 12/01/17 12:57, Hervé Poussineau wrote:
> 
>> Le 11/01/2017 à 17:58, Artyom Tarasenko a écrit :
>>> Hi Hervé,
>>>
>>> nice work!
>>>
>>> On Thu, Dec 29, 2016 at 11:12 PM, Hervé Poussineau
>>> <hpoussin@reactos.org> wrote:
>>>> 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
>>
>>>
>>> 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.
>>>
>>>> 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
>>
>>>
>>>> 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.
> 
> 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

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

* Re: [Qemu-devel] [PATCH 0/6] ppc: add a IBM 40p machine (RS/6000, PReP)
  2017-01-13 12:23     ` Mark Cave-Ayland
  2017-01-13 13:26       ` Thomas Huth
@ 2017-01-13 13:30       ` Artyom Tarasenko
  2017-01-14 13:11       ` Hervé Poussineau
  2 siblings, 0 replies; 36+ messages in thread
From: Artyom Tarasenko @ 2017-01-13 13:30 UTC (permalink / raw)
  To: Mark Cave-Ayland
  Cc: Hervé Poussineau, Giancarlo Teodori, Thomas Huth,
	qemu-devel, qemu-ppc, David Gibson

On Fri, Jan 13, 2017 at 1:23 PM, Mark Cave-Ayland
<mark.cave-ayland@ilande.co.uk> wrote:
> On 12/01/17 12:57, Hervé Poussineau wrote:
>
>> Le 11/01/2017 à 17:58, Artyom Tarasenko a écrit :
>>> Hi Hervé,
>>>
>>> nice work!
>>>
>>> On Thu, Dec 29, 2016 at 11:12 PM, Hervé Poussineau
>>> <hpoussin@reactos.org> wrote:
>>>> 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
>>
>>>
>>> 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.
>>>
>>>> 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
>>
>>>
>>>> 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.
>
> 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


-- 
Regards,
Artyom Tarasenko

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

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

* Re: [Qemu-devel] [PATCH 0/6] ppc: add a IBM 40p machine (RS/6000, PReP)
  2017-01-13 12:23     ` Mark Cave-Ayland
  2017-01-13 13:26       ` Thomas Huth
  2017-01-13 13:30       ` Artyom Tarasenko
@ 2017-01-14 13:11       ` Hervé Poussineau
  2017-01-15 19:23         ` Artyom Tarasenko
  2 siblings, 1 reply; 36+ messages in thread
From: Hervé Poussineau @ 2017-01-14 13:11 UTC (permalink / raw)
  To: Mark Cave-Ayland, Artyom Tarasenko
  Cc: Giancarlo Teodori, Thomas Huth, qemu-devel, qemu-ppc, David Gibson

Le 13/01/2017 à 13:23, Mark Cave-Ayland a écrit :
>>
>> 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)


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

I fully agree on that!

Hervé

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

* Re: [Qemu-devel] [PATCH 0/6] ppc: add a IBM 40p machine (RS/6000, PReP)
  2017-01-14 13:11       ` Hervé Poussineau
@ 2017-01-15 19:23         ` Artyom Tarasenko
  0 siblings, 0 replies; 36+ messages in thread
From: Artyom Tarasenko @ 2017-01-15 19:23 UTC (permalink / raw)
  To: Hervé Poussineau
  Cc: Mark Cave-Ayland, Giancarlo Teodori, Thomas Huth, qemu-devel,
	qemu-ppc, David Gibson

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

On Sat, Jan 14, 2017 at 2:11 PM, Hervé Poussineau <hpoussin@reactos.org> wrote:
> Le 13/01/2017 à 13:23, Mark Cave-Ayland a écrit :
>>>
>>>
>>> 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)
>
>
>> 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

-- 
Regards,
Artyom Tarasenko

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

[-- Attachment #2: qprepofw.rom --]
[-- Type: application/octet-stream, Size: 590080 bytes --]

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

* Re: [Qemu-devel] [PATCH 6/6] prep: add IBM RS/6000 7020 (40p) machine emulation
  2016-12-29 22:12 ` [Qemu-devel] [PATCH 6/6] prep: add IBM RS/6000 7020 (40p) machine emulation Hervé Poussineau
  2017-01-03  5:02   ` David Gibson
@ 2017-05-08 20:49   ` Eduardo Habkost
  2017-05-08 21:32     ` Hervé Poussineau
  1 sibling, 1 reply; 36+ messages in thread
From: Eduardo Habkost @ 2017-05-08 20:49 UTC (permalink / raw)
  To: Hervé Poussineau
  Cc: qemu-devel, Giancarlo Teodori, Thomas Huth, Alexander Graf,
	qemu-ppc, David Gibson, Gerd Hoffmann

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:
[...]
> +static void ibm_40p_init(MachineState *machine)
> +{
[...]
> +    /* initialize audio subsystem */
> +    audio_init();

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

[...]
> +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
> 
> 

-- 
Eduardo

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

* Re: [Qemu-devel] [PATCH 6/6] prep: add IBM RS/6000 7020 (40p) machine emulation
  2017-05-08 20:49   ` Eduardo Habkost
@ 2017-05-08 21:32     ` Hervé Poussineau
  0 siblings, 0 replies; 36+ messages in thread
From: Hervé Poussineau @ 2017-05-08 21:32 UTC (permalink / raw)
  To: Eduardo Habkost
  Cc: qemu-devel, Giancarlo Teodori, Thomas Huth, Alexander Graf,
	qemu-ppc, David Gibson, Gerd Hoffmann

Le 08/05/2017 à 22:49, Eduardo Habkost a écrit :
> 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:
> [...]
>> +static void ibm_40p_init(MachineState *machine)
>> +{
> [...]
>> +    /* 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.

>
> [...]
>> +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
>>
>>
>

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

end of thread, other threads:[~2017-05-08 21:33 UTC | newest]

Thread overview: 36+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-12-29 22:12 [Qemu-devel] [PATCH 0/6] ppc: add a IBM 40p machine (RS/6000, PReP) Hervé Poussineau
2016-12-29 22:12 ` [Qemu-devel] [PATCH 1/6] pci: add pci_vga_type(), giving the device name of the chosen VGA device Hervé Poussineau
2017-01-02 23:01   ` David Gibson
2017-01-10  3:14     ` Michael S. Tsirkin
2017-01-10 21:00       ` Hervé Poussineau
2016-12-29 22:12 ` [Qemu-devel] [PATCH 2/6] vga: increase priority of 0xa0000 memory region Hervé Poussineau
2017-01-02 23:02   ` David Gibson
2017-01-03 22:37     ` Hervé Poussineau
2017-01-04  0:05       ` David Gibson
2016-12-29 22:12 ` [Qemu-devel] [PATCH 3/6] prep: do not use global variable to access nvram Hervé Poussineau
2017-01-03  3:51   ` David Gibson
2016-12-29 22:12 ` [Qemu-devel] [PATCH 4/6] prep: QOM'ify System I/O Hervé Poussineau
2017-01-02 23:03   ` David Gibson
2017-01-03 22:51     ` Hervé Poussineau
2017-01-03 23:39       ` David Gibson
2017-01-03  4:45   ` David Gibson
2017-01-04 21:17     ` Hervé Poussineau
2017-01-05  0:41       ` David Gibson
2017-01-05 20:57         ` Hervé Poussineau
2016-12-29 22:12 ` [Qemu-devel] [PATCH 5/6] prep: add IBM RS/6000 7020 (40p) memory controller Hervé Poussineau
2017-01-03  4:57   ` David Gibson
2017-01-03 22:55     ` Hervé Poussineau
2017-01-03 23:39       ` David Gibson
2016-12-29 22:12 ` [Qemu-devel] [PATCH 6/6] prep: add IBM RS/6000 7020 (40p) machine emulation Hervé Poussineau
2017-01-03  5:02   ` David Gibson
2017-05-08 20:49   ` Eduardo Habkost
2017-05-08 21:32     ` Hervé Poussineau
2017-01-11 16:58 ` [Qemu-devel] [PATCH 0/6] ppc: add a IBM 40p machine (RS/6000, PReP) Artyom Tarasenko
2017-01-11 23:18   ` David Gibson
2017-01-12 12:57   ` Hervé Poussineau
2017-01-12 13:46     ` Artyom Tarasenko
2017-01-13 12:23     ` Mark Cave-Ayland
2017-01-13 13:26       ` Thomas Huth
2017-01-13 13:30       ` Artyom Tarasenko
2017-01-14 13:11       ` Hervé Poussineau
2017-01-15 19:23         ` Artyom Tarasenko

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