All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH 0/7] ppc/prep: add IBM RS/6000 43p machine
@ 2013-05-02 20:08 Hervé Poussineau
  2013-05-02 20:08 ` [Qemu-devel] [PATCH 1/7] pci: add MPC105 PCI host bridge emulation Hervé Poussineau
                   ` (6 more replies)
  0 siblings, 7 replies; 24+ messages in thread
From: Hervé Poussineau @ 2013-05-02 20:08 UTC (permalink / raw)
  To: qemu-devel; +Cc: Hervé Poussineau, qemu-ppc, Andreas Färber

Hi,

This patchset adds an emulation of the IBM RS/6000 43p, also known as 7248.
I've fixed comments of Blue Swirl in this series, so I'm sending it as PATCH instead of RFC.

Andreas did some preliminary patches for OpenBIOS to support PReP machines, available at
git://repo.or.cz/openbios/afaerber.git branch prep.
43p emulation has been tested with this firmware, and also with the official firmware,
named P93H1904.IMG.

Command line may look like
qemu-system-ppc -M 43p -readconfig ibm_43p.cfg

Changes RFC v2 -> PATCH v1:
- rebased on master
- add a Nvram interface on m48t59
- kept ISA io_base in patch 3
- renamed QOM parent objects as parent_obj

Changes RFC v1 -> RFC v2:
- rebased on master
- works with OpenBIOS
- rework on m48t59 patches
- remove rs6000 debug port emulation (not strictly required)
- checkpatch.pl doesn't complain anymore

Known bugs/missing parts:
- incomplete MPC105 (PCI host bridge) emulation (memory controller)
- no video card (should be a S3)
- QEMU can't change endianness at runtime

OpenBIOS status:
- detects CPU and memory, then freezes with a "Dictionary space overflow"

Official firmware status:
- can boot from a IDE hard disk containing a PReP boot partition
- can't boot from IDE cdroms (overlapping commands not supported by QEMU IDE emulation)
- can't boot from floppies (READ commands are issued, but it seems completion is ignored)
- can't boot from network (detects the netcard, but doesn't use it)
- needs a hack to m48t59 device to work

Regards,

Hervé

Hervé Poussineau (7):
  pci: add MPC105 PCI host bridge emulation
  qom: handle registration of new types when initializing the first
    ones
  m48t59: move ISA ports/memory regions registration to QOM constructor
  m48t59: register a QOM type for each nvram type we support
  m48t59: add a Nvram interface
  prep: add IBM RS/6000 7248 (43p) machine emulation
  prep: QOM'ify System I/O

 default-configs/ppc-softmmu.mak |    1 +
 docs/ibm_43p.cfg                |   43 ++++
 hw/pci-host/Makefile.objs       |    1 +
 hw/pci-host/mpc105.c            |  488 +++++++++++++++++++++++++++++++++++++++
 hw/ppc/Makefile.objs            |    1 +
 hw/ppc/prep.c                   |  213 +++++++++++++++++
 hw/ppc/prep_systemio.c          |  298 ++++++++++++++++++++++++
 hw/timer/m48t59.c               |  304 ++++++++++++++++++------
 include/hw/pci/pci_ids.h        |    1 +
 include/hw/timer/m48t59.h       |   24 ++
 qom/object.c                    |   45 +++-
 trace-events                    |   11 +
 12 files changed, 1349 insertions(+), 81 deletions(-)
 create mode 100644 docs/ibm_43p.cfg
 create mode 100644 hw/pci-host/mpc105.c
 create mode 100644 hw/ppc/prep_systemio.c

-- 
1.7.10.4

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

* [Qemu-devel] [PATCH 1/7] pci: add MPC105 PCI host bridge emulation
  2013-05-02 20:08 [Qemu-devel] [PATCH 0/7] ppc/prep: add IBM RS/6000 43p machine Hervé Poussineau
@ 2013-05-02 20:08 ` Hervé Poussineau
  2013-05-02 21:01   ` [Qemu-devel] [Qemu-ppc] " Alexander Graf
  2013-05-02 20:08 ` [Qemu-devel] [PATCH 2/7] qom: handle registration of new types when initializing the first ones Hervé Poussineau
                   ` (5 subsequent siblings)
  6 siblings, 1 reply; 24+ messages in thread
From: Hervé Poussineau @ 2013-05-02 20:08 UTC (permalink / raw)
  To: qemu-devel; +Cc: Hervé Poussineau, qemu-ppc, Andreas Färber

Non-contiguous I/O is not implemented.

There is also somewhere a bug in the memory controller, which means
that some real firmwares may not detect the correct amount of memory.
This can be bypassed by adding '-m 1G' on the command line.

Add x-auto-conf property, to automatically configure the memory
controller at startup. This will be required by OpenBIOS, which
doesn't know how to do it.

Signed-off-by: Hervé Poussineau <hpoussin@reactos.org>
---
 default-configs/ppc-softmmu.mak |    1 +
 hw/pci-host/Makefile.objs       |    1 +
 hw/pci-host/mpc105.c            |  488 +++++++++++++++++++++++++++++++++++++++
 include/hw/pci/pci_ids.h        |    1 +
 trace-events                    |    7 +
 5 files changed, 498 insertions(+)
 create mode 100644 hw/pci-host/mpc105.c

diff --git a/default-configs/ppc-softmmu.mak b/default-configs/ppc-softmmu.mak
index cc3587f..f79b058 100644
--- a/default-configs/ppc-softmmu.mak
+++ b/default-configs/ppc-softmmu.mak
@@ -28,6 +28,7 @@ CONFIG_MAC_NVRAM=y
 CONFIG_MAC_DBDMA=y
 CONFIG_HEATHROW_PIC=y
 CONFIG_GRACKLE_PCI=y
+CONFIG_MPC105_PCI=y
 CONFIG_UNIN_PCI=y
 CONFIG_DEC_PCI=y
 CONFIG_PPCE500_PCI=y
diff --git a/hw/pci-host/Makefile.objs b/hw/pci-host/Makefile.objs
index 909e702..ec4427b 100644
--- a/hw/pci-host/Makefile.objs
+++ b/hw/pci-host/Makefile.objs
@@ -3,6 +3,7 @@ common-obj-y += pam.o
 # PPC devices
 common-obj-$(CONFIG_PREP_PCI) += prep.o
 common-obj-$(CONFIG_GRACKLE_PCI) += grackle.o
+common-obj-$(CONFIG_MPC105_PCI) += mpc105.o
 # NewWorld PowerMac
 common-obj-$(CONFIG_UNIN_PCI) += uninorth.o
 common-obj-$(CONFIG_DEC_PCI) += dec.o
diff --git a/hw/pci-host/mpc105.c b/hw/pci-host/mpc105.c
new file mode 100644
index 0000000..8e4cc95
--- /dev/null
+++ b/hw/pci-host/mpc105.c
@@ -0,0 +1,488 @@
+/*
+ * QEMU MPC-105 Eagle PCI host
+ *
+ * Copyright (c) 2013 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 "hw/pci/pci.h"
+#include "hw/pci/pci_bus.h"
+#include "hw/pci/pci_host.h"
+#include "hw/i386/pc.h"
+#include "hw/loader.h"
+#include "exec/address-spaces.h"
+#include "elf.h"
+#include "trace.h"
+
+#define TYPE_MPC105_PCI_HOST_BRIDGE "mpc105-pcihost"
+#define MPC105_PCI_HOST_BRIDGE(obj) \
+    OBJECT_CHECK(Mpc105HostState, (obj), TYPE_MPC105_PCI_HOST_BRIDGE)
+
+#define TYPE_MPC105 "mpc105"
+#define MPC105(obj) \
+    OBJECT_CHECK(Mpc105State, (obj), TYPE_MPC105)
+
+#define MEM_STA_03     0x0080
+#define MEM_STA_47     0x0084
+#define EXT_MEM_STA_03 0x0088
+#define EXT_MEM_STA_47 0x008c
+#define MEM_END_03     0x0090
+#define MEM_END_47     0x0094
+#define EXT_MEM_END_03 0x0098
+#define EXT_MEM_END_47 0x009c
+#define MEM_BANK_EN    0x00a0
+#define PROC_CFG_A8    0x00a8
+#define PROC_CFG_AC    0x00ac
+#define ALT_OSV_1      0x00ba
+#define ERR_EN_REG1    0x00c0
+#define ERR_DR1        0x00c1
+#define ERR_EN_REG2    0x00c4
+#define MEM_CFG_1      0x00f0
+#define MEM_CFG_2      0x00f4
+#define MEM_CFG_4      0x00fc
+
+#define MEM_CFG_1_MEMGO (1 << 19)
+
+#define BIOS_SIZE (1024 * 1024)
+
+typedef struct Mpc105State {
+    PCIDevice parent_obj;
+    uint32_t ram_size;
+    uint32_t elf_machine;
+    uint32_t x_auto_conf;
+    char *bios_name;
+    MemoryRegion bios;
+    MemoryRegion simm[8];
+    bool use_sizer[8];
+    /* use a sizer to allow access to only part of a simm */
+    MemoryRegion sizer[8];
+} Mpc105State;
+
+static uint64_t mpc105_unassigned_read(void *opaque, hwaddr addr,
+                                       unsigned int size)
+{
+    trace_mpc105_unassigned_mem_read(addr);
+    return 0;
+}
+
+static void mpc105_unassigned_write(void *opaque, hwaddr addr, uint64_t data,
+                                    unsigned int size)
+{
+    trace_mpc105_unassigned_mem_write(addr, data);
+}
+
+static const MemoryRegionOps mpc105_unassigned_ops = {
+    .read = mpc105_unassigned_read,
+    .write = mpc105_unassigned_write,
+};
+
+static void mpc105_update_memory_mappings(Mpc105State *s)
+{
+    uint32_t start_address, end_address;
+    uint32_t start, ext_start, end, ext_end;
+    uint32_t cfg1;
+    uint64_t simm_size;
+    uint8_t *pci_conf;
+    uint8_t en;
+    bool enabled;
+    int i;
+
+    pci_conf = PCI_DEVICE(s)->config;
+    cfg1 = pci_get_long(pci_conf + MEM_CFG_1);
+
+    memory_region_transaction_begin();
+    if (cfg1 & MEM_CFG_1_MEMGO) {
+        en = pci_get_byte(pci_conf + MEM_BANK_EN);
+    } else {
+        en = 0;
+    }
+
+    for (i = 0; i < 8; i++) {
+        enabled = (en & (1 << i));
+
+        start = pci_get_byte(pci_conf + MEM_STA_03 + i);
+        ext_start = pci_get_byte(pci_conf + EXT_MEM_STA_03 + i) & 0x3;
+        end = pci_get_byte(pci_conf + MEM_END_03 + i);
+        ext_end = pci_get_byte(pci_conf + EXT_MEM_STA_03 + i) & 0x3;
+        start_address = (ext_start << 28) | (start << 20);
+        end_address = (ext_end << 28) | (end << 20) | 0xfffff;
+
+        enabled &= start_address < end_address;
+
+        if (enabled) {
+            trace_mpc105_simm_enable(i, start_address, end_address + 1);
+        } else {
+            trace_mpc105_simm_disable(i);
+        }
+
+        simm_size = memory_region_size(&s->simm[i]);
+        if (simm_size == 0) {
+            continue;
+        }
+
+        /* Clean links between system memory, sizer and simm */
+        if (s->use_sizer[i]) {
+            memory_region_del_subregion(get_system_memory(), &s->sizer[i]);
+            memory_region_del_subregion(&s->sizer[i], &s->simm[i]);
+            s->use_sizer[i] = false;
+        } else {
+            memory_region_del_subregion(get_system_memory(), &s->simm[i]);
+        }
+
+        /* Recreate links compatible with new memory layout */
+        if (enabled && end_address - start_address + 1 < simm_size) {
+            memory_region_init_io(&s->sizer[i], &mpc105_unassigned_ops,
+                                  s, memory_region_name(&s->sizer[i]),
+                                  end_address - start_address + 1);
+            memory_region_add_subregion(&s->sizer[i], 0, &s->simm[i]);
+            memory_region_add_subregion(get_system_memory(), start_address,
+                                        &s->sizer[i]);
+            s->use_sizer[i] = true;
+        } else {
+            memory_region_add_subregion(get_system_memory(), start_address,
+                                        &s->simm[i]);
+        }
+        memory_region_set_enabled(&s->simm[i], enabled);
+    }
+    memory_region_transaction_commit();
+}
+
+static void mpc105_write_config(PCIDevice *dev, uint32_t addr, uint32_t val,
+                                int l)
+{
+    Mpc105State *s = MPC105(dev);
+
+    pci_default_write_config(dev, addr, val, l);
+    if ((addr >= MEM_STA_03 && addr <= MEM_BANK_EN) || addr == MEM_CFG_1) {
+        mpc105_update_memory_mappings(s);
+    }
+}
+
+static void mpc105_reset(Mpc105State *s)
+{
+    PCIDevice *pci = PCI_DEVICE(s);
+    uint8_t *pci_conf;
+    int id;
+
+    pci_conf = pci->config;
+
+    memset(pci_conf + PCI_CONFIG_HEADER_SIZE, 0,
+           PCI_CONFIG_SPACE_SIZE - PCI_CONFIG_HEADER_SIZE);
+    pci_conf[PCI_COMMAND] = PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY;
+    pci_conf[PCI_STATUS] = PCI_STATUS_FAST_BACK;
+    pci_set_long(pci_conf + PROC_CFG_A8, 0xff000010);
+    pci_set_long(pci_conf + PROC_CFG_AC, 0x000c060c);
+    pci_set_byte(pci_conf + ALT_OSV_1, 0x04);
+    pci_set_byte(pci_conf + ERR_EN_REG1, 0x01);
+    pci_set_long(pci_conf + MEM_CFG_1, 0xff020000);
+    pci_set_long(pci_conf + MEM_CFG_2, 0x00000003);
+    pci_set_long(pci_conf + MEM_CFG_4, 0x00100000);
+
+    memset(pci->wmask + PCI_CONFIG_HEADER_SIZE, 0,
+           MEM_CFG_1 - PCI_CONFIG_HEADER_SIZE);
+    memset(pci->wmask + 0x70, 0xff, 2);
+    memset(pci->wmask + MEM_STA_03, 0xff, MEM_BANK_EN - MEM_STA_03 + 1);
+    memset(pci->wmask + PROC_CFG_A8, 0xff, 8);
+    pci_set_word(pci->wmask + ALT_OSV_1, 0xffff);
+    pci_set_byte(pci->wmask + ERR_EN_REG1, 0xff);
+    pci_set_byte(pci->w1cmask + ERR_DR1, 0xff);
+    pci_set_byte(pci->w1cmask + 0xc3, 0xff);
+    pci_set_byte(pci->wmask + ERR_EN_REG2, 0xff);
+    pci_set_byte(pci->w1cmask + 0xc5, 0xff);
+    pci_set_byte(pci->w1cmask + 0xc7, 0xff);
+
+    for (id = 0; id < 8; ++id) {
+        memory_region_set_enabled(&s->simm[id], false);
+    }
+
+    if (s->x_auto_conf) {
+        /* enable all memory banks, starting from address 0 */
+        uint32_t start_address = 0, end_address = 0;
+        uint8_t ext_start, ext_end, enabled = 0;
+        int i;
+        for (i = 0; i < 8; i++) {
+            if (!memory_region_size(&s->simm[i])) {
+                continue;
+            }
+            end_address += memory_region_size(&s->simm[i]);
+            ext_start = pci_get_byte(pci_conf + EXT_MEM_STA_03 + i) & ~0x3;
+            ext_end = pci_get_byte(pci_conf + EXT_MEM_STA_03 + i) & ~0x3;
+            ext_start |= (start_address >> 28) & 0x3;
+            ext_end |= ((end_address - 1) >> 28) & 0x3;
+            pci_set_byte(pci_conf + MEM_STA_03 + i, start_address >> 20);
+            pci_set_byte(pci_conf + EXT_MEM_STA_03 + i, ext_start);
+            pci_set_byte(pci_conf + MEM_END_03 + i, (end_address - 1) >> 20);
+            pci_set_byte(pci_conf + EXT_MEM_END_03 + i, ext_end);
+            start_address = end_address;
+            enabled |= 1 << i;
+        }
+        pci_set_byte(pci_conf + MEM_BANK_EN, enabled);
+        pci_long_test_and_set_mask(pci_conf + MEM_CFG_1, MEM_CFG_1_MEMGO);
+        mpc105_update_memory_mappings(s);
+    }
+}
+
+static void qdev_mpc105_reset(DeviceState *dev)
+{
+    Mpc105State *s = MPC105(dev);
+    mpc105_reset(s);
+}
+
+static int mpc105_post_load(void *opaque, int version_id)
+{
+    Mpc105State *s = opaque;
+    mpc105_update_memory_mappings(s);
+    return 0;
+}
+
+static const VMStateDescription vmstate_mpc105 = {
+    .name = "mpc105",
+    .version_id = 1,
+    .minimum_version_id = 0,
+    .minimum_version_id_old = 1,
+    .post_load = mpc105_post_load,
+    .fields = (VMStateField[]) {
+        VMSTATE_PCI_DEVICE(parent_obj, Mpc105State),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static uint64_t mpc105_intack_read(void *opaque, hwaddr addr,
+                                   unsigned int size)
+{
+    return pic_read_irq(isa_pic);
+}
+
+static const MemoryRegionOps mpc105_intack_ops = {
+    .read = mpc105_intack_read,
+    .valid = {
+        .max_access_size = 1,
+    },
+};
+
+static int mpc105_initfn(PCIDevice *dev)
+{
+    Mpc105State *s = MPC105(dev);
+    char *filename;
+    int bios_size = -1;
+    int i = 0;
+    uint32_t simm_size[8] = { 0 };
+
+    unsigned int ram_size = s->ram_size / (1024 * 1024);
+    while (i < 8) {
+        int idx = qemu_fls(ram_size);
+        if (idx < 5) {
+            /* Need at least 16 Mb for a slot */
+            break;
+        } else if (idx >= 8) {
+            /* Limit to 128 Mb by slot (at max) */
+            idx = 8;
+        }
+        simm_size[i] = 1 << (idx - 1);
+        ram_size -= simm_size[i];
+        i++;
+    }
+
+    for (i = 0; i < 8; i++) {
+        char name[] = "simm.?";
+        name[5] = i + '0';
+        if (simm_size[i]) {
+            trace_mpc105_simm_size(i, simm_size[i]);
+            memory_region_init_ram(&s->simm[i], name,
+                                   simm_size[i] * 1024 * 1024);
+            vmstate_register_ram_global(&s->simm[i]);
+        } else {
+            memory_region_init(&s->simm[i], name, 0);
+        }
+        memory_region_init(&s->sizer[i], "sizer", 0);
+        memory_region_add_subregion_overlap(get_system_memory(), 0,
+                                            &s->simm[i], i);
+        memory_region_set_enabled(&s->simm[i], false);
+    }
+
+    memory_region_init_ram(&s->bios, "bios", BIOS_SIZE);
+    memory_region_set_readonly(&s->bios, true);
+    memory_region_add_subregion(get_system_memory(), (uint32_t)(-BIOS_SIZE),
+                                &s->bios);
+    vmstate_register_ram_global(&s->bios);
+    if (s->bios_name) {
+        filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, s->bios_name);
+        if (filename) {
+            if (s->elf_machine != EM_NONE) {
+                bios_size = load_elf(filename, NULL, NULL, NULL,
+                                     NULL, NULL, 1, s->elf_machine, 0);
+            }
+            if (bios_size < 0) {
+                bios_size = get_image_size(filename);
+                if (bios_size > 0 && bios_size <= BIOS_SIZE) {
+                    hwaddr bios_addr;
+                    bios_size = (bios_size + 0xfff) & ~0xfff;
+                    bios_addr = (uint32_t)(-BIOS_SIZE);
+                    bios_size = load_image_targphys(filename, bios_addr,
+                                                    bios_size);
+                }
+            }
+        }
+        if (bios_size < 0 || bios_size > BIOS_SIZE) {
+            hw_error("qemu: could not load bios image '%s'\n", s->bios_name);
+        }
+        if (filename) {
+            g_free(filename);
+        }
+    }
+
+    return 0;
+}
+
+static void mpc105_class_init(ObjectClass *klass, void *data)
+{
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
+    k->init = mpc105_initfn;
+    k->vendor_id = PCI_VENDOR_ID_MOTOROLA;
+    k->device_id = PCI_DEVICE_ID_MOTOROLA_MPC105;
+    k->class_id = PCI_CLASS_BRIDGE_HOST;
+    k->config_write = mpc105_write_config;
+    dc->desc = "MPC105 PCI bridge/Memory controller";
+    dc->reset = qdev_mpc105_reset;
+    dc->vmsd = &vmstate_mpc105;
+    dc->no_user = 1;
+}
+
+static TypeInfo mpc105_info = {
+    .name          = TYPE_MPC105,
+    .parent        = TYPE_PCI_DEVICE,
+    .instance_size = sizeof(Mpc105State),
+    .class_init    = mpc105_class_init,
+};
+
+typedef struct Mpc105HostState {
+    PCIHostState host_state;
+    uint32_t ram_size;
+    qemu_irq irq[PCI_NUM_PINS];
+    PCIBus pci_bus;
+    MemoryRegion pci_io;
+    MemoryRegion isa_io;
+    MemoryRegion pci_intack;
+    MemoryRegion pci_memory;
+    MemoryRegion rom;
+    Mpc105State pci_dev;
+} Mpc105HostState;
+
+static void mpc105_set_irq(void *opaque, int irq_num, int level)
+{
+    qemu_irq *pic = opaque;
+
+    qemu_set_irq(pic[irq_num] , level);
+}
+
+static int mpc105_map_irq(PCIDevice *pci_dev, int irq_num)
+{
+    return (irq_num + (pci_dev->devfn >> 3)) & 1;
+}
+
+static void mpc105_pcihost_realizefn(DeviceState *d, Error **errp)
+{
+    SysBusDevice *dev = SYS_BUS_DEVICE(d);
+    PCIHostState *h = PCI_HOST_BRIDGE(dev);
+    Mpc105HostState *s = MPC105_PCI_HOST_BRIDGE(dev);
+    int i;
+
+    for (i = 0; i < PCI_NUM_PINS; i++) {
+        sysbus_init_irq(dev, &s->irq[i]);
+    }
+
+    pci_bus_irqs(&s->pci_bus, mpc105_set_irq, mpc105_map_irq, s->irq, 4);
+
+    memory_region_init_io(&h->conf_mem, &pci_host_conf_le_ops, s,
+                          "pci-conf-idx", 1);
+    memory_region_add_subregion(get_system_io(), 0xcf8, &h->conf_mem);
+
+    memory_region_init_io(&h->data_mem, &pci_host_data_le_ops, s,
+                          "pci-conf-data", 4);
+    memory_region_add_subregion(get_system_io(), 0xcfc, &h->data_mem);
+
+    object_property_set_bool(OBJECT(&s->pci_dev), true, "realized", errp);
+}
+
+static void mpc105_pcihost_initfn(Object *obj)
+{
+    PCIHostState *h = PCI_HOST_BRIDGE(obj);
+    Mpc105HostState *s = MPC105_PCI_HOST_BRIDGE(obj);
+    DeviceState *pci_dev;
+
+    memory_region_init(&s->pci_io, "pci-io", 0x3f800000);
+    /* FIXME: should handle non-contiguous I/O */
+    isa_mmio_setup(&s->isa_io, 0x800000);
+    memory_region_init(&s->pci_memory, "pci-memory", 0x3f000000);
+    memory_region_init_io(&s->pci_intack, &mpc105_intack_ops, &s->pci_dev,
+                          "pci-intack", 0x10);
+
+    memory_region_init_io(get_system_memory(), &mpc105_unassigned_ops,
+                          &s->pci_dev, "system", UINT32_MAX);
+    memory_region_add_subregion(get_system_memory(), 0x80000000, &s->pci_io);
+    memory_region_add_subregion(&s->pci_io, 0, &s->isa_io);
+    memory_region_add_subregion(get_system_memory(), 0xc0000000,
+                                &s->pci_memory);
+    memory_region_add_subregion(get_system_memory(), 0xbffffff0,
+                                &s->pci_intack);
+
+    pci_bus_new_inplace(&s->pci_bus, DEVICE(obj), NULL,
+                        &s->pci_memory, get_system_io(), 0, TYPE_PCI_BUS);
+    h->bus = &s->pci_bus;
+
+    object_initialize(&s->pci_dev, TYPE_MPC105);
+    pci_dev = DEVICE(&s->pci_dev);
+    qdev_set_parent_bus(pci_dev, BUS(&s->pci_bus));
+    object_property_set_int(OBJECT(&s->pci_dev), PCI_DEVFN(0, 0), "addr",
+                            NULL);
+    qdev_prop_set_bit(pci_dev, "multifunction", false);
+}
+
+static Property mpc105_pcihost_properties[] = {
+    DEFINE_PROP_UINT32("ram-size", Mpc105HostState, pci_dev.ram_size, 0),
+    DEFINE_PROP_UINT32("elf-machine", Mpc105HostState, pci_dev.elf_machine,
+                       EM_NONE),
+    DEFINE_PROP_BIT("x-auto-conf", Mpc105HostState, pci_dev.x_auto_conf, 0,
+                    true),
+    DEFINE_PROP_STRING("bios-name", Mpc105HostState, pci_dev.bios_name),
+    DEFINE_PROP_END_OF_LIST()
+};
+
+static void mpc105_pcihost_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
+    dc->realize = mpc105_pcihost_realizefn;
+    dc->props = mpc105_pcihost_properties;
+    dc->no_user = 1;
+}
+
+static TypeInfo mpc105_pcihost_info = {
+    .name = TYPE_MPC105_PCI_HOST_BRIDGE,
+    .parent = TYPE_PCI_HOST_BRIDGE,
+    .instance_size = sizeof(Mpc105HostState),
+    .instance_init = mpc105_pcihost_initfn,
+    .class_init = mpc105_pcihost_class_init,
+};
+
+static void mpc105_register_types(void)
+{
+    type_register_static(&mpc105_pcihost_info);
+    type_register_static(&mpc105_info);
+}
+
+type_init(mpc105_register_types)
diff --git a/include/hw/pci/pci_ids.h b/include/hw/pci/pci_ids.h
index d8dc2f1..933b987 100644
--- a/include/hw/pci/pci_ids.h
+++ b/include/hw/pci/pci_ids.h
@@ -69,6 +69,7 @@
 #define PCI_VENDOR_ID_TI                 0x104c
 
 #define PCI_VENDOR_ID_MOTOROLA           0x1057
