[Top][All Lists]
[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
- Re: [Qemu-devel] [PATCH 24/25] Add a fallback bios file search, if -L fails., (continued)
Re: [Qemu-devel] [PATCH 00/25] q35 series take #1, Isaku Yamahata, 2012/09/14