public inbox for kvm@vger.kernel.org
 help / color / mirror / Atom feed
* [RFC][PATCH 1/2] Make irq0->inti2 override in BIOS configurable from userspace
@ 2009-01-23  4:29 Beth Kon
  2009-01-23  4:29 ` [RFC][PATCH 2/2] Finish hpet implementation for KVM Beth Kon
  2009-01-25  1:31 ` [RFC][PATCH 1/2] Make irq0->inti2 override in BIOS configurable from userspace Marcelo Tosatti
  0 siblings, 2 replies; 3+ messages in thread
From: Beth Kon @ 2009-01-23  4:29 UTC (permalink / raw)
  To: kvm; +Cc: Beth Kon

This series of patches (nearly) resolves the irq0->inti2 override issue, and gets the hpet working on kvm with and
without the in-kernel irqchip (i.e., it disables userspace and in-kernel pit as needed).

- irq0->inti2
  The resolution was to always use the override unless the kernel cannot do irq routing (i.e., compatibility with old
  kernels). So qemu checks whether the kernel is capable of irq routing. If so, qemu tells kvm to route irq0 to 
  inti2 via the irq routing interface, and tells bios to add the irq0->inti2 override to the MADT interrupt source 
  override table, and to the mp table (for the non-acpi case). The only outstanding problem here is that when I set 
  acpi=off on the kernel boot line, the boot fails. Apparently linux does not like the way I implemented the override 
  for the mp table in rombios32.c. Since I am pressed for time at the moment, I'm putting this patch set out for comments 
  in hopes that someone else may immediately see the problem. Otherwise  I'll keep looking into it as time permits.

- hpet
  The hpet works with and without in-kernel irqchip. And many thanks to Marcelo for finding a bios corruption bug that
  was the primary source of win2k864 problems. Now the hpet works on linux (ubuntu 8.0.4), win2k832. On win2k864 it works
  with the in-kernel irqchip but is broken (i.e.,black screen) when -no-kvm-irqchip is specified. Though I found that 
  it is also broken when I remove these 2 patches, so it appears to have nothing to do with hpet or irq routing. Needs 
  more looking into.


Signed-off-by: Beth Kon <eak@us.ibm.com>
---
 bios/Makefile    |    2 +-
 bios/rombios32.c |   40 ++++++++++++++++++++++++++++++++++++----
 qemu/hw/apic.c   |    5 ++---
 qemu/hw/fw_cfg.c |    1 +
 qemu/hw/fw_cfg.h |    1 +
 qemu/qemu-kvm.c  |    5 ++++-
 qemu/sysemu.h    |    1 +
 qemu/vl.c        |   10 ++++++++--
 8 files changed, 54 insertions(+), 11 deletions(-)

diff --git a/bios/Makefile b/bios/Makefile
index 2d1f40d..374d70e 100644
--- a/bios/Makefile
+++ b/bios/Makefile
@@ -48,7 +48,7 @@ LIBS =  -lm
 RANLIB = ranlib
 
 BCC = bcc
-GCC = gcc $(CFLAGS)
+GCC = gcc $(CFLAGS) -fno-stack-protector
 HOST_CC = gcc
 AS86 = as86
 
diff --git a/bios/rombios32.c b/bios/rombios32.c
index 9d2eaaa..84f15fb 100755
--- a/bios/rombios32.c
+++ b/bios/rombios32.c
@@ -443,6 +443,7 @@ uint32_t cpuid_ext_features;
 unsigned long ram_size;
 uint64_t ram_end;
 uint8_t bios_uuid[16];
+uint8_t irq0_override;
 #ifdef BX_USE_EBDA_TABLES
 unsigned long ebda_cur_addr;
 #endif
@@ -475,6 +476,7 @@ void wrmsr_smp(uint32_t index, uint64_t val)
 #define QEMU_CFG_SIGNATURE  0x00
 #define QEMU_CFG_ID         0x01
 #define QEMU_CFG_UUID       0x02
+#define QEMU_CFG_IRQ0_OVERRIDE 0x07
 
 int qemu_cfg_port;
 