+#define PCI_DEVICE_ID_MOTOROLA_MPC105    0x0001
 #define PCI_DEVICE_ID_MOTOROLA_MPC106    0x0002
 #define PCI_DEVICE_ID_MOTOROLA_RAVEN     0x4801
 
diff --git a/trace-events b/trace-events
index 55e80be..1970b5c 100644
--- a/trace-events
+++ b/trace-events
@@ -766,6 +766,13 @@ pc87312_info_ide(uint32_t base) "base 0x%x"
 pc87312_info_parallel(uint32_t base, uint32_t irq) "base 0x%x, irq %u"
 pc87312_info_serial(int n, uint32_t base, uint32_t irq) "id=%d, base 0x%x, irq %u"
 
+# hw/pci-host/mpc105.c
+mpc105_unassigned_mem_read(uint64_t addr) "Unassigned mem read %" PRIx64
+mpc105_unassigned_mem_write(uint64_t addr, uint64_t val) "Unassigned mem write %" PRIx64 " = 0x%" PRIx64
+mpc105_simm_enable(int id, uint32_t start, uint32_t end) "SIMM #%d 0x%08x-0x%08x"
+mpc105_simm_disable(int id) "SIMM #%d disabled"
+mpc105_simm_size(int id, uint32_t size) "SIMM #%d is %u MB"
+
 # hw/scsi/vmw_pvscsi.c
 pvscsi_ring_init_data(uint32_t txr_len_log2, uint32_t rxr_len_log2) "TX/RX rings logarithms set to %d/%d"
 pvscsi_ring_init_msg(uint32_t len_log2) "MSG ring logarithm set to %d"
-- 
1.7.10.4

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

* [Qemu-devel] [PATCH 2/7] qom: handle registration of new types when initializing the first ones
  2013-05-02 20:08 [Qemu-devel] [PATCH 0/7] ppc/prep: add IBM RS/6000 43p machine Hervé Poussineau
  2013-05-02 20:08 ` [Qemu-devel] [PATCH 1/7] pci: add MPC105 PCI host bridge emulation Hervé Poussineau
@ 2013-05-02 20:08 ` Hervé Poussineau
  2013-05-03 11:46   ` Andreas Färber
  2013-05-02 20:09 ` [Qemu-devel] [PATCH 3/7] m48t59: move ISA ports/memory regions registration to QOM constructor Hervé Poussineau
                   ` (4 subsequent siblings)
  6 siblings, 1 reply; 24+ messages in thread
From: Hervé Poussineau @ 2013-05-02 20:08 UTC (permalink / raw)
  To: qemu-devel; +Cc: Hervé Poussineau, qemu-ppc, Andreas Färber

When initializing all types in object_class_foreach, called by object_class_get_list,
some new types may be registered. Those will change the type internal hashtable which
is currently enumerated, and may crash QEMU.

Fix it, by adding a second hash table which contains all the non-initialized types,
merged to the main one before each round of initializations.

Bug has been detected when registering dynamic types containing an interface.

Signed-off-by: Hervé Poussineau <hpoussin@reactos.org>
---
 qom/object.c |   45 +++++++++++++++++++++++++++++++++++++--------
 1 file changed, 37 insertions(+), 8 deletions(-)

diff --git a/qom/object.c b/qom/object.c
index 75e6aac..e0a24dc 100644
--- a/qom/object.c
+++ b/qom/object.c
@@ -65,25 +65,39 @@ struct TypeImpl
 
 static Type type_interface;
 
+static GHashTable *type_table_to_initialize;
+static GHashTable *type_table_initialized;
+
 static GHashTable *type_table_get(void)
 {
-    static GHashTable *type_table;
-
-    if (type_table == NULL) {
-        type_table = g_hash_table_new(g_str_hash, g_str_equal);
+    if (!type_table_initialized) {
+        type_table_initialized = g_hash_table_new(g_str_hash, g_str_equal);
     }
 
-    return type_table;
+    return type_table_initialized;
 }
 
 static void type_table_add(TypeImpl *ti)
 {
-    g_hash_table_insert(type_table_get(), (void *)ti->name, ti);
+    GHashTable **type_table;
+    if (ti->class) {
+        type_table = &type_table_initialized;
+    } else {
+        type_table = &type_table_to_initialize;
+    }
+    if (!*type_table) {
+        *type_table = g_hash_table_new(g_str_hash, g_str_equal);
+    }
+    g_hash_table_insert(*type_table, (void *)ti->name, ti);
 }
 
 static TypeImpl *type_table_lookup(const char *name)
 {
-    return g_hash_table_lookup(type_table_get(), name);
+    TypeImpl *ret = g_hash_table_lookup(type_table_get(), name);
+    if (!ret && type_table_to_initialize) {
+        ret = g_hash_table_lookup(type_table_to_initialize, name);
+    }
+    return ret;
 }
 
 static TypeImpl *type_register_internal(const TypeInfo *info)
@@ -573,13 +587,28 @@ static void object_class_foreach_tramp(gpointer key, gpointer value,
     data->fn(k, data->opaque);
 }
 
+static void object_class_merge(gpointer key, gpointer value,
+                               gpointer opaque)
+{
+    g_hash_table_insert(type_table_get(), key, value);
+}
+
 void object_class_foreach(void (*fn)(ObjectClass *klass, void *opaque),
                           const char *implements_type, bool include_abstract,
                           void *opaque)
 {
     OCFData data = { fn, implements_type, include_abstract, opaque };
 
-    g_hash_table_foreach(type_table_get(), object_class_foreach_tramp, &data);
+    while (type_table_to_initialize &&
+           g_hash_table_size(type_table_to_initialize) > 0) {
+        g_hash_table_foreach(type_table_to_initialize, object_class_merge,
+                             NULL);
+        g_hash_table_destroy(type_table_to_initialize);
+        type_table_to_initialize = NULL;
+
+        g_hash_table_foreach(type_table_get(), object_class_foreach_tramp,
+                             &data);
+    }
 }
 
 int object_child_foreach(Object *obj, int (*fn)(Object *child, void *opaque),
-- 
1.7.10.4

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

* [Qemu-devel] [PATCH 3/7] m48t59: move ISA ports/memory regions registration to QOM constructor
  2013-05-02 20:08 [Qemu-devel] [PATCH 0/7] ppc/prep: add IBM RS/6000 43p machine Hervé Poussineau
  2013-05-02 20:08 ` [Qemu-devel] [PATCH 1/7] pci: add MPC105 PCI host bridge emulation Hervé Poussineau
  2013-05-02 20:08 ` [Qemu-devel] [PATCH 2/7] qom: handle registration of new types when initializing the first ones Hervé Poussineau
@ 2013-05-02 20:09 ` Hervé Poussineau
  2013-05-02 20:09 ` [Qemu-devel] [PATCH 4/7] m48t59: register a QOM type for each nvram type we support Hervé Poussineau
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 24+ messages in thread
From: Hervé Poussineau @ 2013-05-02 20:09 UTC (permalink / raw)
  To: qemu-devel; +Cc: Hervé Poussineau, qemu-ppc, Andreas Färber

-device m48t59_isa can now be used to create a fully functional nvram.

Signed-off-by: Hervé Poussineau <hpoussin@reactos.org>
---
 hw/timer/m48t59.c |   15 ++++++++-------
 1 file changed, 8 insertions(+), 7 deletions(-)

diff --git a/hw/timer/m48t59.c b/hw/timer/m48t59.c
index 45753d8..fb78d20 100644
--- a/hw/timer/m48t59.c
+++ b/hw/timer/m48t59.c
@@ -655,9 +655,9 @@ M48t59State *m48t59_init(qemu_irq IRQ, hwaddr mem_base,
     d = FROM_SYSBUS(M48t59SysBusState, s);
     state = &d->state;
     sysbus_connect_irq(s, 0, IRQ);
-    memory_region_init_io(&d->io, &m48t59_io_ops, state, "m48t59", 4);
     if (io_base != 0) {
-        memory_region_add_subregion(get_system_io(), io_base, &d->io);
+        memory_region_add_subregion(get_system_io(), io_base,
+                                    sysbus_mmio_get_region(dev, 1));
     }
     if (mem_base != 0) {
         sysbus_mmio_map(s, 0, mem_base);
@@ -683,11 +683,6 @@ M48t59State *m48t59_init_isa(ISABus *bus, uint32_t io_base, uint16_t size,
     d = ISA_M48T59(isadev);
     s = &d->state;
 
-    memory_region_init_io(&d->io, &m48t59_io_ops, s, "m48t59", 4);
-    if (io_base != 0) {
-        isa_register_ioport(isadev, &d->io, io_base);
-    }
-
     return s;
 }
 
@@ -710,6 +705,10 @@ static int m48t59_init_isa1(ISADevice *dev)
 
     isa_init_irq(dev, &s->IRQ, 8);
     m48t59_init_common(s);
+    memory_region_init_io(&d->io, &m48t59_io_ops, s, "m48t59", 4);
+    if (s->io_base != 0) {
+        isa_register_ioport(dev, &d->io, s->io_base);
+    }
 
     return 0;
 }
@@ -723,6 +722,8 @@ static int m48t59_init1(SysBusDevice *dev)
 
     memory_region_init_io(&s->iomem, &nvram_ops, s, "m48t59.nvram", s->size);
     sysbus_init_mmio(dev, &s->iomem);
+    memory_region_init_io(&d->io, &m48t59_io_ops, s, "m48t59", 4);
+    sysbus_init_mmio(dev, &d->io);
     m48t59_init_common(s);
 
     return 0;
-- 
1.7.10.4

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

* [Qemu-devel] [PATCH 4/7] m48t59: register a QOM type for each nvram type we support
  2013-05-02 20:08 [Qemu-devel] [PATCH 0/7] ppc/prep: add IBM RS/6000 43p machine Hervé Poussineau
                   ` (2 preceding siblings ...)
  2013-05-02 20:09 ` [Qemu-devel] [PATCH 3/7] m48t59: move ISA ports/memory regions registration to QOM constructor Hervé Poussineau
@ 2013-05-02 20:09 ` Hervé Poussineau
  2013-05-02 21:29   ` Artyom Tarasenko
  2013-05-02 20:09 ` [Qemu-devel] [PATCH 5/7] m48t59: add a Nvram interface Hervé Poussineau
                   ` (2 subsequent siblings)
  6 siblings, 1 reply; 24+ messages in thread
From: Hervé Poussineau @ 2013-05-02 20:09 UTC (permalink / raw)
  To: qemu-devel; +Cc: Hervé Poussineau, qemu-ppc, Andreas Färber

As m48t59 devices can only be created with m48t59_init() or m48t59_init_isa(),
we know exactly which nvram types are required. Register only those three
types.
Remove .model and .size properties as they can be infered from nvram name.

Rename type to 'isa-*' (and 'sysbus-*') to do like other devices ISA devices
(isa-ide, isa-parallel, isa-serial...)

Signed-off-by: Hervé Poussineau <hpoussin@reactos.org>
---
 hw/timer/m48t59.c |  248 +++++++++++++++++++++++++++++++++++++----------------
 1 file changed, 172 insertions(+), 76 deletions(-)

diff --git a/hw/timer/m48t59.c b/hw/timer/m48t59.c
index fb78d20..23a6ab3 100644
--- a/hw/timer/m48t59.c
+++ b/hw/timer/m48t59.c
@@ -2,6 +2,7 @@
  * QEMU M48T59 and M48T08 NVRAM emulation for PPC PREP and Sparc platforms
  *
  * Copyright (c) 2003-2005, 2007 Jocelyn Mayer
+ * Copyright (c) 2013 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
@@ -37,12 +38,31 @@
 #define NVRAM_PRINTF(fmt, ...) do { } while (0)
 #endif
 
+#define TYPE_M48TXX_SYS_BUS "m48txx-sysbus"
+#define M48TXX_SYS_BUS_CLASS(klass) \
+    OBJECT_CLASS_CHECK(M48txxSysBusDeviceClass, (klass), TYPE_M48TXX_SYS_BUS)
+#define M48TXX_SYS_BUS(obj) \
+    OBJECT_CHECK(M48txxSysBusState, (obj), TYPE_M48TXX_SYS_BUS)
+
+#define TYPE_M48TXX_ISA "m48txx-isa"
+#define M48TXX_ISA_CLASS(klass) \
+    OBJECT_CLASS_CHECK(M48txxISADeviceClass, (klass), TYPE_M48TXX_ISA)
+#define M48TXX_ISA(obj) \
+    OBJECT_CHECK(M48txxISAState, (obj), TYPE_M48TXX_ISA)
+
 /*
  * The M48T02, M48T08 and M48T59 chips are very similar. The newer '59 has
  * alarm and a watchdog timer and related control registers. In the
  * PPC platform there is also a nvram lock function.
  */
 
+typedef struct M48txxInfo {
+    const char *isa_name;
+    const char *sysbus_name;
+    uint32_t model; /* 2 = m48t02, 8 = m48t08, 59 = m48t59 */
+    uint32_t size;
+} M48txxInfo;
+
 /*
  * Chipset docs:
  * http://www.st.com/stonline/products/literature/ds/2410/m48t02.pdf
@@ -54,7 +74,6 @@ struct M48t59State {
     /* Hardware parameters */
     qemu_irq IRQ;
     MemoryRegion iomem;
-    uint32_t io_base;
     uint32_t size;
     /* RTC management */
     time_t   time_offset;
@@ -72,22 +91,45 @@ struct M48t59State {
     uint8_t  lock;
 };
 
-#define TYPE_ISA_M48T59 "m48t59_isa"
-#define ISA_M48T59(obj) \
-    OBJECT_CHECK(M48t59ISAState, (obj), TYPE_ISA_M48T59)
-
-typedef struct M48t59ISAState {
+typedef struct M48txxISAState {
     ISADevice parent_obj;
-
     M48t59State state;
+    uint32_t io_base;
     MemoryRegion io;
-} M48t59ISAState;
+} M48txxISAState;
+
+typedef struct M48txxISADeviceClass {
+    ISADeviceClass parent_class;
+    M48txxInfo info;
+} M48txxISADeviceClass;
 
-typedef struct M48t59SysBusState {
-    SysBusDevice busdev;
+typedef struct M48txxSysBusState {
+    SysBusDevice parent_obj;
     M48t59State state;
     MemoryRegion io;
-} M48t59SysBusState;
+} M48txxSysBusState;
+
+typedef struct M48txxSysBusDeviceClass {
+    SysBusDeviceClass parent_class;
+    M48txxInfo info;
+} M48txxSysBusDeviceClass;
+
+static M48txxInfo m48txx_info[] = {
+    {
+        .sysbus_name = "sysbus-m48t02",
+        .model = 2,
+        .size = 0x800,
+    },{
+        .sysbus_name = "sysbus-m48t08",
+        .model = 8,
+        .size = 0x2000,
+    },{
+        .isa_name = "isa-m48t59",
+        .model = 59,
+        .size = 0x2000,
+    }
+};
+
 
 /* Fake timer functions */
 
@@ -613,7 +655,7 @@ static void m48t59_reset_common(M48t59State *NVRAM)
 
 static void m48t59_reset_isa(DeviceState *d)
 {
-    M48t59ISAState *isa = ISA_M48T59(d);
+    M48txxISAState *isa = M48TXX_ISA(d);
     M48t59State *NVRAM = &isa->state;
 
     m48t59_reset_common(NVRAM);
@@ -621,7 +663,7 @@ static void m48t59_reset_isa(DeviceState *d)
 
 static void m48t59_reset_sysbus(DeviceState *d)
 {
-    M48t59SysBusState *sys = container_of(d, M48t59SysBusState, busdev.qdev);
+    M48txxSysBusState *sys = M48TXX_SYS_BUS(d);
     M48t59State *NVRAM = &sys->state;
 
     m48t59_reset_common(NVRAM);
@@ -643,47 +685,62 @@ M48t59State *m48t59_init(qemu_irq IRQ, hwaddr mem_base,
 {
     DeviceState *dev;
     SysBusDevice *s;
-    M48t59SysBusState *d;
+    M48txxSysBusState *d;
     M48t59State *state;
+    int i;
 
-    dev = qdev_create(NULL, "m48t59");
-    qdev_prop_set_uint32(dev, "model", model);
-    qdev_prop_set_uint32(dev, "size", size);
-    qdev_prop_set_uint32(dev, "io_base", io_base);
-    qdev_init_nofail(dev);
-    s = SYS_BUS_DEVICE(dev);
-    d = FROM_SYSBUS(M48t59SysBusState, s);
-    state = &d->state;
-    sysbus_connect_irq(s, 0, IRQ);
-    if (io_base != 0) {
-        memory_region_add_subregion(get_system_io(), io_base,
-                                    sysbus_mmio_get_region(dev, 1));
-    }
-    if (mem_base != 0) {
-        sysbus_mmio_map(s, 0, mem_base);
+    for (i = 0; i < ARRAY_SIZE(m48txx_info); i++) {
+        if (!m48txx_info[i].sysbus_name ||
+            m48txx_info[i].size != size ||
+            m48txx_info[i].model != model) {
+            continue;
+        }
+
+        dev = qdev_create(NULL, m48txx_info[i].sysbus_name);
+        qdev_init_nofail(dev);
+        s = SYS_BUS_DEVICE(dev);
+        d = M48TXX_SYS_BUS(s);
+        state = &d->state;
+        sysbus_connect_irq(s, 0, IRQ);
+        memory_region_init_io(&d->io, &m48t59_io_ops, state, "m48t59", 4);
+        if (io_base != 0) {
+            memory_region_add_subregion(get_system_io(), io_base,
+                                        sysbus_mmio_get_region(s, 1));
+        }
+        if (mem_base != 0) {
+            sysbus_mmio_map(s, 0, mem_base);
+        }
+
+        return state;
     }
 
-    return state;
+    assert(false);
+    return NULL;
 }
 
 M48t59State *m48t59_init_isa(ISABus *bus, uint32_t io_base, uint16_t size,
                              int model)
 {
-    M48t59ISAState *d;
-    ISADevice *isadev;
+    M48txxISAState *d;
     DeviceState *dev;
-    M48t59State *s;
-
-    isadev = isa_create(bus, TYPE_ISA_M48T59);
-    dev = DEVICE(isadev);
-    qdev_prop_set_uint32(dev, "model", model);
-    qdev_prop_set_uint32(dev, "size", size);
-    qdev_prop_set_uint32(dev, "io_base", io_base);
-    qdev_init_nofail(dev);
-    d = ISA_M48T59(isadev);
-    s = &d->state;
-
-    return s;
+    int i;
+
+    for (i = 0; i < ARRAY_SIZE(m48txx_info); i++) {
+        if (!m48txx_info[i].isa_name ||
+            m48txx_info[i].size != size ||
+            m48txx_info[i].model != model) {
+            continue;
+        }
+
+        dev = DEVICE(isa_create(bus, m48txx_info[i].isa_name));
+        qdev_prop_set_uint32(dev, "iobase", io_base);
+        qdev_init_nofail(dev);
+        d = container_of(ISA_DEVICE(dev), M48txxISAState, parent_obj);
+        return &d->state;
+    }
+
+    assert(false);
+    return NULL;
 }
 
 static void m48t59_init_common(M48t59State *s)
@@ -700,14 +757,19 @@ static void m48t59_init_common(M48t59State *s)
 
 static int m48t59_init_isa1(ISADevice *dev)
 {
-    M48t59ISAState *d = ISA_M48T59(dev);
+    ISADeviceClass *ic = ISA_DEVICE_GET_CLASS(dev);
+    M48txxISADeviceClass *u = container_of(ic, M48txxISADeviceClass,
+                                           parent_class);
+    M48txxISAState *d = container_of(dev, M48txxISAState, parent_obj);
     M48t59State *s = &d->state;
 
+    s->model = u->info.model;
+    s->size = u->info.size;
     isa_init_irq(dev, &s->IRQ, 8);
     m48t59_init_common(s);
     memory_region_init_io(&d->io, &m48t59_io_ops, s, "m48t59", 4);
-    if (s->io_base != 0) {
-        isa_register_ioport(dev, &d->io, s->io_base);
+    if (d->io_base != 0) {
+        isa_register_ioport(dev, &d->io, d->io_base);
     }
 
     return 0;
@@ -715,9 +777,14 @@ static int m48t59_init_isa1(ISADevice *dev)
 
 static int m48t59_init1(SysBusDevice *dev)
 {
-    M48t59SysBusState *d = FROM_SYSBUS(M48t59SysBusState, dev);
+    SysBusDeviceClass *k = SYS_BUS_DEVICE_GET_CLASS(dev);
+    M48txxSysBusDeviceClass *u = container_of(k, M48txxSysBusDeviceClass,
+                                              parent_class);
+    M48txxSysBusState *d = container_of(dev, M48txxSysBusState, parent_obj);
     M48t59State *s = &d->state;
 
+    s->model = u->info.model;
+    s->size = u->info.size;
     sysbus_init_irq(dev, &s->IRQ);
 
     memory_region_init_io(&s->iomem, &nvram_ops, s, "m48t59.nvram", s->size);
@@ -730,57 +797,86 @@ static int m48t59_init1(SysBusDevice *dev)
 }
 
 static Property m48t59_isa_properties[] = {
-    DEFINE_PROP_UINT32("size",    M48t59ISAState, state.size,    -1),
-    DEFINE_PROP_UINT32("model",   M48t59ISAState, state.model,   -1),
-    DEFINE_PROP_HEX32( "io_base", M48t59ISAState, state.io_base,  0),
+    DEFINE_PROP_HEX32("iobase", M48txxISAState, io_base, 0x74),
     DEFINE_PROP_END_OF_LIST(),
 };
 
-static void m48t59_isa_class_init(ObjectClass *klass, void *data)
+static void m48txx_isa_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
     ISADeviceClass *ic = ISA_DEVICE_CLASS(klass);
+    M48txxISADeviceClass *u = M48TXX_ISA_CLASS(klass);
+    M48txxInfo *info = data;
+
     ic->init = m48t59_init_isa1;
     dc->no_user = 1;
     dc->reset = m48t59_reset_isa;
-    dc->props = m48t59_isa_properties;
+    if (info) {
+        dc->props = m48t59_isa_properties;
+        u->info = *info;
+    }
 }
 
-static const TypeInfo m48t59_isa_info = {
-    .name          = TYPE_ISA_M48T59,
-    .parent        = TYPE_ISA_DEVICE,
-    .instance_size = sizeof(M48t59ISAState),
-    .class_init    = m48t59_isa_class_init,
-};
-
-static Property m48t59_properties[] = {
-    DEFINE_PROP_UINT32("size",    M48t59SysBusState, state.size,    -1),
-    DEFINE_PROP_UINT32("model",   M48t59SysBusState, state.model,   -1),
-    DEFINE_PROP_HEX32( "io_base", M48t59SysBusState, state.io_base,  0),
-    DEFINE_PROP_END_OF_LIST(),
-};
-
-static void m48t59_class_init(ObjectClass *klass, void *data)
+static void m48txx_sysbus_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
     SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+    M48txxSysBusDeviceClass *u = M48TXX_SYS_BUS_CLASS(klass);
+    M48txxInfo *info = data;
 
     k->init = m48t59_init1;
     dc->reset = m48t59_reset_sysbus;
-    dc->props = m48t59_properties;
+    if (info) {
+        u->info = *info;
+    }
 }
 
-static const TypeInfo m48t59_info = {
-    .name          = "m48t59",
-    .parent        = TYPE_SYS_BUS_DEVICE,
-    .instance_size = sizeof(M48t59SysBusState),
-    .class_init    = m48t59_class_init,
+static const TypeInfo m48txx_sysbus_type_info = {
+    .name = TYPE_M48TXX_SYS_BUS,
+    .parent = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(M48txxSysBusState),
+    .abstract = true,
+    .class_init = m48txx_sysbus_class_init,
+};
+
+static const TypeInfo m48txx_isa_type_info = {
+    .name = TYPE_M48TXX_ISA,
+    .parent = TYPE_ISA_DEVICE,
+    .instance_size = sizeof(M48txxISAState),
+    .abstract = true,
+    .class_init = m48txx_isa_class_init,
 };
 
 static void m48t59_register_types(void)
 {
-    type_register_static(&m48t59_info);
-    type_register_static(&m48t59_isa_info);
+    TypeInfo sysbus_type_info = {
+        .parent = TYPE_M48TXX_SYS_BUS,
+        .class_size = sizeof(M48txxSysBusDeviceClass),
+        .class_init = m48txx_sysbus_class_init,
+    };
+    TypeInfo isa_type_info = {
+        .parent = TYPE_M48TXX_ISA,
+        .class_size = sizeof(M48txxISADeviceClass),
+        .class_init = m48txx_isa_class_init,
+    };
+    int i;
+
+    type_register_static(&m48txx_sysbus_type_info);
+    type_register_static(&m48txx_isa_type_info);
+
+    for (i = 0; i < ARRAY_SIZE(m48txx_info); i++) {
+        if (m48txx_info[i].sysbus_name) {
+            sysbus_type_info.name = m48txx_info[i].sysbus_name;
+            sysbus_type_info.class_data = &m48txx_info[i];
+            type_register(&sysbus_type_info);
+        }
+
+        if (m48txx_info[i].isa_name) {
+            isa_type_info.name = m48txx_info[i].isa_name;
+            isa_type_info.class_data = &m48txx_info[i];
+            type_register(&isa_type_info);
+        }
+    }
 }
 
 type_init(m48t59_register_types)
-- 
1.7.10.4

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

* [Qemu-devel] [PATCH 5/7] m48t59: add a Nvram interface
  2013-05-02 20:08 [Qemu-devel] [PATCH 0/7] ppc/prep: add IBM RS/6000 43p machine Hervé Poussineau
                   ` (3 preceding siblings ...)
  2013-05-02 20:09 ` [Qemu-devel] [PATCH 4/7] m48t59: register a QOM type for each nvram type we support Hervé Poussineau
@ 2013-05-02 20:09 ` Hervé Poussineau
  2013-05-02 20:09 ` [Qemu-devel] [PATCH 6/7] prep: add IBM RS/6000 7248 (43p) machine emulation Hervé Poussineau
  2013-05-02 20:09 ` [Qemu-devel] [PATCH 7/7] prep: QOM'ify System I/O Hervé Poussineau
  6 siblings, 0 replies; 24+ messages in thread
