qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH 12/25] q35: Re-base q35 to 1.2


From: Jason Baron
Subject: [Qemu-devel] [PATCH 12/25] q35: Re-base q35 to 1.2
Date: Thu, 13 Sep 2012 16:12:43 -0400

Rebase q35 to 1.2 - memory api updates, acpi updates, qom...

Signed-off-by: Jason Baron <address@hidden>
---
 hw/acpi_ich9.c |   65 ++++----
 hw/acpi_ich9.h |    9 +-
 hw/pc.h        |    2 +
 hw/pc_piix.c   |    4 +-
 hw/pc_q35.c    |  189 +++++++++++++++-------
 hw/q35.c       |  477 +++++++++++++++++++++++++++++++-------------------------
 hw/q35.h       |   97 +++++++++++-
 hw/q35_smbus.c |   78 +++++----
 8 files changed, 568 insertions(+), 353 deletions(-)

diff --git a/hw/acpi_ich9.c b/hw/acpi_ich9.c
index 59c0807..0d66109 100644
--- a/hw/acpi_ich9.c
+++ b/hw/acpi_ich9.c
@@ -18,6 +18,7 @@
 /*
  *  Copyright (c) 2009 Isaku Yamahata <yamahata at valinux co jp>
  *                     VA Linux Systems Japan K.K.
+ *  Copyright (C) 2012 Jason Baron <address@hidden>
  *
  *  This is based on acpi.c.
  */