@@ -516,6 +518,18 @@ void uuid_probe(void)
     memset(bios_uuid, 0, 16);
 }
 
+void irq0_override_probe(void)
+{
+#ifdef BX_QEMU
+    if(qemu_cfg_port) {
+        qemu_cfg_select(QEMU_CFG_IRQ0_OVERRIDE);
+        qemu_cfg_read(&irq0_override, 1);
+        return;
+    }
+#endif
+    memset(&irq0_override, 0, 1);
+}
+
 void cpu_probe(void)
 {
     uint32_t eax, ebx, ecx, edx;
@@ -1149,6 +1163,8 @@ static void mptable_init(void)
 
     /* irqs */
     for(i = 0; i < 16; i++) {
+        if (irq0_override && i == 2)
+            continue;
         putb(&q, 3); /* entry type = I/O interrupt */
         putb(&q, 0); /* interrupt type = vectored interrupt */
         putb(&q, 0); /* flags: po=0, el=0 */
@@ -1156,7 +1172,10 @@ static void mptable_init(void)
         putb(&q, 0); /* source bus ID = ISA */
         putb(&q, i); /* source bus IRQ */
         putb(&q, ioapic_id); /* dest I/O APIC ID */
-        putb(&q, i); /* dest I/O APIC interrupt in */
+        if (irq0_override && i == 0)
+            putb(&q, 2); /* dest I/O APIC interrupt in */
+        else 
+            putb(&q, i); /* dest I/O APIC interrupt in */
     }
     /* patch length */
     len = q - mp_config_table;
@@ -1505,6 +1524,11 @@ void acpi_bios_init(void)
         sizeof(struct madt_processor_apic) * MAX_CPUS +
         sizeof(struct madt_io_apic);
     madt = (void *)(addr);
+    for (i = 0; i < 16; i++)
+        if (PCI_ISA_IRQ_MASK & (1U << i))
+            madt_size += sizeof(struct madt_intsrcovr);
+    if (irq0_override)
+        madt_size += sizeof(struct madt_intsrcovr);
     addr += madt_size;
 
     acpi_tables_size = addr - base_addr;
@@ -1594,8 +1618,15 @@ void acpi_bios_init(void)
         io_apic->interrupt = cpu_to_le32(0);
 
         intsrcovr = (struct madt_intsrcovr*)(io_apic + 1);
-        for ( i = 0; i < 16; i++ ) {
-            if ( PCI_ISA_IRQ_MASK & (1U << i) ) {
+        for (i = 0; i < 16; i++) {
+            if (irq0_override && i == 0) {
+                memset(intsrcovr, 0, sizeof(*intsrcovr));
+                intsrcovr->type   = APIC_XRUPT_OVERRIDE;
+                intsrcovr->length = sizeof(*intsrcovr);
+                intsrcovr->source = i;
+                intsrcovr->gsi    = 2;
+                intsrcovr->flags  = 0;  //conforms to bus specifications
+            } else if (PCI_ISA_IRQ_MASK & (1U << i)) {
                 memset(intsrcovr, 0, sizeof(*intsrcovr));
                 intsrcovr->type   = APIC_XRUPT_OVERRIDE;
                 intsrcovr->length = sizeof(*intsrcovr);
@@ -1607,7 +1638,6 @@ void acpi_bios_init(void)
                 continue;
             }
             intsrcovr++;
-            madt_size += sizeof(struct madt_intsrcovr);
         }
         acpi_build_table_header((struct acpi_table_header *)madt,
                                 "APIC", madt_size, 1);
@@ -2232,6 +2262,8 @@ void rombios32_init(uint32_t *s3_resume_vector, uint8_t *shutdown_flag)
         uuid_probe();
 
         smbios_init();
+ 
+        irq0_override_probe();
 
         if (acpi_enabled)
             acpi_bios_init();
diff --git a/qemu/hw/apic.c b/qemu/hw/apic.c
index 782b398..f28a103 100644
--- a/qemu/hw/apic.c
+++ b/qemu/hw/apic.c
@@ -19,6 +19,7 @@
  */
 #include "hw.h"
 #include "pc.h"
+#include "sysemu.h"
 #include "qemu-timer.h"
 #include "host-utils.h"
 
@@ -1077,14 +1078,12 @@ void ioapic_set_irq(void *opaque, int vector, int level)
 {
     IOAPICState *s = opaque;
 
-#if 0
     /* ISA IRQs map to GSI 1-1 except for IRQ0 which maps
      * to GSI 2.  GSI maps to ioapic 1-1.  This is not
      * the cleanest way of doing it but it should work. */
 
-    if (vector == 0)
+    if (vector == 0 && irq0override)
         vector = 2;
-#endif
 
     if (vector >= 0 && vector < IOAPIC_NUM_PINS) {
         uint32_t mask = 1 << vector;
diff --git a/qemu/hw/fw_cfg.c b/qemu/hw/fw_cfg.c
index 4333ed9..1b31ad2 100644
--- a/qemu/hw/fw_cfg.c
+++ b/qemu/hw/fw_cfg.c
@@ -287,6 +287,7 @@ void *fw_cfg_init(uint32_t ctl_port, uint32_t data_port,
     fw_cfg_add_bytes(s, FW_CFG_UUID, qemu_uuid, 16);
     fw_cfg_add_i16(s, FW_CFG_NOGRAPHIC, (uint16_t)nographic);
     fw_cfg_add_i16(s, FW_CFG_NB_CPUS, (uint16_t)smp_cpus);
+    fw_cfg_add_i16(s, FW_CFG_IRQ0_OVERRIDE, (uint16_t)irq0override);
 
     register_savevm("fw_cfg", -1, 1, fw_cfg_save, fw_cfg_load, s);
     qemu_register_reset(fw_cfg_reset, s);
diff --git a/qemu/hw/fw_cfg.h b/qemu/hw/fw_cfg.h
index ef8f378..a4e81d2 100644
--- a/qemu/hw/fw_cfg.h
+++ b/qemu/hw/fw_cfg.h
@@ -8,6 +8,7 @@
 #define FW_CFG_NOGRAPHIC        0x04
 #define FW_CFG_NB_CPUS          0x05
 #define FW_CFG_MACHINE_ID       0x06
+#define FW_CFG_IRQ0_OVERRIDE    0x07
 #define FW_CFG_MAX_ENTRY        0x10
 
 #define FW_CFG_WRITE_CHANNEL    0x4000
diff --git a/qemu/qemu-kvm.c b/qemu/qemu-kvm.c
index 5ff63ad..e32b4c2 100644
--- a/qemu/qemu-kvm.c
+++ b/qemu/qemu-kvm.c
@@ -815,7 +815,10 @@ int kvm_qemu_create_context(void)
                 return r;
         }
         for (i = 0; i < 24; ++i) {
-            r = kvm_add_irq_route(kvm_context, i, KVM_IRQCHIP_IOAPIC, i);
+            if (i == 0)
+                r = kvm_add_irq_route(kvm_context, i, KVM_IRQCHIP_IOAPIC, 2);
+            else
+                r = kvm_add_irq_route(kvm_context, i, KVM_IRQCHIP_IOAPIC, i);
             if (r < 0)
                 return r;
         }
diff --git a/qemu/sysemu.h b/qemu/sysemu.h
index c8f268e..04db217 100644
--- a/qemu/sysemu.h
+++ b/qemu/sysemu.h
@@ -92,6 +92,7 @@ extern int graphic_width;
 extern int graphic_height;
 extern int graphic_depth;
 extern int nographic;
+extern int irq0override;
 extern const char *keyboard_layout;
 extern int win2k_install_hack;
 extern int rtc_td_hack;
diff --git a/qemu/vl.c b/qemu/vl.c
index 9557a06..21b3e51 100644
--- a/qemu/vl.c
+++ b/qemu/vl.c
@@ -194,6 +194,7 @@ static int vga_ram_size;
 enum vga_retrace_method vga_retrace_method = VGA_RETRACE_DUMB;
 static DisplayState *display_state;
 int nographic;
+int irq0override;
 static int curses;
 static int sdl;
 const char* keyboard_layout = NULL;
@@ -4874,6 +4875,7 @@ int main(int argc, char **argv, char **envp)
 #endif
     snapshot = 0;
     nographic = 0;
+    irq0override = 1;
     curses = 0;
     kernel_filename = NULL;
     kernel_cmdline = "";
@@ -5871,8 +5873,12 @@ int main(int argc, char **argv, char **envp)
         }
     }
 
-    if (kvm_enabled())
-	kvm_init_ap();
+    if (kvm_enabled()) {
+       kvm_init_ap();
+        if (kvm_irqchip && !kvm_has_gsi_routing(kvm_context)) {
+           irq0override = 0;
+        }
+    }
 
     machine->init(ram_size, vga_ram_size, boot_devices,
                   kernel_filename, kernel_cmdline, initrd_filename, cpu_model);

^ permalink raw reply related	[flat|nested] 3+ messages in thread

* [RFC][PATCH 2/2] Finish hpet implementation for KVM
  2009-01-23  4:29 [RFC][PATCH 1/2] Make irq0->inti2 override in BIOS configurable from userspace Beth Kon
@ 2009-01-23  4:29 ` Beth Kon
  2009-01-25  1:31 ` [RFC][PATCH 1/2] Make irq0->inti2 override in BIOS configurable from userspace Marcelo Tosatti
  1 sibling, 0 replies; 3+ messages in thread
From: Beth Kon @ 2009-01-23  4:29 UTC (permalink / raw)
  To: kvm; +Cc: Beth Kon

- add hpet to BIOS
- add disable/enable of kernel pit when hpet enters/leaves legacy mode

Signed-off-by: Beth Kon <eak@us.ibm.com>
diff --git a/bios/acpi-dsdt.dsl b/bios/acpi-dsdt.dsl
index d67616d..9981a1f 100755
--- a/bios/acpi-dsdt.dsl
+++ b/bios/acpi-dsdt.dsl
@@ -233,6 +233,24 @@ DefinitionBlock (
                     ,, , AddressRangeMemory, TypeStatic)
             })
         }