From: Hervé Poussineau @ 2013-05-02 20:09 UTC (permalink / raw)
  To: qemu-devel; +Cc: Hervé Poussineau, qemu-ppc, Andreas Färber

Signed-off-by: Hervé Poussineau <hpoussin@reactos.org>
---
 hw/timer/m48t59.c         |   61 +++++++++++++++++++++++++++++++++++++++++++++
 include/hw/timer/m48t59.h |   24 ++++++++++++++++++
 2 files changed, 85 insertions(+)

diff --git a/hw/timer/m48t59.c b/hw/timer/m48t59.c
index 23a6ab3..3ecb14e 100644
--- a/hw/timer/m48t59.c
+++ b/hw/timer/m48t59.c
@@ -796,6 +796,24 @@ static int m48t59_init1(SysBusDevice *dev)
     return 0;
 }
 
+static uint32_t m48txx_isa_read(Nvram *obj, uint32_t addr)
+{
+    M48txxISAState *d = M48TXX_ISA(obj);
+    return m48t59_read(&d->state, addr);
+}
+
+static void m48txx_isa_write(Nvram *obj, uint32_t addr, uint32_t val)
+{
+    M48txxISAState *d = M48TXX_ISA(obj);
+    m48t59_write(&d->state, addr, val);
+}
+
+static void m48txx_isa_toggle_lock(Nvram *obj, int lock)
+{
+    M48txxISAState *d = M48TXX_ISA(obj);
+    m48t59_toggle_lock(&d->state, lock);
+}
+
 static Property m48t59_isa_properties[] = {
     DEFINE_PROP_HEX32("iobase", M48txxISAState, io_base, 0x74),
     DEFINE_PROP_END_OF_LIST(),
@@ -805,6 +823,7 @@ static void m48txx_isa_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
     ISADeviceClass *ic = ISA_DEVICE_CLASS(klass);
+    NvramClass *nc = NVRAM_CLASS(klass);
     M48txxISADeviceClass *u = M48TXX_ISA_CLASS(klass);
     M48txxInfo *info = data;
 
@@ -814,13 +833,36 @@ static void m48txx_isa_class_init(ObjectClass *klass, void *data)
     if (info) {
         dc->props = m48t59_isa_properties;
         u->info = *info;
+    } else {
+        nc->read = m48txx_isa_read;
+        nc->write = m48txx_isa_write;
+        nc->toggle_lock = m48txx_isa_toggle_lock;
     }
 }
 
+static uint32_t m48txx_sysbus_read(Nvram *obj, uint32_t addr)
+{
+    M48txxSysBusState *d = M48TXX_SYS_BUS(obj);
+    return m48t59_read(&d->state, addr);
+}
+
+static void m48txx_sysbus_write(Nvram *obj, uint32_t addr, uint32_t val)
+{
+    M48txxSysBusState *d = M48TXX_SYS_BUS(obj);
+    m48t59_write(&d->state, addr, val);
+}
+
+static void m48txx_sysbus_toggle_lock(Nvram *obj, int lock)
+{
+    M48txxSysBusState *d = M48TXX_SYS_BUS(obj);
+    m48t59_toggle_lock(&d->state, lock);
+}
+
 static void m48txx_sysbus_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
     SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+    NvramClass *nc = NVRAM_CLASS(klass);
     M48txxSysBusDeviceClass *u = M48TXX_SYS_BUS_CLASS(klass);
     M48txxInfo *info = data;
 
@@ -828,15 +870,29 @@ static void m48txx_sysbus_class_init(ObjectClass *klass, void *data)
     dc->reset = m48t59_reset_sysbus;
     if (info) {
         u->info = *info;
+    } else {
+        nc->read = m48txx_sysbus_read;
+        nc->write = m48txx_sysbus_write;
+        nc->toggle_lock = m48txx_sysbus_toggle_lock;
     }
 }
 
+static const TypeInfo nvram_info = {
+    .name = TYPE_NVRAM,
+    .parent = TYPE_INTERFACE,
+    .class_size = sizeof(NvramClass),
+};
+
 static const TypeInfo m48txx_sysbus_type_info = {
     .name = TYPE_M48TXX_SYS_BUS,
     .parent = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(M48txxSysBusState),
     .abstract = true,
     .class_init = m48txx_sysbus_class_init,
+    .interfaces = (InterfaceInfo[]) {
+        { TYPE_NVRAM },
+        { }
+    }
 };
 
 static const TypeInfo m48txx_isa_type_info = {
@@ -845,6 +901,10 @@ static const TypeInfo m48txx_isa_type_info = {
     .instance_size = sizeof(M48txxISAState),
     .abstract = true,
     .class_init = m48txx_isa_class_init,
+    .interfaces = (InterfaceInfo[]) {
+        { TYPE_NVRAM },
+        { }
+    }
 };
 
 static void m48t59_register_types(void)
@@ -861,6 +921,7 @@ static void m48t59_register_types(void)
     };
     int i;
 
+    type_register_static(&nvram_info);
     type_register_static(&m48txx_sysbus_type_info);
     type_register_static(&m48txx_isa_type_info);
 
diff --git a/include/hw/timer/m48t59.h b/include/hw/timer/m48t59.h
index 59337fa..72b7ac1 100644
--- a/include/hw/timer/m48t59.h
+++ b/include/hw/timer/m48t59.h
@@ -1,6 +1,9 @@
 #ifndef NVRAM_H
 #define NVRAM_H
 
+#include "qemu-common.h"
+#include "qom/object.h"
+
 /* NVRAM helpers */
 typedef uint32_t (*nvram_read_t)(void *private, uint32_t addr);
 typedef void (*nvram_write_t)(void *private, uint32_t addr, uint32_t val);
@@ -31,4 +34,25 @@ M48t59State *m48t59_init_isa(ISABus *bus, uint32_t io_base, uint16_t size,
 M48t59State *m48t59_init(qemu_irq IRQ, hwaddr mem_base,
                          uint32_t io_base, uint16_t size, int type);
 
+#define TYPE_NVRAM "nvram"
+
+#define NVRAM_CLASS(klass) \
+    OBJECT_CLASS_CHECK(NvramClass, (klass), TYPE_NVRAM)
+#define NVRAM_GET_CLASS(obj) \
+    OBJECT_GET_CLASS(NvramClass, (obj), TYPE_NVRAM)
+#define NVRAM(obj) \
+    INTERFACE_CHECK(Nvram, (obj), TYPE_NVRAM)
+
+typedef struct Nvram {
+    Object parent;
+} Nvram;
+
+typedef struct NvramClass {
+    InterfaceClass parent;
+
+    uint32_t (*read)(Nvram *obj, uint32_t addr);
+    void (*write)(Nvram *obj, uint32_t addr, uint32_t val);
+    void (*toggle_lock)(Nvram *obj, int lock);
+} NvramClass;
+
 #endif /* !NVRAM_H */
-- 
1.7.10.4

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

* [Qemu-devel] [PATCH 6/7] prep: add IBM RS/6000 7248 (43p) machine emulation
  2013-05-02 20:08 [Qemu-devel] [PATCH 0/7] ppc/prep: add IBM RS/6000 43p machine Hervé Poussineau
                   ` (4 preceding siblings ...)
  2013-05-02 20:09 ` [Qemu-devel] [PATCH 5/7] m48t59: add a Nvram interface Hervé Poussineau
@ 2013-05-02 20:09 ` Hervé Poussineau
  2013-05-02 20:09 ` [Qemu-devel] [PATCH 7/7] prep: QOM'ify System I/O Hervé Poussineau
  6 siblings, 0 replies; 24+ messages in thread
From: Hervé Poussineau @ 2013-05-02 20:09 UTC (permalink / raw)
  To: qemu-devel; +Cc: Hervé Poussineau, qemu-ppc, Andreas Färber

Machine is very simple (only one PCI host bridge and an ISA bridge).
Provide a ibm_43p.cfg file to add more devices to this machine.

Syntax is:
qemu-system-ppc -M 43p -readconfig ibm_43p.cfg

Signed-off-by: Hervé Poussineau <hpoussin@reactos.org>
---
 docs/ibm_43p.cfg |   38 ++++++++++
 hw/ppc/prep.c    |  213 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 251 insertions(+)
 create mode 100644 docs/ibm_43p.cfg

diff --git a/docs/ibm_43p.cfg b/docs/ibm_43p.cfg
new file mode 100644
index 0000000..70bbfdb
--- /dev/null
+++ b/docs/ibm_43p.cfg
@@ -0,0 +1,38 @@
+############################################################################
+#
+# qemu-system-ppc -M 43p creates a bare machine with just the very essential
+# chipset devices being present:
+#
+#     00.0 - Host bridge
+#     0b.0 - ISA bridge
+#
+# This config file documents the other devices and how they are
+# created.  You can simply use "-readconfig $thisfile" to create
+# them all.
+
+[device]
+  driver = "i8042"
+
+[device]
+  driver = "pc87312"
+  config = "12"
+
+[device]
+  driver = "pcnet"
+  addr = "12.0"
+
+[device]
+  driver = "isa-m48t59"
+  iobase = "0x74"
+
+[device]
+  driver = "isa-ide"
+  iobase = "0x1f0"
+  iobase2 = "0x3f6"
+  irq = "14"
+
+[device]
+  driver = "isa-ide"
+  iobase = "0x170"
+  iobase2 = "0x376"
+  irq = "15"
diff --git a/hw/ppc/prep.c b/hw/ppc/prep.c
index 59c7da3..f307d41 100644
--- a/hw/ppc/prep.c
+++ b/hw/ppc/prep.c
@@ -30,6 +30,7 @@
 #include "sysemu/sysemu.h"
 #include "hw/isa/isa.h"
 #include "hw/pci/pci.h"
+#include "hw/pci/pci_bus.h"
 #include "hw/pci/pci_host.h"
 #include "hw/ppc/ppc.h"
 #include "hw/boards.h"
@@ -41,6 +42,9 @@
 #include "sysemu/blockdev.h"
 #include "sysemu/arch_init.h"
 #include "exec/address-spaces.h"
+#include "elf.h"
+#include "hw/nvram/fw_cfg.h"
+#include "hw/sparc/firmware_abi.h"
 
 //#define HARD_DEBUG_PPC_IO
 //#define DEBUG_PPC_IO
@@ -50,6 +54,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
@@ -413,6 +419,61 @@ static const MemoryRegionOps PPC_prep_io_ops = {
 
 #define NVRAM_SIZE        0x2000
 
+static int fw_cfg_boot_set(void *opaque, const char *boot_device)
+{
+    fw_cfg_add_i16(opaque, FW_CFG_BOOT_DEVICE, boot_device[0]);
+    return 0;
+}
+
+#define DEF_SYSTEM_SIZE 0xc10
+
+static void nvram_init(NvramClass *k, Nvram *nvram)
+{
+    uint8_t image[NVRAM_SIZE];
+    struct OpenBIOS_nvpart_v1 *part_header;
+    uint32_t start, end;
+    unsigned int i;
+
+    memset(image, '\0', sizeof(image));
+
+    start = 0;
+
+    /* OpenBIOS nvram variables */
+    /* Variable partition */
+    part_header = (struct OpenBIOS_nvpart_v1 *)&image[start];
+    part_header->signature = OPENBIOS_PART_SYSTEM;
+    pstrcpy(part_header->name, sizeof(part_header->name), "system");
+
+    end = start + sizeof(struct OpenBIOS_nvpart_v1);
+    for (i = 0; i < nb_prom_envs; i++) {
+        end = OpenBIOS_set_var(image, end, prom_envs[i]);
+    }
+
+    /* End marker */
+    image[end++] = '\0';
+
+    end = start + ((end - start + 15) & ~15);
+    /* XXX: OpenBIOS is not able to grow up a partition. Leave some space for
+       new variables. */
+    if (end < DEF_SYSTEM_SIZE) {
+        end = DEF_SYSTEM_SIZE;
+    }
+    OpenBIOS_finish_partition(part_header, end - start);
+
+    /* free partition */
+    start = end;
+    part_header = (struct OpenBIOS_nvpart_v1 *)&image[start];
+    part_header->signature = OPENBIOS_PART_FREE;
+    pstrcpy(part_header->name, sizeof(part_header->name), "free");
+
+    end = NVRAM_SIZE;
+    OpenBIOS_finish_partition(part_header, end - start);
+
+    for (i = 0; i < sizeof(image); i++) {
+        k->write(nvram, i, image[i]);
+    }
+}
+
 static void cpu_request_exit(void *opaque, int irq, int level)
 {
     CPUPPCState *env = cpu_single_env;
@@ -660,6 +721,150 @@ static void ppc_prep_init(QEMUMachineInitArgs *args)
     register_ioport_write(0x0F00, 4, 1, &PPC_debug_write, NULL);
 }
 
+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 int prep_init_m48t59(DeviceState *dev, void *opaque)
+{
+    if (object_dynamic_cast(OBJECT(dev), TYPE_NVRAM)) {
+        /* if nvram is initialized, we expect first word to be not null */
+        Nvram *nvram = NVRAM(dev);
+        NvramClass *k = NVRAM_GET_CLASS(dev);
+        if (k->read(nvram, 0) == 0 && k->read(nvram, 1) == 0) {
+            nvram_init(k, nvram);
+        }
+    }
+    return 0;
+}
+
+static void ppc_prep_init_m48t59(void *opaque)
+{
+    BusState *bus = opaque;
+    qbus_walk_children(bus, prep_init_m48t59, NULL, NULL);
+}
+
+static void ibm_43p_init(QEMUMachineInitArgs *args)
+{
+    CPUPPCState *env = NULL;
+    uint16_t cmos_checksum;
+    PowerPCCPU *cpu;
+    DeviceState *dev;
+    SysBusDevice *pcihost;
+    PCIBus *pci_bus;
+    ISABus *isa_bus;
+    qemu_irq *cpu_exit_irq;
+    void *fw_cfg;
+
+    /* init CPU */
+    if (!args->cpu_model) {
+        args->cpu_model = "604";
+    }
+    cpu = cpu_ppc_init(args->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 */
+    pcihost = SYS_BUS_DEVICE(qdev_create(NULL, "mpc105-pcihost"));
+    qdev_prop_set_uint32(DEVICE(pcihost), "ram-size", (uint32_t)args->ram_size);
+    qdev_prop_set_uint32(DEVICE(pcihost), "elf-machine", ELF_MACHINE);
+    qdev_prop_set_bit(DEVICE(pcihost), "x-auto-conf", 1);
+    if (bios_name == NULL) {
+        bios_name = "openbios-ppc.elf";
+    }
+    qdev_prop_set_string(DEVICE(pcihost), "bios-name", bios_name);
+    object_property_add_child(qdev_get_machine(), "eagle", OBJECT(pcihost),
+                              NULL);
+    qdev_init_nofail(DEVICE(pcihost));
+    pci_bus = PCI_BUS(qdev_get_child_bus(DEVICE(pcihost), "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"));
+    cpu_exit_irq = qemu_allocate_irqs(cpu_request_exit, NULL, 1);
+    qdev_connect_gpio_out(dev, 0,
+                          first_cpu->irq_inputs[PPC6xx_INPUT_INT]);
+    qdev_connect_gpio_out(dev, 1, *cpu_exit_irq);
+    sysbus_connect_irq(pcihost, 0, qdev_get_gpio_in(dev, 9));
+    sysbus_connect_irq(pcihost, 1, qdev_get_gpio_in(dev, 11));
+    sysbus_connect_irq(pcihost, 2, qdev_get_gpio_in(dev, 9));
+    sysbus_connect_irq(pcihost, 3, qdev_get_gpio_in(dev, 11));
+    isa_bus = ISA_BUS(qdev_get_child_bus(dev, "isa.0"));
+
+    /* initialize CMOS checksums */
+    cmos_checksum = 0x6aa9;
+    qbus_walk_children(BUS(isa_bus), prep_set_cmos_checksum, NULL,
+                       &cmos_checksum);
+
+    /* initialize audio subsystem */
+    audio_init();
+
+    /* Initialize NVRAM (if empty) at next reboot */
+    qemu_register_reset(ppc_prep_init_m48t59, BUS(isa_bus));
+
+    /* Prepare firmware configuration for OpenBIOS */
+    fw_cfg = fw_cfg_init(0, 0, CFG_ADDR, CFG_ADDR + 2);
+    fw_cfg_add_i16(fw_cfg, FW_CFG_MAX_CPUS, (uint16_t)max_cpus);
+    fw_cfg_add_i32(fw_cfg, FW_CFG_ID, 1);
+    fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, (uint64_t)args->ram_size);
+    fw_cfg_add_i16(fw_cfg, FW_CFG_MACHINE_ID, ARCH_PREP);
+    fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_ADDR, 0);
+    fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_SIZE, 0);
+    fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_CMDLINE, 0);
+    fw_cfg_add_i32(fw_cfg, FW_CFG_INITRD_ADDR, 0);
+    fw_cfg_add_i32(fw_cfg, FW_CFG_INITRD_SIZE, 0);
+    fw_cfg_add_i16(fw_cfg, FW_CFG_BOOT_DEVICE, '\0');
+
+    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, get_ticks_per_sec());
+    }
+    qemu_register_boot_set(fw_cfg_boot_set, fw_cfg);
+}
+
 static QEMUMachine prep_machine = {
     .name = "prep",
     .desc = "PowerPC PREP platform",
@@ -668,9 +873,17 @@ static QEMUMachine prep_machine = {
     DEFAULT_MACHINE_OPTIONS,
 };
 
+static QEMUMachine ibm_43p_machine = {
+    .name = "43p",
+    .desc = "IBM RS/6000 7248 (43p)",
+    .init = ibm_43p_init,
+    .max_cpus = 1,
+};
+
 static void prep_machine_init(void)
 {
     qemu_register_machine(&prep_machine);
+    qemu_register_machine(&ibm_43p_machine);
 }
 
 machine_init(prep_machine_init);
-- 
1.7.10.4

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

* [Qemu-devel] [PATCH 7/7] prep: QOM'ify System I/O
  2013-05-02 20:08 [Qemu-devel] [PATCH 0/7] ppc/prep: add IBM RS/6000 43p machine Hervé Poussineau
                   ` (5 preceding siblings ...)
  2013-05-02 20:09 ` [Qemu-devel] [PATCH 6/7] prep: add IBM RS/6000 7248 (43p) machine emulation Hervé Poussineau
@ 2013-05-02 20:09 ` Hervé Poussineau
  2013-05-03 11:36   ` Andreas Färber
  6 siblings, 1 reply; 24+ messages in thread
From: Hervé Poussineau @ 2013-05-02 20:09 UTC (permalink / raw)
  To: qemu-devel
  Cc: Hervé Poussineau, qemu-ppc, Andreas Färber, Julio Guerra

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

Document it for the IBM 43p emulation.

Cc: Julio Guerra <guerr@julio.in>
Signed-off-by: Hervé Poussineau <hpoussin@reactos.org>
---
 docs/ibm_43p.cfg       |    5 +
 hw/ppc/Makefile.objs   |    1 +
 hw/ppc/prep_systemio.c |  298 ++++++++++++++++++++++++++++++++++++++++++++++++
 trace-events           |    4 +
 4 files changed, 308 insertions(+)
 create mode 100644 hw/ppc/prep_systemio.c

diff --git a/docs/ibm_43p.cfg b/docs/ibm_43p.cfg
index 70bbfdb..653d50b 100644
--- a/docs/ibm_43p.cfg
+++ b/docs/ibm_43p.cfg
@@ -36,3 +36,8 @@
   iobase = "0x170"
   iobase2 = "0x376"
   irq = "15"
+
+[device]
+  driver = "prep-systemio"
+  ibm-planar-id = "0xc0"
+  equipment = "0xff"
diff --git a/hw/ppc/Makefile.objs b/hw/ppc/Makefile.objs
index be00d1d..cd1eb1b 100644
--- a/hw/ppc/Makefile.objs
+++ b/hw/ppc/Makefile.objs
@@ -9,6 +9,7 @@ obj-y += ppc405_boards.o ppc4xx_devs.o ppc405_uc.o ppc440_bamboo.o
 obj-y += ppc4xx_pci.o
 # PReP
 obj-y += prep.o
+obj-y += prep_systemio.o
 # OldWorld PowerMac
 obj-y += 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..1ea511c
--- /dev/null
+++ b/hw/ppc/prep_systemio.c
@@ -0,0 +1,298 @@
+/*
+ * QEMU PReP System I/O emulation
+ *
+ * Copyright (c) 2003-2007 Jocelyn Mayer
+ * Copyright (c) 2010-2012 Herve Poussineau
+ * Copyright (c) 2010-2011 Andreas Faerber
+ *
+ * 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 "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 "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 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;
+} PrepSystemIoState;
+
+/* PORT 0092 -- Special Port 92 (Read/Write) */
+
+enum {
+    PORT0092_SOFTRESET  = BIT(7),
+    PORT0092_LE_MODE    = 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  = 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    = 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               = BIT(1),
+    PORT080C_L2_COPYBACK            = BIT(4),
+    PORT080C_L2_256                 = BIT(5),
+    PORT080C_UPGRADE_CPU            = BIT(6),
+    PORT080C_L2                     = 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   = BIT(3),
+    PORT081C_MASK_TEA               = BIT(2),
+    PORT081C_L2_UPDATE_INHIBIT      = BIT(1),
+    PORT081C_L2_CACHEMISS_INHIBIT   = 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    = 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 int prep_systemio_init(ISADevice *dev)
+{
+    PrepSystemIoState *s = PREP_SYSTEMIO(dev);
+    qdev_init_gpio_out(&dev->qdev, &s->non_contiguous_io_map_irq, 1);
+    s->iomap_type = 0; /* contiguous mode XXX 0x1? */
+    s->softreset_irq = first_cpu->irq_inputs[PPC6xx_INPUT_HRESET];
+
+    isa_register_portio_list(dev, 0x0, ppc_io800_port_list, s, "systemio800");
+
+    memory_region_init_io(&s->ppc_parity_mem, &ppc_parity_error_ops, s,
+                          "ppc-parity", 0x4);
+    memory_region_add_subregion(get_system_memory(), 0xbfffeff0,
+                                &s->ppc_parity_mem);
+    return 0;
+}
+
+static const VMStateDescription vmstate_prep_systemio = {
+    .name = "prep_systemio",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT8(system_control, PrepSystemIoState),
+        VMSTATE_UINT8(iomap_type, PrepSystemIoState),
+        VMSTATE_END_OF_LIST()
+    },
+};
+
+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);
+    ISADeviceClass *ic = ISA_DEVICE_CLASS(klass);
+    ic->init = prep_systemio_init;
+    dc->vmsd = &vmstate_prep_systemio;
+    dc->props = prep_systemio_properties;
+    dc->no_user = 1;
+}
+
+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/trace-events b/trace-events
index 1970b5c..be35eed 100644
--- a/trace-events
+++ b/trace-events
@@ -773,6 +773,10 @@ mpc105_simm_enable(int id, uint32_t start, uint32_t end) "SIMM #%d 0x%08x-0x%08x
 mpc105_simm_disable(int id) "SIMM #%d disabled"
 mpc105_simm_size(int id, uint32_t size) "SIMM #%d is %u MB"
 
