Skip to contentSkip to conversation

Don't route PIC interrupts through the local APIC if the local APIC config says so

PATCH RESEND New Avi Kivity 1 participant 1 message Oct 8, 2007 KVM

lore
Share & tools
lore

Avi Kivity

author
#0 lore raw

PATCH RESEND 1/1 Don't route PIC interrupts through the local APIC if the local APIC config says so

Under certain conditions, PIC interrupts should not be passed through by the local APIC. This is usually when the guest uses the IOAPIC instead of the PIC.

Currently qemu does not block PIC interrupts when the local APIC is configured to do so; this results in interrupts begin received twice and time running at double speed on Linux x86_64 guest.

The attached patch, from Qing He and myself, fixes the problem.

Signature · 1 line
error compiling committee.c: too many arguments to function

Index: vl.h
===================================================================
RCS file: /sources/qemu/qemu/vl.h,v
retrieving revision 1.273

vl.h +1 -0
diff -u -u -r1.273 vl.h
@@ -1138,6 +1138,7 @@
 typedef struct IOAPICState IOAPICState;
 
 int apic_init(CPUState *env);
+int apic_accept_pic_intr(CPUState *env);
 int apic_get_interrupt(CPUState *env);
 IOAPICState *ioapic_init(void);
 void ioapic_set_irq(void *opaque, int vector, int level);

Index: hw/apic.c
===================================================================
RCS file: /sources/qemu/qemu/hw/apic.c,v
retrieving revision 1.16

apic.c +33 -0
diff -u -u -r1.16 apic.c
@@ -484,6 +484,25 @@
     return intno;
 }
 
+int apic_accept_pic_intr(CPUState *env)
+{
+    APICState *s = env->apic_state;
+    uint32_t lvt0;
+
+    if (!s)
+        return -1;
+
+    lvt0 = s->lvt[APIC_LVT_LINT0];
+
+    if (s->id == 0 &&
+        ((s->apicbase & MSR_IA32_APICBASE_ENABLE) == 0 ||
+         ((lvt0 & APIC_LVT_MASKED) == 0 &&
+          ((lvt0 >> 8) & 0x7) == APIC_DM_EXTINT)))
+        return 1;
+
+    return 0;
+}
+
 static uint32_t apic_get_current_count(APICState *s)
 {
     int64_t d;
@@ -790,6 +809,13 @@
 {
     APICState *s = opaque;
     apic_init_ipi(s);
+
+    /*
+     * LINT0 delivery mode is set to ExtInt at initialization time
+     * typically by BIOS, so PIC interrupt can be delivered to the
+     * processor when local APIC is enabled.
+     */
+    s->lvt[APIC_LVT_LINT0] = 0x700;
 }
 
 static CPUReadMemoryFunc *apic_mem_read[3] = {
@@ -821,6 +847,13 @@
     s->apicbase = 0xfee00000 |
         (s->id ? 0 : MSR_IA32_APICBASE_BSP) | MSR_IA32_APICBASE_ENABLE;
 
+    /*
+     * LINT0 delivery mode is set to ExtInt at initialization time
+     * typically by BIOS, so PIC interrupt can be delivered to the
+     * processor when local APIC is enabled.
+     */
+    s->lvt[APIC_LVT_LINT0] = 0x700;
+
     /* XXX: mapping more APICs at the same memory location */
     if (apic_io_memory == 0) {
         /* NOTE: the APIC is directly connected to the CPU - it is not

Index: hw/pc.c
===================================================================
RCS file: /sources/qemu/qemu/hw/pc.c,v
retrieving revision 1.85

pc.c +4 -3
diff -u -u -r1.85 pc.c
@@ -93,6 +93,9 @@
         return intno;
     }
     /* read the irq from the PIC */
+    if (!apic_accept_pic_intr(env))
+        return -1;
+
     intno = pic_read_irq(isa_pic);
     return intno;
 }
@@ -100,10 +103,8 @@
 static void pic_irq_request(void *opaque, int irq, int level)
 {
     CPUState *env = opaque;
-    if (level)
+    if (level && apic_accept_pic_intr(env))
         cpu_interrupt(env, CPU_INTERRUPT_HARD);
-    else
-        cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
 }
 
 /* PC cmos mappings */

-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems? Stop. Now Search log events and configuration files using AJAX and a browser. Download your FREE copy of Splunk now >> http://get.splunk.com/

_______________________________________________
kvm-devel mailing list [email protected]
https://lists.sourceforge.net/lists/listinfo/kvm-devel