qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH][RESEND] Don't route PIC interrupts through the loca


From: Avi Kivity
Subject: [Qemu-devel] [PATCH][RESEND] Don't route PIC interrupts through the local APIC if the local APIC config says so
Date: Mon, 08 Oct 2007 12:09:38 +0200
User-agent: Thunderbird 2.0.0.5 (X11/20070719)

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.

-- 
error compiling committee.c: too many arguments to function


Index: vl.h
===================================================================
RCS file: /sources/qemu/qemu/vl.h,v
retrieving revision 1.273
diff -u -u -r1.273 vl.h
--- vl.h        30 Sep 2007 14:44:52 -0000      1.273
+++ vl.h        2 Oct 2007 10:28:55 -0000
@@ -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
diff -u -u -r1.16 apic.c
--- hw/apic.c   17 Sep 2007 08:09:46 -0000      1.16
+++ hw/apic.c   2 Oct 2007 10:28:55 -0000
@@ -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
diff -u -u -r1.85 pc.c
--- hw/pc.c     17 Sep 2007 08:09:47 -0000      1.85
+++ hw/pc.c     2 Oct 2007 10:28:55 -0000
@@ -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 */


reply via email to

[Prev in Thread] Current Thread [Next in Thread]