RE: [RFC]RE: [PATCH] kvm-ia64 irq assignment 1/2 kernel

Xu, Anthony
2008-07-03T01:22:50Z

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

Hi Jes,

You can use this one, I'm considering how to make it more generic per
AVI comment.

Anthony

Jes Sorensen wrote:
> Hi Anthony,
>
> Looking back through this thread - do you happen to have an updated
> patch for the irq problem? If not, could you let me know which is your
> latest version and I will try and look at it.
>
> Cheers,
> Jes

[-- Attachment #2: 0002-Irq-assignment.patch --]
[-- Type: application/octet-stream, Size: 6407 bytes --]

From 67806cc642cb666fb59fec60115fee37b80ecb3a Mon Sep 17 00:00:00 2001
From: Anthony Xu <anthony.xu@intel.com>
Date: Wed, 18 Jun 2008 14:32:46 -0400
Subject: [PATCH] Irq assignment

1. use bimodal _PRT
2. pci device can use irq > 15, reduce interrupt sharing
3. test by running linux guest in kvm-ia64, kvm-i32(w/ wo/ -no-kvm)

signed-off-by: Anthony Xu <anthony.xu@intel.com>
---
bios/acpi-dsdt.dsl | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++-
qemu/hw/apic.c | 22 ++++++++++++++++++-
qemu/hw/ipf.c | 24 +++++++++++++++++++++
qemu/hw/pc.c | 2 +-
qemu/hw/pc.h | 4 +++
qemu/hw/pci.c | 8 +++++++
6 files changed, 116 insertions(+), 3 deletions(-)

diff --git a/bios/acpi-dsdt.dsl b/bios/acpi-dsdt.dsl
index d1bfa2c..62dd612 100755
--- a/bios/acpi-dsdt.dsl
+++ b/bios/acpi-dsdt.dsl
@@ -89,6 +89,12 @@ DefinitionBlock (
}
}

+ Name (PICD, 0)
+
+ Method(_PIC, 1)
+ {
+ Store(Arg0, PICD)
+ }

