[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH 61/61] pc_q35: apic mode for pci interrupt routing.
From: |
Isaku Yamahata |
Subject: |
[Qemu-devel] [PATCH 61/61] pc_q35: apic mode for pci interrupt routing. |
Date: |
Wed, 30 Sep 2009 19:18:37 +0900 |
apic mode for pci interrupt routing.
Signed-off-by: Isaku Yamahata <address@hidden>
---
hw/pc_q35.c | 4 +-
hw/q35.c | 87 +++++++++++++++++++++++++++++++++++++++++++++++-----------
hw/q35.h | 6 +++-
3 files changed, 77 insertions(+), 20 deletions(-)
diff --git a/hw/pc_q35.c b/hw/pc_q35.c
index 9980a39..105b97b 100644
--- a/hw/pc_q35.c
+++ b/hw/pc_q35.c
@@ -132,10 +132,10 @@ static void pc_q35_init(ram_addr_t ram_size,
i8259 = i8259_init(cpu_irq[0]);
isa_irq_state = qemu_mallocz(sizeof(*isa_irq_state));
isa_irq_state->i8259 = i8259;
- isa_irq_state->ioapic = ioapic_init();
isa_irq = qemu_allocate_irqs(isa_irq_handler, isa_irq_state, 24);
- host_bus = gmch_init(&gmch_state, isa_irq, &ich9_lpc_devfn);
+ host_bus = gmch_init(&gmch_state, isa_irq, &ich9_lpc_devfn,
+ &isa_irq_state->ioapic);
isa_bus_irqs(isa_irq);
pc_register_ferr_irq(isa_reserve_irq(13));
diff --git a/hw/q35.c b/hw/q35.c
index 05267ea..06dbdf9 100644
--- a/hw/q35.c
+++ b/hw/q35.c
@@ -59,6 +59,7 @@ struct ICH9_LPCState {
/* ICH9 LPC PCI to ISA bridge */
PCIDevice d;
+ int apic_mode;
int pci_irq_levels[ICH9_LPC_NB_PIRQS];
APMState apm;
@@ -68,6 +69,7 @@ struct ICH9_LPCState {
struct ICH9_LPCIrqState {
struct ICH9_LPCState *lpc;
qemu_irq *pic;
+ qemu_irq *ioapic;
};
typedef struct GMCHState {
@@ -154,12 +156,42 @@ static void gmch_update_pcixbar(struct GMCH_PCIState *gs)
static struct ICH9_LPCState *ich9_lpc_init(PCIBus *bus, int devfn, struct
ICH9_LPCIrqState *irq_state);
static void ich9_lpc_set_irq(void *opaque, int irq_num, int level);
+static void ich9_lpc_ioapic_update_fn(void *opaque, int reset)
+{
+ struct ICH9_LPCIrqState *irq_state = opaque;
+ struct ICH9_LPCState *ich9_lpc = irq_state->lpc;
+
+ /* this can be called via gmch_init() where ich9_lpc isn't
+ allocated yet */
+ if (ich9_lpc == NULL)
+ return;
+
+ if (reset)
+ ich9_lpc->apic_mode = 0;
+ else
+ ich9_lpc->apic_mode = 1;
+}
+
/* return the global irq number corresponding to a given device irq
- pin. We could also use the bus number to have a more precise
- mapping. */
-static int pci_slot_get_pirq(void *opaque, PCIDevice *pci_dev, int irq_num)
+ pin.
+ pic mode: LNKx
+ apic mode: gsi
+ We could also use the bus number/device to have a more precise mapping. */
+static int pci_slot_map_irq(void *opaque, PCIDevice *pci_dev, int irq_num)
{
- return pci_swizzle_map_irq_fn(NULL, pci_dev, irq_num);
+ struct ICH9_LPCIrqState *irq_state = opaque;
+ struct ICH9_LPCState *lpc = irq_state->lpc;
+ int pin = pci_swizzle_map_irq_fn(NULL, pci_dev, irq_num);
+
+ if (!lpc->apic_mode) {
+ /* INTA -> INKA, ...
+ this would be device wise... */
+ return pin;
+ }
+
+ /* APIC mode INTA -> 16, ...
+ this would be device wise... */
+ return pin + ICH9_LPC_PIC_NUM_PINS;
}
/* PAM */
@@ -385,24 +417,30 @@ static int gmch_initfn(PCIDevice *d)
}
/* host bridge */
-PCIBus *gmch_init(PCIDevice **pgmch_state, qemu_irq *pic, int *ich9_lpc_devfn)
+PCIBus *gmch_init(PCIDevice **pgmch_state, qemu_irq *pic, int *ich9_lpc_devfn,
+ qemu_irq **ioapic)
{
DeviceState *dev;
GMCHState *s;
PCIBus *b;
PCIDevice *d;
struct GMCH_PCIState *gs;
- struct ICH9_LPCIrqState *irq_state = qemu_malloc(sizeof(*irq_state));
+ struct ICH9_LPCIrqState *irq_state = qemu_mallocz(sizeof(*irq_state));
irq_state->pic = pic;
dev = qdev_create(NULL, "gmch-pcihost");
s = gmchstate_from_sysbus(sysbus_from_qdev(dev));
b = pci_register_bus(dev, "pci.0",
- ich9_lpc_set_irq, pci_slot_get_pirq, irq_state, 0,
+ ich9_lpc_set_irq, pci_slot_map_irq, irq_state, 0,
24 /* 24 pin IO APIC */);
s->host.pci.bus = b;
qdev_init(dev);
+ *ioapic = ioapic_init_with_mre(ICH9_LPC_IOAPIC_NUM_PINS,
+ ich9_lpc_ioapic_update_fn,
+ irq_state);
+ irq_state->ioapic = *ioapic;
+
d = pci_create_simple(b, 0, "gmch");
s->dev = d;
gs = DO_UPCAST(struct GMCH_PCIState, d, d);
@@ -554,11 +592,10 @@ static void ich9_lpc_pic_irq(struct ICH9_LPCState *lpc,
int irq_num,
abort();
}
-static void ich9_lpc_set_irq(void *opaque, int irq_num, int level)
+/* irq_num = LNKx: 0 = LNKA, ... */
+static void ich9_lpc_set_irq_pic(struct ICH9_LPCState *ich9_lpc,
+ qemu_irq *pic, int irq_num, int level)
{
- struct ICH9_LPCIrqState *irq_state = opaque;
- struct ICH9_LPCState *ich9_lpc = irq_state->lpc;
- qemu_irq *pic = irq_state->pic;
int i, pic_level;
int pic_irq;
int pic_dis;
@@ -569,16 +606,11 @@ static void ich9_lpc_set_irq(void *opaque, int irq_num,
int level)
/* now we change the pic irq level according to
the ich9 lpc irq mappings */
ich9_lpc_pic_irq(ich9_lpc, irq_num, &pic_irq, &pic_dis);
+ assert(pic_irq < ICH9_LPC_PIC_NUM_PINS);
if (pic_dis) {
return;
}
- if (pic_irq > 24) {
- fprintf(stderr, "%s: error irq_num %d pic_irq %d\n",
- __func__, irq_num, pic_irq);
- return;
- }
-
/* The pic level is the logical OR of all the PCI irqs mapped to it */
pic_level = 0;
for (i = 0; i < ICH9_LPC_NB_PIRQS; i++) {
@@ -592,6 +624,27 @@ static void ich9_lpc_set_irq(void *opaque, int irq_num,
int level)
qemu_set_irq(pic[pic_irq], pic_level);
}
+/* irq_num = GSI */
+static void ich9_lpc_set_irq_apic(struct ICH9_LPCState *ich9_lpc,
+ qemu_irq *ioapic, int irq_num, int level)
+{
+ assert(irq_num < ICH9_LPC_IOAPIC_NUM_PINS);
+ qemu_set_irq(ioapic[irq_num], level);
+}
+
+/* pic mode: irq_num = LNKx
+ apic mode: irq_num = GSI */
+static void ich9_lpc_set_irq(void *opaque, int irq_num, int level)
+{
+ struct ICH9_LPCIrqState *irq_state = opaque;
+ struct ICH9_LPCState *ich9_lpc = irq_state->lpc;
+
+ if (ich9_lpc->apic_mode)
+ ich9_lpc_set_irq_apic(ich9_lpc, irq_state->ioapic, irq_num, level);
+ else
+ ich9_lpc_set_irq_pic(ich9_lpc, irq_state->pic, irq_num, level);
+}
+
/* APM */
static void ich9_apm_ctrl_changed(uint32_t val, void *arg)
{
diff --git a/hw/q35.h b/hw/q35.h
index a3a97b5..2f68152 100644
--- a/hw/q35.h
+++ b/hw/q35.h
@@ -25,7 +25,8 @@
#include "acpi_ich9.h"
void gmch_init_memory_mappings(PCIDevice *d);
-PCIBus *gmch_init(PCIDevice **pgmch_state, qemu_irq *pic, int *ich9_lpc_devfn);
+PCIBus *gmch_init(PCIDevice **pgmch_state, qemu_irq *pic, int *ich9_lpc_devfn,
+ qemu_irq **ioapic);
PCIBus *ich9_d2pbr_init(PCIBus *bus, int devfn, int secondary_bus_num);
@@ -176,6 +177,9 @@ void ich9_hot_add_init(struct ich9_lpc_pm_regs *pm);
#define ICH9_LPC_RCBA_EN 0x1
#define ICH9_LPC_RCBA_DEFAULT 0x0
+#define ICH9_LPC_PIC_NUM_PINS 16
+#define ICH9_LPC_IOAPIC_NUM_PINS 24
+
/* D30:F1 power management I/O registers
offset from the address ICH9_LPC_PMBASE */
--
1.6.0.2
- [Qemu-devel] [PATCH 17/61] pc: split out pci device init from pc_init1() into pc_pci_device_init(), (continued)
- [Qemu-devel] [PATCH 17/61] pc: split out pci device init from pc_init1() into pc_pci_device_init(), Isaku Yamahata, 2009/09/30
- [Qemu-devel] [PATCH 15/61] pc: split out vga initialization from pc_init1() into pc_vga_init()., Isaku Yamahata, 2009/09/30
- [Qemu-devel] [PATCH 09/61] pc: remove a global variable, floppy_controller., Isaku Yamahata, 2009/09/30
- [Qemu-devel] [PATCH 59/61] ioapic: make irr accept more than 32 pins., Isaku Yamahata, 2009/09/30
- [Qemu-devel] [PATCH 16/61] pc: split out basic device init from pc_init1() into pc_basic_device_init(), Isaku Yamahata, 2009/09/30
- [Qemu-devel] [PATCH 14/61] pc: split out memory allocation from pc_init1() into pc_memory_init(), Isaku Yamahata, 2009/09/30
- [Qemu-devel] [PATCH 56/61] ioapic: clean up of #ifdef DEBUG_IOAPIC., Isaku Yamahata, 2009/09/30
- [Qemu-devel] [PATCH 03/61] acpi: add acpi constants from linux header files and use them., Isaku Yamahata, 2009/09/30
- [Qemu-devel] [PATCH 49/61] pci hot add: pass opaque argument to callback., Isaku Yamahata, 2009/09/30
- [Qemu-devel] [PATCH 01/61] acpi: split out pc smbus routines from acpi.c into pc_smbus.c, Isaku Yamahata, 2009/09/30
- [Qemu-devel] [PATCH 61/61] pc_q35: apic mode for pci interrupt routing.,
Isaku Yamahata <=
- [Qemu-devel] [PATCH 11/61] pc: introduce a function to allocate cpu irq., Isaku Yamahata, 2009/09/30
- [Qemu-devel] [PATCH 51/61] vmstate: add a macro for pointer to struct, VMSTATE_STRUCT_POINTER., Isaku Yamahata, 2009/09/30
- [Qemu-devel] [PATCH 54/61] pci: add opaque argument to pci_map_irq_fn()., Isaku Yamahata, 2009/09/30
- [Qemu-devel] [PATCH 30/61] pci_host.h: split non-inline static function in pci_host.h into pci_host_c.h, Isaku Yamahata, 2009/09/30
- [Qemu-devel] [PATCH 37/61] pci: add helper function for pci config write function to check address., Isaku Yamahata, 2009/09/30
- [Qemu-devel] [PATCH 36/61] pci: use QLIST_ macro instead of direct list manipulation., Isaku Yamahata, 2009/09/30
- [Qemu-devel] [PATCH 22/61] pci: use appropriate PRIs in PCI_DPRINTF()., Isaku Yamahata, 2009/09/30