@@ -47,9 +48,9 @@ static void pm_update_sci(ICH9_LPCPmRegs *pm)
 {
     int sci_level, pm1a_sts;
 
-    pm1a_sts = acpi_pm1_evt_get_sts(&pm->pm1a, pm->tmr.overflow_time);
+    pm1a_sts = acpi_pm1_evt_get_sts(&pm->acpi_regs);
 
-    sci_level = (((pm1a_sts & pm->pm1a.en) &
+    sci_level = (((pm1a_sts & pm->acpi_regs.pm1.evt.en) &
                   (ACPI_BITMASK_RT_CLOCK_ENABLE |
                    ACPI_BITMASK_POWER_BUTTON_ENABLE |
                    ACPI_BITMASK_GLOBAL_LOCK_ENABLE |
@@ -57,14 +58,14 @@ static void pm_update_sci(ICH9_LPCPmRegs *pm)
     qemu_set_irq(pm->irq, sci_level);
 
     /* schedule a timer interruption if needed */
-    acpi_pm_tmr_update(&pm->tmr,
-                       (pm->pm1a.en & ACPI_BITMASK_TIMER_ENABLE) &&
+    acpi_pm_tmr_update(&pm->acpi_regs,
+                       (pm->acpi_regs.pm1.evt.en & ACPI_BITMASK_TIMER_ENABLE) 
&&
                        !(pm1a_sts & ACPI_BITMASK_TIMER_STATUS));
 }
 
-static void ich9_pm_update_sci_fn(ACPIPMTimer *tmr)
+static void ich9_pm_update_sci_fn(ACPIREGS *regs)
 {
-    ICH9_LPCPmRegs *pm = container_of(tmr, ICH9_LPCPmRegs, tmr);
+    ICH9_LPCPmRegs *pm = container_of(regs, ICH9_LPCPmRegs, acpi_regs);
     pm_update_sci(pm);
 }
 
@@ -74,7 +75,7 @@ static void pm_ioport_writeb(void *opaque, uint32_t addr, 
uint32_t val)
 
     switch (addr & ICH9_PMIO_MASK) {
     case ICH9_PMIO_GPE0_STS ... (ICH9_PMIO_GPE0_STS + ICH9_PMIO_GPE0_LEN - 1):
-        acpi_gpe_ioport_writeb(&pm->gpe0, addr, val);
+        acpi_gpe_ioport_writeb(&pm->acpi_regs, addr, val);
         break;
     default:
         break;
@@ -90,7 +91,7 @@ static uint32_t pm_ioport_readb(void *opaque, uint32_t addr)
 
     switch (addr & ICH9_PMIO_MASK) {
     case ICH9_PMIO_GPE0_STS ... (ICH9_PMIO_GPE0_STS + ICH9_PMIO_GPE0_LEN - 1):
-        val = acpi_gpe_ioport_readb(&pm->gpe0, addr);
+        val = acpi_gpe_ioport_readb(&pm->acpi_regs, addr);
         break;
     default:
         val = 0;
@@ -106,15 +107,15 @@ static void pm_ioport_writew(void *opaque, uint32_t addr, 
uint32_t val)
 
     switch (addr & ICH9_PMIO_MASK) {
     case ICH9_PMIO_PM1_STS:
-        acpi_pm1_evt_write_sts(&pm->pm1a, &pm->tmr, val);
+        acpi_pm1_evt_write_sts(&pm->acpi_regs, val);
         pm_update_sci(pm);
         break;
     case ICH9_PMIO_PM1_EN:
-        pm->pm1a.en = val;
+        pm->acpi_regs.pm1.evt.en = val;
         pm_update_sci(pm);
         break;
     case ICH9_PMIO_PM1_CNT:
-        acpi_pm1_cnt_write(&pm->pm1a, &pm->pm1_cnt, val);
+        acpi_pm1_cnt_write(&pm->acpi_regs, val, 0);
         break;
     default:
         pm_ioport_write_fallback(opaque, addr, 2, val);
@@ -130,13 +131,13 @@ static uint32_t pm_ioport_readw(void *opaque, uint32_t 
addr)
 
     switch (addr & ICH9_PMIO_MASK) {
     case ICH9_PMIO_PM1_STS:
-        val = acpi_pm1_evt_get_sts(&pm->pm1a, pm->tmr.overflow_time);
+        val = acpi_pm1_evt_get_sts(&pm->acpi_regs);
         break;
     case ICH9_PMIO_PM1_EN:
-        val = pm->pm1a.en;
+        val = pm->acpi_regs.pm1.evt.en;
         break;
     case ICH9_PMIO_PM1_CNT:
-        val = pm->pm1_cnt.cnt;
+        val = pm->acpi_regs.pm1.cnt.cnt;
         break;
     default:
         val = pm_ioport_read_fallback(opaque, addr, 2);
@@ -168,7 +169,7 @@ static uint32_t pm_ioport_readl(void *opaque, uint32_t addr)
 
     switch (addr & ICH9_PMIO_MASK) {
     case ICH9_PMIO_PM1_TMR:
-        val = acpi_pm_tmr_get(&pm->tmr);
+        val = acpi_pm_tmr_get(&pm->acpi_regs);
         break;
     case ICH9_PMIO_SMI_EN:
         val = pm->smi_en;
@@ -238,7 +239,7 @@ void ich9_pm_iospace_update(ICH9_LPCPmRegs *pm, uint32_t 
pm_io_base)
     register_ioport_read(pm_io_base, ICH9_PMIO_SIZE, 4, pm_ioport_readl, pm);
 
     pm->pm_io_base = pm_io_base;
-    acpi_gpe_blk(&pm->gpe0, pm_io_base + ICH9_PMIO_GPE0_STS);
+    acpi_gpe_blk(&pm->acpi_regs, pm_io_base + ICH9_PMIO_GPE0_STS);
 }
 
 static int ich9_pm_post_load(void *opaque, int version_id)
@@ -268,13 +269,13 @@ const VMStateDescription vmstate_ich9_pm = {
     .minimum_version_id_old = 1,
     .post_load = ich9_pm_post_load,
     .fields = (VMStateField[]) {
-        VMSTATE_UINT16(pm1a.sts, ICH9_LPCPmRegs),
-        VMSTATE_UINT16(pm1a.en, ICH9_LPCPmRegs),
-        VMSTATE_UINT16(pm1_cnt.cnt, ICH9_LPCPmRegs),
-        VMSTATE_TIMER(tmr.timer, ICH9_LPCPmRegs),
-        VMSTATE_INT64(tmr.overflow_time, ICH9_LPCPmRegs),
-        VMSTATE_GPE_ARRAY(gpe0.sts, ICH9_LPCPmRegs),
-        VMSTATE_GPE_ARRAY(gpe0.en, ICH9_LPCPmRegs),
+        VMSTATE_UINT16(acpi_regs.pm1.evt.sts, ICH9_LPCPmRegs),
+        VMSTATE_UINT16(acpi_regs.pm1.evt.en, ICH9_LPCPmRegs),
+        VMSTATE_UINT16(acpi_regs.pm1.cnt.cnt, ICH9_LPCPmRegs),
+        VMSTATE_TIMER(acpi_regs.tmr.timer, ICH9_LPCPmRegs),
+        VMSTATE_INT64(acpi_regs.tmr.overflow_time, ICH9_LPCPmRegs),
+        VMSTATE_GPE_ARRAY(acpi_regs.gpe.sts, ICH9_LPCPmRegs),
+        VMSTATE_GPE_ARRAY(acpi_regs.gpe.en, ICH9_LPCPmRegs),
         VMSTATE_UINT32(smi_en, ICH9_LPCPmRegs),
         VMSTATE_UINT32(smi_sts, ICH9_LPCPmRegs),
         VMSTATE_END_OF_LIST()
@@ -286,10 +287,10 @@ static void pm_reset(void *opaque)
     ICH9_LPCPmRegs *pm = opaque;
     ich9_pm_iospace_update(pm, 0);
 
-    acpi_pm1_evt_reset(&pm->pm1a);
-    acpi_pm1_cnt_reset(&pm->pm1_cnt);
-    acpi_pm_tmr_reset(&pm->tmr);
-    acpi_gpe_reset(&pm->gpe0);
+    acpi_pm1_evt_reset(&pm->acpi_regs);
+    acpi_pm1_cnt_reset(&pm->acpi_regs);
+    acpi_pm_tmr_reset(&pm->acpi_regs);
+    acpi_gpe_reset(&pm->acpi_regs);
 
     pm_update_sci(pm);
 }
@@ -297,17 +298,15 @@ static void pm_reset(void *opaque)
 static void pm_powerdown(void *opaque, int irq, int power_failing)
 {
     ICH9_LPCPmRegs *pm = opaque;
-    ACPIPM1EVT *pm1a = pm ? &pm->pm1a : NULL;
-    ACPIPMTimer *tmr = pm ? &pm->tmr : NULL;
 
-    acpi_pm1_evt_power_down(pm1a, tmr);
+    acpi_pm1_evt_power_down(&pm->acpi_regs);
 }
 
 void ich9_pm_init(ICH9_LPCPmRegs *pm, qemu_irq sci_irq, qemu_irq cmos_s3)
 {
-    acpi_pm_tmr_init(&pm->tmr, ich9_pm_update_sci_fn);
-    acpi_pm1_cnt_init(&pm->pm1_cnt, cmos_s3);
-    acpi_gpe_init(&pm->gpe0, ICH9_PMIO_GPE0_LEN);
+    acpi_pm_tmr_init(&pm->acpi_regs, ich9_pm_update_sci_fn);
+    acpi_pm1_cnt_init(&pm->acpi_regs);
+    acpi_gpe_init(&pm->acpi_regs, ICH9_PMIO_GPE0_LEN);
 
     pm->irq = sci_irq;
     qemu_register_reset(pm_reset, pm);
diff --git a/hw/acpi_ich9.h b/hw/acpi_ich9.h
index f55c0e9..9ff4c42 100644
--- a/hw/acpi_ich9.h
+++ b/hw/acpi_ich9.h
@@ -24,19 +24,12 @@
 #include "acpi.h"
 
 typedef struct ICH9_LPCPmRegs {
-    ACPIPM1EVT pm1a;
-
     /*
      * In ich9 spec says that pm1_cnt register is 32bit width and
      * that the upper 16bits are reserved and unused.
      * PM1a_CNT_BLK = 2 in FADT so it is defined as uint16_t.
      */
-    ACPIPM1CNT pm1_cnt;
-
-    ACPIPMTimer tmr;
-
-    ACPIGPE gpe0;
-
+    ACPIREGS acpi_regs;
     uint32_t smi_en;
     uint32_t smi_sts;
 
diff --git a/hw/pc.h b/hw/pc.h
index c78923c..125c1fd 100644
--- a/hw/pc.h
+++ b/hw/pc.h
@@ -69,6 +69,8 @@ int pic_read_irq(DeviceState *d);
 int pic_get_output(DeviceState *d);
 void pic_info(Monitor *mon);
 void irq_info(Monitor *mon);
+void kvm_piix3_gsi_handler(void *opaque, int n, int level);
+void kvm_piix3_setup_irq_routing(bool pci_enabled);
 
 /* Global System Interrupts */
 
diff --git a/hw/pc_piix.c b/hw/pc_piix.c
index 60c7166..57830ec 100644
--- a/hw/pc_piix.c
+++ b/hw/pc_piix.c
@@ -53,7 +53,7 @@ static const int ide_iobase[MAX_IDE_BUS] = { 0x1f0, 0x170 };
 static const int ide_iobase2[MAX_IDE_BUS] = { 0x3f6, 0x376 };
 static const int ide_irq[MAX_IDE_BUS] = { 14, 15 };
 
-static void kvm_piix3_setup_irq_routing(bool pci_enabled)
+void kvm_piix3_setup_irq_routing(bool pci_enabled)
 {
 #ifdef CONFIG_KVM
     KVMState *s = kvm_state;
@@ -82,7 +82,7 @@ static void kvm_piix3_setup_irq_routing(bool pci_enabled)
 #endif /* CONFIG_KVM */
 }
 
-static void kvm_piix3_gsi_handler(void *opaque, int n, int level)
+void kvm_piix3_gsi_handler(void *opaque, int n, int level)
 {
     GSIState *s = opaque;
 
diff --git a/hw/pc_q35.c b/hw/pc_q35.c
index 4f75d97..9d58519 100644
--- a/hw/pc_q35.c
+++ b/hw/pc_q35.c
@@ -27,6 +27,7 @@
  *  Copyright (c) 2009, 2010
  *                     Isaku Yamahata <yamahata at valinux co jp>
  *                     VA Linux Systems Japan K.K.
+ *  Copyright (C) 2012 Jason Baron <address@hidden>
  *
  *  This is based on pc.c, but heavily modified.
  *
@@ -49,7 +50,6 @@
 #include "fdc.h"
 #include "pci.h"
 #include "pci_bridge.h"
-#include "pci_p2pbr.h"
 #include "ioh3420.h"
 #include "xio3130_upstream.h"
 #include "xio3130_downstream.h"
@@ -66,36 +66,16 @@
 #include "watchdog.h"
 #include "smbios.h"
 #include "ide.h"
-#include "usb-uhci.h"
+#include "mc146818rtc.h"
+#include "xen.h"
+#include "kvm.h"
 
 #include "q35.h"
+#include "exec-memory.h"
 
 /* ICH9 AHCI has 6 ports */
 #define MAX_SATA_PORTS     6
 
-#define I21154_REV            0x05
-#define I21154_PI             0x00
-
-static PCIBridge *i21154_init(PCIBus *bus, int devfn, const char *bus_name,
-                              bool multifunction)
-{
-    const PCIP2PBridgeInit init = {
-        .bus = bus,
-        .devfn = devfn,
-        .multifunction = multifunction,
-
-        .bus_name = bus_name,
-        .map_irq = pci_swizzle_map_irq_fn,
-    };
-    const PCIP2PBridgeProp prop = {
-        .vendor_id = PCI_VENDOR_ID_DEC,
-        .device_id = PCI_DEVICE_ID_DEC_21154,
-        .revision_id = I21154_REV,
-        .prog_interface = I21154_PI,
-    };
-    return pci_p2pbr_create_simple(&init, &prop);
-}
-
 static void pc_q35_bridge_init(PCIBus *host_bus, PCIBus *pci_bus)
 {
     uint8_t dev;
@@ -104,7 +84,6 @@ static void pc_q35_bridge_init(PCIBus *host_bus, PCIBus 
*pci_bus)
     uint8_t chassis = 0;
     uint16_t slot = 0;
     uint8_t upstream_port;
-    PCIESlot *s;
     uint8_t fn;
     PCIESlot *root_port;
     PCIBus *root_port_bus;
@@ -116,11 +95,10 @@ static void pc_q35_bridge_init(PCIBus *host_bus, PCIBus 
*pci_bus)
 #define Q35_P2P_BRDIGE_DEV_MAX          32
 #define Q35_P2P_BRDIGE_SUBBUS_BASE      (ICH9_D2P_SECONDARY_DEFAULT + 1)
     for (dev = Q35_P2P_BRDIGE_DEV_BASE; dev < Q35_P2P_BRDIGE_DEV_MAX; dev++) {
-        PCIBridge *br;
         sec_bus = Q35_P2P_BRDIGE_SUBBUS_BASE + dev - Q35_P2P_BRDIGE_DEV_BASE;
 
         snprintf(buf, sizeof(buf), "pci.%d", sec_bus);
-        br = i21154_init(pci_bus, PCI_DEVFN(dev, 0), buf, true);
+        i21154_init(pci_bus, PCI_DEVFN(dev, 0), buf, true);
     }
 
     /* PCIe root port b0:d1:f0 in GMCH.
@@ -128,8 +106,8 @@ static void pc_q35_bridge_init(PCIBus *host_bus, PCIBus 
*pci_bus)
      */
     sec_bus = 32;
     snprintf(buf, sizeof(buf), "pcie.%d", sec_bus);
-    s = ioh3420_init(host_bus, PCI_DEVFN(GMCH_PCIE_DEV, GMCH_PCIE_FUNC), true,
-                     buf, pci_swizzle_map_irq_fn, port, chassis, slot);
+    ioh3420_init(host_bus, PCI_DEVFN(GMCH_PCIE_DEV, GMCH_PCIE_FUNC), true,
+                 buf, pci_swizzle_map_irq_fn, port, chassis, slot);
 
 
     /* more slots. ICH9 doesn't have those, but many slots are wanted. */
@@ -153,8 +131,8 @@ static void pc_q35_bridge_init(PCIBus *host_bus, PCIBus 
*pci_bus)
         slot++;
 
         snprintf(buf, sizeof(buf), "pcie.%d", sec_bus);
-        s = ioh3420_init(host_bus, PCI_DEVFN(23, fn), true,
-                         buf, pci_swizzle_map_irq_fn, port, chassis, slot);
+        ioh3420_init(host_bus, PCI_DEVFN(23, fn), true,
+                     buf, pci_swizzle_map_irq_fn, port, chassis, slot);
     }
 
     /* PCIe root port b0:d24:f0 */
@@ -219,27 +197,38 @@ static void pc_q35_bridge_init(PCIBus *host_bus, PCIBus 
*pci_bus)
         slot++;
 
         snprintf(buf, sizeof(buf), "pcie.%d", sec_bus);
-        s = ioh3420_init(host_bus, PCI_DEVFN(ICH9_PCIE_DEV, fn), true,
-                         buf, pci_swizzle_map_irq_fn,
-                         port, chassis, slot);
+        ioh3420_init(host_bus, PCI_DEVFN(ICH9_PCIE_DEV, fn), true,
+                     buf, pci_swizzle_map_irq_fn,
+                     port, chassis, slot);
     }
 }
 
-static void pc_q35_init_early(qemu_irq *isa_irq, IsaIrqState *isa_irq_state,
+static void pc_q35_init_early(qemu_irq *gsi, GSIState *gsi_state,
                               DeviceState **gmch_host_p,
                               PCIBus **host_bus_p, PCIBus **pci_bus_p,
-                              PCIDevice **lpc_p)
+                              PCIDevice **lpc_p, ISABus **isa_bus,
+                              MemoryRegion *system_memory,
+                              MemoryRegion *pci_address_space,
+                              MemoryRegion *address_space_io,
+                              MemoryRegion *ram_memory,
+                              ram_addr_t below_4g_mem_size,
+                              ram_addr_t above_4g_mem_size)
 {
+    target_phys_addr_t pci_hole64_size;
     DeviceState *gmch_host;
     PCIBus *host_bus;
     PCIBus *pci_bus;
 
     PCIDevice *gmch_state;
     PCIDevice *lpc;
+    GMCH_PCIState *gmps;
+    ICH9_LPCState *ich9_lpc;
 
     /* create pci host bus */
-    host_bus = gmch_host_init(&gmch_host, isa_irq, isa_irq_state->ioapic);
+    host_bus = gmch_host_init(&gmch_host, gsi, gsi_state->ioapic_irq,
+                              pci_address_space, address_space_io);
     gmch_state = gmch_init(gmch_host, host_bus);
+    gmps = GMCH_PCI_DEVICE(gmch_state);
 
     /* create conventional pci bus: pcie2pci bridge */
     pci_bus = ich9_d2pbr_init(host_bus, PCI_DEVFN(ICH9_D2P_BRIDGE_DEV,
@@ -252,10 +241,53 @@ static void pc_q35_init_early(qemu_irq *isa_irq, 
IsaIrqState *isa_irq_state,
     /* create ISA bus */
     lpc = gmch_lpc_init(gmch_host, host_bus);
 
+    gmps->ram_memory = ram_memory;
+    gmps->pci_address_space = pci_address_space;
+    gmps->system_memory = system_memory;
+    /* pci */
+    memory_region_init_alias(&gmps->pci_hole, "pci-hole",
+                             gmps->pci_address_space,
+                             below_4g_mem_size,
+                             0x100000000ULL - below_4g_mem_size);
+    memory_region_add_subregion(gmps->system_memory, below_4g_mem_size,
+                                &gmps->pci_hole);
+    pci_hole64_size = (sizeof(target_phys_addr_t) == 4 ? 0 :
+                                            ((uint64_t)1 << 62));
+    memory_region_init_alias(&gmps->pci_hole_64bit, "pci-hole64",
+                             gmps->pci_address_space,
+                             0x100000000ULL + above_4g_mem_size,
+                             pci_hole64_size);
+    if (pci_hole64_size) {
+        memory_region_add_subregion(gmps->system_memory,
+                                    0x100000000ULL + above_4g_mem_size,
+                                    &gmps->pci_hole_64bit);
+    }
+
+    /* smram */
+    memory_region_init_alias(&gmps->smram_region, "smram-region",
+                             pci_address_space, 0xa0000, 0x20000);
+    memory_region_add_subregion_overlap(system_memory, 0xa0000,
+                                        &gmps->smram_region, 1);
+    memory_region_set_enabled(&gmps->smram_region, false);
+
     *gmch_host_p = gmch_host;
     *host_bus_p = host_bus;
     *pci_bus_p = pci_bus;
     *lpc_p = lpc;
+    ich9_lpc = ICH9_LPC_DEVICE(lpc);
+    *isa_bus = ich9_lpc->isa_bus;
+}
+
+
+/* set CMOS shutdown status register (index 0xF) as S3_resume(0xFE)
+ *    BIOS will read it and start S3 resume at POST Entry */
+static void pc_cmos_set_s3_resume(void *opaque, int irq, int level)
+{
+    ISADevice *s = opaque;
+
+    if (level) {
+        rtc_set_memory(s, 0xF, 0xFE);
+    }
 }
 
 static void pc_q35_init_late(BusState **idebus, ISADevice *rtc_state,
@@ -309,18 +341,22 @@ static void pc_q35_init(ram_addr_t ram_size,
     PCIBus *host_bus;
     PCIBus *pci_bus;
     PCIDevice *lpc;
-    qemu_irq *isa_irq;
-    IsaIrqState *isa_irq_state;
     BusState *idebus[MAX_SATA_PORTS];
     ISADevice *rtc_state;
+    ISADevice *floppy;
     MemoryRegion *pci_memory;
     MemoryRegion *rom_memory;
     MemoryRegion *ram_memory;
+    GSIState *gsi_state;
+    ISABus *isa_bus;
+    int pci_enabled = 1;
+    qemu_irq *cpu_irq;
+    qemu_irq *gsi;
+    qemu_irq *i8259;
+    int i;
 
     pc_cpus_init(cpu_model);
 
-    /* FIXME: add kvm clock ? */
-
     if (ram_size >= 0xe0000000) {
         above_4g_mem_size = ram_size - 0xe0000000;
         below_4g_mem_size = 0xe0000000;
@@ -330,37 +366,70 @@ static void pc_q35_init(ram_addr_t ram_size,
     }
 
     /* pci enabled */
-    pci_memory = g_new(MemoryRegion, 1);
-    memory_region_init(pci_memory, "pci", INT64_MAX);
-    rom_memory = pci_memory;
+    if (pci_enabled) {
+        pci_memory = g_new(MemoryRegion, 1);
+        memory_region_init(pci_memory, "pci", INT64_MAX);
+        rom_memory = pci_memory;
+    } else {
+        pci_memory = NULL;
+        rom_memory = get_system_memory();
+    }
 
     /* allocate ram and load rom/bios */
-    pc_memory_init(get_system_memory(), kernel_filename, kernel_cmdline,
-                   initrd_filename, below_4g_mem_size, above_4g_mem_size,
-                   rom_memory, &ram_memory);
+    if (!xen_enabled()) {
+        pc_memory_init(get_system_memory(), kernel_filename, kernel_cmdline,
+                       initrd_filename, below_4g_mem_size, above_4g_mem_size,
+                       rom_memory, &ram_memory);
+    }
 
     /* irq lines */
-    isa_irq = pc_isa_irq(&isa_irq_state);
-    ioapic_init(isa_irq_state);
+    gsi_state = g_malloc0(sizeof(*gsi_state));
+    if (kvm_irqchip_in_kernel()) {
+        kvm_piix3_setup_irq_routing(pci_enabled);
+        gsi = qemu_allocate_irqs(kvm_piix3_gsi_handler, gsi_state,
+                                 GSI_NUM_PINS);
+    } else {
+        gsi = qemu_allocate_irqs(gsi_handler, gsi_state, GSI_NUM_PINS);
+    }
+
+    pc_q35_init_early(gsi, gsi_state,
+                      &gmch_host, &host_bus, &pci_bus, &lpc, &isa_bus,
+                      get_system_memory(), pci_memory, get_system_io(),
+                      ram_memory, below_4g_mem_size, above_4g_mem_size);
+    isa_bus_irqs(isa_bus, gsi);
+
+    if (kvm_irqchip_in_kernel()) {
+        i8259 = kvm_i8259_init(isa_bus);
+    } else if (xen_enabled()) {
+        i8259 = xen_interrupt_controller_init();
+    } else {
+        cpu_irq = pc_allocate_cpu_irq();
+        i8259 = i8259_init(isa_bus, cpu_irq[0]);
+    }
+
+    for (i = 0; i < ISA_NUM_IRQS; i++) {
+        gsi_state->i8259_irq[i] = i8259[i];
+    }
+    if (pci_enabled) {
+        ioapic_init_gsi(gsi_state, NULL);
+    }
 
-    pc_q35_init_early(isa_irq, isa_irq_state,
-                      &gmch_host, &host_bus, &pci_bus, &lpc);
-    isa_bus_irqs(isa_irq);
-    pc_register_ferr_irq(isa_get_irq(13));
+    pc_register_ferr_irq(gsi[13]);
 
     /* init basic PC hardware */
-    pc_basic_device_init(isa_irq, &rtc_state, false);
+    pc_basic_device_init(isa_bus, gsi, &rtc_state, &floppy, false);
 
     pc_q35_init_late(idebus, rtc_state, gmch_host, host_bus, pci_bus, lpc);
 
     pc_cmos_init(below_4g_mem_size, above_4g_mem_size, boot_device,
-                 idebus[0], idebus[1], rtc_state);
+                 floppy, idebus[0], idebus[1], rtc_state);
 
     /* the rest devices to which pci devfn is automatically assigned */
-    pc_vga_init(host_bus);
-    audio_init(isa_irq, pci_bus);
-    pc_nic_init(pci_bus);
-    pc_pci_device_init(pci_bus);
+    pc_vga_init(isa_bus, host_bus);
+    audio_init(isa_bus, pci_bus);
+    pc_nic_init(isa_bus, pci_bus);
+    if (pci_enabled)
+        pc_pci_device_init(pci_bus);
 }
 
 static QEMUMachine pc_q35_machine = {
diff --git a/hw/q35.c b/hw/q35.c
index 1776ac3..09e8bd7 100644
--- a/hw/q35.c
+++ b/hw/q35.c
@@ -25,6 +25,7 @@
  *  Copyright (c) 2009, 2010, 2011
  *                Isaku Yamahata <yamahata at valinux co jp>
  *                VA Linux Systems Japan K.K.
+ *  Copyright (C) 2012 Jason Baron <address@hidden>
  *
  *  This is based on piix_pci.c, but heavily modified.
  *
@@ -52,62 +53,16 @@
 #include "pci.h"
 #include "pcie_host.h"
 #include "pci_bridge.h"
-#include "pci_p2pbr.h"
 #include "q35.h"
 #include "acpi.h"
 #include "acpi_ich9.h"
 #include "pam.h"
+#include "pci_internals.h"
+#include "exec-memory.h"
+#include "isa.h"
+#include "qemu-common.h"
 
 
-struct ICH9_LPCState;
-
-typedef struct ICH9_LPCIrqState {
-    struct ICH9_LPCState *lpc;
-    qemu_irq *pic;
-    qemu_irq *ioapic;
-} ICH9_LPCIrqState;
-
-typedef struct GMCH_PCIHost {
-    PCIExpressHost      host;
-
-    PCIDevice    *dev;
-    ICH9_LPCIrqState irq_state;
-} GMCH_PCIHost;
-
-typedef struct GMCH_PCIState {
-    PCIDevice   d;
-    /*
-     * GMCH_PCIHost   *gmch_host;
-     * In order to get GMCH_PCIHost
-     *  PCIDevice -> qdev -> parent_bus -> qdev -upcast-> GMCH_PCIHost
-     */
-
-    PAM pam;
-} GMCH_PCIState;
-
-typedef struct ICH9_LPCState {
-    /* ICH9 LPC PCI to ISA bridge */
-    PCIDevice d;
-
-    /* (pci device, intx) -> pirq
-     * In real chipset case, the unused slots are never used
-     * as ICH9 supports only D25-D32 irq routing.
-     * On the other hand in qemu case, any slot/function can be populated
-     * via command line option.
-     * So fallback interrupt routing for any devices in any slots is necessary.
-     */
-    uint8_t irr[PCI_SLOT_MAX][PCI_NUM_PINS];
-
-    APMState apm;
-    ICH9_LPCPmRegs pm;
-    uint32_t sci_level; /* track sci level */
-
-    /* 10.1 Chipset Configuration registers(Memory Space)
-       which is pointed by RCBA */
-    uint8_t chip_config[ICH9_CC_SIZE];
-    int rbca_index;
-} ICH9_LPCState;
-
 
 /****************************************************************************
  * GMCH PCI host
@@ -117,20 +72,20 @@ static int ich9_lpc_map_irq(void *opaque, PCIDevice 
*pci_dev, int intx);
 static void ich9_lpc_set_irq(void *opaque, int irq_num, int level);
 static int ich9_lpc_sci_irq(ICH9_LPCState *lpc);
 
-static GMCH_PCIHost *gmch_pcihost_from_qdev(DeviceState *gmch_host_qdev)
-{
-    SysBusDevice *sysdev = sysbus_from_qdev(gmch_host_qdev);
-    PCIHostState *pci = FROM_SYSBUS(PCIHostState, sysdev);
-    PCIExpressHost *pcie = DO_UPCAST(PCIExpressHost, pci, pci);
-    return DO_UPCAST(GMCH_PCIHost, host, pcie);
-}
-
 static int gmch_pcihost_initfn(SysBusDevice *dev)
 {
-    GMCH_PCIHost *s = gmch_pcihost_from_qdev(&dev->qdev);
+    PCIHostState *pci = FROM_SYSBUS(PCIHostState, dev);
+    GMCH_PCIHost *s = GMCH_HOST_DEVICE(&dev->qdev);
 
-    pci_host_conf_register_ioport(GMCH_HOST_BRIDGE_CONFIG_ADDR, &s->host.pci);
-    pci_host_data_register_ioport(GMCH_HOST_BRIDGE_CONFIG_DATA, &s->host.pci);
+    memory_region_init_io(&pci->conf_mem, &pci_host_conf_le_ops, pci,
+                          "pci-conf-idx", 4);
+    sysbus_add_io(dev, GMCH_HOST_BRIDGE_CONFIG_ADDR, &pci->conf_mem);
+    sysbus_init_ioports(&pci->busdev, GMCH_HOST_BRIDGE_CONFIG_ADDR, 4);
+
+    memory_region_init_io(&pci->data_mem, &pci_host_data_le_ops, pci,
+                          "pci-conf-data", 4);
+    sysbus_add_io(dev, GMCH_HOST_BRIDGE_CONFIG_DATA, &pci->data_mem);
+    sysbus_init_ioports(&pci->busdev, GMCH_HOST_BRIDGE_CONFIG_DATA, 4);
 
     if (pcie_host_init(&s->host) < 0) {
         abort();
@@ -139,36 +94,46 @@ static int gmch_pcihost_initfn(SysBusDevice *dev)
     return 0;
 }
 
-static SysBusDeviceInfo gmch_pcihost_info = {
-    .init         = gmch_pcihost_initfn,
-    .qdev.name    = "gmch-pcihost",
-    .qdev.size    = sizeof(GMCH_PCIHost),
-    .qdev.no_user = 1,
-    .qdev.props = (Property[]) {
-        {
-            .name = "MCFG",
-            .info = &qdev_prop_uint64,
-            .offset = offsetof(GMCH_PCIHost, host.base_addr),
-            .defval = (uint64_t[]){ GMCH_HOST_BRIDGE_PCIEXBAR_DEFAULT },
-        },
-        DEFINE_PROP_END_OF_LIST(),
-    },
+static Property gmch_props[] = {
+    DEFINE_PROP_UINT64("MCFG", GMCH_PCIHost, host.base_addr,
+                        GMCH_HOST_BRIDGE_PCIEXBAR_DEFAULT),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void gmch_pcihost_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+    k->init = gmch_pcihost_initfn;
+    dc->props = gmch_props;
+    dc->no_user = 1;
+}
+
+static TypeInfo gmch_pcihost_info = {
+    .name       = TYPE_GMCH_HOST_DEVICE,
+    .parent     = TYPE_PCIE_HOST_BRIDGE,
+    .instance_size = sizeof(GMCH_PCIHost),
+    .class_init = gmch_pcihost_class_init,
 };
 
 /* host bridge */
 PCIBus *gmch_host_init(DeviceState **gmch_hostp,
-                       qemu_irq *pic, qemu_irq *ioapic)
+                       qemu_irq *pic, qemu_irq *ioapic,
+                       MemoryRegion *pci_address_space,
+                       MemoryRegion *address_space_io)
 {
     DeviceState *dev;
     GMCH_PCIHost *s;
     PCIBus *b;
 
-    dev = qdev_create(NULL, "gmch-pcihost");
-    s = gmch_pcihost_from_qdev(dev);
+    dev = qdev_create(NULL, TYPE_GMCH_HOST_DEVICE);
+    s = GMCH_HOST_DEVICE(dev);
     s->irq_state.pic = pic;
     s->irq_state.ioapic = ioapic;
 
-    b = pci_bus_new(dev, "pcie.0", 0);
+    b = pci_bus_new(&s->host.pci.busdev.qdev, "pcie.0", pci_address_space,
+                    address_space_io, 0);
     pci_bus_irqs(b, ich9_lpc_set_irq, ich9_lpc_map_irq, &s->irq_state,
                  ICH9_LPC_NB_PIRQS);
     s->host.pci.bus = b;
@@ -180,12 +145,8 @@ PCIBus *gmch_host_init(DeviceState **gmch_hostp,
 
 
 /****************************************************************************
- * GMCH
+ * GMCH D0:F0
  */
-static GMCH_PCIState *gmch_from_pci(PCIDevice *gmch_pci)
-{
-    return DO_UPCAST(GMCH_PCIState, d, gmch_pci);
-}
 
 /* PCIE MMCFG */
 static void gmch_update_pciexbar(GMCH_PCIState *gs)
@@ -193,7 +154,7 @@ static void gmch_update_pciexbar(GMCH_PCIState *gs)
     PCIDevice *pci_dev = &gs->d;
     BusState *bus = qdev_get_parent_bus(&pci_dev->qdev);
     DeviceState *qdev = bus->parent;
-    GMCH_PCIHost *s = gmch_pcihost_from_qdev(qdev);
+    GMCH_PCIHost *s = GMCH_HOST_DEVICE(qdev);
 
     uint64_t pciexbar;
     int enable;
@@ -234,27 +195,39 @@ static void gmch_update_pciexbar(GMCH_PCIState *gs)
 static void gmch_update_pam(GMCH_PCIState *gs)
 {
     int i;
+
+    memory_region_transaction_begin();
     for (i = 0; i <= PAM_IDX_MAX; i++) {
-        pam_update(&gs->pam, i, gs->d.config[GMCH_HOST_BRIDGE_PAM0 + i]);
+        pam_update(&gs->pam_regions[0], i,
+                   gs->d.config[GMCH_HOST_BRIDGE_PAM0 + i],
+                   gs->ram_memory, gs->pci_address_space, gs->system_memory);
     }
+    memory_region_transaction_commit();
 }
 
 /* SMRAM */
 static void gmch_update_smram(GMCH_PCIState *gs)
 {
-    smram_update(&gs->pam, gs->d.config[GMCH_HOST_BRDIGE_SMRAM]);
+    memory_region_transaction_begin();
+    smram_update(&gs->smram_region, gs->d.config[GMCH_HOST_BRDIGE_SMRAM],
+                    gs->smm_enabled);
+    memory_region_transaction_commit();
 }
 
 static void gmch_set_smm(int smm, void *arg)
 {
     GMCH_PCIState *gs = arg;
-    smram_set_smm(&gs->pam, smm, gs->d.config[GMCH_HOST_BRDIGE_SMRAM]);
+
+    memory_region_transaction_begin();
+    smram_set_smm(&gs->smm_enabled, smm, gs->d.config[GMCH_HOST_BRDIGE_SMRAM],
+                    &gs->smram_region);
+    memory_region_transaction_commit();
 }
 
 static void gmch_write_config(PCIDevice *d,
                               uint32_t address, uint32_t val, int len)
 {
-    GMCH_PCIState *gs = gmch_from_pci(d);
+    GMCH_PCIState *gs = GMCH_PCI_DEVICE(d);
 
     /* XXX: implement SMRAM.D_LOCK */
     pci_default_write_config(d, address, val, len);
@@ -297,15 +270,15 @@ static const VMStateDescription vmstate_gmch = {
     .post_load = gmch_post_load,
     .fields = (VMStateField []) {
         VMSTATE_PCI_DEVICE(d, GMCH_PCIState),
-        VMSTATE_UINT8(pam.smm_enabled, GMCH_PCIState),
+        VMSTATE_UINT8(smm_enabled, GMCH_PCIState),
         VMSTATE_END_OF_LIST()
     }
 };
 
 static void gmch_reset(DeviceState *qdev)
 {
-    PCIDevice *d = DO_UPCAST(PCIDevice, qdev, qdev);
-    GMCH_PCIState *gs = gmch_from_pci(d);
+    PCIDevice *d = PCI_DEVICE(qdev);
+    GMCH_PCIState *gs = GMCH_PCI_DEVICE(d);
 
     pci_set_quad(d->config + GMCH_HOST_BRIDGE_PCIEXBAR,
                  GMCH_HOST_BRIDGE_PCIEXBAR_DEFAULT);
@@ -315,39 +288,46 @@ static void gmch_reset(DeviceState *qdev)
     gmch_update(gs);
 }
 
-static int gmch_initfn(PCIDevice *d)
+static int pci_gmch_initfn(PCIDevice *d)
 {
-    GMCH_PCIState *gs = gmch_from_pci(d);
-
-    pci_config_set_vendor_id(d->config, PCI_VENDOR_ID_INTEL);
-    pci_config_set_device_id(d->config, PCI_DEVICE_ID_INTEL_Q35_MCH);
-    pci_config_set_revision(d->config, GMCH_HOST_BRIDGE_REVISION_DEFUALT);
-    pci_config_set_class(d->config, PCI_CLASS_BRIDGE_HOST);
+    GMCH_PCIState *gs = GMCH_PCI_DEVICE(d);
 
     cpu_smm_register(&gmch_set_smm, gs);
-    pam_init_memory_mappings(&gs->pam);
 
     return 0;
 }
 
-static PCIDeviceInfo gmch_info = {
-    .qdev.name    = "gmch",
-    .qdev.desc    = "Host bridge",
-    .qdev.size    = sizeof(GMCH_PCIState),
-    .qdev.vmsd    = &vmstate_gmch,
-    .qdev.no_user = 1,
-    .init         = gmch_initfn,
-    .config_write = gmch_write_config,
-    .qdev.reset   = gmch_reset,
+static void pci_gmch_class_init(ObjectClass *klass, void *data)
+{
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
+    k->init = pci_gmch_initfn;
+    k->config_write = gmch_write_config;
+    dc->reset = gmch_reset;
+    dc->desc = "Host bridge";
+    dc->vmsd = &vmstate_gmch;
+    dc->no_user = 1;
+    k->vendor_id = PCI_VENDOR_ID_INTEL;
+    k->device_id = PCI_DEVICE_ID_INTEL_Q35_MCH;
+    k->revision = GMCH_HOST_BRIDGE_REVISION_DEFUALT;
+    k->class_id = PCI_CLASS_BRIDGE_HOST;
+}
+
+struct TypeInfo pci_gmch_info = {
+    .name = TYPE_GMCH_PCI_DEVICE,
+    .parent     = TYPE_PCI_DEVICE,
+    .instance_size = sizeof(GMCH_PCIState),
+    .class_init = pci_gmch_class_init,
 };
 
 /* host bridge */
 PCIDevice *gmch_init(DeviceState *gmch_host, PCIBus *b)
 {
-    GMCH_PCIHost *s = gmch_pcihost_from_qdev(gmch_host);
+    GMCH_PCIHost *s = GMCH_HOST_DEVICE(gmch_host);
     PCIDevice *d;
 
-    d = pci_create_simple_multifunction(b, 0, false, "gmch");
+    d = pci_create_simple_multifunction(b, 0, false, TYPE_GMCH_PCI_DEVICE);
     s->dev = d;
 
     return d;
@@ -359,54 +339,135 @@ PCIDevice *gmch_init(DeviceState *gmch_host, PCIBus *b)
 #define I82801ba_SSVID_SVID     0
 #define I82801ba_SSVID_SSID     0
 
-static PCIBridge *i82801ba11_init(PCIBus *bus, int devfn, const char *bus_name,
-                                  bool multifunction)
+struct i82801b11_bridge {
+    PCIBridge br;
+};
+
+static int i82801b11_bridge_initfn(PCIDevice *d)
 {
-    const PCIP2PBridgeInit init = {
-        .bus = bus,
-        .devfn = devfn,
-        .multifunction = multifunction,
+    int rc;
+
+    rc = pci_bridge_initfn(d);
+    if (rc < 0) {
+        return rc;
+    }
+
+    rc = pci_bridge_ssvid_init(d, I82801ba_SSVID_OFFSET,
+                               I82801ba_SSVID_SVID, I82801ba_SSVID_SSID);
+    if (rc < 0) {
+        goto err_bridge;
+    }
+    return 0;
 
-        .bus_name = bus_name,
-        .map_irq = pci_swizzle_map_irq_fn,
-    };
-    const PCIP2PBridgeProp prop = {
-        .vendor_id = PCI_VENDOR_ID_INTEL,
-        .device_id = PCI_DEVICE_ID_INTEL_82801BA_11,
-        .revision_id = ICH9_D2P_A2_REVISION,
-        .prog_interface = PCI_CLASS_BRDIGE_PCI_INF_SUB,
+err_bridge:
+    pci_bridge_exitfn(d);
 
-        .ssvid_cap = I82801ba_SSVID_OFFSET,
-        .svid = I82801ba_SSVID_SVID,
-        .ssid = I82801ba_SSVID_SSID,
-    };
-    return pci_p2pbr_create_simple(&init, &prop);
+    return rc;
 }
 
+static void i82801b11_bridge_class_init(ObjectClass *klass, void *data)
+{
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+    k->is_bridge = 1;
+    k->vendor_id = PCI_VENDOR_ID_INTEL;
+    k->device_id = PCI_DEVICE_ID_INTEL_82801BA_11;
+    k->revision = ICH9_D2P_A2_REVISION;
+    k->init = i82801b11_bridge_initfn;
+}
+
+static TypeInfo i82801b11_bridge_info = {
+    .name          = "i82801b11-bridge",
+    .parent        = TYPE_PCI_DEVICE,
+    .instance_size = sizeof(struct i82801b11_bridge),
+    .class_init    = i82801b11_bridge_class_init,
+};
+
 PCIBus *ich9_d2pbr_init(PCIBus *bus, int devfn, int sec_bus)
 {
+    PCIDevice *d;
     PCIBridge *br;
     char buf[16];
+    DeviceState *qdev;
 
-    snprintf(buf, sizeof(buf), "pci.%d", sec_bus);
-    br = i82801ba11_init(bus, devfn, buf, true);
-    if (br == NULL) {
+    d = pci_create_multifunction(bus, devfn, true, "i82801b11-bridge");
+    if (!d) {
         return NULL;
     }
+    br = DO_UPCAST(PCIBridge, dev, d);
+    qdev = &br->dev.qdev;
+
+    snprintf(buf, sizeof(buf), "pci.%d", sec_bus);
+    pci_bridge_map_irq(br, buf, pci_swizzle_map_irq_fn);
+    qdev_init_nofail(qdev);
+
     return pci_bridge_get_sec_bus(br);
 }
+/*****************************************************************************/
+/* i21154 pci bridge*/
 
+struct i21154_bridge {
+    PCIBridge br;
+};
 
-/*****************************************************************************/
-/* ICH9 LPC PCI to ISA bridge */
+static int i21154_bridge_initfn(PCIDevice *d)
+{
+    int rc;
 
-static void ich9_lpc_reset(DeviceState *qdev);
+    rc = pci_bridge_initfn(d);
+    if (rc < 0) {
+        return rc;
+    }
+
+    return 0;
+}
+
+#define I21154_REV            0x05
+#define I21154_PI             0x00
+
+static void i21154_bridge_class_init(ObjectClass *klass, void *data)
+{
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+    k->is_bridge = 1;
+    k->vendor_id = PCI_VENDOR_ID_DEC;
+    k->device_id = PCI_DEVICE_ID_DEC_21154;
+    k->revision = I21154_REV;
+    k->init = i21154_bridge_initfn;
+}
+
+static TypeInfo i21154_bridge_info = {
+    .name          = "i21154-bridge",
+    .parent        = TYPE_PCI_DEVICE,
+    .instance_size = sizeof(struct i21154_bridge),
+    .class_init    = i21154_bridge_class_init,
+};
 
-static ICH9_LPCState *ich9_lpc_from_pci(PCIDevice *lpc_pci)
+PCIBridge *i21154_init(PCIBus *bus, int devfn, const char *bus_name,
+                              bool multifunction)
 {
-    return DO_UPCAST(ICH9_LPCState, d, lpc_pci);
+    PCIDevice *d;
+    PCIBridge *br;
+    DeviceState *qdev;
+
+    d = pci_create_multifunction(bus, devfn, multifunction, "i21154-bridge");
+    if (!d) {
+        return NULL;
+    }
+    br = DO_UPCAST(PCIBridge, dev, d);
+    qdev = &br->dev.qdev;
+
+    pci_bridge_map_irq(br, bus_name, pci_swizzle_map_irq_fn);
+    qdev_init_nofail(qdev);
+
+    return br;
 }
 
+/*****************************************************************************/
+/* ICH9 LPC PCI to ISA bridge */
+
+static void ich9_lpc_reset(DeviceState *qdev);
+
 /* chipset configuration register
  * to access chipset configuration registers, pci_[sg]et_{byte, word, long}
  * are used.
@@ -485,7 +546,7 @@ static void ich9_cc_reset(ICH9_LPCState *lpc)
     ich9_cc_update(lpc);
 }
 
-static void ich9_cc_addr_len(uint32_t *addr, int *len)
+static void ich9_cc_addr_len(uint64_t *addr, unsigned *len)
 {
     *addr &= ICH9_CC_ADDR_MASK;
     if (*addr + *len >= ICH9_CC_SIZE) {
@@ -494,56 +555,27 @@ static void ich9_cc_addr_len(uint32_t *addr, int *len)
 }
 
 /* val: little endian */
-static void ich9_cc_write(ICH9_LPCState *lpc, uint32_t addr,
-                          uint32_t val, int len)
+static void ich9_cc_write(void *opaque, target_phys_addr_t addr,
+                          uint64_t val, unsigned len)
 {
+    ICH9_LPCState *lpc = (ICH9_LPCState *)opaque;
+
     ich9_cc_addr_len(&addr, &len);
     memcpy(lpc->chip_config + addr, &val, len);
 }
 
 /* return value: little endian */
-static uint32_t ich9_cc_read(ICH9_LPCState *lpc, uint32_t addr, int len)
+static uint64_t ich9_cc_read(void *opaque, target_phys_addr_t addr,
+                              unsigned len)
 {
+    ICH9_LPCState *lpc = (ICH9_LPCState *)opaque;
+
     uint32_t val = 0;
     ich9_cc_addr_len(&addr, &len);
     memcpy(&val, lpc->chip_config + addr, len);
     return val;
 }
 
-#define ICH9_CC_MMIO_WRITE(type, len)                           \
-    static void ich9_cc_mmio_write ## type                      \
-    (void *opaque, target_phys_addr_t addr, uint32_t val)       \
-    {                                                           \
-        ich9_cc_write(opaque, addr, val, len);                  \
-    }
-
-#define ICH9_CC_MMIO_READ(type, len)            \
-    static uint32_t ich9_cc_mmio_read ## type   \
-    (void *opaque, target_phys_addr_t addr)     \
-    {                                           \
-        return ich9_cc_read(opaque, addr, len); \
-    }
-
-ICH9_CC_MMIO_WRITE(b, 1)
-ICH9_CC_MMIO_WRITE(w, 2)
-ICH9_CC_MMIO_WRITE(l, 4)
-
-ICH9_CC_MMIO_READ(b, 1)
-ICH9_CC_MMIO_READ(w, 2)
-ICH9_CC_MMIO_READ(l, 4)
-
-static CPUWriteMemoryFunc * const ich9_cc_mmio_write[] = {
-    ich9_cc_mmio_writeb,
-    ich9_cc_mmio_writew,
-    ich9_cc_mmio_writel,
-};
-
-static CPUReadMemoryFunc * const ich9_cc_mmio_read[] = {
-    ich9_cc_mmio_readb,
-    ich9_cc_mmio_readw,
-    ich9_cc_mmio_readl,
-};
-
 /* IRQ routing */
 /* */
 static void ich9_lpc_rout(uint8_t pirq_rout, int *pic_irq, int *pic_dis)
@@ -702,8 +734,8 @@ static void ich9_set_sci(void *opaque, int irq_num, int 
level)
 void ich9_lpc_pm_init(DeviceState *gmch_host, PCIDevice *lpc_pci,
                       qemu_irq cmos_s3)
 {
-    GMCH_PCIHost *s = gmch_pcihost_from_qdev(gmch_host);
-    ICH9_LPCState *lpc = ich9_lpc_from_pci(lpc_pci);
+    GMCH_PCIHost *s = GMCH_HOST_DEVICE(gmch_host);
+    ICH9_LPCState *lpc = ICH9_LPC_DEVICE(lpc_pci);
     qemu_irq *sci_irq;
 
     sci_irq = qemu_allocate_irqs(ich9_set_sci, &s->irq_state, 1);
@@ -713,12 +745,14 @@ void ich9_lpc_pm_init(DeviceState *gmch_host, PCIDevice 
*lpc_pci,
 }
 
 /* APM */
+
+
 static void ich9_apm_ctrl_changed(uint32_t val, void *arg)
 {
     ICH9_LPCState *lpc = arg;
 
     /* ACPI specs 3.0, 4.7.2.5 */
-    acpi_pm1_cnt_update(&lpc->pm.pm1_cnt,
+    acpi_pm1_cnt_update(&lpc->pm.acpi_regs,
                         val == ICH9_APM_ACPI_ENABLE,
                         val == ICH9_APM_ACPI_DISABLE);
 
@@ -744,12 +778,12 @@ static void ich9_lpc_rcba_update(ICH9_LPCState *lpc, 
uint32_t rbca_old)
     uint32_t rbca = pci_get_long(lpc->d.config + ICH9_LPC_RCBA);
 
     if (rbca_old & ICH9_LPC_RCBA_EN) {
-        cpu_register_physical_memory(rbca_old & ICH9_LPC_RCBA_BA_MASK,
-                                     ICH9_CC_SIZE, IO_MEM_UNASSIGNED);
+            memory_region_del_subregion(get_system_memory(), &lpc->rbca_mem);
     }
     if (rbca & ICH9_LPC_RCBA_EN) {
-        cpu_register_physical_memory(rbca & ICH9_LPC_RCBA_BA_MASK,
-                                     ICH9_CC_SIZE, lpc->rbca_index);
+            memory_region_add_subregion_overlap(get_system_memory(),
+                                                rbca & ICH9_LPC_RCBA_BA_MASK,
+                                                &lpc->rbca_mem, 1);
     }
 }
 
@@ -765,7 +799,7 @@ static int ich9_lpc_post_load(void *opaque, int version_id)
 static void ich9_lpc_config_write(PCIDevice *d,
                                   uint32_t addr, uint32_t val, int len)
 {
-    ICH9_LPCState *lpc = ich9_lpc_from_pci(d);
+    ICH9_LPCState *lpc = ICH9_LPC_DEVICE(d);
     uint32_t rbca_old = pci_get_long(d->config + ICH9_LPC_RCBA);
 
     pci_default_write_config(d, addr, val, len);
@@ -779,8 +813,8 @@ static void ich9_lpc_config_write(PCIDevice *d,
 
 static void ich9_lpc_reset(DeviceState *qdev)
 {
-    PCIDevice *d = DO_UPCAST(PCIDevice, qdev, qdev);
-    ICH9_LPCState *lpc = ich9_lpc_from_pci(d);
+    PCIDevice *d = PCI_DEVICE(qdev);
+    ICH9_LPCState *lpc = ICH9_LPC_DEVICE(d);
     uint32_t rbca_old = pci_get_long(d->config + ICH9_LPC_RCBA);
     int i;
 
@@ -805,22 +839,26 @@ static void ich9_lpc_reset(DeviceState *qdev)
     lpc->sci_level = 0;
 }
 
+static const MemoryRegionOps rbca_mmio_ops = {
+    .read = ich9_cc_read,
+    .write = ich9_cc_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+};
+
 static int ich9_lpc_initfn(PCIDevice *d)
 {
-    ICH9_LPCState *lpc = ich9_lpc_from_pci(d);
+    ICH9_LPCState *lpc = ICH9_LPC_DEVICE(d);
+    ISABus *isa_bus;
 
-    isa_bus_new(&d->qdev);
-    pci_config_set_vendor_id(d->config, PCI_VENDOR_ID_INTEL);
-    pci_config_set_device_id(d->config, PCI_DEVICE_ID_INTEL_ICH9_8); /* ICH9 
LPC */
-    pci_config_set_revision(d->config, ICH9_A2_LPC_REVISION);
-    pci_config_set_class(d->config, PCI_CLASS_BRIDGE_ISA);
+    isa_bus = isa_bus_new(&d->qdev, get_system_io());
 
     pci_set_long(d->wmask + ICH9_LPC_PMBASE,
                  ICH9_LPC_PMBASE_BASE_ADDRESS_MASK);
 
-    lpc->rbca_index = cpu_register_io_memory(ich9_cc_mmio_read,
-                                             ich9_cc_mmio_write,
-                                             lpc, DEVICE_LITTLE_ENDIAN);
+    memory_region_init_io(&lpc->rbca_mem, &rbca_mmio_ops, lpc,
+                            "lpc-rbca-mmio", ICH9_CC_SIZE);
+
+    lpc->isa_bus = isa_bus;
 
     ich9_cc_init(lpc);
     apm_init(&lpc->apm, ich9_apm_ctrl_changed, lpc);
@@ -845,33 +883,50 @@ static const VMStateDescription vmstate_ich9_lpc = {
 
 PCIDevice *gmch_lpc_init(DeviceState *gmch_host, PCIBus *bus)
 {
-    GMCH_PCIHost *s = gmch_pcihost_from_qdev(gmch_host);
+    GMCH_PCIHost *s = GMCH_HOST_DEVICE(gmch_host);
     PCIDevice *d;
     ICH9_LPCState *lpc;
 
     d = pci_create_simple_multifunction(bus, PCI_DEVFN(ICH9_LPC_DEV,
                                                        ICH9_LPC_FUNC),
-                                        true, "ICH9 LPC");
-    lpc = ich9_lpc_from_pci(d);
+                                        true, TYPE_ICH9_LPC_DEVICE);
+    lpc = ICH9_LPC_DEVICE(d);
     s->irq_state.lpc = lpc;
     return &lpc->d;
 }
 
-static PCIDeviceInfo ich9_lpc_info = {
-    .qdev.name    = "ICH9 LPC",
-    .qdev.desc    = "ICH9 LPC bridge",
-    .qdev.size    = sizeof(ICH9_LPCState),
-    .qdev.vmsd    = &vmstate_ich9_lpc,
-    .qdev.no_user = 1,
-    .init         = ich9_lpc_initfn,
-    .config_write = ich9_lpc_config_write,
-    .qdev.reset   = ich9_lpc_reset,
+static void ich9_lpc_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+    dc->reset = ich9_lpc_reset;
+    k->init = ich9_lpc_initfn;
+    dc->vmsd = &vmstate_ich9_lpc;
+    dc->no_user = 1;
+    k->config_write = ich9_lpc_config_write;
+    dc->desc = "ICH9 LPC bridge";
+    k->vendor_id = PCI_VENDOR_ID_INTEL;
+    k->device_id = PCI_DEVICE_ID_INTEL_ICH9_8;
+    k->revision = ICH9_A2_LPC_REVISION;
+    k->class_id = PCI_CLASS_BRIDGE_ISA;
+
+}
+
+static TypeInfo ich9_lpc_info = {
+    .name       = TYPE_ICH9_LPC_DEVICE,
+    .parent     = TYPE_PCI_DEVICE,
+    .instance_size = sizeof(struct ICH9_LPCState),
+    .class_init  = ich9_lpc_class_init,
 };
 
 static void q35_register(void)
 {
-    sysbus_register_withprop(&gmch_pcihost_info);
-    pci_qdev_register(&gmch_info);
-    pci_qdev_register(&ich9_lpc_info);
+    type_register_static(&pci_gmch_info);
+    type_register_static(&gmch_pcihost_info);
+    type_register_static(&i82801b11_bridge_info);
+    type_register_static(&i21154_bridge_info);
+    type_register_static(&ich9_lpc_info);
 }
-device_init(q35_register);
+
+type_init(q35_register);
diff --git a/hw/q35.h b/hw/q35.h
index be2e96b..030386e 100644
--- a/hw/q35.h
+++ b/hw/q35.h
@@ -21,19 +21,109 @@
 #ifndef HW_Q35_H
 #define HW_Q35_H
 
+#include "hw.h"
+#include "range.h"
+#include "isa.h"
 #include "sysbus.h"
+#include "pc.h"
+#include "apm.h"
+#include "apic.h"
+#include "pci.h"
+#include "pcie_host.h"
+#include "pci_bridge.h"
+#include "q35.h"
+#include "acpi.h"
 #include "acpi_ich9.h"
+#include "pam.h"
+#include "pci_internals.h"
+
+
+#define ICH9_CC_SIZE                            (16 * 1024)     /* 16KB */
+
+#define TYPE_GMCH_HOST_DEVICE "gmch-pcihost"
+#define GMCH_HOST_DEVICE(obj) \
+     OBJECT_CHECK(GMCH_PCIHost, (obj), TYPE_GMCH_HOST_DEVICE)
+
+#define TYPE_GMCH_PCI_DEVICE "gmch"
+#define GMCH_PCI_DEVICE(obj) \
+     OBJECT_CHECK(GMCH_PCIState, (obj), TYPE_GMCH_PCI_DEVICE)
+
+#define TYPE_ICH9_LPC_DEVICE "ICH9 LPC"
+#define ICH9_LPC_DEVICE(obj) \
+     OBJECT_CHECK(ICH9_LPCState, (obj), TYPE_ICH9_LPC_DEVICE)
+
+struct ICH9_LPCState;
+
+typedef struct ICH9_LPCIrqState {
+    struct ICH9_LPCState *lpc;
+    qemu_irq *pic;
+    qemu_irq *ioapic;
+} ICH9_LPCIrqState;
+
+typedef struct GMCH_PCIHost {
+    PCIExpressHost      host;
+
+    PCIDevice    *dev;
+    ICH9_LPCIrqState irq_state;
+} GMCH_PCIHost;
+
+typedef struct GMCH_PCIState {
+    PCIDevice   d;
+    /*
+     * GMCH_PCIHost   *gmch_host;
+     * In order to get GMCH_PCIHost
+     *  PCIDevice -> qdev -> parent_bus -> qdev -upcast-> GMCH_PCIHost
+     */
+    MemoryRegion *ram_memory;
+    MemoryRegion *pci_address_space;
+    MemoryRegion *system_memory;
+    PAMMemoryRegion pam_regions[13];
+    MemoryRegion smram_region;
+    MemoryRegion pci_hole;
+    MemoryRegion pci_hole_64bit;
+    uint8_t smm_enabled;
+} GMCH_PCIState;
+
+typedef struct ICH9_LPCState {
+    /* ICH9 LPC PCI to ISA bridge */
+    PCIDevice d;
+
+    /* (pci device, intx) -> pirq
+     * In real chipset case, the unused slots are never used
+     * as ICH9 supports only D25-D32 irq routing.
+     * On the other hand in qemu case, any slot/function can be populated
+     * via command line option.
+     * So fallback interrupt routing for any devices in any slots is necessary.
+    */
+    uint8_t irr[PCI_SLOT_MAX][PCI_NUM_PINS];
+
+    APMState apm;
+    ICH9_LPCPmRegs pm;
+    uint32_t sci_level; /* track sci level */
+
+    /* 10.1 Chipset Configuration registers(Memory Space)
+     which is pointed by RCBA */
+    uint8_t chip_config[ICH9_CC_SIZE];
+    /* isa bus */
+    ISABus *isa_bus;
+    MemoryRegion rbca_mem;
+} ICH9_LPCState;
 
-PCIBus *gmch_host_init(DeviceState **gmch_hostp,
-                       qemu_irq *pic, qemu_irq *ioapic);
 
+
+
+PCIBus *gmch_host_init(DeviceState **gmch_hostp,
+                       qemu_irq *pic, qemu_irq *ioapic,
+                       MemoryRegion *pci_address_space,
+                       MemoryRegion *address_space_io);
 PCIDevice *gmch_init(DeviceState *gmch_host, PCIBus *b);
 PCIBus *ich9_d2pbr_init(PCIBus *bus, int devfn, int sec_bus);
 PCIDevice *gmch_lpc_init(DeviceState *gmch_host, PCIBus *bus);
 void ich9_lpc_pm_init(DeviceState *gmch_host, PCIDevice *pci_lpc,
                       qemu_irq cmos_s3);
-
 i2c_bus *ich9_smb_init(PCIBus *bus, int devfn, uint32_t smb_io_base);
+PCIBridge *i21154_init(PCIBus *bus, int devfn, const char *bus_name,
+                              bool multifunction);
 
 #define Q35_MASK(bit, ms_bit, ls_bit) \
 ((uint##bit##_t)(((1ULL << ((ms_bit) + 1)) - 1) & ~((1ULL << ls_bit) - 1)))
@@ -124,7 +214,6 @@ i2c_bus *ich9_smb_init(PCIBus *bus, int devfn, uint32_t 
smb_io_base);
  */
 
 /* ICH9: Chipset Configuration Registers */
-#define ICH9_CC_SIZE                            (16 * 1024)     /* 16KB */
 #define ICH9_CC_ADDR_MASK                       (ICH9_CC_SIZE - 1)
 
 #define ICH9_CC
diff --git a/hw/q35_smbus.c b/hw/q35_smbus.c
index fe445ac..0ee404e 100644
--- a/hw/q35_smbus.c
+++ b/hw/q35_smbus.c
@@ -18,6 +18,7 @@
 /*
  *  Copyright (c) 2009 Isaku Yamahata <yamahata at valinux co jp>
  *                     VA Linux Systems Japan K.K.
+ *  Copyright (C) 2012 Jason Baron <address@hidden>
  *
  *  This is based on acpi.c, but heavily rewritten.
  */
@@ -35,6 +36,7 @@ typedef struct ICH9_SMBState {
     PCIDevice dev;
 
     PMSMBus smb;
+    MemoryRegion mem_bar;
 } ICH9_SMBState;
 
 static ICH9_SMBState *ich9_pci_to_smb(PCIDevice* pci_dev)
@@ -53,7 +55,8 @@ static const VMStateDescription vmstate_ich9_smbus = {
     }
 };
 
-static void ich9_smb_ioport_writeb(void *opaque, uint32_t addr, uint32_t val)
+static void ich9_smb_ioport_writeb(void *opaque, target_phys_addr_t addr,
+                                   uint64_t val, unsigned size)
 {
     ICH9_SMBState *s = opaque;
     uint8_t hostc = s->dev.config[ICH9_SMB_HOSTC];
@@ -64,7 +67,8 @@ static void ich9_smb_ioport_writeb(void *opaque, uint32_t 
addr, uint32_t val)
     }
 }
 
-static uint32_t ich9_smb_ioport_readb(void *opaque, uint32_t addr)
+static uint64_t ich9_smb_ioport_readb(void *opaque, target_phys_addr_t addr,
+                                      unsigned size)
 {
     ICH9_SMBState *s = opaque;
     uint8_t hostc = s->dev.config[ICH9_SMB_HOSTC];
@@ -77,32 +81,22 @@ static uint32_t ich9_smb_ioport_readb(void *opaque, 
uint32_t addr)
     return 0xff;
 }
 
-static void ich9_smb_map_ioport(PCIDevice *dev, int region_num,
-                                uint64_t addr, uint64_t size, int type)
-{
-    ICH9_SMBState *s = ich9_pci_to_smb(dev);
-
-    assert(size == ICH9_SMB_SMB_BASE_SIZE);
-    assert(type == PCI_BASE_ADDRESS_SPACE_IO);
-
-    register_ioport_write(addr, 64, 1, ich9_smb_ioport_writeb, s);
-    register_ioport_read(addr, 64, 1, ich9_smb_ioport_readb, s);
-}
+static const MemoryRegionOps lpc_smb_mmio_ops = {
+    .read = ich9_smb_ioport_readb,
+    .write = ich9_smb_ioport_writeb,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+    .impl = {
+        .min_access_size = 1,
+        .max_access_size = 1,
+    },
+};
 
-static int ich9_smb_initfn(PCIDevice *d)
+static int ich9_smbus_initfn(PCIDevice *d)
 {
     ICH9_SMBState *s = ich9_pci_to_smb(d);
 
-    pci_config_set_vendor_id(d->config, PCI_VENDOR_ID_INTEL);
-    pci_config_set_device_id(d->config, PCI_DEVICE_ID_INTEL_ICH9_6);
-
     pci_set_word(d->wmask + PCI_STATUS,
-                 PCI_STATUS_SIG_SYSTEM_ERROR | PCI_STATUS_DETECTED_PARITY);
-
-    pci_config_set_revision(d->config, ICH9_A2_SMB_REVISION);
-    pci_config_set_prog_interface(d->config, ICH9_SMB_PI);
-    pci_config_set_class(d->config, PCI_CLASS_SERIAL_SMBUS);
-
+                    PCI_STATUS_SIG_SYSTEM_ERROR | PCI_STATUS_DETECTED_PARITY);
     /* TODO? D31IP.SMIP in chipset configuration space */
     pci_config_set_interrupt_pin(d->config, 0x01); /* interrupt pin 1 */
 
@@ -121,14 +115,30 @@ static int ich9_smb_initfn(PCIDevice *d)
     /* TODO smb_io_base */
     pci_set_byte(d->config + ICH9_SMB_HOSTC, 0);
     /* TODO bar0, bar1: 64bit BAR support*/
-    pci_register_bar(d, ICH9_SMB_SMB_BASE_BAR,
-                     ICH9_SMB_SMB_BASE_SIZE, PCI_BASE_ADDRESS_SPACE_IO,
-                     &ich9_smb_map_ioport);
 
+    memory_region_init_io(&s->mem_bar, &lpc_smb_mmio_ops, s, "ich9-smbus-bar",
+                            ICH9_SMB_SMB_BASE_SIZE);
+    pci_register_bar(d, ICH9_SMB_SMB_BASE_BAR, PCI_BASE_ADDRESS_SPACE_IO,
+                        &s->mem_bar);
     pm_smbus_init(&d->qdev, &s->smb);
     return 0;
 }
 
+static void ich9_smb_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+    k->vendor_id = PCI_VENDOR_ID_INTEL;
+    k->device_id = PCI_DEVICE_ID_INTEL_ICH9_6;
+    k->revision = ICH9_A2_SMB_REVISION;
+    k->class_id = PCI_CLASS_SERIAL_SMBUS;
+    dc->no_user = 1;
+    dc->vmsd = &vmstate_ich9_smbus;
+    dc->desc = "ICH9 SMBUS Bridge";
+    k->init = ich9_smbus_initfn;
+}
+
 i2c_bus *ich9_smb_init(PCIBus *bus, int devfn, uint32_t smb_io_base)
 {
     PCIDevice *d =
@@ -137,18 +147,16 @@ i2c_bus *ich9_smb_init(PCIBus *bus, int devfn, uint32_t 
smb_io_base)
     return s->smb.smbus;
 }
 
-static PCIDeviceInfo ich9_smb_info = {
-    .qdev.name = "ICH9 SMB",
-    .qdev.desc = "ICH9 SMBUS Bridge",
-    .qdev.size = sizeof(ICH9_SMBState),
-    .qdev.vmsd = &vmstate_ich9_smbus,
-    .qdev.no_user = 1,
-    .init = ich9_smb_initfn,
+static TypeInfo ich9_smb_info = {
+    .name   = "ICH9 SMB",
+    .parent = TYPE_PCI_DEVICE,
+    .instance_size = sizeof(ICH9_SMBState),
+    .class_init = ich9_smb_class_init,
 };
 
 static void ich9_smb_register(void)
 {
-    pci_qdev_register(&ich9_smb_info);
+    type_register_static(&ich9_smb_info);
 }
 
-device_init(ich9_smb_register);
+type_init(ich9_smb_register);
-- 
1.7.1




reply via email to

[Prev in Thread] Current Thread [Next in Thread]