+        Device(HPET) {
+            Name(_HID,  EISAID("PNP0103"))
+            Name(_UID, 0)
+            Method (_STA, 0, NotSerialized) {
+                    Return(0x0F)
+            }
+            Name(_CRS, ResourceTemplate() {
+                DWordMemory(
+                    ResourceConsumer, PosDecode, MinFixed, MaxFixed,
+                    NonCacheable, ReadWrite,
+                    0x00000000,
+                    0xFED00000,
+                    0xFED003FF,
+                    0x00000000,
+                    0x00000400 /* 1K memory: FED00000 - FED003FF */
+                )
+            })
+        }
     }
 
     Scope(\_SB.PCI0) {
diff --git a/bios/rombios32.c b/bios/rombios32.c
index 84f15fb..17c3704 100755
--- a/bios/rombios32.c
+++ b/bios/rombios32.c
@@ -1272,7 +1272,7 @@ struct rsdp_descriptor         /* Root System Descriptor Pointer */
 struct rsdt_descriptor_rev1
 {
 	ACPI_TABLE_HEADER_DEF                           /* ACPI common table header */
-	uint32_t                             table_offset_entry [2]; /* Array of pointers to other */
+	uint32_t                             table_offset_entry [3]; /* Array of pointers to other */
 			 /* ACPI tables */
 } __attribute__((__packed__));
 
@@ -1412,6 +1412,31 @@ struct madt_processor_apic
 #endif
 } __attribute__((__packed__));
 
