Hi all, Thanks for your comments. I made this new patch based on your comments 1. use bimodal _PRT, to take advantage of IOAPIC pin 16~23 the mapping is simple, slot -> (slot&7)+16 IOAPIC pin, someone may provide good mapping ? 2. use ISA-bridge configure space 0x64 byte as a communication mechansim. When guest BIOS invokes _PIC, the value is passed to qemu through byte 0x64. qemu know whether it is PIC mode and APIC mode by checking byte 0x64. 3. pci_slot_get_pirq and piix3_set_irq adopt different operation based on PIC mode/APIC mode 4. All pci devices are still using active high level-triggered interrupt, while IOAPIC pin 16~23 use active low level-triggered interrupt. piix3_set_irq is responsible to reserve the level if it is in APIC mode. 5. interrupt sharing for PCI devices is still supported Test by runing guest linux, NIC is using IOAPIC pin > 15 0: 980211 IO-APIC-edge timer 1: 179 IO-APIC-edge i8042 8: 0 IO-APIC-edge rtc 9: 0 IO-APIC-level acpi 12: 289 IO-APIC-edge i8042 14: 3266 IO-APIC-edge ide0 15: 13489 IO-APIC-edge ide1 185: 485 IO-APIC-level eth0 Didn't try guest linux only with PIC, I think it works, because the path for PIC is not changed at all. Please comment! Thanks, Anthony diff --git a/bios/acpi-dsdt.dsl b/bios/acpi-dsdt.dsl index 21fc76a..64219f2 100755 --- a/bios/acpi-dsdt.dsl +++ b/bios/acpi-dsdt.dsl @@ -201,14 +201,24 @@ DefinitionBlock ( } } + Name (PICD, 0) - /* PCI Bus definition */ + + /*PCI Bus definition */ Scope(\_SB) { Device(PCI0) { Name (_HID, EisaId ("PNP0A03")) Name (_ADR, 0x00) Name (_UID, 1) - Name(_PRT, Package() { + + Method(_PRT,0){ + If(PICD){ + Return(PRTA) + } + Return(PRTP) + } + + Name(PRTP, Package() { /* PCI IRQ routing table, example from ACPI 2.0a specification, section 6.2.8.1 */ /* Note: we provide the same info as the PCI routing @@ -407,6 +417,202 @@ DefinitionBlock ( Package() {0x001fffff, 3, LNKB, 0}, }) + Name(PRTA, Package() { + /* IOAPIC use fixed connection */ + + // PCI Slot 0 + Package() {0x0000ffff, 0, 0, 16}, + Package() {0x0000ffff, 1, 0, 16}, + Package() {0x0000ffff, 2, 0, 16}, + Package() {0x0000ffff, 3, 0, 16}, + + // PCI Slot 1 + Package() {0x0001ffff, 0, 0, 17}, + Package() {0x0001ffff, 1, 0, 17}, + Package() {0x0001ffff, 2, 0, 17}, + Package() {0x0001ffff, 3, 0, 17}, + + // PCI Slot 2 + Package() {0x0002ffff, 0, 0, 18}, + Package() {0x0002ffff, 1, 0, 18}, + Package() {0x0002ffff, 2, 0, 18}, + Package() {0x0002ffff, 3, 0, 18}, + + // PCI Slot 3 + Package() {0x0003ffff, 0, 0, 19}, + Package() {0x0003ffff, 1, 0, 19}, + Package() {0x0003ffff, 2, 0, 19}, + Package() {0x0003ffff, 3, 0, 19}, + + // PCI Slot 4 + Package() {0x0004ffff, 0, 0, 20}, + Package() {0x0004ffff, 1, 0, 20}, + Package() {0x0004ffff, 2, 0, 20}, + Package() {0x0004ffff, 3, 0, 20}, + + // PCI Slot 5 + Package() {0x0005ffff, 0, 0, 21}, + Package() {0x0005ffff, 1, 0, 21}, + Package() {0x0005ffff, 2, 0, 21}, + Package() {0x0005ffff, 3, 0, 21}, + + // PCI Slot 6 + Package() {0x0006ffff, 0, 0, 22}, + Package() {0x0006ffff, 1, 0, 22}, + Package() {0x0006ffff, 2, 0, 22}, + Package() {0x0006ffff, 3, 0, 22}, + + // PCI Slot 7 + Package() {0x0007ffff, 0, 0, 23}, + Package() {0x0007ffff, 1, 0, 23}, + Package() {0x0007ffff, 2, 0, 23}, + Package() {0x0007ffff, 3, 0, 23}, + + // PCI Slot 8 + Package() {0x0008ffff, 0, 0, 16}, + Package() {0x0008ffff, 1, 0, 16}, + Package() {0x0008ffff, 2, 0, 16}, + Package() {0x0008ffff, 3, 0, 16}, + + // PCI Slot 9 + Package() {0x0009ffff, 0, 0, 17}, + Package() {0x0009ffff, 1, 0, 17}, + Package() {0x0009ffff, 2, 0, 17}, + Package() {0x0009ffff, 3, 0, 17}, + + // PCI Slot 10 + Package() {0x000affff, 0, 0, 18}, + Package() {0x000affff, 1, 0, 18}, + Package() {0x000affff, 2, 0, 18}, + Package() {0x000affff, 3, 0, 18}, + + // PCI Slot 11 + Package() {0x000bffff, 0, 0, 19}, + Package() {0x000bffff, 1, 0, 19}, + Package() {0x000bffff, 2, 0, 19}, + Package() {0x000bffff, 3, 0, 19}, + + // PCI Slot 12 + Package() {0x000cffff, 0, 0, 20}, + Package() {0x000cffff, 1, 0, 20}, + Package() {0x000cffff, 2, 0, 20}, + Package() {0x000cffff, 3, 0, 20}, + + // PCI Slot 13 + Package() {0x000dffff, 0, 0, 21}, + Package() {0x000dffff, 1, 0, 21}, + Package() {0x000dffff, 2, 0, 21}, + Package() {0x000dffff, 3, 0, 21}, + + // PCI Slot 14 + Package() {0x000effff, 0, 0, 22}, + Package() {0x000effff, 1, 0, 22}, + Package() {0x000effff, 2, 0, 22}, + Package() {0x000effff, 3, 0, 22}, + + // PCI Slot 15 + Package() {0x000fffff, 0, 0, 23}, + Package() {0x000fffff, 1, 0, 23}, + Package() {0x000fffff, 2, 0, 23}, + Package() {0x000fffff, 3, 0, 23}, + + // PCI Slot 16 + Package() {0x0010ffff, 0, 0, 16}, + Package() {0x0010ffff, 1, 0, 16}, + Package() {0x0010ffff, 2, 0, 16}, + Package() {0x0010ffff, 3, 0, 16}, + + // PCI Slot 17 + Package() {0x0011ffff, 0, 0, 17}, + Package() {0x0011ffff, 1, 0, 17}, + Package() {0x0011ffff, 2, 0, 17}, + Package() {0x0011ffff, 3, 0, 17}, + + // PCI Slot 18 + Package() {0x0012ffff, 0, 0, 18}, + Package() {0x0012ffff, 1, 0, 18}, + Package() {0x0012ffff, 2, 0, 18}, + Package() {0x0012ffff, 3, 0, 18}, + + // PCI Slot 19 + Package() {0x0013ffff, 0, 0, 19}, + Package() {0x0013ffff, 1, 0, 19}, + Package() {0x0013ffff, 2, 0, 19}, + Package() {0x0013ffff, 3, 0, 19}, + + // PCI Slot 20 + Package() {0x0014ffff, 0, 0, 20}, + Package() {0x0014ffff, 1, 0, 20}, + Package() {0x0014ffff, 2, 0, 20}, + Package() {0x0014ffff, 3, 0, 20}, + + // PCI Slot 21 + Package() {0x0015ffff, 0, 0, 21}, + Package() {0x0015ffff, 1, 0, 21}, + Package() {0x0015ffff, 2, 0, 21}, + Package() {0x0015ffff, 3, 0, 21}, + + // PCI Slot 22 + Package() {0x0016ffff, 0, 0, 22}, + Package() {0x0016ffff, 1, 0, 22}, + Package() {0x0016ffff, 2, 0, 22}, + Package() {0x0016ffff, 3, 0, 22}, + + // PCI Slot 23 + Package() {0x0017ffff, 0, 0, 23}, + Package() {0x0017ffff, 1, 0, 23}, + Package() {0x0017ffff, 2, 0, 23}, + Package() {0x0017ffff, 3, 0, 23}, + + // PCI Slot 24 + Package() {0x0018ffff, 0, 0, 16}, + Package() {0x0018ffff, 1, 0, 16}, + Package() {0x0018ffff, 2, 0, 16}, + Package() {0x0018ffff, 3, 0, 16}, + + // PCI Slot 25 + Package() {0x0019ffff, 0, 0, 17}, + Package() {0x0019ffff, 1, 0, 17}, + Package() {0x0019ffff, 2, 0, 17}, + Package() {0x0019ffff, 3, 0, 17}, + + // PCI Slot 26 + Package() {0x001affff, 0, 0, 18}, + Package() {0x001affff, 1, 0, 18}, + Package() {0x001affff, 2, 0, 18}, + Package() {0x001affff, 3, 0, 18}, + + // PCI Slot 27 + Package() {0x001bffff, 0, 0, 19}, + Package() {0x001bffff, 1, 0, 19}, + Package() {0x001bffff, 2, 0, 19}, + Package() {0x001bffff, 3, 0, 19}, + + // PCI Slot 28 + Package() {0x001cffff, 0, 0, 20}, + Package() {0x001cffff, 1, 0, 20}, + Package() {0x001cffff, 2, 0, 20}, + Package() {0x001cffff, 3, 0, 20}, + + // PCI Slot 29 + Package() {0x001dffff, 0, 0, 21}, + Package() {0x001dffff, 1, 0, 21}, + Package() {0x001dffff, 2, 0, 21}, + Package() {0x001dffff, 3, 0, 21}, + + // PCI Slot 30 + Package() {0x001effff, 0, 0, 22}, + Package() {0x001effff, 1, 0, 22}, + Package() {0x001effff, 2, 0, 22}, + Package() {0x001effff, 3, 0, 22}, + + // PCI Slot 31 + Package() {0x001fffff, 0, 0, 23}, + Package() {0x001fffff, 1, 0, 23}, + Package() {0x001fffff, 2, 0, 23}, + Package() {0x001fffff, 3, 0, 23}, + }) + OperationRegion(PCST, SystemIO, 0xae00, 0x08) Field (PCST, DWordAcc, NoLock, WriteAsZeros) { @@ -770,6 +976,9 @@ DefinitionBlock ( /* PIIX PCI to ISA irq remapping */ OperationRegion (P40C, PCI_Config, 0x60, 0x04) + /* APIC and PIC flag */ + OperationRegion (P40D, PCI_Config, 0x64, 0x01) + /* Real-time clock */ Device (RTC) { @@ -960,6 +1169,19 @@ DefinitionBlock ( } } + + Field (\_SB.PCI0.ISA.P40D, ByteAcc, NoLock, Preserve) + { + FLAG, 8, + } + + Method(_PIC, 1) + { + Store(Arg0, PICD) + Store(Arg0, FLAG) + } + + /* PCI IRQs */ Scope(\_SB) { Field (\_SB.PCI0.ISA.P40C, ByteAcc, NoLock, Preserve) diff --git a/qemu/hw/piix_pci.c b/qemu/hw/piix_pci.c index 90cb3a6..da6bcab 100644 --- a/qemu/hw/piix_pci.c +++ b/qemu/hw/piix_pci.c @@ -28,6 +28,7 @@ typedef uint32_t pci_addr_t; #include "pci_host.h" +#include "qemu-kvm.h" typedef PCIHostState I440FXState; @@ -45,6 +46,25 @@ static uint32_t i440fx_addr_readl(void* opaque, uint32_t addr) static void piix3_set_irq(qemu_irq *pic, int irq_num, int level); +/* PIIX3 PCI to ISA bridge */ + +PCIDevice *piix3_dev; +PCIDevice *piix4_dev; + + +#ifdef KVM_CAP_IRQCHIP +static int pci_slot_get_pirq(PCIDevice *pci_dev, int irq_num) +{ + int slot_addend; + if( piix3_dev->config[0x64]) // APIC mode + return ((pci_dev->devfn >> 3) & 7)+16; + else { // PIC mode + slot_addend = (pci_dev->devfn >> 3) - 1; + return (irq_num + slot_addend) & 3; + } +} + +#else /* 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. */ @@ -54,6 +74,7 @@ static int pci_slot_get_pirq(PCIDevice *pci_dev, int irq_num) slot_addend = (pci_dev->devfn >> 3) - 1; return (irq_num + slot_addend) & 3; } +#endif static target_phys_addr_t isa_page_descs[384 / 4]; static uint8_t smm_enabled; @@ -171,12 +192,17 @@ static int i440fx_load(QEMUFile* f, void *opaque, int version_id) PCIBus *i440fx_init(PCIDevice **pi440fx_state, qemu_irq *pic) { + int irq_num; PCIBus *b; PCIDevice *d; I440FXState *s; - +#ifdef KVM_CAP_IRQCHIP + irq_num = 24; +#else + irq_num = 4; +#endif s = qemu_mallocz(sizeof(I440FXState)); - b = pci_register_bus(piix3_set_irq, pci_slot_get_pirq, pic, 0, 4); + b = pci_register_bus(piix3_set_irq, pci_slot_get_pirq, pic, 0, irq_num); s->bus = b; register_ioport_write(0xcf8, 4, 4, i440fx_addr_writel, s); @@ -208,10 +234,6 @@ PCIBus *i440fx_init(PCIDevice **pi440fx_state, qemu_irq *pic) return b; } -/* PIIX3 PCI to ISA bridge */ - -PCIDevice *piix3_dev; -PCIDevice *piix4_dev; /* just used for simpler irq handling. */ #define PCI_IRQ_WORDS ((PCI_DEVICES_MAX + 31) / 32) @@ -220,6 +242,12 @@ static void piix3_set_irq(qemu_irq *pic, int irq_num, int level) { int i, pic_irq, pic_level; +#ifdef KVM_CAP_IRQCHIP + if (piix3_dev->config[0x64]){ // APIC mode + kvm_set_irq(irq_num, !level); + return; + } +#endif pci_irq_levels[irq_num] = level; /* now we change the pic irq level according to the piix irq mappings */ -- To unsubscribe from this list: send the line "unsubscribe kvm-ia64" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html