x86: LAPIC error handling
authorBarret Rhoden <brho@cs.berkeley.edu>
Thu, 27 Mar 2014 21:46:42 +0000 (14:46 -0700)
committerBarret Rhoden <brho@cs.berkeley.edu>
Sat, 29 Mar 2014 01:17:05 +0000 (18:17 -0700)
We were unmasking the error handler, but didn't have one registered.
We'd take an error, but then fail to send_eoi(), and then never received
further LAPIC IRQs (like the timer).

kern/arch/x86/apic.h
kern/arch/x86/apic9.c
kern/arch/x86/trap.c

index d1c7eb0..b3a8bf3 100644 (file)
@@ -13,6 +13,7 @@
  */
 #include <arch/mmu.h>
 #include <arch/x86.h>
+#include <ros/trapframe.h>
 #include <atomic.h>
 
 // Local APIC
@@ -40,7 +41,6 @@
 #define LAPIC_TIMER_INIT                       (LAPIC_BASE + 0x380)
 #define LAPIC_TIMER_CURRENT                    (LAPIC_BASE + 0x390)
 #define LAPIC_TIMER_DIVIDE                     (LAPIC_BASE + 0x3e0)
-#define LAPIC_TIMER_DEFAULT_VECTOR     0xeb    /* Aka 235, IRQ203 */
 /* Quick note on the divisor.  The LAPIC timer ticks once per divisor-bus ticks
  * (system bus or APIC bus, depending on the model).  Ex: A divisor of 128 means
  * 128 bus ticks results in 1 timer tick.  The divisor increases the time range
@@ -89,6 +89,7 @@ void __lapic_set_timer(uint32_t ticks, uint8_t vec, bool periodic, uint8_t div);
 void lapic_set_timer(uint32_t usec, bool periodic);
 uint32_t lapic_get_default_id(void);
 int apiconline(void);
+void handle_lapic_error(struct hw_trapframe *hw_tf, void *data);
 
 static inline void lapic_send_eoi(int unused);
 static inline uint32_t lapic_get_version(void);
index 9eea81b..d03d0d6 100644 (file)
@@ -199,6 +199,15 @@ char *apicdump(char *start, char *end)
        return start;
 }
 
+void handle_lapic_error(struct hw_trapframe *hw_tf, void *data)
+{
+       uint32_t err;
+       apicrput(Es, 0);
+       err = apicrget(Es);
+       /* i get a shitload of these on my nehalem, many with err == 0 */
+       printd("LAPIC error vector, got 0x%08x\n", err);
+}
+
 int apiconline(void)
 {
        struct apic *apic;
@@ -275,7 +284,7 @@ int apiconline(void)
 
        apicrput(Es, 0);
        apicrget(Es);
-       apicrput(Elvt, IdtLAPIC_ERROR);
+       apicrput(Elvt, IdtLAPIC_ERROR | Im);
 
        /* Not sure we need this from plan 9, Akaros never did:
         *
index 6d8edbe..625f171 100644 (file)
@@ -181,10 +181,11 @@ void idt_init(void)
        unmask_lapic_lvt(LAPIC_LVT_LINT0);
 #endif
 
-       /* register the generic timer_interrupt() handler for the per-core timers */
+       /* the lapic IRQs need to be unmasked on a per-core basis */
        register_irq(IdtLAPIC_TIMER, timer_interrupt, NULL,
                     MKBUS(BusLAPIC, 0, 0, 0));
-       /* register the kernel message handler */
+       register_irq(IdtLAPIC_ERROR, handle_lapic_error, NULL,
+                    MKBUS(BusLAPIC, 0, 0, 0));
        register_irq(I_KERNEL_MSG, handle_kmsg_ipi, NULL, MKBUS(BusIPI, 0, 0, 0));
 }