+/*
+ *  * ACPI 2.0 Generic Address Space definition.
+ *   */
+struct acpi_20_generic_address {
+    uint8_t  address_space_id;
+    uint8_t  register_bit_width;
+    uint8_t  register_bit_offset;
+    uint8_t  reserved;
+    uint64_t address;
+} __attribute__((__packed__));
+
+/*
+ *  * HPET Description Table
+ *   */
+struct acpi_20_hpet {
+    ACPI_TABLE_HEADER_DEF                           /* ACPI common table header */
+    uint32_t           timer_block_id;
+    struct acpi_20_generic_address addr;
+    uint8_t            hpet_number;
+    uint16_t           min_tick;
+    uint8_t            page_protect;
+} __attribute__((__packed__));
+
+#define ACPI_HPET_ADDRESS 0xFED00000UL
+
 struct madt_io_apic
 {
 	APIC_HEADER_DEF
@@ -1484,6 +1509,8 @@ void acpi_bios_init(void)
     struct facs_descriptor_rev1 *facs;
     struct multiple_apic_table *madt;
     uint8_t *dsdt;
+    struct acpi_20_hpet *hpet;
+    uint32_t hpet_addr;
     uint32_t base_addr, rsdt_addr, fadt_addr, addr, facs_addr, dsdt_addr;
     uint32_t acpi_tables_size, madt_addr, madt_size;
     int i;
@@ -1531,6 +1558,11 @@ void acpi_bios_init(void)
         madt_size += sizeof(struct madt_intsrcovr);
     addr += madt_size;
 
+    addr = (addr + 7) & ~7;
+    hpet_addr = addr;
+    hpet = (void *)(addr);
+    addr += sizeof(*hpet);
+
     acpi_tables_size = addr - base_addr;
 
     BX_INFO("ACPI tables: RSDP addr=0x%08lx ACPI DATA addr=0x%08lx size=0x%x\n",
@@ -1552,6 +1584,7 @@ void acpi_bios_init(void)
     memset(rsdt, 0, sizeof(*rsdt));
     rsdt->table_offset_entry[0] = cpu_to_le32(fadt_addr);
     rsdt->table_offset_entry[1] = cpu_to_le32(madt_addr);
+    rsdt->table_offset_entry[2] = cpu_to_le32(hpet_addr);
     acpi_build_table_header((struct acpi_table_header *)rsdt,
                             "RSDT", sizeof(*rsdt), 1);
 
@@ -1641,6 +1674,15 @@ void acpi_bios_init(void)
         }
         acpi_build_table_header((struct acpi_table_header *)madt,
                                 "APIC", madt_size, 1);
+        /* HPET */
+        memset(hpet, 0, sizeof(*hpet));
+        /* Note timer_block_id value must be kept in sync with value advertised by
+         * emulated hpet
+         */
+        hpet->timer_block_id = cpu_to_le32(0x8086a201);
+        hpet->addr.address = cpu_to_le32(ACPI_HPET_ADDRESS);
+        acpi_build_table_header((struct  acpi_table_header *)hpet,
+                                 "HPET", sizeof(*hpet), 1);
     }
 }
 