+# 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/scsi/vmw_pvscsi.c
 pvscsi_ring_init_data(uint32_t txr_len_log2, uint32_t rxr_len_log2) "TX/RX rings logarithms set to %d/%d"
 pvscsi_ring_init_msg(uint32_t len_log2) "MSG ring logarithm set to %d"
-- 
1.7.10.4

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

* Re: [Qemu-devel] [Qemu-ppc] [PATCH 1/7] pci: add MPC105 PCI host bridge emulation
  2013-05-02 20:08 ` [Qemu-devel] [PATCH 1/7] pci: add MPC105 PCI host bridge emulation Hervé Poussineau
@ 2013-05-02 21:01   ` Alexander Graf
  2013-05-03  5:57     ` Hervé Poussineau
  0 siblings, 1 reply; 24+ messages in thread
From: Alexander Graf @ 2013-05-02 21:01 UTC (permalink / raw)
  To: Hervé Poussineau; +Cc: qemu-ppc, qemu-devel, Andreas Färber



Am 02.05.2013 um 22:08 schrieb Hervé Poussineau <hpoussin@reactos.org>:

> Non-contiguous I/O is not implemented.
> 
> There is also somewhere a bug in the memory controller, which means
> that some real firmwares may not detect the correct amount of memory.
> This can be bypassed by adding '-m 1G' on the command line.
> 
> Add x-auto-conf property, to automatically configure the memory
> controller at startup. This will be required by OpenBIOS, which
> doesn't know how to do it.

Why not teach it? I'd prefer to see that logic in firmware.

> 
> Signed-off-by: Hervé Poussineau <hpoussin@reactos.org>
> ---
> default-configs/ppc-softmmu.mak |    1 +
> hw/pci-host/Makefile.objs       |    1 +
> hw/pci-host/mpc105.c            |  488 +++++++++++++++++++++++++++++++++++++++
> include/hw/pci/pci_ids.h        |    1 +
> trace-events                    |    7 +
> 5 files changed, 498 insertions(+)
> create mode 100644 hw/pci-host/mpc105.c
> 
> diff --git a/default-configs/ppc-softmmu.mak b/default-configs/ppc-softmmu.mak
> index cc3587f..f79b058 100644
> --- a/default-configs/ppc-softmmu.mak
> +++ b/default-configs/ppc-softmmu.mak
> @@ -28,6 +28,7 @@ CONFIG_MAC_NVRAM=y
> CONFIG_MAC_DBDMA=y
> CONFIG_HEATHROW_PIC=y
> CONFIG_GRACKLE_PCI=y
> +CONFIG_MPC105_PCI=y
> CONFIG_UNIN_PCI=y
> CONFIG_DEC_PCI=y
> CONFIG_PPCE500_PCI=y
> diff --git a/hw/pci-host/Makefile.objs b/hw/pci-host/Makefile.objs
> index 909e702..ec4427b 100644
> --- a/hw/pci-host/Makefile.objs
> +++ b/hw/pci-host/Makefile.objs
> @@ -3,6 +3,7 @@ common-obj-y += pam.o
> # PPC devices
> common-obj-$(CONFIG_PREP_PCI) += prep.o
> common-obj-$(CONFIG_GRACKLE_PCI) += grackle.o
> +common-obj-$(CONFIG_MPC105_PCI) += mpc105.o
> # NewWorld PowerMac
> common-obj-$(CONFIG_UNIN_PCI) += uninorth.o
> common-obj-$(CONFIG_DEC_PCI) += dec.o
> diff --git a/hw/pci-host/mpc105.c b/hw/pci-host/mpc105.c
> new file mode 100644
> index 0000000..8e4cc95
> --- /dev/null
> +++ b/hw/pci-host/mpc105.c
> @@ -0,0 +1,488 @@
> +/*
> + * QEMU MPC-105 Eagle PCI host
> + *
> + * Copyright (c) 2013 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 "hw/pci/pci.h"
> +#include "hw/pci/pci_bus.h"
> +#include "hw/pci/pci_host.h"
> +#include "hw/i386/pc.h"

That include sounds odd :).

> +#include "hw/loader.h"
> +#include "exec/address-spaces.h"
> +#include "elf.h"
> +#include "trace.h"
> +
> +#define TYPE_MPC105_PCI_HOST_BRIDGE "mpc105-pcihost"
> +#define MPC105_PCI_HOST_BRIDGE(obj) \
> +    OBJECT_CHECK(Mpc105HostState, (obj), TYPE_MPC105_PCI_HOST_BRIDGE)
> +
> +#define TYPE_MPC105 "mpc105"
> +#define MPC105(obj) \
> +    OBJECT_CHECK(Mpc105State, (obj), TYPE_MPC105)
> +
> +#define MEM_STA_03     0x0080
> +#define MEM_STA_47     0x0084
> +#define EXT_MEM_STA_03 0x0088
> +#define EXT_MEM_STA_47 0x008c
> +#define MEM_END_03     0x0090
> +#define MEM_END_47     0x0094
> +#define EXT_MEM_END_03 0x0098
> +#define EXT_MEM_END_47 0x009c
> +#define MEM_BANK_EN    0x00a0
> +#define PROC_CFG_A8    0x00a8
> +#define PROC_CFG_AC    0x00ac
> +#define ALT_OSV_1      0x00ba
> +#define ERR_EN_REG1    0x00c0
> +#define ERR_DR1        0x00c1
> +#define ERR_EN_REG2    0x00c4
> +#define MEM_CFG_1      0x00f0
> +#define MEM_CFG_2      0x00f4
> +#define MEM_CFG_4      0x00fc
> +
> +#define MEM_CFG_1_MEMGO (1 << 19)
> +
> +#define BIOS_SIZE (1024 * 1024)
> +
> +typedef struct Mpc105State {
> +    PCIDevice parent_obj;
> +    uint32_t ram_size;
> +    uint32_t elf_machine;
> +    uint32_t x_auto_conf;
> +    char *bios_name;
> +    MemoryRegion bios;
> +    MemoryRegion simm[8];
> +    bool use_sizer[8];
> +    /* use a sizer to allow access to only part of a simm */
> +    MemoryRegion sizer[8];
> +} Mpc105State;
> +
> +static uint64_t mpc105_unassigned_read(void *opaque, hwaddr addr,
> +                                       unsigned int size)
> +{
> +    trace_mpc105_unassigned_mem_read(addr);
> +    return 0;
> +}
> +
> +static void mpc105_unassigned_write(void *opaque, hwaddr addr, uint64_t data,
> +                                    unsigned int size)
> +{
> +    trace_mpc105_unassigned_mem_write(addr, data);
> +}
> +
> +static const MemoryRegionOps mpc105_unassigned_ops = {
> +    .read = mpc105_unassigned_read,
> +    .write = mpc105_unassigned_write,
> +};
> +
> +static void mpc105_update_memory_mappings(Mpc105State *s)
> +{
> +    uint32_t start_address, end_address;
> +    uint32_t start, ext_start, end, ext_end;
> +    uint32_t cfg1;
> +    uint64_t simm_size;
> +    uint8_t *pci_conf;
> +    uint8_t en;
> +    bool enabled;
> +    int i;
> +
> +    pci_conf = PCI_DEVICE(s)->config;
> +    cfg1 = pci_get_long(pci_conf + MEM_CFG_1);
> +
> +    memory_region_transaction_begin();
> +    if (cfg1 & MEM_CFG_1_MEMGO) {
> +        en = pci_get_byte(pci_conf + MEM_BANK_EN);
> +    } else {
> +        en = 0;
> +    }
> +
> +    for (i = 0; i < 8; i++) {
> +        enabled = (en & (1 << i));
> +
> +        start = pci_get_byte(pci_conf + MEM_STA_03 + i);
> +        ext_start = pci_get_byte(pci_conf + EXT_MEM_STA_03 + i) & 0x3;
> +        end = pci_get_byte(pci_conf + MEM_END_03 + i);
> +        ext_end = pci_get_byte(pci_conf + EXT_MEM_STA_03 + i) & 0x3;
> +        start_address = (ext_start << 28) | (start << 20);
> +        end_address = (ext_end << 28) | (end << 20) | 0xfffff;
> +
> +        enabled &= start_address < end_address;
> +
> +        if (enabled) {
> +            trace_mpc105_simm_enable(i, start_address, end_address + 1);
> +        } else {
> +            trace_mpc105_simm_disable(i);
> +        }
> +
> +        simm_size = memory_region_size(&s->simm[i]);
> +        if (simm_size == 0) {
> +            continue;
> +        }
> +
> +        /* Clean links between system memory, sizer and simm */
> +        if (s->use_sizer[i]) {
> +            memory_region_del_subregion(get_system_memory(), &s->sizer[i]);
> +            memory_region_del_subregion(&s->sizer[i], &s->simm[i]);
> +            s->use_sizer[i] = false;
> +        } else {
> +            memory_region_del_subregion(get_system_memory(), &s->simm[i]);
> +        }
> +
> +        /* Recreate links compatible with new memory layout */
> +        if (enabled && end_address - start_address + 1 < simm_size) {
> +            memory_region_init_io(&s->sizer[i], &mpc105_unassigned_ops,
> +                                  s, memory_region_name(&s->sizer[i]),
> +                                  end_address - start_address + 1);
> +            memory_region_add_subregion(&s->sizer[i], 0, &s->simm[i]);
> +            memory_region_add_subregion(get_system_memory(), start_address,
> +                                        &s->sizer[i]);
> +            s->use_sizer[i] = true;
> +        } else {
> +            memory_region_add_subregion(get_system_memory(), start_address,
> +                                        &s->simm[i]);
> +        }
> +        memory_region_set_enabled(&s->simm[i], enabled);
> +    }
> +    memory_region_transaction_commit();
> +}
> +
> +static void mpc105_write_config(PCIDevice *dev, uint32_t addr, uint32_t val,
> +                                int l)
> +{
> +    Mpc105State *s = MPC105(dev);
> +
> +    pci_default_write_config(dev, addr, val, l);
> +    if ((addr >= MEM_STA_03 && addr <= MEM_BANK_EN) || addr == MEM_CFG_1) {
> +        mpc105_update_memory_mappings(s);
> +    }
> +}
> +
> +static void mpc105_reset(Mpc105State *s)
> +{
> +    PCIDevice *pci = PCI_DEVICE(s);
> +    uint8_t *pci_conf;
> +    int id;
> +
> +    pci_conf = pci->config;
> +
> +    memset(pci_conf + PCI_CONFIG_HEADER_SIZE, 0,
> +           PCI_CONFIG_SPACE_SIZE - PCI_CONFIG_HEADER_SIZE);
> +    pci_conf[PCI_COMMAND] = PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY;
> +    pci_conf[PCI_STATUS] = PCI_STATUS_FAST_BACK;
> +    pci_set_long(pci_conf + PROC_CFG_A8, 0xff000010);
> +    pci_set_long(pci_conf + PROC_CFG_AC, 0x000c060c);
> +    pci_set_byte(pci_conf + ALT_OSV_1, 0x04);
> +    pci_set_byte(pci_conf + ERR_EN_REG1, 0x01);
> +    pci_set_long(pci_conf + MEM_CFG_1, 0xff020000);
> +    pci_set_long(pci_conf + MEM_CFG_2, 0x00000003);
> +    pci_set_long(pci_conf + MEM_CFG_4, 0x00100000);
> +
> +    memset(pci->wmask + PCI_CONFIG_HEADER_SIZE, 0,
> +           MEM_CFG_1 - PCI_CONFIG_HEADER_SIZE);
> +    memset(pci->wmask + 0x70, 0xff, 2);
> +    memset(pci->wmask + MEM_STA_03, 0xff, MEM_BANK_EN - MEM_STA_03 + 1);
> +    memset(pci->wmask + PROC_CFG_A8, 0xff, 8);
> +    pci_set_word(pci->wmask + ALT_OSV_1, 0xffff);
> +    pci_set_byte(pci->wmask + ERR_EN_REG1, 0xff);
> +    pci_set_byte(pci->w1cmask + ERR_DR1, 0xff);
> +    pci_set_byte(pci->w1cmask + 0xc3, 0xff);
> +    pci_set_byte(pci->wmask + ERR_EN_REG2, 0xff);
> +    pci_set_byte(pci->w1cmask + 0xc5, 0xff);
> +    pci_set_byte(pci->w1cmask + 0xc7, 0xff);
> +
> +    for (id = 0; id < 8; ++id) {
> +        memory_region_set_enabled(&s->simm[id], false);
> +    }
> +
> +    if (s->x_auto_conf) {
> +        /* enable all memory banks, starting from address 0 */
> +        uint32_t start_address = 0, end_address = 0;
> +        uint8_t ext_start, ext_end, enabled = 0;
> +        int i;
> +        for (i = 0; i < 8; i++) {
> +            if (!memory_region_size(&s->simm[i])) {
> +                continue;
> +            }
> +            end_address += memory_region_size(&s->simm[i]);
> +            ext_start = pci_get_byte(pci_conf + EXT_MEM_STA_03 + i) & ~0x3;
> +            ext_end = pci_get_byte(pci_conf + EXT_MEM_STA_03 + i) & ~0x3;
> +            ext_start |= (start_address >> 28) & 0x3;
> +            ext_end |= ((end_address - 1) >> 28) & 0x3;
> +            pci_set_byte(pci_conf + MEM_STA_03 + i, start_address >> 20);
> +            pci_set_byte(pci_conf + EXT_MEM_STA_03 + i, ext_start);
> +            pci_set_byte(pci_conf + MEM_END_03 + i, (end_address - 1) >> 20);
> +            pci_set_byte(pci_conf + EXT_MEM_END_03 + i, ext_end);
> +            start_address = end_address;
> +            enabled |= 1 << i;
> +        }
> +        pci_set_byte(pci_conf + MEM_BANK_EN, enabled);
> +        pci_long_test_and_set_mask(pci_conf + MEM_CFG_1, MEM_CFG_1_MEMGO);
> +        mpc105_update_memory_mappings(s);
> +    }
> +}
> +
> +static void qdev_mpc105_reset(DeviceState *dev)
> +{
> +    Mpc105State *s = MPC105(dev);
> +    mpc105_reset(s);
> +}
> +
> +static int mpc105_post_load(void *opaque, int version_id)
> +{
> +    Mpc105State *s = opaque;
> +    mpc105_update_memory_mappings(s);
> +    return 0;
> +}
> +
> +static const VMStateDescription vmstate_mpc105 = {
> +    .name = "mpc105",
> +    .version_id = 1,
> +    .minimum_version_id = 0,
> +    .minimum_version_id_old = 1,
> +    .post_load = mpc105_post_load,
> +    .fields = (VMStateField[]) {
> +        VMSTATE_PCI_DEVICE(parent_obj, Mpc105State),
> +        VMSTATE_END_OF_LIST()
> +    }
> +};
> +
> +static uint64_t mpc105_intack_read(void *opaque, hwaddr addr,
> +                                   unsigned int size)
> +{
> +    return pic_read_irq(isa_pic);
> +}
> +
> +static const MemoryRegionOps mpc105_intack_ops = {
> +    .read = mpc105_intack_read,
> +    .valid = {
> +        .max_access_size = 1,
> +    },
> +};
> +
> +static int mpc105_initfn(PCIDevice *dev)
> +{
> +    Mpc105State *s = MPC105(dev);
> +    char *filename;
> +    int bios_size = -1;
> +    int i = 0;
> +    uint32_t simm_size[8] = { 0 };
> +
> +    unsigned int ram_size = s->ram_size / (1024 * 1024);
> +    while (i < 8) {
> +        int idx = qemu_fls(ram_size);
> +        if (idx < 5) {
> +            /* Need at least 16 Mb for a slot */
> +            break;
> +        } else if (idx >= 8) {
> +            /* Limit to 128 Mb by slot (at max) */
> +            idx = 8;
> +        }
> +        simm_size[i] = 1 << (idx - 1);
> +        ram_size -= simm_size[i];
> +        i++;
> +    }
> +
> +    for (i = 0; i < 8; i++) {
> +        char name[] = "simm.?";
> +        name[5] = i + '0';
> +        if (simm_size[i]) {
> +            trace_mpc105_simm_size(i, simm_size[i]);
> +            memory_region_init_ram(&s->simm[i], name,
> +                                   simm_size[i] * 1024 * 1024);
> +            vmstate_register_ram_global(&s->simm[i]);
> +        } else {
> +            memory_region_init(&s->simm[i], name, 0);
> +        }
> +        memory_region_init(&s->sizer[i], "sizer", 0);
> +        memory_region_add_subregion_overlap(get_system_memory(), 0,
> +                                            &s->simm[i], i);
> +        memory_region_set_enabled(&s->simm[i], false);
> +    }
> +
> +    memory_region_init_ram(&s->bios, "bios", BIOS_SIZE);
> +    memory_region_set_readonly(&s->bios, true);
> +    memory_region_add_subregion(get_system_memory(), (uint32_t)(-BIOS_SIZE),
> +                                &s->bios);
> +    vmstate_register_ram_global(&s->bios);
> +    if (s->bios_name) {

Can't you just reuse the normal -bios logic?

> +        filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, s->bios_name);
> +        if (filename) {
> +            if (s->elf_machine != EM_NONE) {

Elf machine?

Alex

> +                bios_size = load_elf(filename, NULL, NULL, NULL,
> +                                     NULL, NULL, 1, s->elf_machine, 0);
> +            }
> +            if (bios_size < 0) {
> +                bios_size = get_image_size(filename);
> +                if (bios_size > 0 && bios_size <= BIOS_SIZE) {
> +                    hwaddr bios_addr;
> +                    bios_size = (bios_size + 0xfff) & ~0xfff;
> +                    bios_addr = (uint32_t)(-BIOS_SIZE);
> +                    bios_size = load_image_targphys(filename, bios_addr,
> +                                                    bios_size);
> +                }
> +            }
> +        }
> +        if (bios_size < 0 || bios_size > BIOS_SIZE) {
> +            hw_error("qemu: could not load bios image '%s'\n", s->bios_name);
> +        }
> +        if (filename) {
> +            g_free(filename);
> +        }
> +    }
> +
> +    return 0;
> +}
> +
> +static void mpc105_class_init(ObjectClass *klass, void *data)
> +{
> +    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
> +    DeviceClass *dc = DEVICE_CLASS(klass);
> +
> +    k->init = mpc105_initfn;
> +    k->vendor_id = PCI_VENDOR_ID_MOTOROLA;
> +    k->device_id = PCI_DEVICE_ID_MOTOROLA_MPC105;
> +    k->class_id = PCI_CLASS_BRIDGE_HOST;
> +    k->config_write = mpc105_write_config;
> +    dc->desc = "MPC105 PCI bridge/Memory controller";
> +    dc->reset = qdev_mpc105_reset;
> +    dc->vmsd = &vmstate_mpc105;
> +    dc->no_user = 1;
> +}
> +
> +static TypeInfo mpc105_info = {
> +    .name          = TYPE_MPC105,
> +    .parent        = TYPE_PCI_DEVICE,
> +    .instance_size = sizeof(Mpc105State),
> +    .class_init    = mpc105_class_init,
> +};
> +
> +typedef struct Mpc105HostState {
> +    PCIHostState host_state;
> +    uint32_t ram_size;
> +    qemu_irq irq[PCI_NUM_PINS];
> +    PCIBus pci_bus;
> +    MemoryRegion pci_io;
> +    MemoryRegion isa_io;
> +    MemoryRegion pci_intack;
> +    MemoryRegion pci_memory;
> +    MemoryRegion rom;
> +    Mpc105State pci_dev;
> +} Mpc105HostState;
> +
> +static void mpc105_set_irq(void *opaque, int irq_num, int level)
> +{
> +    qemu_irq *pic = opaque;
> +
> +    qemu_set_irq(pic[irq_num] , level);
> +}
> +
> +static int mpc105_map_irq(PCIDevice *pci_dev, int irq_num)
> +{
> +    return (irq_num + (pci_dev->devfn >> 3)) & 1;
> +}
> +
> +static void mpc105_pcihost_realizefn(DeviceState *d, Error **errp)
> +{
> +    SysBusDevice *dev = SYS_BUS_DEVICE(d);
> +    PCIHostState *h = PCI_HOST_BRIDGE(dev);
> +    Mpc105HostState *s = MPC105_PCI_HOST_BRIDGE(dev);
> +    int i;
> +
> +    for (i = 0; i < PCI_NUM_PINS; i++) {
> +        sysbus_init_irq(dev, &s->irq[i]);
> +    }
> +
> +    pci_bus_irqs(&s->pci_bus, mpc105_set_irq, mpc105_map_irq, s->irq, 4);
> +
> +    memory_region_init_io(&h->conf_mem, &pci_host_conf_le_ops, s,
> +                          "pci-conf-idx", 1);
> +    memory_region_add_subregion(get_system_io(), 0xcf8, &h->conf_mem);
> +
> +    memory_region_init_io(&h->data_mem, &pci_host_data_le_ops, s,
> +                          "pci-conf-data", 4);
> +

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

* Re: [Qemu-devel] [PATCH 4/7] m48t59: register a QOM type for each nvram type we support
  2013-05-02 20:09 ` [Qemu-devel] [PATCH 4/7] m48t59: register a QOM type for each nvram type we support Hervé Poussineau
@ 2013-05-02 21:29   ` Artyom Tarasenko
  2013-05-03  5:50     ` Hervé Poussineau
  0 siblings, 1 reply; 24+ messages in thread
From: Artyom Tarasenko @ 2013-05-02 21:29 UTC (permalink / raw)
  To: Hervé Poussineau, Blue Swirl
  Cc: qemu-ppc, qemu-devel, Andreas Färber

On Thu, May 2, 2013 at 10:09 PM, Hervé Poussineau <hpoussin@reactos.org> wrote:
> As m48t59 devices can only be created with m48t59_init() or m48t59_init_isa(),
> we know exactly which nvram types are required. Register only those three
> types.

Wasn't this patch NACKed by Blue?