/* PCI Bus definition */
Scope(\_SB) {
@@ -96,7 +102,15 @@ DefinitionBlock (
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
@@ -147,6 +161,49 @@ DefinitionBlock (
prt_slot3(0x001f),
})

+ Name (PRTA, Package() {
+ /* IOAPIC use fixed connection */
+
+#define aprt_slot(nr, irq) \
+ Package() { nr##ffff, 0, 0, irq }, \
+ Package() { nr##ffff, 1, 0, irq }, \
+ Package() { nr##ffff, 2, 0, irq }, \
+ Package() { nr##ffff, 3, 0, irq }
+
+ aprt_slot(0x0000, 16),
+ aprt_slot(0x0001, 17),
+ aprt_slot(0x0002, 18),
+ aprt_slot(0x0003, 19),
+ aprt_slot(0x0004, 20),
+ aprt_slot(0x0005, 21),
+ aprt_slot(0x0006, 22),
+ aprt_slot(0x0007, 23),
+ aprt_slot(0x0008, 16),
+ aprt_slot(0x0009, 17),
+ aprt_slot(0x000a, 18),
+ aprt_slot(0x000b, 19),
+ aprt_slot(0x000c, 20),
+ aprt_slot(0x000d, 21),
+ aprt_slot(0x000e, 22),
+ aprt_slot(0x000f, 23),
+ aprt_slot(0x0010, 16),
+ aprt_slot(0x0011, 17),
+ aprt_slot(0x0012, 18),
+ aprt_slot(0x0013, 19),
+ aprt_slot(0x0014, 20),
+ aprt_slot(0x0015, 21),
+ aprt_slot(0x0016, 22),
+ aprt_slot(0x0017, 23),
+ aprt_slot(0x0018, 16),
+ aprt_slot(0x0019, 17),
+ aprt_slot(0x001a, 18),
+ aprt_slot(0x001b, 19),
+ aprt_slot(0x001c, 20),
+ aprt_slot(0x001d, 21),
+ aprt_slot(0x001e, 22),
+ aprt_slot(0x001f, 23),
+ })
+
OperationRegion(PCST, SystemIO, 0xae00, 0x08)
Field (PCST, DWordAcc, NoLock, WriteAsZeros)
{
diff --git a/qemu/hw/apic.c b/qemu/hw/apic.c
index 4ebf1ff..98bf3ad 100644
--- a/qemu/hw/apic.c
+++ b/qemu/hw/apic.c
@@ -1053,10 +1053,30 @@ static void ioapic_service(IOAPICState *s)
}
}

+int ioapic_map_irq(int devfn, int irq_num)
+{
+ int irq;
+ irq = ((devfn >> 3) & 7) + 16;
+ return irq;
+}
+
+static int ioapic_irq_count[IOAPIC_NUM_PINS];
+
void ioapic_set_irq(void *opaque, int vector, int level)
{
IOAPICState *s = opaque;
-
+ if( vector >= 16 ){
+ if( level )
+ ioapic_irq_count[vector] += 1;
+ else
+ ioapic_irq_count[vector] -= 1;
+ level = (ioapic_irq_count[vector] != 0);
+ }
+#ifdef KVM_CAP_IRQCHIP
+ if (kvm_enabled())
+ if (kvm_set_irq(vector, ioapic_irq_count[vector] == 0))
+ return;
+#endif
if (vector >= 0 && vector < IOAPIC_NUM_PINS) {
uint32_t mask = 1 << vector;
uint64_t entry = s->ioredtbl[vector];
diff --git a/qemu/hw/ipf.c b/qemu/hw/ipf.c
index b11e328..dabd7cc 100644
--- a/qemu/hw/ipf.c
+++ b/qemu/hw/ipf.c
@@ -672,3 +672,27 @@ QEMUMachine ipf_machine = {
ipf_init_pci,
VGA_RAM_SIZE + VGA_RAM_SIZE,
};
+
+#define IOAPIC_NUM_PINS 48
+static int ioapic_irq_count[IOAPIC_NUM_PINS];
+
+int ioapic_map_irq(int devfn, int irq_num)
+{
+ int irq, dev;
+ dev = devfn >> 3;
+ irq = ((((dev << 2) + (dev >> 3) + irq_num) & 31) + 16);
+ return irq;
+}
+
+void ioapic_set_irq(void *opaque, int vector, int level)
+{
+ if( level )
+ ioapic_irq_count[vector] += 1;
+ else
+ ioapic_irq_count[vector] -= 1;
+
+ if (kvm_enabled())
+ if (kvm_set_irq(vector, ioapic_irq_count[vector] == 0))
+ return;
+}
+
diff --git a/qemu/hw/pc.c b/qemu/hw/pc.c
index 42c2687..bf49689 100644
--- a/qemu/hw/pc.c
+++ b/qemu/hw/pc.c
@@ -53,8 +53,8 @@
static fdctrl_t *floppy_controller;
static RTCState *rtc_state;
static PITState *pit;
-static IOAPICState *ioapic;
static PCIDevice *i440fx_state;
+IOAPICState *ioapic;

static void ioport80_write(void *opaque, uint32_t addr, uint32_t data)
{
diff --git a/qemu/hw/pc.h b/qemu/hw/pc.h
index c284bf1..379b386 100644
--- a/qemu/hw/pc.h
+++ b/qemu/hw/pc.h
@@ -47,6 +47,7 @@ int apic_accept_pic_intr(CPUState *env);
void apic_local_deliver(CPUState *env, int vector);
int apic_get_interrupt(CPUState *env);
IOAPICState *ioapic_init(void);
+int ioapic_map_irq(int devfn, int irq_num);
void ioapic_set_irq(void *opaque, int vector, int level);

/* i8254.c */
@@ -95,6 +96,9 @@ void ioport_set_a20(int enable);
int ioport_get_a20(void);
CPUState *pc_new_cpu(int cpu, const char *cpu_model, int pci_enabled);

+/* pc.c */
+extern IOAPICState *ioapic;
+
/* acpi.c */
extern int acpi_enabled;
i2c_bus *piix4_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base,
diff --git a/qemu/hw/pci.c b/qemu/hw/pci.c
index 92683d1..c1a0361 100644
--- a/qemu/hw/pci.c
+++ b/qemu/hw/pci.c
@@ -538,12 +538,20 @@ static void pci_set_irq(void *opaque, int irq_num, int level)
PCIDevice *pci_dev = (PCIDevice *)opaque;
PCIBus *bus;
int change;
+ int irq;

change = level - pci_dev->irq_state[irq_num];
if (!change)
return;

pci_dev->irq_state[irq_num] = level;
+
+ irq = ioapic_map_irq(pci_dev->devfn, irq_num);
+#if defined(TARGET_IA64)
+ ioapic_set_irq(NULL, irq, level);
+#else
+ ioapic_set_irq(ioapic, irq, level);
+#endif
for (;;) {
bus = pci_dev->bus;
irq_num = bus->map_irq(pci_dev, irq_num);
--
1.5.5