diff --git a/qemu/hw/hpet.c b/qemu/hw/hpet.c
index 7df2d05..80b2edd 100644
--- a/qemu/hw/hpet.c
+++ b/qemu/hw/hpet.c
@@ -30,8 +30,9 @@
 #include "console.h"
 #include "qemu-timer.h"
 #include "hpet_emul.h"
+#include "qemu-kvm.h"
 
-//#define HPET_DEBUG
+#define HPET_DEBUG
 #ifdef HPET_DEBUG
 #define dprintf printf
 #else
@@ -48,6 +49,43 @@ uint32_t hpet_in_legacy_mode(void)
         return 0;
 }
 
+static void hpet_kpit_enable(void)
+{
+    struct kvm_pit_state ps;
+    kvm_get_pit(kvm_context, &ps);
+    kvm_set_pit(kvm_context, &ps);
+}
+
+static void hpet_kpit_disable(void)
+{
+    struct kvm_pit_state ps;
+    kvm_get_pit(kvm_context, &ps);
+    ps.channels[0].mode = 0xff;
+    kvm_set_pit(kvm_context, &ps);
+}
+
+static void hpet_legacy_enable(void)
+{
+    if (qemu_kvm_pit_in_kernel()) {
+       hpet_kpit_disable();
+       dprintf("qemu: hpet disabled kernel pit\n");
+    } else {
+       hpet_pit_disable();
+       dprintf("qemu: hpet disabled userspace pit\n");
+    }
+}
+
+static void hpet_legacy_disable(void)
+{
+    if (qemu_kvm_pit_in_kernel()) {
+       hpet_kpit_enable();
+       dprintf("qemu: hpet enabled kernel pit\n");
+    } else {
+       hpet_pit_enable();
+       dprintf("qemu: hpet enabled userspace pit\n");
+    }
+}
+
 static uint32_t timer_int_route(struct HPETTimer *timer)
 {
     uint32_t route;
@@ -475,9 +513,9 @@ static void hpet_ram_writel(void *opaque, target_phys_addr_t addr,
                 }
                 /* i8254 and RTC are disabled when HPET is in legacy mode */
                 if (activating_bit(old_val, new_val, HPET_CFG_LEGACY)) {
-                    hpet_pit_disable();
+                    hpet_legacy_enable();
                 } else if (deactivating_bit(old_val, new_val, HPET_CFG_LEGACY)) {
-                    hpet_pit_enable();
+                    hpet_legacy_disable();
                 }
                 break;
             case HPET_CFG + 4:
@@ -560,7 +598,7 @@ static void hpet_reset(void *opaque) {
          * hpet_reset is called due to system reset. At this point control must
          * be returned to pit until SW reenables hpet.
          */
-        hpet_pit_enable();
+        hpet_legacy_disable();
     count = 1;
 }
 
diff --git a/qemu/vl.c b/qemu/vl.c
index 21b3e51..c977deb 100644
--- a/qemu/vl.c
+++ b/qemu/vl.c
@@ -5877,6 +5877,12 @@ int main(int argc, char **argv, char **envp)
        kvm_init_ap();
         if (kvm_irqchip && !kvm_has_gsi_routing(kvm_context)) {
            irq0override = 0;
+
+           /* if kernel can't do irq routing, interrupt source
+            * override 0->2 can not be set up as required by hpet,
+            * so disable hpet.
+            */
+           no_hpet=1;
         }
     }
 