> Remove .model and .size properties as they can be infered from nvram name.
>
> Rename type to 'isa-*' (and 'sysbus-*') to do like other devices ISA devices
> (isa-ide, isa-parallel, isa-serial...)
>
> Signed-off-by: Hervé Poussineau <hpoussin@reactos.org>
> ---
>  hw/timer/m48t59.c |  248 +++++++++++++++++++++++++++++++++++++----------------
>  1 file changed, 172 insertions(+), 76 deletions(-)
>
> diff --git a/hw/timer/m48t59.c b/hw/timer/m48t59.c
> index fb78d20..23a6ab3 100644
> --- a/hw/timer/m48t59.c
> +++ b/hw/timer/m48t59.c
> @@ -2,6 +2,7 @@
>   * QEMU M48T59 and M48T08 NVRAM emulation for PPC PREP and Sparc platforms
>   *
>   * Copyright (c) 2003-2005, 2007 Jocelyn Mayer
> + * Copyright (c) 2013 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
> @@ -37,12 +38,31 @@
>  #define NVRAM_PRINTF(fmt, ...) do { } while (0)
>  #endif
>
> +#define TYPE_M48TXX_SYS_BUS "m48txx-sysbus"
> +#define M48TXX_SYS_BUS_CLASS(klass) \
> +    OBJECT_CLASS_CHECK(M48txxSysBusDeviceClass, (klass), TYPE_M48TXX_SYS_BUS)
> +#define M48TXX_SYS_BUS(obj) \
> +    OBJECT_CHECK(M48txxSysBusState, (obj), TYPE_M48TXX_SYS_BUS)
> +
> +#define TYPE_M48TXX_ISA "m48txx-isa"
> +#define M48TXX_ISA_CLASS(klass) \
> +    OBJECT_CLASS_CHECK(M48txxISADeviceClass, (klass), TYPE_M48TXX_ISA)
> +#define M48TXX_ISA(obj) \
> +    OBJECT_CHECK(M48txxISAState, (obj), TYPE_M48TXX_ISA)
> +
>  /*
>   * The M48T02, M48T08 and M48T59 chips are very similar. The newer '59 has
>   * alarm and a watchdog timer and related control registers. In the
>   * PPC platform there is also a nvram lock function.
>   */
>
> +typedef struct M48txxInfo {
> +    const char *isa_name;
> +    const char *sysbus_name;
> +    uint32_t model; /* 2 = m48t02, 8 = m48t08, 59 = m48t59 */
> +    uint32_t size;
> +} M48txxInfo;
> +
>  /*
>   * Chipset docs:
>   * http://www.st.com/stonline/products/literature/ds/2410/m48t02.pdf
> @@ -54,7 +74,6 @@ struct M48t59State {
>      /* Hardware parameters */
>      qemu_irq IRQ;
>      MemoryRegion iomem;
> -    uint32_t io_base;
>      uint32_t size;
>      /* RTC management */
>      time_t   time_offset;
> @@ -72,22 +91,45 @@ struct M48t59State {
>      uint8_t  lock;
>  };
>
> -#define TYPE_ISA_M48T59 "m48t59_isa"
> -#define ISA_M48T59(obj) \
> -    OBJECT_CHECK(M48t59ISAState, (obj), TYPE_ISA_M48T59)
> -
> -typedef struct M48t59ISAState {
> +typedef struct M48txxISAState {
>      ISADevice parent_obj;
> -
>      M48t59State state;
> +    uint32_t io_base;
>      MemoryRegion io;
> -} M48t59ISAState;
> +} M48txxISAState;
> +
> +typedef struct M48txxISADeviceClass {
> +    ISADeviceClass parent_class;
> +    M48txxInfo info;
> +} M48txxISADeviceClass;
>
> -typedef struct M48t59SysBusState {
> -    SysBusDevice busdev;
> +typedef struct M48txxSysBusState {
> +    SysBusDevice parent_obj;
>      M48t59State state;
>      MemoryRegion io;
> -} M48t59SysBusState;
> +} M48txxSysBusState;
> +
> +typedef struct M48txxSysBusDeviceClass {
> +    SysBusDeviceClass parent_class;
> +    M48txxInfo info;
> +} M48txxSysBusDeviceClass;
> +
> +static M48txxInfo m48txx_info[] = {
> +    {
> +        .sysbus_name = "sysbus-m48t02",
> +        .model = 2,
> +        .size = 0x800,
> +    },{
> +        .sysbus_name = "sysbus-m48t08",
> +        .model = 8,
> +        .size = 0x2000,
> +    },{
> +        .isa_name = "isa-m48t59",
> +        .model = 59,
> +        .size = 0x2000,
> +    }
> +};
> +
>
>  /* Fake timer functions */
>
> @@ -613,7 +655,7 @@ static void m48t59_reset_common(M48t59State *NVRAM)
>
>  static void m48t59_reset_isa(DeviceState *d)
>  {
> -    M48t59ISAState *isa = ISA_M48T59(d);
> +    M48txxISAState *isa = M48TXX_ISA(d);
>      M48t59State *NVRAM = &isa->state;
>
>      m48t59_reset_common(NVRAM);
> @@ -621,7 +663,7 @@ static void m48t59_reset_isa(DeviceState *d)
>
>  static void m48t59_reset_sysbus(DeviceState *d)
>  {
> -    M48t59SysBusState *sys = container_of(d, M48t59SysBusState, busdev.qdev);
> +    M48txxSysBusState *sys = M48TXX_SYS_BUS(d);
>      M48t59State *NVRAM = &sys->state;
>
>      m48t59_reset_common(NVRAM);
> @@ -643,47 +685,62 @@ M48t59State *m48t59_init(qemu_irq IRQ, hwaddr mem_base,
>  {
>      DeviceState *dev;
>      SysBusDevice *s;
> -    M48t59SysBusState *d;
> +    M48txxSysBusState *d;
>      M48t59State *state;
> +    int i;
>
> -    dev = qdev_create(NULL, "m48t59");
> -    qdev_prop_set_uint32(dev, "model", model);
> -    qdev_prop_set_uint32(dev, "size", size);
> -    qdev_prop_set_uint32(dev, "io_base", io_base);
> -    qdev_init_nofail(dev);
> -    s = SYS_BUS_DEVICE(dev);
> -    d = FROM_SYSBUS(M48t59SysBusState, s);
> -    state = &d->state;
> -    sysbus_connect_irq(s, 0, IRQ);
> -    if (io_base != 0) {
> -        memory_region_add_subregion(get_system_io(), io_base,
> -                                    sysbus_mmio_get_region(dev, 1));
> -    }
> -    if (mem_base != 0) {
> -        sysbus_mmio_map(s, 0, mem_base);
> +    for (i = 0; i < ARRAY_SIZE(m48txx_info); i++) {
> +        if (!m48txx_info[i].sysbus_name ||
> +            m48txx_info[i].size != size ||
> +            m48txx_info[i].model != model) {
> +            continue;
> +        }
> +
> +        dev = qdev_create(NULL, m48txx_info[i].sysbus_name);
> +        qdev_init_nofail(dev);
> +        s = SYS_BUS_DEVICE(dev);
> +        d = M48TXX_SYS_BUS(s);
> +        state = &d->state;
> +        sysbus_connect_irq(s, 0, IRQ);
> +        memory_region_init_io(&d->io, &m48t59_io_ops, state, "m48t59", 4);
> +        if (io_base != 0) {
> +            memory_region_add_subregion(get_system_io(), io_base,
> +                                        sysbus_mmio_get_region(s, 1));
> +        }
> +        if (mem_base != 0) {
> +            sysbus_mmio_map(s, 0, mem_base);
> +        }
> +
> +        return state;
>      }
>
> -    return state;
> +    assert(false);
> +    return NULL;
>  }
>
>  M48t59State *m48t59_init_isa(ISABus *bus, uint32_t io_base, uint16_t size,
>                               int model)
>  {
> -    M48t59ISAState *d;
> -    ISADevice *isadev;
> +    M48txxISAState *d;
>      DeviceState *dev;
> -    M48t59State *s;
> -
> -    isadev = isa_create(bus, TYPE_ISA_M48T59);
> -    dev = DEVICE(isadev);
> -    qdev_prop_set_uint32(dev, "model", model);
> -    qdev_prop_set_uint32(dev, "size", size);
> -    qdev_prop_set_uint32(dev, "io_base", io_base);
> -    qdev_init_nofail(dev);
> -    d = ISA_M48T59(isadev);
> -    s = &d->state;
> -
> -    return s;
> +    int i;
> +
> +    for (i = 0; i < ARRAY_SIZE(m48txx_info); i++) {
> +        if (!m48txx_info[i].isa_name ||
> +            m48txx_info[i].size != size ||
> +            m48txx_info[i].model != model) {
> +            continue;
> +        }
> +
> +        dev = DEVICE(isa_create(bus, m48txx_info[i].isa_name));
> +        qdev_prop_set_uint32(dev, "iobase", io_base);
> +        qdev_init_nofail(dev);
> +        d = container_of(ISA_DEVICE(dev), M48txxISAState, parent_obj);
> +        return &d->state;
> +    }
> +
> +    assert(false);
> +    return NULL;
>  }
>
>  static void m48t59_init_common(M48t59State *s)
> @@ -700,14 +757,19 @@ static void m48t59_init_common(M48t59State *s)
>
>  static int m48t59_init_isa1(ISADevice *dev)
>  {
> -    M48t59ISAState *d = ISA_M48T59(dev);
> +    ISADeviceClass *ic = ISA_DEVICE_GET_CLASS(dev);
> +    M48txxISADeviceClass *u = container_of(ic, M48txxISADeviceClass,
> +                                           parent_class);
> +    M48txxISAState *d = container_of(dev, M48txxISAState, parent_obj);
>      M48t59State *s = &d->state;
>
> +    s->model = u->info.model;
> +    s->size = u->info.size;
>      isa_init_irq(dev, &s->IRQ, 8);
>      m48t59_init_common(s);
>      memory_region_init_io(&d->io, &m48t59_io_ops, s, "m48t59", 4);
> -    if (s->io_base != 0) {
> -        isa_register_ioport(dev, &d->io, s->io_base);
> +    if (d->io_base != 0) {
> +        isa_register_ioport(dev, &d->io, d->io_base);
>      }
>
>      return 0;
> @@ -715,9 +777,14 @@ static int m48t59_init_isa1(ISADevice *dev)
>
>  static int m48t59_init1(SysBusDevice *dev)
>  {
> -    M48t59SysBusState *d = FROM_SYSBUS(M48t59SysBusState, dev);
> +    SysBusDeviceClass *k = SYS_BUS_DEVICE_GET_CLASS(dev);
> +    M48txxSysBusDeviceClass *u = container_of(k, M48txxSysBusDeviceClass,
> +                                              parent_class);
> +    M48txxSysBusState *d = container_of(dev, M48txxSysBusState, parent_obj);
>      M48t59State *s = &d->state;
>
> +    s->model = u->info.model;
> +    s->size = u->info.size;
>      sysbus_init_irq(dev, &s->IRQ);
>
>      memory_region_init_io(&s->iomem, &nvram_ops, s, "m48t59.nvram", s->size);
> @@ -730,57 +797,86 @@ static int m48t59_init1(SysBusDevice *dev)
>  }
>
>  static Property m48t59_isa_properties[] = {
> -    DEFINE_PROP_UINT32("size",    M48t59ISAState, state.size,    -1),
> -    DEFINE_PROP_UINT32("model",   M48t59ISAState, state.model,   -1),
> -    DEFINE_PROP_HEX32( "io_base", M48t59ISAState, state.io_base,  0),
> +    DEFINE_PROP_HEX32("iobase", M48txxISAState, io_base, 0x74),
>      DEFINE_PROP_END_OF_LIST(),
>  };
>
> -static void m48t59_isa_class_init(ObjectClass *klass, void *data)
> +static void m48txx_isa_class_init(ObjectClass *klass, void *data)
>  {
>      DeviceClass *dc = DEVICE_CLASS(klass);
>      ISADeviceClass *ic = ISA_DEVICE_CLASS(klass);
> +    M48txxISADeviceClass *u = M48TXX_ISA_CLASS(klass);
> +    M48txxInfo *info = data;
> +
>      ic->init = m48t59_init_isa1;
>      dc->no_user = 1;
>      dc->reset = m48t59_reset_isa;
> -    dc->props = m48t59_isa_properties;
> +    if (info) {
> +        dc->props = m48t59_isa_properties;
> +        u->info = *info;
> +    }
>  }
>
> -static const TypeInfo m48t59_isa_info = {
> -    .name          = TYPE_ISA_M48T59,
> -    .parent        = TYPE_ISA_DEVICE,
> -    .instance_size = sizeof(M48t59ISAState),
> -    .class_init    = m48t59_isa_class_init,
> -};
> -
> -static Property m48t59_properties[] = {
> -    DEFINE_PROP_UINT32("size",    M48t59SysBusState, state.size,    -1),
> -    DEFINE_PROP_UINT32("model",   M48t59SysBusState, state.model,   -1),
> -    DEFINE_PROP_HEX32( "io_base", M48t59SysBusState, state.io_base,  0),
> -    DEFINE_PROP_END_OF_LIST(),
> -};
> -
> -static void m48t59_class_init(ObjectClass *klass, void *data)
> +static void m48txx_sysbus_class_init(ObjectClass *klass, void *data)
>  {
>      DeviceClass *dc = DEVICE_CLASS(klass);
>      SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
> +    M48txxSysBusDeviceClass *u = M48TXX_SYS_BUS_CLASS(klass);
> +    M48txxInfo *info = data;
>
>      k->init = m48t59_init1;
>      dc->reset = m48t59_reset_sysbus;
> -    dc->props = m48t59_properties;
> +    if (info) {
> +        u->info = *info;
> +    }
>  }
>
> -static const TypeInfo m48t59_info = {
> -    .name          = "m48t59",
> -    .parent        = TYPE_SYS_BUS_DEVICE,
> -    .instance_size = sizeof(M48t59SysBusState),
> -    .class_init    = m48t59_class_init,
> +static const TypeInfo m48txx_sysbus_type_info = {
> +    .name = TYPE_M48TXX_SYS_BUS,
> +    .parent = TYPE_SYS_BUS_DEVICE,
> +    .instance_size = sizeof(M48txxSysBusState),
> +    .abstract = true,
> +    .class_init = m48txx_sysbus_class_init,
> +};
> +
> +static const TypeInfo m48txx_isa_type_info = {
> +    .name = TYPE_M48TXX_ISA,
> +    .parent = TYPE_ISA_DEVICE,
> +    .instance_size = sizeof(M48txxISAState),
> +    .abstract = true,
> +    .class_init = m48txx_isa_class_init,
>  };
>
>  static void m48t59_register_types(void)
>  {
> -    type_register_static(&m48t59_info);
> -    type_register_static(&m48t59_isa_info);
> +    TypeInfo sysbus_type_info = {
> +        .parent = TYPE_M48TXX_SYS_BUS,
> +        .class_size = sizeof(M48txxSysBusDeviceClass),
> +        .class_init = m48txx_sysbus_class_init,
> +    };
> +    TypeInfo isa_type_info = {
> +        .parent = TYPE_M48TXX_ISA,
> +        .class_size = sizeof(M48txxISADeviceClass),
> +        .class_init = m48txx_isa_class_init,
> +    };
> +    int i;
> +
> +    type_register_static(&m48txx_sysbus_type_info);
> +    type_register_static(&m48txx_isa_type_info);
> +
> +    for (i = 0; i < ARRAY_SIZE(m48txx_info); i++) {
> +        if (m48txx_info[i].sysbus_name) {
> +            sysbus_type_info.name = m48txx_info[i].sysbus_name;
> +            sysbus_type_info.class_data = &m48txx_info[i];
> +            type_register(&sysbus_type_info);
> +        }
> +
> +        if (m48txx_info[i].isa_name) {
> +            isa_type_info.name = m48txx_info[i].isa_name;
> +            isa_type_info.class_data = &m48txx_info[i];
> +            type_register(&isa_type_info);
> +        }
> +    }
>  }
>
>  type_init(m48t59_register_types)
> --
> 1.7.10.4
>
>



--
Regards,
Artyom Tarasenko

linux/sparc and solaris/sparc under qemu blog:
http://tyom.blogspot.com/search/label/qemu

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

* Re: [Qemu-devel] [PATCH 4/7] m48t59: register a QOM type for each nvram type we support
  2013-05-02 21:29   ` Artyom Tarasenko
@ 2013-05-03  5:50     ` Hervé Poussineau
  2013-05-03 23:16       ` Artyom Tarasenko
  0 siblings, 1 reply; 24+ messages in thread
From: Hervé Poussineau @ 2013-05-03  5:50 UTC (permalink / raw)
  To: Artyom Tarasenko; +Cc: Blue Swirl, qemu-ppc, qemu-devel, Andreas Färber

Artyom Tarasenko a écrit :
> On Thu, May 2, 2013 at 10:09 PM, Hervé Poussineau <hpoussin@reactos.org> wrote:
>> As m48t59 devices can only be created with m48t59_init() or m48t59_init_isa(),
>> we know exactly which nvram types are required. Register only those three
>> types.
> 
> Wasn't this patch NACKed by Blue?

I think I changed what's requested, ie I kept the io-base property of 
the ISA variant, so the sun4u emulation can be changed later to the 
right address. However, fixing sun4u emulation is not part of this patchset.

Otherwise, if I didn't understood, please elaborate.

Regards,

Hervé

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

* Re: [Qemu-devel] [Qemu-ppc] [PATCH 1/7] pci: add MPC105 PCI host bridge emulation
  2013-05-02 21:01   ` [Qemu-devel] [Qemu-ppc] " Alexander Graf
@ 2013-05-03  5:57     ` Hervé Poussineau
  2013-05-06 15:01       ` Alexander Graf
  0 siblings, 1 reply; 24+ messages in thread
From: Hervé Poussineau @ 2013-05-03  5:57 UTC (permalink / raw)
  To: Alexander Graf; +Cc: qemu-ppc, qemu-devel, Andreas Färber

Alexander Graf a écrit :
> 
> Am 02.05.2013 um 22:08 schrieb Hervé Poussineau <hpoussin@reactos.org>:
> 
>> Non-contiguous I/O is not implemented.
>>
>> There is also somewhere a bug in the memory controller, which means
>> that some real firmwares may not detect the correct amount of memory.
>> This can be bypassed by adding '-m 1G' on the command line.
>>
>> Add x-auto-conf property, to automatically configure the memory
>> controller at startup. This will be required by OpenBIOS, which
>> doesn't know how to do it.
> 
> Why not teach it? I'd prefer to see that logic in firmware.

Me too, but I'm not confident enough in my capabilities to do it.
Autoconfiguration is only in one place of the code, so I think it can be 
removed easily once OpenBIOS has this logic.

> 
>> Signed-off-by: Hervé Poussineau <hpoussin@reactos.org>
>> ---
>> default-configs/ppc-softmmu.mak |    1 +
>> hw/pci-host/Makefile.objs       |    1 +
>> hw/pci-host/mpc105.c            |  488 +++++++++++++++++++++++++++++++++++++++
>> include/hw/pci/pci_ids.h        |    1 +
>> trace-events                    |    7 +
>> 5 files changed, 498 insertions(+)
>> create mode 100644 hw/pci-host/mpc105.c
>>
>> diff --git a/default-configs/ppc-softmmu.mak b/default-configs/ppc-softmmu.mak
>> index cc3587f..f79b058 100644
>> --- a/default-configs/ppc-softmmu.mak
>> +++ b/default-configs/ppc-softmmu.mak
>> @@ -28,6 +28,7 @@ CONFIG_MAC_NVRAM=y
>> CONFIG_MAC_DBDMA=y
>> CONFIG_HEATHROW_PIC=y
>> CONFIG_GRACKLE_PCI=y
>> +CONFIG_MPC105_PCI=y
>> CONFIG_UNIN_PCI=y
>> CONFIG_DEC_PCI=y
>> CONFIG_PPCE500_PCI=y
>> diff --git a/hw/pci-host/Makefile.objs b/hw/pci-host/Makefile.objs
>> index 909e702..ec4427b 100644
>> --- a/hw/pci-host/Makefile.objs
>> +++ b/hw/pci-host/Makefile.objs
>> @@ -3,6 +3,7 @@ common-obj-y += pam.o
>> # PPC devices
>> common-obj-$(CONFIG_PREP_PCI) += prep.o
>> common-obj-$(CONFIG_GRACKLE_PCI) += grackle.o
>> +common-obj-$(CONFIG_MPC105_PCI) += mpc105.o
>> # NewWorld PowerMac
>> common-obj-$(CONFIG_UNIN_PCI) += uninorth.o
>> common-obj-$(CONFIG_DEC_PCI) += dec.o
>> diff --git a/hw/pci-host/mpc105.c b/hw/pci-host/mpc105.c
>> new file mode 100644
>> index 0000000..8e4cc95
>> --- /dev/null
>> +++ b/hw/pci-host/mpc105.c
>> @@ -0,0 +1,488 @@
>> +/*
>> + * QEMU MPC-105 Eagle PCI host
>> + *
>> + * Copyright (c) 2013 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 "hw/pci/pci.h"
>> +#include "hw/pci/pci_bus.h"
>> +#include "hw/pci/pci_host.h"
>> +#include "hw/i386/pc.h"
> 
> That include sounds odd :).

Sure, but you need to access pic_read_irq() :)
hw/pci-host/prep.c also includes it.

> 
>> +#include "hw/loader.h"
>> +#include "exec/address-spaces.h"
>> +#include "elf.h"
>> +#include "trace.h"
>> +
>> +#define TYPE_MPC105_PCI_HOST_BRIDGE "mpc105-pcihost"
>> +#define MPC105_PCI_HOST_BRIDGE(obj) \
>> +    OBJECT_CHECK(Mpc105HostState, (obj), TYPE_MPC105_PCI_HOST_BRIDGE)
>> +
>> +#define TYPE_MPC105 "mpc105"
>> +#define MPC105(obj) \
>> +    OBJECT_CHECK(Mpc105State, (obj), TYPE_MPC105)
>> +
>> +#define MEM_STA_03     0x0080
>> +#define MEM_STA_47     0x0084
>> +#define EXT_MEM_STA_03 0x0088
>> +#define EXT_MEM_STA_47 0x008c
>> +#define MEM_END_03     0x0090
>> +#define MEM_END_47     0x0094
>> +#define EXT_MEM_END_03 0x0098
>> +#define EXT_MEM_END_47 0x009c
>> +#define MEM_BANK_EN    0x00a0
>> +#define PROC_CFG_A8    0x00a8
>> +#define PROC_CFG_AC    0x00ac
>> +#define ALT_OSV_1      0x00ba
>> +#define ERR_EN_REG1    0x00c0
>> +#define ERR_DR1        0x00c1
>> +#define ERR_EN_REG2    0x00c4
>> +#define MEM_CFG_1      0x00f0
>> +#define MEM_CFG_2      0x00f4
>> +#define MEM_CFG_4      0x00fc
>> +
>> +#define MEM_CFG_1_MEMGO (1 << 19)
>> +
>> +#define BIOS_SIZE (1024 * 1024)
>> +
>> +typedef struct Mpc105State {
>> +    PCIDevice parent_obj;
>> +    uint32_t ram_size;
>> +    uint32_t elf_machine;
>> +    uint32_t x_auto_conf;
>> +    char *bios_name;
>> +    MemoryRegion bios;
>> +    MemoryRegion simm[8];
>> +    bool use_sizer[8];
>> +    /* use a sizer to allow access to only part of a simm */
>> +    MemoryRegion sizer[8];
>> +} Mpc105State;
>> +
>> +static uint64_t mpc105_unassigned_read(void *opaque, hwaddr addr,
>> +                                       unsigned int size)
>> +{
>> +    trace_mpc105_unassigned_mem_read(addr);
>> +    return 0;
>> +}
>> +
>> +static void mpc105_unassigned_write(void *opaque, hwaddr addr, uint64_t data,
>> +                                    unsigned int size)
>> +{
>> +    trace_mpc105_unassigned_mem_write(addr, data);
>> +}
>> +
>> +static const MemoryRegionOps mpc105_unassigned_ops = {
>> +    .read = mpc105_unassigned_read,
>> +    .write = mpc105_unassigned_write,
>> +};
>> +
>> +static void mpc105_update_memory_mappings(Mpc105State *s)
>> +{
>> +    uint32_t start_address, end_address;
>> +    uint32_t start, ext_start, end, ext_end;
>> +    uint32_t cfg1;
>> +    uint64_t simm_size;
>> +    uint8_t *pci_conf;
>> +    uint8_t en;
>> +    bool enabled;
>> +    int i;
>> +
>> +    pci_conf = PCI_DEVICE(s)->config;
>> +    cfg1 = pci_get_long(pci_conf + MEM_CFG_1);
>> +
>> +    memory_region_transaction_begin();
>> +    if (cfg1 & MEM_CFG_1_MEMGO) {
>> +        en = pci_get_byte(pci_conf + MEM_BANK_EN);
>> +    } else {
>> +        en = 0;
>> +    }
>> +
>> +    for (i = 0; i < 8; i++) {
>> +        enabled = (en & (1 << i));
>> +
>> +        start = pci_get_byte(pci_conf + MEM_STA_03 + i);
>> +        ext_start = pci_get_byte(pci_conf + EXT_MEM_STA_03 + i) & 0x3;
>> +        end = pci_get_byte(pci_conf + MEM_END_03 + i);
>> +        ext_end = pci_get_byte(pci_conf + EXT_MEM_STA_03 + i) & 0x3;
>> +        start_address = (ext_start << 28) | (start << 20);
>> +        end_address = (ext_end << 28) | (end << 20) | 0xfffff;
>> +
>> +        enabled &= start_address < end_address;
>> +
>> +        if (enabled) {
>> +            trace_mpc105_simm_enable(i, start_address, end_address + 1);
>> +        } else {
>> +            trace_mpc105_simm_disable(i);
>> +        }
>> +
>> +        simm_size = memory_region_size(&s->simm[i]);
>> +        if (simm_size == 0) {
>> +            continue;
>> +        }
>> +
>> +        /* Clean links between system memory, sizer and simm */
>> +        if (s->use_sizer[i]) {
>> +            memory_region_del_subregion(get_system_memory(), &s->sizer[i]);
>> +            memory_region_del_subregion(&s->sizer[i], &s->simm[i]);
>> +            s->use_sizer[i] = false;
>> +        } else {
>> +            memory_region_del_subregion(get_system_memory(), &s->simm[i]);
>> +        }
>> +
>> +        /* Recreate links compatible with new memory layout */
>> +        if (enabled && end_address - start_address + 1 < simm_size) {
>> +            memory_region_init_io(&s->sizer[i], &mpc105_unassigned_ops,
>> +                                  s, memory_region_name(&s->sizer[i]),
>> +                                  end_address - start_address + 1);
>> +            memory_region_add_subregion(&s->sizer[i], 0, &s->simm[i]);
>> +            memory_region_add_subregion(get_system_memory(), start_address,
>> +                                        &s->sizer[i]);
>> +            s->use_sizer[i] = true;
>> +        } else {
>> +            memory_region_add_subregion(get_system_memory(), start_address,
>> +                                        &s->simm[i]);
>> +        }
>> +        memory_region_set_enabled(&s->simm[i], enabled);
>> +    }
>> +    memory_region_transaction_commit();
>> +}
>> +
>> +static void mpc105_write_config(PCIDevice *dev, uint32_t addr, uint32_t val,
>> +                                int l)
>> +{
>> +    Mpc105State *s = MPC105(dev);
>> +
>> +    pci_default_write_config(dev, addr, val, l);
>> +    if ((addr >= MEM_STA_03 && addr <= MEM_BANK_EN) || addr == MEM_CFG_1) {
>> +        mpc105_update_memory_mappings(s);
>> +    }
>> +}
>> +
>> +static void mpc105_reset(Mpc105State *s)
>> +{
>> +    PCIDevice *pci = PCI_DEVICE(s);
>> +    uint8_t *pci_conf;
>> +    int id;
>> +
>> +    pci_conf = pci->config;
>> +
>> +    memset(pci_conf + PCI_CONFIG_HEADER_SIZE, 0,
>> +           PCI_CONFIG_SPACE_SIZE - PCI_CONFIG_HEADER_SIZE);
>> +    pci_conf[PCI_COMMAND] = PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY;
>> +    pci_conf[PCI_STATUS] = PCI_STATUS_FAST_BACK;
>> +    pci_set_long(pci_conf + PROC_CFG_A8, 0xff000010);
>> +    pci_set_long(pci_conf + PROC_CFG_AC, 0x000c060c);
>> +    pci_set_byte(pci_conf + ALT_OSV_1, 0x04);
>> +    pci_set_byte(pci_conf + ERR_EN_REG1, 0x01);
>> +    pci_set_long(pci_conf + MEM_CFG_1, 0xff020000);
>> +    pci_set_long(pci_conf + MEM_CFG_2, 0x00000003);
>> +    pci_set_long(pci_conf + MEM_CFG_4, 0x00100000);
>> +
>> +    memset(pci->wmask + PCI_CONFIG_HEADER_SIZE, 0,
>> +           MEM_CFG_1 - PCI_CONFIG_HEADER_SIZE);
>> +    memset(pci->wmask + 0x70, 0xff, 2);
>> +    memset(pci->wmask + MEM_STA_03, 0xff, MEM_BANK_EN - MEM_STA_03 + 1);
>> +    memset(pci->wmask + PROC_CFG_A8, 0xff, 8);
>> +    pci_set_word(pci->wmask + ALT_OSV_1, 0xffff);
>> +    pci_set_byte(pci->wmask + ERR_EN_REG1, 0xff);
>> +    pci_set_byte(pci->w1cmask + ERR_DR1, 0xff);
>> +    pci_set_byte(pci->w1cmask + 0xc3, 0xff);
>> +    pci_set_byte(pci->wmask + ERR_EN_REG2, 0xff);
>> +    pci_set_byte(pci->w1cmask + 0xc5, 0xff);
>> +    pci_set_byte(pci->w1cmask + 0xc7, 0xff);
>> +
>> +    for (id = 0; id < 8; ++id) {
>> +        memory_region_set_enabled(&s->simm[id], false);
>> +    }
>> +
>> +    if (s->x_auto_conf) {
>> +        /* enable all memory banks, starting from address 0 */
>> +        uint32_t start_address = 0, end_address = 0;
>> +        uint8_t ext_start, ext_end, enabled = 0;
>> +        int i;
>> +        for (i = 0; i < 8; i++) {
>> +            if (!memory_region_size(&s->simm[i])) {
>> +                continue;
>> +            }
>> +            end_address += memory_region_size(&s->simm[i]);
>> +            ext_start = pci_get_byte(pci_conf + EXT_MEM_STA_03 + i) & ~0x3;
>> +            ext_end = pci_get_byte(pci_conf + EXT_MEM_STA_03 + i) & ~0x3;
>> +            ext_start |= (start_address >> 28) & 0x3;
>> +            ext_end |= ((end_address - 1) >> 28) & 0x3;
>> +            pci_set_byte(pci_conf + MEM_STA_03 + i, start_address >> 20);
>> +            pci_set_byte(pci_conf + EXT_MEM_STA_03 + i, ext_start);
>> +            pci_set_byte(pci_conf + MEM_END_03 + i, (end_address - 1) >> 20);
>> +            pci_set_byte(pci_conf + EXT_MEM_END_03 + i, ext_end);
>> +            start_address = end_address;
>> +            enabled |= 1 << i;
>> +        }
>> +        pci_set_byte(pci_conf + MEM_BANK_EN, enabled);
>> +        pci_long_test_and_set_mask(pci_conf + MEM_CFG_1, MEM_CFG_1_MEMGO);
>> +        mpc105_update_memory_mappings(s);
>> +    }
>> +}
>> +
>> +static void qdev_mpc105_reset(DeviceState *dev)
>> +{
>> +    Mpc105State *s = MPC105(dev);
>> +    mpc105_reset(s);
>> +}
>> +
>> +static int mpc105_post_load(void *opaque, int version_id)
>> +{
>> +    Mpc105State *s = opaque;
>> +    mpc105_update_memory_mappings(s);
>> +    return 0;
>> +}
>> +
>> +static const VMStateDescription vmstate_mpc105 = {
>> +    .name = "mpc105",
>> +    .version_id = 1,
>> +    .minimum_version_id = 0,
>> +    .minimum_version_id_old = 1,
>> +    .post_load = mpc105_post_load,
>> +    .fields = (VMStateField[]) {
>> +        VMSTATE_PCI_DEVICE(parent_obj, Mpc105State),
>> +        VMSTATE_END_OF_LIST()
>> +    }
>> +};
>> +
>> +static uint64_t mpc105_intack_read(void *opaque, hwaddr addr,
>> +                                   unsigned int size)
>> +{
>> +    return pic_read_irq(isa_pic);
>> +}
>> +
>> +static const MemoryRegionOps mpc105_intack_ops = {
>> +    .read = mpc105_intack_read,
>> +    .valid = {
>> +        .max_access_size = 1,
>> +    },
>> +};
>> +
>> +static int mpc105_initfn(PCIDevice *dev)
>> +{
>> +    Mpc105State *s = MPC105(dev);
>> +    char *filename;
>> +    int bios_size = -1;
>> +    int i = 0;
>> +    uint32_t simm_size[8] = { 0 };
>> +
>> +    unsigned int ram_size = s->ram_size / (1024 * 1024);
>> +    while (i < 8) {
>> +        int idx = qemu_fls(ram_size);
>> +        if (idx < 5) {
>> +            /* Need at least 16 Mb for a slot */
>> +            break;
>> +        } else if (idx >= 8) {
>> +            /* Limit to 128 Mb by slot (at max) */
>> +            idx = 8;
>> +        }
>> +        simm_size[i] = 1 << (idx - 1);
>> +        ram_size -= simm_size[i];
>> +        i++;
>> +    }
>> +
>> +    for (i = 0; i < 8; i++) {
>> +        char name[] = "simm.?";
>> +        name[5] = i + '0';
>> +        if (simm_size[i]) {
>> +            trace_mpc105_simm_size(i, simm_size[i]);
>> +            memory_region_init_ram(&s->simm[i], name,
>> +                                   simm_size[i] * 1024 * 1024);
>> +            vmstate_register_ram_global(&s->simm[i]);
>> +        } else {
>> +            memory_region_init(&s->simm[i], name, 0);
>> +        }
>> +        memory_region_init(&s->sizer[i], "sizer", 0);
>> +        memory_region_add_subregion_overlap(get_system_memory(), 0,
>> +                                            &s->simm[i], i);
>> +        memory_region_set_enabled(&s->simm[i], false);
>> +    }
>> +
>> +    memory_region_init_ram(&s->bios, "bios", BIOS_SIZE);
>> +    memory_region_set_readonly(&s->bios, true);
>> +    memory_region_add_subregion(get_system_memory(), (uint32_t)(-BIOS_SIZE),
>> +                                &s->bios);
>> +    vmstate_register_ram_global(&s->bios);
>> +    if (s->bios_name) {
> 
> Can't you just reuse the normal -bios logic?

bios property is filled with -bios name in the machine init function.
mpc105 datasheet explicity says where the bios/firmware i loaded, and I 
wanted to keep the machine init function as small as possible.

> 
>> +        filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, s->bios_name);
>> +        if (filename) {
>> +            if (s->elf_machine != EM_NONE) {
> 
> Elf machine?

Yes, like EM_PPC, required by function load_elf below.

> 
>> +                bios_size = load_elf(filename, NULL, NULL, NULL,
>> +                                     NULL, NULL, 1, s->elf_machine, 0);
>> +            }
>> +            if (bios_size < 0) {
>> +                bios_size = get_image_size(filename);
>> +                if (bios_size > 0 && bios_size <= BIOS_SIZE) {
>> +                    hwaddr bios_addr;
>> +                    bios_size = (bios_size + 0xfff) & ~0xfff;
>> +                    bios_addr = (uint32_t)(-BIOS_SIZE);
>> +                    bios_size = load_image_targphys(filename, bios_addr,
>> +                                                    bios_size);
>> +                }
>> +            }
>> +        }
>> +        if (bios_size < 0 || bios_size > BIOS_SIZE) {
>> +            hw_error("qemu: could not load bios image '%s'\n", s->bios_name);
>> +        }
>> +        if (filename) {
>> +            g_free(filename);
>> +        }
>> +    }
>> +
>> +    return 0;
>> +}
>> +
>> +static void mpc105_class_init(ObjectClass *klass, void *data)
>> +{
>> +    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
>> +    DeviceClass *dc = DEVICE_CLASS(klass);
>> +
>> +    k->init = mpc105_initfn;
>> +    k->vendor_id = PCI_VENDOR_ID_MOTOROLA;
>> +    k->device_id = PCI_DEVICE_ID_MOTOROLA_MPC105;
>> +    k->class_id = PCI_CLASS_BRIDGE_HOST;
>> +    k->config_write = mpc105_write_config;
>> +    dc->desc = "MPC105 PCI bridge/Memory controller";
>> +    dc->reset = qdev_mpc105_reset;
>> +    dc->vmsd = &vmstate_mpc105;
>> +    dc->no_user = 1;
>> +}
>> +
>> +static TypeInfo mpc105_info = {
>> +    .name          = TYPE_MPC105,
>> +    .parent        = TYPE_PCI_DEVICE,
>> +    .instance_size = sizeof(Mpc105State),
>> +    .class_init    = mpc105_class_init,
>> +};
>> +
>> +typedef struct Mpc105HostState {
>> +    PCIHostState host_state;
>> +    uint32_t ram_size;
>> +    qemu_irq irq[PCI_NUM_PINS];
>> +    PCIBus pci_bus;
>> +    MemoryRegion pci_io;
>> +    MemoryRegion isa_io;
>> +    MemoryRegion pci_intack;
>> +    MemoryRegion pci_memory;
>> +    MemoryRegion rom;
>> +    Mpc105State pci_dev;
>> +} Mpc105HostState;
>> +
>> +static void mpc105_set_irq(void *opaque, int irq_num, int level)
>> +{
>> +    qemu_irq *pic = opaque;
>> +
>> +    qemu_set_irq(pic[irq_num] , level);
>> +}
>> +
>> +static int mpc105_map_irq(PCIDevice *pci_dev, int irq_num)
>> +{
>> +    return (irq_num + (pci_dev->devfn >> 3)) & 1;
>> +}
>> +
>> +static void mpc105_pcihost_realizefn(DeviceState *d, Error **errp)
>> +{
>> +    SysBusDevice *dev = SYS_BUS_DEVICE(d);
>> +    PCIHostState *h = PCI_HOST_BRIDGE(dev);
>> +    Mpc105HostState *s = MPC105_PCI_HOST_BRIDGE(dev);
>> +    int i;
>> +
>> +    for (i = 0; i < PCI_NUM_PINS; i++) {
>> +        sysbus_init_irq(dev, &s->irq[i]);
>> +    }
>> +
>> +    pci_bus_irqs(&s->pci_bus, mpc105_set_irq, mpc105_map_irq, s->irq, 4);
>> +
>> +    memory_region_init_io(&h->conf_mem, &pci_host_conf_le_ops, s,
>> +                          "pci-conf-idx", 1);
>> +    memory_region_add_subregion(get_system_io(), 0xcf8, &h->conf_mem);
>> +
>> +    memory_region_init_io(&h->data_mem, &pci_host_data_le_ops, s,
>> +                          "pci-conf-data", 4);
>> +
> 

Hervé

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

* Re: [Qemu-devel] [PATCH 7/7] prep: QOM'ify System I/O
  2013-05-02 20:09 ` [Qemu-devel] [PATCH 7/7] prep: QOM'ify System I/O Hervé Poussineau
@ 2013-05-03 11:36   ` Andreas Färber
  2013-05-04  9:38     ` Hervé Poussineau
  0 siblings, 1 reply; 24+ messages in thread
From: Andreas Färber @ 2013-05-03 11:36 UTC (permalink / raw)
  To: Hervé Poussineau; +Cc: Julio Guerra, qemu-ppc, qemu-devel

Am 02.05.2013 22:09, schrieb Hervé Poussineau:
> Most of the functionality is extracted from hw/ppc/prep.c.
> Also add support for board identification/equipment registers.
> 
> Document it for the IBM 43p emulation.
> 
> Cc: Julio Guerra <guerr@julio.in>
> Signed-off-by: Hervé Poussineau <hpoussin@reactos.org>
> ---
>  docs/ibm_43p.cfg       |    5 +
>  hw/ppc/Makefile.objs   |    1 +
>  hw/ppc/prep_systemio.c |  298 ++++++++++++++++++++++++++++++++++++++++++++++++
>  trace-events           |    4 +
>  4 files changed, 308 insertions(+)
>  create mode 100644 hw/ppc/prep_systemio.c

Haven't reviewed the full patch yet, but since this is not modifying
hw/ppc/prep.c, it is duplicating code rather than QOM'ifying the
existing code.

Have you looked into Julio's patch whom you CC? I'm still not sure how
to solve things for 1.5 (and this series a consider -next).

Regards,
Andreas

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

* Re: [Qemu-devel] [PATCH 2/7] qom: handle registration of new types when initializing the first ones
  2013-05-02 20:08 ` [Qemu-devel] [PATCH 2/7] qom: handle registration of new types when initializing the first ones Hervé Poussineau
@ 2013-05-03 11:46   ` Andreas Färber
  2013-05-05  8:38     ` Hervé Poussineau
  0 siblings, 1 reply; 24+ messages in thread
From: Andreas Färber @ 2013-05-03 11:46 UTC (permalink / raw)
  To: Hervé Poussineau
  Cc: Paolo Bonzini, qemu-ppc, qemu-devel, Anthony Liguori

Am 02.05.2013 22:08, schrieb Hervé Poussineau:
> When initializing all types in object_class_foreach, called by object_class_get_list,
> some new types may be registered. Those will change the type internal hashtable which
> is currently enumerated, and may crash QEMU.
> 
> Fix it, by adding a second hash table which contains all the non-initialized types,
> merged to the main one before each round of initializations.
> 
> Bug has been detected when registering dynamic types containing an interface.
> 
> Signed-off-by: Hervé Poussineau <hpoussin@reactos.org>
> ---
>  qom/object.c |   45 +++++++++++++++++++++++++++++++++++++--------
>  1 file changed, 37 insertions(+), 8 deletions(-)

Could you be more specific about how to reproduce the problem? Is it a
generic issue or specific to some later patch in this series? I find
neither object_class_get_list() nor object_class_for_each() being used
in this series. And registering types during object_class_for_each()
doesn't sound right... CC'ing Anthony and Paolo.

Andreas

> diff --git a/qom/object.c b/qom/object.c
> index 75e6aac..e0a24dc 100644
> --- a/qom/object.c
> +++ b/qom/object.c
> @@ -65,25 +65,39 @@ struct TypeImpl
>  
>  static Type type_interface;
>  
> +static GHashTable *type_table_to_initialize;
> +static GHashTable *type_table_initialized;
> +
>  static GHashTable *type_table_get(void)
>  {
> -    static GHashTable *type_table;
> -
> -    if (type_table == NULL) {
> -        type_table = g_hash_table_new(g_str_hash, g_str_equal);
> +    if (!type_table_initialized) {
> +        type_table_initialized = g_hash_table_new(g_str_hash, g_str_equal);
>      }
>  
> -    return type_table;
> +    return type_table_initialized;
>  }
>  
>  static void type_table_add(TypeImpl *ti)
>  {
> -    g_hash_table_insert(type_table_get(), (void *)ti->name, ti);
> +    GHashTable **type_table;
> +    if (ti->class) {
> +        type_table = &type_table_initialized;
> +    } else {
> +        type_table = &type_table_to_initialize;
> +    }
> +    if (!*type_table) {
> +        *type_table = g_hash_table_new(g_str_hash, g_str_equal);
> +    }
> +    g_hash_table_insert(*type_table, (void *)ti->name, ti);
>  }
>  
>  static TypeImpl *type_table_lookup(const char *name)
>  {
> -    return g_hash_table_lookup(type_table_get(), name);
> +    TypeImpl *ret = g_hash_table_lookup(type_table_get(), name);
> +    if (!ret && type_table_to_initialize) {
> +        ret = g_hash_table_lookup(type_table_to_initialize, name);
> +    }
> +    return ret;
>  }
>  
>  static TypeImpl *type_register_internal(const TypeInfo *info)
> @@ -573,13 +587,28 @@ static void object_class_foreach_tramp(gpointer key, gpointer value,
>      data->fn(k, data->opaque);
>  }
>  
> +static void object_class_merge(gpointer key, gpointer value,
> +                               gpointer opaque)
> +{
> +    g_hash_table_insert(type_table_get(), key, value);
> +}
> +
>  void object_class_foreach(void (*fn)(ObjectClass *klass, void *opaque),
>                            const char *implements_type, bool include_abstract,
>                            void *opaque)
>  {
>      OCFData data = { fn, implements_type, include_abstract, opaque };
>  
> -    g_hash_table_foreach(type_table_get(), object_class_foreach_tramp, &data);
> +    while (type_table_to_initialize &&
> +           g_hash_table_size(type_table_to_initialize) > 0) {
> +        g_hash_table_foreach(type_table_to_initialize, object_class_merge,
> +                             NULL);
> +        g_hash_table_destroy(type_table_to_initialize);
> +        type_table_to_initialize = NULL;
> +
> +        g_hash_table_foreach(type_table_get(), object_class_foreach_tramp,
> +                             &data);
> +    }
>  }
>  
>  int object_child_foreach(Object *obj, int (*fn)(Object *child, void *opaque),
> 


-- 
SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 Nürnberg, Germany
GF: Jeff Hawn, Jennifer Guild, Felix Imendörffer; HRB 16746 AG Nürnberg

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

* Re: [Qemu-devel] [PATCH 4/7] m48t59: register a QOM type for each nvram type we support
  2013-05-03  5:50     ` Hervé Poussineau
@ 2013-05-03 23:16       ` Artyom Tarasenko
  2013-05-04  5:24         ` Hervé Poussineau
  0 siblings, 1 reply; 24+ messages in thread
From: Artyom Tarasenko @ 2013-05-03 23:16 UTC (permalink / raw)
  To: Hervé Poussineau
  Cc: Blue Swirl, qemu-ppc, qemu-devel, Andreas Färber

On Fri, May 3, 2013 at 7:50 AM, Hervé Poussineau <hpoussin@reactos.org> wrote:
> Artyom Tarasenko a écrit :
>
>> On Thu, May 2, 2013 at 10:09 PM, Hervé Poussineau <hpoussin@reactos.org>
>> wrote:
>>>
>>> As m48t59 devices can only be created with m48t59_init() or
>>> m48t59_init_isa(),
>>> we know exactly which nvram types are required. Register only those three
>>> types.
>>
>>
>> Wasn't this patch NACKed by Blue?
>
>
> I think I changed what's requested, ie I kept the io-base property of the
> ISA variant, so the sun4u emulation can be changed later to the right
> address. However, fixing sun4u emulation is not part of this patchset.

Sorry, I misread the patch. The value 0x74 is now just a default value for
the isa port, right? How would I create an isa m48t59 card on some other port?

Artyom

--
Regards,
Artyom Tarasenko

linux/sparc and solaris/sparc under qemu blog:
http://tyom.blogspot.com/search/label/qemu

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

* Re: [Qemu-devel] [PATCH 4/7] m48t59: register a QOM type for each nvram type we support
  2013-05-03 23:16       ` Artyom Tarasenko
@ 2013-05-04  5:24         ` Hervé Poussineau
  0 siblings, 0 replies; 24+ messages in thread
From: Hervé Poussineau @ 2013-05-04  5:24 UTC (permalink / raw)
  To: Artyom Tarasenko; +Cc: Blue Swirl, qemu-ppc, qemu-devel, Andreas Färber

Artyom Tarasenko a écrit :
> On Fri, May 3, 2013 at 7:50 AM, Hervé Poussineau <hpoussin@reactos.org> wrote:
>> Artyom Tarasenko a écrit :
>>
>>> On Thu, May 2, 2013 at 10:09 PM, Hervé Poussineau <hpoussin@reactos.org>
>>> wrote:
>>>> As m48t59 devices can only be created with m48t59_init() or
>>>> m48t59_init_isa(),
>>>> we know exactly which nvram types are required. Register only those three
>>>> types.
>>>
>>> Wasn't this patch NACKed by Blue?
>>
>> I think I changed what's requested, ie I kept the io-base property of the
>> ISA variant, so the sun4u emulation can be changed later to the right
>> address. However, fixing sun4u emulation is not part of this patchset.
> 
> Sorry, I misread the patch. The value 0x74 is now just a default value for
> the isa port, right? How would I create an isa m48t59 card on some other port?

Yes, 0x74 is now the default value.

You can create an isa m48t59 device on port 0x100
- with command line: -device isa-m4859,iobase=0x100
- in code using the helper: m48t59_init_isa(isa_bus, 0x100, 0x2000, 59);
- with QOM: DeviceState *dev;
             dev = DEVICE(isa_create(isa_bus, "isa-m48t59"));
             qdev_prop_set_uint16(dev, "iobase", 0x100);
             qdev_init_nofail(dev);

Hervé

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

* Re: [Qemu-devel] [PATCH 7/7] prep: QOM'ify System I/O
  2013-05-03 11:36   ` Andreas Färber
@ 2013-05-04  9:38     ` Hervé Poussineau
  0 siblings, 0 replies; 24+ messages in thread
From: Hervé Poussineau @ 2013-05-04  9:38 UTC (permalink / raw)
  To: Andreas Färber; +Cc: Julio Guerra, qemu-ppc, qemu-devel

Andreas Färber a écrit :
> Am 02.05.2013 22:09, schrieb Hervé Poussineau:
>> Most of the functionality is extracted from hw/ppc/prep.c.
>> Also add support for board identification/equipment registers.
>>
>> Document it for the IBM 43p emulation.
>>
>> Cc: Julio Guerra <guerr@julio.in>
>> Signed-off-by: Hervé Poussineau <hpoussin@reactos.org>
>> ---
>>  docs/ibm_43p.cfg       |    5 +
>>  hw/ppc/Makefile.objs   |    1 +
>>  hw/ppc/prep_systemio.c |  298 ++++++++++++++++++++++++++++++++++++++++++++++++
>>  trace-events           |    4 +
>>  4 files changed, 308 insertions(+)
>>  create mode 100644 hw/ppc/prep_systemio.c
> 
> Haven't reviewed the full patch yet, but since this is not modifying
> hw/ppc/prep.c, it is duplicating code rather than QOM'ifying the
> existing code.
> 
> Have you looked into Julio's patch whom you CC? I'm still not sure how
> to solve things for 1.5 (and this series a consider -next).

Yes, I've partly taken Julio's patch into account, ie port 0x92 is now 
read/write. However, I didn't change the way the reset is done due to 
missing agrement of how it should be done: "this is touching on the same 
soft reset topic that I am awaiting the outcome for x86". [1]

Moreover, registers emulated are not exactly the same as in hw/ppc/prep.c:
Registers not present in hw/ppc/prep_systemio.c:
0x800: Motorola CPU configuration register
0x802: Motorola base module feature register
0x803: Motorola base module status register
0x823: Something related to no L2 cache?
Those seem specific to Motorola, so they probably belong to another device.

New registers added to hw/ppc/prep_systemio.c:
0x818: Key lock (Read Only)
0x852: System Board Identification (Read Only)

I'm not really sure of impacts of changing 'prep' machine to remove some 
registers and adding new ones, so I prefered to keep it as is. However, 
if you think that I should use the QOM'ified System I/O device in 'prep' 
machine (and this will change emulated machine), I'll do it.

Hervé

[1] https://lists.gnu.org/archive/html/qemu-devel/2013-04/msg03359.html

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

* Re: [Qemu-devel] [PATCH 2/7] qom: handle registration of new types when initializing the first ones
  2013-05-03 11:46   ` Andreas Färber
@ 2013-05-05  8:38     ` Hervé Poussineau
  0 siblings, 0 replies; 24+ messages in thread
From: Hervé Poussineau @ 2013-05-05  8:38 UTC (permalink / raw)
  To: Andreas Färber; +Cc: Paolo Bonzini, qemu-ppc, qemu-devel, Anthony Liguori

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

Andreas Färber a écrit :
> Am 02.05.2013 22:08, schrieb Hervé Poussineau:
>> When initializing all types in object_class_foreach, called by object_class_get_list,
>> some new types may be registered. Those will change the type internal hashtable which
>> is currently enumerated, and may crash QEMU.
>>
>> Fix it, by adding a second hash table which contains all the non-initialized types,
>> merged to the main one before each round of initializations.
>>
>> Bug has been detected when registering dynamic types containing an interface.
>>
>> Signed-off-by: Hervé Poussineau <hpoussin@reactos.org>
>> ---
>>  qom/object.c |   45 +++++++++++++++++++++++++++++++++++++--------
>>  1 file changed, 37 insertions(+), 8 deletions(-)
> 
> Could you be more specific about how to reproduce the problem? Is it a
> generic issue or specific to some later patch in this series? I find
> neither object_class_get_list() nor object_class_for_each() being used
> in this series. And registering types during object_class_for_each()
> doesn't sound right... CC'ing Anthony and Paolo.

Try the attached patch, and run with qemu-system-ppc (no arguments)
I added a dummy interface to a random device, but the problem should be 
exposed by whatever interface on whatever device. I saw the problem in 
patch 5/7 ("add a Nvram interface").
However, the problem doesn't seem to appear on other system emulations 
like i386.

With attached patch, you'll get an assert:
qemu-system-ppc: qom/object.c:82: type_table_add: Assertion 
`!enumerating' failed.

Program received signal SIGABRT, Aborted.
0xb7fe1430 in __kernel_vsyscall ()
(gdb) bt
  #0  0xb7fe1430 in __kernel_vsyscall ()
  #1  0xb6f27941 in *__GI_raise (sig=6) at 
../nptl/sysdeps/unix/sysv/linux/raise.c:64
  #2  0xb6f2ad72 in *__GI_abort () at abort.c:92
  #3  0xb6f20b58 in *__GI___assert_fail 
(assertion=assertion@entry=0x803809f8 "!enumerating",
      file=file@entry=0x80380adc "qom/object.c", line=line@entry=82,
      function=function@entry=0x80380c6c "type_table_add") at assert.c:81
  #4  0x80197513 in type_table_add (ti=0x80b67bd0) at qom/object.c:82
  #5  type_register_internal (info=0xbfffef0c) at qom/object.c:124
  #6  0x8019764c in type_initialize_interface (parent=0x80b3ec18 
"interface",
      ti=<error reading variable: Unhandled dwarf expression opcode 0xfa>,
      ti=<error reading variable: Unhandled dwarf expression opcode 
0xfa>) at qom/object.c:218
  #7  0x801978fe in type_initialize (ti=<optimized out>) at qom/object.c:271
  #8  type_initialize (ti=0x80b3eb30) at qom/object.c:229
  #9  0x80197dfa in object_class_foreach_tramp (key=0x80b3ebf0, 
value=0x80b3eb30, opaque=0xbffff03c)
      at qom/object.c:563
  #10 0xb7ef35e2 in g_hash_table_foreach () from 
/lib/i386-linux-gnu/libglib-2.0.so.0
  #11 0x801980b1 in object_class_foreach (fn=fn@entry=0x80197180 
<object_class_get_list_tramp>,
      implements_type=implements_type@entry=0x8039b834 "powerpc-cpu", 
include_abstract=include_abstract@entry=false,
      opaque=opaque@entry=0xbffff078) at qom/object.c:585
  #12 0x801981ba in object_class_get_list 
(implements_type=implements_type@entry=0x8039b834 "powerpc-cpu",
      include_abstract=include_abstract@entry=false) at qom/object.c:618
  #13 0x80328d4e in ppc_cpu_class_by_name (name=name@entry=0x8039dc69 "G3")
      at target-ppc/translate_init.c:8003
  #14 0x80328f7a in cpu_ppc_init (cpu_model=cpu_model@entry=0x8039dc69 "G3")
      at target-ppc/translate_init.c:8020
  #15 0x80216724 in ppc_heathrow_init (args=0xbffff2a8) at 
hw/ppc/mac_oldworld.c:109
  #16 0x80040b81 in main (argc=1, argv=0xbffff4b4, envp=0xbffff4bc) at 
vl.c:4304
> 
>> diff --git a/qom/object.c b/qom/object.c
>> index 75e6aac..e0a24dc 100644
>> --- a/qom/object.c
>> +++ b/qom/object.c
>> @@ -65,25 +65,39 @@ struct TypeImpl
>>  
>>  static Type type_interface;
>>  
>> +static GHashTable *type_table_to_initialize;
>> +static GHashTable *type_table_initialized;
>> +
>>  static GHashTable *type_table_get(void)
>>  {
>> -    static GHashTable *type_table;
>> -
>> -    if (type_table == NULL) {
>> -        type_table = g_hash_table_new(g_str_hash, g_str_equal);
>> +    if (!type_table_initialized) {
>> +        type_table_initialized = g_hash_table_new(g_str_hash, g_str_equal);
>>      }
>>  
>> -    return type_table;
>> +    return type_table_initialized;
>>  }
>>  
>>  static void type_table_add(TypeImpl *ti)
>>  {
>> -    g_hash_table_insert(type_table_get(), (void *)ti->name, ti);
>> +    GHashTable **type_table;
>> +    if (ti->class) {
>> +        type_table = &type_table_initialized;
>> +    } else {
>> +        type_table = &type_table_to_initialize;
>> +    }
>> +    if (!*type_table) {
>> +        *type_table = g_hash_table_new(g_str_hash, g_str_equal);
>> +    }
>> +    g_hash_table_insert(*type_table, (void *)ti->name, ti);
>>  }
>>  
>>  static TypeImpl *type_table_lookup(const char *name)
>>  {
>> -    return g_hash_table_lookup(type_table_get(), name);
>> +    TypeImpl *ret = g_hash_table_lookup(type_table_get(), name);
>> +    if (!ret && type_table_to_initialize) {
>> +        ret = g_hash_table_lookup(type_table_to_initialize, name);
>> +    }
>> +    return ret;
>>  }
>>  
>>  static TypeImpl *type_register_internal(const TypeInfo *info)
>> @@ -573,13 +587,28 @@ static void object_class_foreach_tramp(gpointer key, gpointer value,
>>      data->fn(k, data->opaque);
>>  }
>>  
>> +static void object_class_merge(gpointer key, gpointer value,
>> +                               gpointer opaque)
>> +{
>> +    g_hash_table_insert(type_table_get(), key, value);
>> +}
>> +
>>  void object_class_foreach(void (*fn)(ObjectClass *klass, void *opaque),
>>                            const char *implements_type, bool include_abstract,
>>                            void *opaque)
>>  {
>>      OCFData data = { fn, implements_type, include_abstract, opaque };
>>  
>> -    g_hash_table_foreach(type_table_get(), object_class_foreach_tramp, &data);
>> +    while (type_table_to_initialize &&
>> +           g_hash_table_size(type_table_to_initialize) > 0) {
>> +        g_hash_table_foreach(type_table_to_initialize, object_class_merge,
>> +                             NULL);
>> +        g_hash_table_destroy(type_table_to_initialize);
>> +        type_table_to_initialize = NULL;
>> +
>> +        g_hash_table_foreach(type_table_get(), object_class_foreach_tramp,
>> +                             &data);
>> +    }
>>  }
>>  
>>  int object_child_foreach(Object *obj, int (*fn)(Object *child, void *opaque),
>>
> 
> 


[-- Attachment #2: 0001-usb-ehci-add-an-empty-interface-to-expose-a-problem-.patch --]
[-- Type: text/plain, Size: 3765 bytes --]

From 4da22be31d5fc8df887b8c76c609b9844bebe9f4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Herv=C3=A9=20Poussineau?= <hpoussin@reactos.org>
Date: Sun, 5 May 2013 10:31:24 +0200
Subject: [PATCH] usb-ehci: add an empty interface to expose a problem in QOM

Run with qemu-system-ppc (no arguments)

qemu-system-ppc: qom/object.c:82: type_table_add: Assertion `!enumerating' failed.

Program received signal SIGABRT, Aborted.
0xb7fe1430 in __kernel_vsyscall ()
(gdb) bt
 #0  0xb7fe1430 in __kernel_vsyscall ()
 #1  0xb6f27941 in *__GI_raise (sig=6) at ../nptl/sysdeps/unix/sysv/linux/raise.c:64
 #2  0xb6f2ad72 in *__GI_abort () at abort.c:92
 #3  0xb6f20b58 in *__GI___assert_fail (assertion=assertion@entry=0x803809f8 "!enumerating",
     file=file@entry=0x80380adc "qom/object.c", line=line@entry=82,
     function=function@entry=0x80380c6c "type_table_add") at assert.c:81
 #4  0x80197513 in type_table_add (ti=0x80b67bd0) at qom/object.c:82
 #5  type_register_internal (info=0xbfffef0c) at qom/object.c:124
 #6  0x8019764c in type_initialize_interface (parent=0x80b3ec18 "interface",
     ti=<error reading variable: Unhandled dwarf expression opcode 0xfa>,
     ti=<error reading variable: Unhandled dwarf expression opcode 0xfa>) at qom/object.c:218
 #7  0x801978fe in type_initialize (ti=<optimized out>) at qom/object.c:271
 #8  type_initialize (ti=0x80b3eb30) at qom/object.c:229
 #9  0x80197dfa in object_class_foreach_tramp (key=0x80b3ebf0, value=0x80b3eb30, opaque=0xbffff03c)
     at qom/object.c:563
 #10 0xb7ef35e2 in g_hash_table_foreach () from /lib/i386-linux-gnu/libglib-2.0.so.0
 #11 0x801980b1 in object_class_foreach (fn=fn@entry=0x80197180 <object_class_get_list_tramp>,
     implements_type=implements_type@entry=0x8039b834 "powerpc-cpu", include_abstract=include_abstract@entry=false,
     opaque=opaque@entry=0xbffff078) at qom/object.c:585
 #12 0x801981ba in object_class_get_list (implements_type=implements_type@entry=0x8039b834 "powerpc-cpu",
     include_abstract=include_abstract@entry=false) at qom/object.c:618
 #13 0x80328d4e in ppc_cpu_class_by_name (name=name@entry=0x8039dc69 "G3")
     at target-ppc/translate_init.c:8003
 #14 0x80328f7a in cpu_ppc_init (cpu_model=cpu_model@entry=0x8039dc69 "G3")
     at target-ppc/translate_init.c:8020
 #15 0x80216724 in ppc_heathrow_init (args=0xbffff2a8) at hw/ppc/mac_oldworld.c:109
 #16 0x80040b81 in main (argc=1, argv=0xbffff4b4, envp=0xbffff4bc) at vl.c:4304
---
 hw/usb/hcd-uhci.c |    4 ++++
 qom/object.c      |    4 ++++
 2 files changed, 8 insertions(+)

diff --git a/hw/usb/hcd-uhci.c b/hw/usb/hcd-uhci.c
index f8c4286..a95ca30 100644
--- a/hw/usb/hcd-uhci.c
+++ b/hw/usb/hcd-uhci.c
@@ -1386,6 +1386,10 @@ static void uhci_register_types(void)
         .instance_size = sizeof(UHCIState),
         .class_size    = sizeof(UHCIPCIDeviceClass),
         .class_init    = uhci_class_init,
+        .interfaces = (InterfaceInfo[]) {
+            { TYPE_INTERFACE },
+            { }
+        }
     };
     int i;
 
diff --git a/qom/object.c b/qom/object.c
index 75e6aac..b8e9f4f 100644
--- a/qom/object.c
+++ b/qom/object.c
@@ -76,8 +76,10 @@ static GHashTable *type_table_get(void)
     return type_table;
 }
 
+static bool enumerating = false;
 static void type_table_add(TypeImpl *ti)
 {
+    assert(!enumerating);
     g_hash_table_insert(type_table_get(), (void *)ti->name, ti);
 }
 
@@ -579,7 +581,9 @@ void object_class_foreach(void (*fn)(ObjectClass *klass, void *opaque),
 {
     OCFData data = { fn, implements_type, include_abstract, opaque };
 
+    enumerating = true;
     g_hash_table_foreach(type_table_get(), object_class_foreach_tramp, &data);
+    enumerating = false;
 }
 
 int object_child_foreach(Object *obj, int (*fn)(Object *child, void *opaque),
-- 
1.7.10.4


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

* Re: [Qemu-devel] [Qemu-ppc] [PATCH 1/7] pci: add MPC105 PCI host bridge emulation
  2013-05-03  5:57     ` Hervé Poussineau
@ 2013-05-06 15:01       ` Alexander Graf
  2013-05-06 20:57         ` Hervé Poussineau
  0 siblings, 1 reply; 24+ messages in thread
From: Alexander Graf @ 2013-05-06 15:01 UTC (permalink / raw)
  To: Hervé Poussineau; +Cc: qemu-ppc, qemu-devel, Andreas Färber

On 05/03/2013 07:57 AM, Hervé Poussineau wrote:
> Alexander Graf a écrit :
>>
>> Am 02.05.2013 um 22:08 schrieb Hervé Poussineau <hpoussin@reactos.org>:
>>
>>> Non-contiguous I/O is not implemented.
>>>
>>> There is also somewhere a bug in the memory controller, which means
>>> that some real firmwares may not detect the correct amount of memory.
>>> This can be bypassed by adding '-m 1G' on the command line.
>>>
>>> Add x-auto-conf property, to automatically configure the memory
>>> controller at startup. This will be required by OpenBIOS, which
>>> doesn't know how to do it.
>>
>> Why not teach it? I'd prefer to see that logic in firmware.
>
> Me too, but I'm not confident enough in my capabilities to do it.

Huh? Why not? Most of the device initialization code in OpenBIOS happens 
in C, so you don't even have to touch Forth code :).

> Autoconfiguration is only in one place of the code, so I think it can 
> be removed easily once OpenBIOS has this logic.

I'd prefer if we could come up with a clean model from the start. It 
really shouldn't be hard at all.

>
>>
>>> Signed-off-by: Hervé Poussineau <hpoussin@reactos.org>
>>> ---
>>> default-configs/ppc-softmmu.mak |    1 +
>>> hw/pci-host/Makefile.objs       |    1 +
>>> hw/pci-host/mpc105.c            |  488 
>>> +++++++++++++++++++++++++++++++++++++++
>>> include/hw/pci/pci_ids.h        |    1 +
>>> trace-events                    |    7 +
>>> 5 files changed, 498 insertions(+)
>>> create mode 100644 hw/pci-host/mpc105.c
>>>
>>> diff --git a/default-configs/ppc-softmmu.mak 
>>> b/default-configs/ppc-softmmu.mak
>>> index cc3587f..f79b058 100644
>>> --- a/default-configs/ppc-softmmu.mak
>>> +++ b/default-configs/ppc-softmmu.mak
>>> @@ -28,6 +28,7 @@ CONFIG_MAC_NVRAM=y
>>> CONFIG_MAC_DBDMA=y
>>> CONFIG_HEATHROW_PIC=y
>>> CONFIG_GRACKLE_PCI=y
>>> +CONFIG_MPC105_PCI=y
>>> CONFIG_UNIN_PCI=y
>>> CONFIG_DEC_PCI=y
>>> CONFIG_PPCE500_PCI=y
>>> diff --git a/hw/pci-host/Makefile.objs b/hw/pci-host/Makefile.objs
>>> index 909e702..ec4427b 100644
>>> --- a/hw/pci-host/Makefile.objs
>>> +++ b/hw/pci-host/Makefile.objs
>>> @@ -3,6 +3,7 @@ common-obj-y += pam.o
>>> # PPC devices
>>> common-obj-$(CONFIG_PREP_PCI) += prep.o
>>> common-obj-$(CONFIG_GRACKLE_PCI) += grackle.o
>>> +common-obj-$(CONFIG_MPC105_PCI) += mpc105.o
>>> # NewWorld PowerMac
>>> common-obj-$(CONFIG_UNIN_PCI) += uninorth.o
>>> common-obj-$(CONFIG_DEC_PCI) += dec.o
>>> diff --git a/hw/pci-host/mpc105.c b/hw/pci-host/mpc105.c
>>> new file mode 100644
>>> index 0000000..8e4cc95
>>> --- /dev/null
>>> +++ b/hw/pci-host/mpc105.c
>>> @@ -0,0 +1,488 @@
>>> +/*
>>> + * QEMU MPC-105 Eagle PCI host
>>> + *
>>> + * Copyright (c) 2013 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 "hw/pci/pci.h"
>>> +#include "hw/pci/pci_bus.h"
>>> +#include "hw/pci/pci_host.h"
>>> +#include "hw/i386/pc.h"
>>
>> That include sounds odd :).
>
> Sure, but you need to access pic_read_irq() :)
> hw/pci-host/prep.c also includes it.

Phew. Would be a good thing to pull out of there. But it's out of the 
scope for this set.

>
>>
>>> +#include "hw/loader.h"
>>> +#include "exec/address-spaces.h"
>>> +#include "elf.h"
>>> +#include "trace.h"
>>> +
>>> +#define TYPE_MPC105_PCI_HOST_BRIDGE "mpc105-pcihost"
>>> +#define MPC105_PCI_HOST_BRIDGE(obj) \
>>> +    OBJECT_CHECK(Mpc105HostState, (obj), TYPE_MPC105_PCI_HOST_BRIDGE)
>>> +
>>> +#define TYPE_MPC105 "mpc105"
>>> +#define MPC105(obj) \
>>> +    OBJECT_CHECK(Mpc105State, (obj), TYPE_MPC105)
>>> +
>>> +#define MEM_STA_03     0x0080
>>> +#define MEM_STA_47     0x0084
>>> +#define EXT_MEM_STA_03 0x0088
>>> +#define EXT_MEM_STA_47 0x008c
>>> +#define MEM_END_03     0x0090
>>> +#define MEM_END_47     0x0094
>>> +#define EXT_MEM_END_03 0x0098
>>> +#define EXT_MEM_END_47 0x009c
>>> +#define MEM_BANK_EN    0x00a0
>>> +#define PROC_CFG_A8    0x00a8
>>> +#define PROC_CFG_AC    0x00ac
>>> +#define ALT_OSV_1      0x00ba
>>> +#define ERR_EN_REG1    0x00c0
>>> +#define ERR_DR1        0x00c1
>>> +#define ERR_EN_REG2    0x00c4
>>> +#define MEM_CFG_1      0x00f0
>>> +#define MEM_CFG_2      0x00f4
>>> +#define MEM_CFG_4      0x00fc
>>> +
>>> +#define MEM_CFG_1_MEMGO (1 << 19)
>>> +
>>> +#define BIOS_SIZE (1024 * 1024)
>>> +
>>> +typedef struct Mpc105State {
>>> +    PCIDevice parent_obj;
>>> +    uint32_t ram_size;
>>> +    uint32_t elf_machine;
>>> +    uint32_t x_auto_conf;
>>> +    char *bios_name;
>>> +    MemoryRegion bios;
>>> +    MemoryRegion simm[8];
>>> +    bool use_sizer[8];
>>> +    /* use a sizer to allow access to only part of a simm */
>>> +    MemoryRegion sizer[8];
>>> +} Mpc105State;
>>> +
>>> +static uint64_t mpc105_unassigned_read(void *opaque, hwaddr addr,
>>> +                                       unsigned int size)
>>> +{
>>> +    trace_mpc105_unassigned_mem_read(addr);
>>> +    return 0;
>>> +}
>>> +
>>> +static void mpc105_unassigned_write(void *opaque, hwaddr addr, 
>>> uint64_t data,
>>> +                                    unsigned int size)
>>> +{
>>> +    trace_mpc105_unassigned_mem_write(addr, data);
>>> +}
>>> +
>>> +static const MemoryRegionOps mpc105_unassigned_ops = {
>>> +    .read = mpc105_unassigned_read,
>>> +    .write = mpc105_unassigned_write,
>>> +};
>>> +
>>> +static void mpc105_update_memory_mappings(Mpc105State *s)
>>> +{
>>> +    uint32_t start_address, end_address;
>>> +    uint32_t start, ext_start, end, ext_end;
>>> +    uint32_t cfg1;
>>> +    uint64_t simm_size;
>>> +    uint8_t *pci_conf;
>>> +    uint8_t en;
>>> +    bool enabled;
>>> +    int i;
>>> +
>>> +    pci_conf = PCI_DEVICE(s)->config;
>>> +    cfg1 = pci_get_long(pci_conf + MEM_CFG_1);
>>> +
>>> +    memory_region_transaction_begin();
>>> +    if (cfg1 & MEM_CFG_1_MEMGO) {
>>> +        en = pci_get_byte(pci_conf + MEM_BANK_EN);
>>> +    } else {
>>> +        en = 0;
>>> +    }
>>> +
>>> +    for (i = 0; i < 8; i++) {
>>> +        enabled = (en & (1 << i));
>>> +
>>> +        start = pci_get_byte(pci_conf + MEM_STA_03 + i);
>>> +        ext_start = pci_get_byte(pci_conf + EXT_MEM_STA_03 + i) & 0x3;
>>> +        end = pci_get_byte(pci_conf + MEM_END_03 + i);
>>> +        ext_end = pci_get_byte(pci_conf + EXT_MEM_STA_03 + i) & 0x3;
>>> +        start_address = (ext_start << 28) | (start << 20);
>>> +        end_address = (ext_end << 28) | (end << 20) | 0xfffff;
>>> +
>>> +        enabled &= start_address < end_address;
>>> +
>>> +        if (enabled) {
>>> +            trace_mpc105_simm_enable(i, start_address, end_address 
>>> + 1);
>>> +        } else {
>>> +            trace_mpc105_simm_disable(i);
>>> +        }
>>> +
>>> +        simm_size = memory_region_size(&s->simm[i]);
>>> +        if (simm_size == 0) {
>>> +            continue;
>>> +        }
>>> +
>>> +        /* Clean links between system memory, sizer and simm */
>>> +        if (s->use_sizer[i]) {
>>> +            memory_region_del_subregion(get_system_memory(), 
>>> &s->sizer[i]);
>>> +            memory_region_del_subregion(&s->sizer[i], &s->simm[i]);
>>> +            s->use_sizer[i] = false;
>>> +        } else {
>>> +            memory_region_del_subregion(get_system_memory(), 
>>> &s->simm[i]);
>>> +        }
>>> +
>>> +        /* Recreate links compatible with new memory layout */
>>> +        if (enabled && end_address - start_address + 1 < simm_size) {
>>> +            memory_region_init_io(&s->sizer[i], 
>>> &mpc105_unassigned_ops,
>>> +                                  s, memory_region_name(&s->sizer[i]),
>>> +                                  end_address - start_address + 1);
>>> +            memory_region_add_subregion(&s->sizer[i], 0, &s->simm[i]);
>>> +            memory_region_add_subregion(get_system_memory(), 
>>> start_address,
>>> + &s->sizer[i]);
>>> +            s->use_sizer[i] = true;
>>> +        } else {
>>> +            memory_region_add_subregion(get_system_memory(), 
>>> start_address,
>>> + &s->simm[i]);
>>> +        }
>>> +        memory_region_set_enabled(&s->simm[i], enabled);
>>> +    }
>>> +    memory_region_transaction_commit();
>>> +}
>>> +
>>> +static void mpc105_write_config(PCIDevice *dev, uint32_t addr, 
>>> uint32_t val,
>>> +                                int l)
>>> +{
>>> +    Mpc105State *s = MPC105(dev);
>>> +
>>> +    pci_default_write_config(dev, addr, val, l);
>>> +    if ((addr >= MEM_STA_03 && addr <= MEM_BANK_EN) || addr == 
>>> MEM_CFG_1) {
>>> +        mpc105_update_memory_mappings(s);
>>> +    }
>>> +}
>>> +
>>> +static void mpc105_reset(Mpc105State *s)
>>> +{
>>> +    PCIDevice *pci = PCI_DEVICE(s);
>>> +    uint8_t *pci_conf;
>>> +    int id;
>>> +
>>> +    pci_conf = pci->config;
>>> +
>>> +    memset(pci_conf + PCI_CONFIG_HEADER_SIZE, 0,
>>> +           PCI_CONFIG_SPACE_SIZE - PCI_CONFIG_HEADER_SIZE);
>>> +    pci_conf[PCI_COMMAND] = PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY;
>>> +    pci_conf[PCI_STATUS] = PCI_STATUS_FAST_BACK;
>>> +    pci_set_long(pci_conf + PROC_CFG_A8, 0xff000010);
>>> +    pci_set_long(pci_conf + PROC_CFG_AC, 0x000c060c);
>>> +    pci_set_byte(pci_conf + ALT_OSV_1, 0x04);
>>> +    pci_set_byte(pci_conf + ERR_EN_REG1, 0x01);
>>> +    pci_set_long(pci_conf + MEM_CFG_1, 0xff020000);
>>> +    pci_set_long(pci_conf + MEM_CFG_2, 0x00000003);
>>> +    pci_set_long(pci_conf + MEM_CFG_4, 0x00100000);
>>> +
>>> +    memset(pci->wmask + PCI_CONFIG_HEADER_SIZE, 0,
>>> +           MEM_CFG_1 - PCI_CONFIG_HEADER_SIZE);
>>> +    memset(pci->wmask + 0x70, 0xff, 2);
>>> +    memset(pci->wmask + MEM_STA_03, 0xff, MEM_BANK_EN - MEM_STA_03 
>>> + 1);
>>> +    memset(pci->wmask + PROC_CFG_A8, 0xff, 8);
>>> +    pci_set_word(pci->wmask + ALT_OSV_1, 0xffff);
>>> +    pci_set_byte(pci->wmask + ERR_EN_REG1, 0xff);
>>> +    pci_set_byte(pci->w1cmask + ERR_DR1, 0xff);
>>> +    pci_set_byte(pci->w1cmask + 0xc3, 0xff);
>>> +    pci_set_byte(pci->wmask + ERR_EN_REG2, 0xff);
>>> +    pci_set_byte(pci->w1cmask + 0xc5, 0xff);
>>> +    pci_set_byte(pci->w1cmask + 0xc7, 0xff);
>>> +
>>> +    for (id = 0; id < 8; ++id) {
>>> +        memory_region_set_enabled(&s->simm[id], false);
>>> +    }
>>> +
>>> +    if (s->x_auto_conf) {
>>> +        /* enable all memory banks, starting from address 0 */
>>> +        uint32_t start_address = 0, end_address = 0;
>>> +        uint8_t ext_start, ext_end, enabled = 0;
>>> +        int i;
>>> +        for (i = 0; i < 8; i++) {
>>> +            if (!memory_region_size(&s->simm[i])) {
>>> +                continue;
>>> +            }
>>> +            end_address += memory_region_size(&s->simm[i]);
>>> +            ext_start = pci_get_byte(pci_conf + EXT_MEM_STA_03 + i) 
>>> & ~0x3;
>>> +            ext_end = pci_get_byte(pci_conf + EXT_MEM_STA_03 + i) & 
>>> ~0x3;
>>> +            ext_start |= (start_address >> 28) & 0x3;
>>> +            ext_end |= ((end_address - 1) >> 28) & 0x3;
>>> +            pci_set_byte(pci_conf + MEM_STA_03 + i, start_address 
>>> >> 20);
>>> +            pci_set_byte(pci_conf + EXT_MEM_STA_03 + i, ext_start);
>>> +            pci_set_byte(pci_conf + MEM_END_03 + i, (end_address - 
>>> 1) >> 20);
>>> +            pci_set_byte(pci_conf + EXT_MEM_END_03 + i, ext_end);
>>> +            start_address = end_address;
>>> +            enabled |= 1 << i;
>>> +        }
>>> +        pci_set_byte(pci_conf + MEM_BANK_EN, enabled);
>>> +        pci_long_test_and_set_mask(pci_conf + MEM_CFG_1, 
>>> MEM_CFG_1_MEMGO);
>>> +        mpc105_update_memory_mappings(s);
>>> +    }
>>> +}
>>> +
>>> +static void qdev_mpc105_reset(DeviceState *dev)
>>> +{
>>> +    Mpc105State *s = MPC105(dev);
>>> +    mpc105_reset(s);
>>> +}
>>> +
>>> +static int mpc105_post_load(void *opaque, int version_id)
>>> +{
>>> +    Mpc105State *s = opaque;
>>> +    mpc105_update_memory_mappings(s);
>>> +    return 0;
>>> +}
>>> +
>>> +static const VMStateDescription vmstate_mpc105 = {
>>> +    .name = "mpc105",
>>> +    .version_id = 1,
>>> +    .minimum_version_id = 0,
>>> +    .minimum_version_id_old = 1,
>>> +    .post_load = mpc105_post_load,
>>> +    .fields = (VMStateField[]) {
>>> +        VMSTATE_PCI_DEVICE(parent_obj, Mpc105State),
>>> +        VMSTATE_END_OF_LIST()
>>> +    }
>>> +};
>>> +
>>> +static uint64_t mpc105_intack_read(void *opaque, hwaddr addr,
>>> +                                   unsigned int size)
>>> +{
>>> +    return pic_read_irq(isa_pic);
>>> +}
>>> +
>>> +static const MemoryRegionOps mpc105_intack_ops = {
>>> +    .read = mpc105_intack_read,
>>> +    .valid = {
>>> +        .max_access_size = 1,
>>> +    },
>>> +};
>>> +
>>> +static int mpc105_initfn(PCIDevice *dev)
>>> +{
>>> +    Mpc105State *s = MPC105(dev);
>>> +    char *filename;
>>> +    int bios_size = -1;
>>> +    int i = 0;
>>> +    uint32_t simm_size[8] = { 0 };
>>> +
>>> +    unsigned int ram_size = s->ram_size / (1024 * 1024);
>>> +    while (i < 8) {
>>> +        int idx = qemu_fls(ram_size);
>>> +        if (idx < 5) {
>>> +            /* Need at least 16 Mb for a slot */
>>> +            break;
>>> +        } else if (idx >= 8) {
>>> +            /* Limit to 128 Mb by slot (at max) */
>>> +            idx = 8;
>>> +        }
>>> +        simm_size[i] = 1 << (idx - 1);
>>> +        ram_size -= simm_size[i];
>>> +        i++;
>>> +    }
>>> +
>>> +    for (i = 0; i < 8; i++) {
>>> +        char name[] = "simm.?";
>>> +        name[5] = i + '0';
>>> +        if (simm_size[i]) {
>>> +            trace_mpc105_simm_size(i, simm_size[i]);
>>> +            memory_region_init_ram(&s->simm[i], name,
>>> +                                   simm_size[i] * 1024 * 1024);
>>> +            vmstate_register_ram_global(&s->simm[i]);
>>> +        } else {
>>> +            memory_region_init(&s->simm[i], name, 0);
>>> +        }
>>> +        memory_region_init(&s->sizer[i], "sizer", 0);
>>> +        memory_region_add_subregion_overlap(get_system_memory(), 0,
>>> + &s->simm[i], i);
>>> +        memory_region_set_enabled(&s->simm[i], false);
>>> +    }
>>> +
>>> +    memory_region_init_ram(&s->bios, "bios", BIOS_SIZE);
>>> +    memory_region_set_readonly(&s->bios, true);
>>> +    memory_region_add_subregion(get_system_memory(), 
>>> (uint32_t)(-BIOS_SIZE),
>>> + &s->bios);
>>> +    vmstate_register_ram_global(&s->bios);
>>> +    if (s->bios_name) {
>>
>> Can't you just reuse the normal -bios logic?
>
> bios property is filled with -bios name in the machine init function.
> mpc105 datasheet explicity says where the bios/firmware i loaded, and 
> I wanted to keep the machine init function as small as possible.

I see, you just pass it from the machine model to the device. That's fine.

>
>>
>>> +        filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, s->bios_name);
>>> +        if (filename) {
>>> +            if (s->elf_machine != EM_NONE) {
>>
>> Elf machine?
>
> Yes, like EM_PPC, required by function load_elf below.

to make the device target agnostic. Works for me :).


Alex

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

* Re: [Qemu-devel] [Qemu-ppc] [PATCH 1/7] pci: add MPC105 PCI host bridge emulation
  2013-05-06 15:01       ` Alexander Graf
@ 2013-05-06 20:57         ` Hervé Poussineau
  2013-05-06 22:16           ` Alexander Graf
  2013-05-06 22:41           ` Andreas Färber
  0 siblings, 2 replies; 24+ messages in thread
From: Hervé Poussineau @ 2013-05-06 20:57 UTC (permalink / raw)
  To: Alexander Graf; +Cc: qemu-ppc, qemu-devel, Andreas Färber

Alexander Graf a écrit :
> On 05/03/2013 07:57 AM, Hervé Poussineau wrote:
>> Alexander Graf a écrit :
>>>
>>> Am 02.05.2013 um 22:08 schrieb Hervé Poussineau <hpoussin@reactos.org>:
>>>
>>>> Non-contiguous I/O is not implemented.
>>>>
>>>> There is also somewhere a bug in the memory controller, which means
>>>> that some real firmwares may not detect the correct amount of memory.
>>>> This can be bypassed by adding '-m 1G' on the command line.
>>>>
>>>> Add x-auto-conf property, to automatically configure the memory
>>>> controller at startup. This will be required by OpenBIOS, which
>>>> doesn't know how to do it.
>>>
>>> Why not teach it? I'd prefer to see that logic in firmware.
>>
>> Me too, but I'm not confident enough in my capabilities to do it.
> 
> Huh? Why not? Most of the device initialization code in OpenBIOS happens 
> in C, so you don't even have to touch Forth code :).
> 
>> Autoconfiguration is only in one place of the code, so I think it can 
>> be removed easily once OpenBIOS has this logic.
> 
> I'd prefer if we could come up with a clean model from the start. It 
> really shouldn't be hard at all.
> 

I thought that for all other usages of OpenBIOS in QEMU, RAM was 
supposed to be available as soon as machine was powered on.

However, I checked OpenBIOS code:
One of the first things done in arch/ppc/qemu/start.S is to copy the 
exception vectors. So, I should add code before it to detect memory 
controller, detect ram size and configure memory controller?
It seems quite a bit of code.
Do you have an example of how to do it for another memory controller, so 
I can adapt the code?

Regards,

Hervé

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

* Re: [Qemu-devel] [Qemu-ppc] [PATCH 1/7] pci: add MPC105 PCI host bridge emulation
  2013-05-06 20:57         ` Hervé Poussineau
@ 2013-05-06 22:16           ` Alexander Graf
  2013-05-06 22:41           ` Andreas Färber
  1 sibling, 0 replies; 24+ messages in thread
From: Alexander Graf @ 2013-05-06 22:16 UTC (permalink / raw)
  To: Hervé Poussineau; +Cc: qemu-ppc, qemu-devel, Andreas Färber


On 06.05.2013, at 22:57, Hervé Poussineau wrote:

> Alexander Graf a écrit :
>> On 05/03/2013 07:57 AM, Hervé Poussineau wrote:
>>> Alexander Graf a écrit :
>>>> 
>>>> Am 02.05.2013 um 22:08 schrieb Hervé Poussineau <hpoussin@reactos.org>:
>>>> 
>>>>> Non-contiguous I/O is not implemented.
>>>>> 
>>>>> There is also somewhere a bug in the memory controller, which means
>>>>> that some real firmwares may not detect the correct amount of memory.
>>>>> This can be bypassed by adding '-m 1G' on the command line.
>>>>> 
>>>>> Add x-auto-conf property, to automatically configure the memory
>>>>> controller at startup. This will be required by OpenBIOS, which
>>>>> doesn't know how to do it.
>>>> 
>>>> Why not teach it? I'd prefer to see that logic in firmware.
>>> 
>>> Me too, but I'm not confident enough in my capabilities to do it.
>> Huh? Why not? Most of the device initialization code in OpenBIOS happens in C, so you don't even have to touch Forth code :).
>>> Autoconfiguration is only in one place of the code, so I think it can be removed easily once OpenBIOS has this logic.
>> I'd prefer if we could come up with a clean model from the start. It really shouldn't be hard at all.
> 
> I thought that for all other usages of OpenBIOS in QEMU, RAM was supposed to be available as soon as machine was powered on.
> 
> However, I checked OpenBIOS code:
> One of the first things done in arch/ppc/qemu/start.S is to copy the exception vectors. So, I should add code before it to detect memory controller, detect ram size and configure memory controller?

You could just try to poke fw_cfg and ask it for the machine model. Based on that you can do all the initialization hardcoded.

> It seems quite a bit of code.
> Do you have an example of how to do it for another memory controller, so I can adapt the code?

Unfortunately not, no.


Alex

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

* Re: [Qemu-devel] [Qemu-ppc] [PATCH 1/7] pci: add MPC105 PCI host bridge emulation
  2013-05-06 20:57         ` Hervé Poussineau
  2013-05-06 22:16           ` Alexander Graf
@ 2013-05-06 22:41           ` Andreas Färber
  2013-05-07  5:48             ` Hervé Poussineau
  1 sibling, 1 reply; 24+ messages in thread
From: Andreas Färber @ 2013-05-06 22:41 UTC (permalink / raw)
  To: Hervé Poussineau; +Cc: qemu-ppc, Alexander Graf, qemu-devel

Am 06.05.2013 22:57, schrieb Hervé Poussineau:
> Alexander Graf a écrit :
>> On 05/03/2013 07:57 AM, Hervé Poussineau wrote:
>>> Alexander Graf a écrit :
>>>>
>>>> Am 02.05.2013 um 22:08 schrieb Hervé Poussineau <hpoussin@reactos.org>:
>>>>
>>>>> Non-contiguous I/O is not implemented.
>>>>>
>>>>> There is also somewhere a bug in the memory controller, which means
>>>>> that some real firmwares may not detect the correct amount of memory.
>>>>> This can be bypassed by adding '-m 1G' on the command line.
>>>>>
>>>>> Add x-auto-conf property, to automatically configure the memory
>>>>> controller at startup. This will be required by OpenBIOS, which
>>>>> doesn't know how to do it.
>>>>
>>>> Why not teach it? I'd prefer to see that logic in firmware.
>>>
>>> Me too, but I'm not confident enough in my capabilities to do it.
>>
>> Huh? Why not? Most of the device initialization code in OpenBIOS
>> happens in C, so you don't even have to touch Forth code :).
>>
>>> Autoconfiguration is only in one place of the code, so I think it can
>>> be removed easily once OpenBIOS has this logic.
>>
>> I'd prefer if we could come up with a clean model from the start. It
>> really shouldn't be hard at all.
>>
> 
> I thought that for all other usages of OpenBIOS in QEMU, RAM was
> supposed to be available as soon as machine was powered on.
> 
> However, I checked OpenBIOS code:
> One of the first things done in arch/ppc/qemu/start.S is to copy the
> exception vectors. So, I should add code before it to detect memory
> controller, detect ram size and configure memory controller?

No. Why? QEMU does not depend on the memory controller being
initialized, only the OS might expect some registers to be filled in. So
you should look at or add the MPC105 PHB initialization hook in
OpenBIOS' PCI code, long after the memory is set up.

> It seems quite a bit of code.
> Do you have an example of how to do it for another memory controller, so
> I can adapt the code?

Not sure if there's a memory controller specifically, but the Mac PHBs
are being initialized and on my PReP OpenBIOS branch I may have touched
that code...

Regards,
Andreas

-- 
SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 Nürnberg, Germany
GF: Jeff Hawn, Jennifer Guild, Felix Imendörffer; HRB 16746 AG Nürnberg

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

* Re: [Qemu-devel] [Qemu-ppc] [PATCH 1/7] pci: add MPC105 PCI host bridge emulation
  2013-05-06 22:41           ` Andreas Färber
@ 2013-05-07  5:48             ` Hervé Poussineau
  2013-05-09 17:47               ` Blue Swirl
  0 siblings, 1 reply; 24+ messages in thread
From: Hervé Poussineau @ 2013-05-07  5:48 UTC (permalink / raw)
  To: Andreas Färber; +Cc: qemu-ppc, Alexander Graf, qemu-devel

Andreas Färber a écrit :
> Am 06.05.2013 22:57, schrieb Hervé Poussineau:
>> Alexander Graf a écrit :
>>> On 05/03/2013 07:57 AM, Hervé Poussineau wrote:
>>>> Alexander Graf a écrit :
>>>>> Am 02.05.2013 um 22:08 schrieb Hervé Poussineau <hpoussin@reactos.org>:
>>>>>
>>>>>> Non-contiguous I/O is not implemented.
>>>>>>
>>>>>> There is also somewhere a bug in the memory controller, which means
>>>>>> that some real firmwares may not detect the correct amount of memory.
>>>>>> This can be bypassed by adding '-m 1G' on the command line.
>>>>>>
>>>>>> Add x-auto-conf property, to automatically configure the memory
>>>>>> controller at startup. This will be required by OpenBIOS, which
>>>>>> doesn't know how to do it.
>>>>> Why not teach it? I'd prefer to see that logic in firmware.
>>>> Me too, but I'm not confident enough in my capabilities to do it.
>>> Huh? Why not? Most of the device initialization code in OpenBIOS
>>> happens in C, so you don't even have to touch Forth code :).
>>>
>>>> Autoconfiguration is only in one place of the code, so I think it can
>>>> be removed easily once OpenBIOS has this logic.
>>> I'd prefer if we could come up with a clean model from the start. It
>>> really shouldn't be hard at all.
>>>
>> I thought that for all other usages of OpenBIOS in QEMU, RAM was
>> supposed to be available as soon as machine was powered on.
>>
>> However, I checked OpenBIOS code:
>> One of the first things done in arch/ppc/qemu/start.S is to copy the
>> exception vectors. So, I should add code before it to detect memory
>> controller, detect ram size and configure memory controller?
> 
> No. Why? QEMU does not depend on the memory controller being
> initialized, only the OS might expect some registers to be filled in. So
> you should look at or add the MPC105 PHB initialization hook in
> OpenBIOS' PCI code, long after the memory is set up.

OpenBIOS depends of memory being available (at least the first KB/MB) 
even at its very startup, in arch/ppc/qemu/start.S. PCI initialization 
code comes much later.
At boot, MPC105 datasheet says that memory controller is not configured, 
ie you have to not use RAM in OpenBIOS before PCI initialization.

For other PPC targets (mac99, g3beige) using OpenBIOS, RAM is accessible 
at startup, so that's not a problem for OpenBIOS.

So, no, QEMU does not depend of the memory controller being initialized, 
but OpenBIOS depends of the RAM being accessible ways before PCI 
initialization.
I don't speak of the OS which might (or might not) expect some registers 
to be filled in.
x-auto-conf property correctly sets some registers, so that memory is 
available at startup (like on mac99, g3beige emulations).

Hervé

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

* Re: [Qemu-devel] [Qemu-ppc] [PATCH 1/7] pci: add MPC105 PCI host bridge emulation
  2013-05-07  5:48             ` Hervé Poussineau
@ 2013-05-09 17:47               ` Blue Swirl
  0 siblings, 0 replies; 24+ messages in thread
From: Blue Swirl @ 2013-05-09 17:47 UTC (permalink / raw)
  To: Hervé Poussineau
  Cc: The OpenBIOS Mailinglist, qemu-ppc, Andreas Färber, qemu-devel

On Tue, May 7, 2013 at 5:48 AM, Hervé Poussineau <hpoussin@reactos.org> wrote:
> Andreas Färber a écrit :
>
>> Am 06.05.2013 22:57, schrieb Hervé Poussineau:
>>>
>>> Alexander Graf a écrit :
>>>>
>>>> On 05/03/2013 07:57 AM, Hervé Poussineau wrote:
>>>>>
>>>>> Alexander Graf a écrit :
>>>>>>
>>>>>> Am 02.05.2013 um 22:08 schrieb Hervé Poussineau
>>>>>> <hpoussin@reactos.org>:
>>>>>>
>>>>>>> Non-contiguous I/O is not implemented.
>>>>>>>
>>>>>>> There is also somewhere a bug in the memory controller, which means
>>>>>>> that some real firmwares may not detect the correct amount of memory.
>>>>>>> This can be bypassed by adding '-m 1G' on the command line.
>>>>>>>
>>>>>>> Add x-auto-conf property, to automatically configure the memory
>>>>>>> controller at startup. This will be required by OpenBIOS, which
>>>>>>> doesn't know how to do it.
>>>>>>
>>>>>> Why not teach it? I'd prefer to see that logic in firmware.
>>>>>
>>>>> Me too, but I'm not confident enough in my capabilities to do it.
>>>>
>>>> Huh? Why not? Most of the device initialization code in OpenBIOS
>>>> happens in C, so you don't even have to touch Forth code :).
>>>>
>>>>> Autoconfiguration is only in one place of the code, so I think it can
>>>>> be removed easily once OpenBIOS has this logic.
>>>>
>>>> I'd prefer if we could come up with a clean model from the start. It
>>>> really shouldn't be hard at all.
>>>>
>>> I thought that for all other usages of OpenBIOS in QEMU, RAM was
>>> supposed to be available as soon as machine was powered on.
>>>
>>> However, I checked OpenBIOS code:
>>> One of the first things done in arch/ppc/qemu/start.S is to copy the
>>> exception vectors. So, I should add code before it to detect memory
>>> controller, detect ram size and configure memory controller?
>>
>>
>> No. Why? QEMU does not depend on the memory controller being
>> initialized, only the OS might expect some registers to be filled in. So
>> you should look at or add the MPC105 PHB initialization hook in
>> OpenBIOS' PCI code, long after the memory is set up.
>
>
> OpenBIOS depends of memory being available (at least the first KB/MB) even
> at its very startup, in arch/ppc/qemu/start.S. PCI initialization code comes
> much later.

OpenBIOS for Sparc32 and Sparc64 does not use RAM before RAM size has
been read from fw_cfg. A check for QEMU signature is done and machine
ID is also read before that.
arch/sparc32/entry.S
arch/sparc64/entry.S

It should be easy to change PPC to check the machine ID before accessing RAM.

> At boot, MPC105 datasheet says that memory controller is not configured, ie
> you have to not use RAM in OpenBIOS before PCI initialization.

The memory controller should be initialized much earlier than PCI.

>
> For other PPC targets (mac99, g3beige) using OpenBIOS, RAM is accessible at
> startup, so that's not a problem for OpenBIOS.
>
> So, no, QEMU does not depend of the memory controller being initialized, but
> OpenBIOS depends of the RAM being accessible ways before PCI initialization.
> I don't speak of the OS which might (or might not) expect some registers to
> be filled in.
> x-auto-conf property correctly sets some registers, so that memory is
> available at startup (like on mac99, g3beige emulations).
>
> Hervé
>

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

end of thread, other threads:[~2013-05-09 17:47 UTC | newest]

Thread overview: 24+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-05-02 20:08 [Qemu-devel] [PATCH 0/7] ppc/prep: add IBM RS/6000 43p machine Hervé Poussineau
2013-05-02 20:08 ` [Qemu-devel] [PATCH 1/7] pci: add MPC105 PCI host bridge emulation Hervé Poussineau
2013-05-02 21:01   ` [Qemu-devel] [Qemu-ppc] " Alexander Graf
2013-05-03  5:57     ` Hervé Poussineau
2013-05-06 15:01       ` Alexander Graf
2013-05-06 20:57         ` Hervé Poussineau
2013-05-06 22:16           ` Alexander Graf
2013-05-06 22:41           ` Andreas Färber
2013-05-07  5:48             ` Hervé Poussineau
2013-05-09 17:47               ` Blue Swirl
2013-05-02 20:08 ` [Qemu-devel] [PATCH 2/7] qom: handle registration of new types when initializing the first ones Hervé Poussineau
2013-05-03 11:46   ` Andreas Färber
2013-05-05  8:38     ` Hervé Poussineau
2013-05-02 20:09 ` [Qemu-devel] [PATCH 3/7] m48t59: move ISA ports/memory regions registration to QOM constructor Hervé Poussineau
2013-05-02 20:09 ` [Qemu-devel] [PATCH 4/7] m48t59: register a QOM type for each nvram type we support Hervé Poussineau
2013-05-02 21:29   ` Artyom Tarasenko
2013-05-03  5:50     ` Hervé Poussineau
2013-05-03 23:16       ` Artyom Tarasenko
2013-05-04  5:24         ` Hervé Poussineau
2013-05-02 20:09 ` [Qemu-devel] [PATCH 5/7] m48t59: add a Nvram interface Hervé Poussineau
2013-05-02 20:09 ` [Qemu-devel] [PATCH 6/7] prep: add IBM RS/6000 7248 (43p) machine emulation Hervé Poussineau
2013-05-02 20:09 ` [Qemu-devel] [PATCH 7/7] prep: QOM'ify System I/O Hervé Poussineau
2013-05-03 11:36   ` Andreas Färber
2013-05-04  9:38     ` Hervé Poussineau

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.