^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [RFC][PATCH 1/2] Make irq0->inti2 override in BIOS configurable from userspace
  2009-01-23  4:29 [RFC][PATCH 1/2] Make irq0->inti2 override in BIOS configurable from userspace Beth Kon
  2009-01-23  4:29 ` [RFC][PATCH 2/2] Finish hpet implementation for KVM Beth Kon
@ 2009-01-25  1:31 ` Marcelo Tosatti
  1 sibling, 0 replies; 3+ messages in thread
From: Marcelo Tosatti @ 2009-01-25  1:31 UTC (permalink / raw)
  To: Beth Kon; +Cc: kvm

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

Hi Beth,

On Thu, Jan 22, 2009 at 10:29:36PM -0600, Beth Kon wrote:
> This series of patches (nearly) resolves the irq0->inti2 override issue, and gets the hpet working on kvm with and
> without the in-kernel irqchip (i.e., it disables userspace and in-kernel pit as needed).
> 
> - irq0->inti2
>   The resolution was to always use the override unless the kernel cannot do irq routing (i.e., compatibility with old
>   kernels). So qemu checks whether the kernel is capable of irq routing. If so, qemu tells kvm to route irq0 to 
>   inti2 via the irq routing interface, and tells bios to add the irq0->inti2 override to the MADT interrupt source 
>   override table, and to the mp table (for the non-acpi case). The only outstanding problem here is that when I set 
>   acpi=off on the kernel boot line, the boot fails. Apparently linux does not like the way I implemented the override 
>   for the mp table in rombios32.c. Since I am pressed for time at the moment, I'm putting this patch set out for comments 
>   in hopes that someone else may immediately see the problem. Otherwise  I'll keep looking into it as time permits.

The mptable is not being initialized as you intented because
irq0override is read from fw cfg after mptable initialization (oops).

Also the kernel irq ack notifiers lack knowledge about the routing
table, assuming identity mapping.

See attached patches (qemu-kvm.c change avoids the creation of two
routing entries for pin 2 pointing to different gsi's, 0 and 2).

RHEL5 guests complain about "Invalid checksum", so there's still
something wrong in either acpi or mptable setup. I'll try to look
into this next week if nobody beats me.

BIOS-e820: 00000000fffbc000 - 0000000100000000 (reserved)
DMI 2.4 present.
  >>> ERROR: Invalid checksum
No NUMA configuration found

Great work Beth, thanks!



[-- Attachment #2: beth-fixes.patch --]
[-- Type: text/plain, Size: 1068 bytes --]

Index: kvm-userspace.tip/bios/rombios32.c
===================================================================
--- kvm-userspace.tip.orig/bios/rombios32.c
+++ kvm-userspace.tip/bios/rombios32.c
@@ -2299,14 +2299,14 @@ void rombios32_init(uint32_t *s3_resume_
 
     if (bios_table_cur_addr != 0) {
 
+        irq0_override_probe();
+
         mptable_init();
 
         uuid_probe();
 
         smbios_init();
  
-        irq0_override_probe();
-
         if (acpi_enabled)
             acpi_bios_init();
 
Index: kvm-userspace.tip/qemu/qemu-kvm.c
===================================================================
--- kvm-userspace.tip.orig/qemu/qemu-kvm.c
+++ kvm-userspace.tip/qemu/qemu-kvm.c
@@ -817,7 +817,7 @@ int kvm_qemu_create_context(void)
         for (i = 0; i < 24; ++i) {
             if (i == 0)
                 r = kvm_add_irq_route(kvm_context, i, KVM_IRQCHIP_IOAPIC, 2);
-            else
+            else if (i != 2)
                 r = kvm_add_irq_route(kvm_context, i, KVM_IRQCHIP_IOAPIC, i);
             if (r < 0)
                 return r;

[-- Attachment #3: kvm-irq-ack-map.patch --]
[-- Type: text/plain, Size: 3682 bytes --]

diff --git a/arch/x86/kvm/i8259.c b/arch/x86/kvm/i8259.c
index 179dcb0..9316037 100644
--- a/arch/x86/kvm/i8259.c
+++ b/arch/x86/kvm/i8259.c
@@ -49,7 +49,8 @@ static void pic_unlock(struct kvm_pic *s)
 	spin_unlock(&s->lock);
 
 	while (acks) {
-		kvm_notify_acked_irq(kvm, __ffs(acks));
+		kvm_notify_acked_irq(kvm, SELECT_PIC(__ffs(acks)),
+				     __ffs(acks));
 		acks &= acks - 1;
 	}
 
@@ -232,7 +233,7 @@ int kvm_pic_read_irq(struct kvm *kvm)
 	}
 	pic_update_irq(s);
 	pic_unlock(s);
-	kvm_notify_acked_irq(kvm, irq);
+	kvm_notify_acked_irq(kvm, SELECT_PIC(irq), irq);
 
 	return intno;
 }
diff --git a/arch/x86/kvm/irq.h b/arch/x86/kvm/irq.h
index 82579ee..9f59318 100644
--- a/arch/x86/kvm/irq.h
+++ b/arch/x86/kvm/irq.h
@@ -32,6 +32,8 @@
 #include "lapic.h"
 
 #define PIC_NUM_PINS 16
+#define SELECT_PIC(irq) \
+	((irq) < 8 ? KVM_IRQCHIP_PIC_MASTER : KVM_IRQCHIP_PIC_SLAVE)
 
 struct kvm;
 struct kvm_vcpu;
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index ce285e0..c03a0a9 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -352,7 +352,7 @@ void kvm_unregister_irq_mask_notifier(struct kvm *kvm, int irq,
 void kvm_fire_mask_notifiers(struct kvm *kvm, int irq, bool mask);
 
 void kvm_set_irq(struct kvm *kvm, int irq_source_id, int irq, int level);
-void kvm_notify_acked_irq(struct kvm *kvm, unsigned gsi);
+void kvm_notify_acked_irq(struct kvm *kvm, unsigned irqchip, unsigned pin);
 void kvm_register_irq_ack_notifier(struct kvm *kvm,
 				   struct kvm_irq_ack_notifier *kian);
 void kvm_unregister_irq_ack_notifier(struct kvm_irq_ack_notifier *kian);
diff --git a/virt/kvm/ioapic.c b/virt/kvm/ioapic.c
index e85a2bc..1c986ac 100644
--- a/virt/kvm/ioapic.c
+++ b/virt/kvm/ioapic.c
@@ -293,20 +293,20 @@ void kvm_ioapic_set_irq(struct kvm_ioapic *ioapic, int irq, int level)
 	}
 }
 
-static void __kvm_ioapic_update_eoi(struct kvm_ioapic *ioapic, int gsi,
+static void __kvm_ioapic_update_eoi(struct kvm_ioapic *ioapic, int pin,
 				    int trigger_mode)
 {
 	union ioapic_redir_entry *ent;
 
-	ent = &ioapic->redirtbl[gsi];
+	ent = &ioapic->redirtbl[pin];
 
-	kvm_notify_acked_irq(ioapic->kvm, gsi);
+	kvm_notify_acked_irq(ioapic->kvm, KVM_IRQCHIP_IOAPIC, pin);
 
 	if (trigger_mode == IOAPIC_LEVEL_TRIG) {
 		ASSERT(ent->fields.trig_mode == IOAPIC_LEVEL_TRIG);
 		ent->fields.remote_irr = 0;
-		if (!ent->fields.mask && (ioapic->irr & (1 << gsi)))
-			ioapic_service(ioapic, gsi);
+		if (!ent->fields.mask && (ioapic->irr & (1 << pin)))
+			ioapic_service(ioapic, pin);
 	}
 }
 
diff --git a/virt/kvm/irq_comm.c b/virt/kvm/irq_comm.c
index a797fa5..0b4c69f 100644
--- a/virt/kvm/irq_comm.c
+++ b/virt/kvm/irq_comm.c
@@ -59,10 +59,19 @@ void kvm_set_irq(struct kvm *kvm, int irq_source_id, int irq, int level)
 			e->set(e, kvm, !!(*irq_state));
 }
 
-void kvm_notify_acked_irq(struct kvm *kvm, unsigned gsi)
+void kvm_notify_acked_irq(struct kvm *kvm, unsigned irqchip, unsigned pin)
 {
+	struct kvm_kernel_irq_routing_entry *e;
 	struct kvm_irq_ack_notifier *kian;
 	struct hlist_node *n;
+	unsigned gsi = -1;
+	
+	list_for_each_entry(e, &kvm->irq_routing, link)
+		if (e->irqchip.irqchip == irqchip &&
+		    e->irqchip.pin == pin) {
+			gsi = e->gsi;
+			break;
+		}
 
 	hlist_for_each_entry(kian, n, &kvm->arch.irq_ack_notifier_list, link)
 		if (kian->gsi == gsi)
@@ -237,8 +246,6 @@ out:
 #define ROUTING_ENTRY1(irq) IOAPIC_ROUTING_ENTRY(irq)
 
 #ifdef CONFIG_X86
-#define SELECT_PIC(irq) \
-	((irq) < 8 ? KVM_IRQCHIP_PIC_MASTER : KVM_IRQCHIP_PIC_SLAVE)
 #  define PIC_ROUTING_ENTRY(irq) \
 	{ .gsi = irq, .type = KVM_IRQ_ROUTING_IRQCHIP,	\
 	  .u.irqchip.irqchip = SELECT_PIC(irq), .u.irqchip.pin = (irq) % 8 }

^ permalink raw reply related	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2009-01-25  1:32 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-01-23  4:29 [RFC][PATCH 1/2] Make irq0->inti2 override in BIOS configurable from userspace Beth Kon
2009-01-23  4:29 ` [RFC][PATCH 2/2] Finish hpet implementation for KVM Beth Kon
2009-01-25  1:31 ` [RFC][PATCH 1/2] Make irq0->inti2 override in BIOS configurable from userspace Marcelo Tosatti

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox