Create ros/vmm/vmx.h, prepare to move lots of code to user mode from kernel driver.
[akaros.git] / kern / arch / x86 / apic.c
index c997431..b0550e7 100644 (file)
@@ -4,11 +4,6 @@
  * See LICENSE for details.
  */
 
-#ifdef __SHARC__
-#pragma nosharc
-#define SINIT(x) x
-#endif
-
 #include <arch/mmu.h>
 #include <arch/x86.h>
 #include <arch/arch.h>
 #include <assert.h>
 #include <stdio.h>
 #include <bitmask.h>
-#include <arch/coreid.h>
-
-bool core_id_ready = FALSE;
+#include <arch/topology.h>
 
 bool lapic_check_spurious(int trap_nr)
 {
        /* FYI: lapic_spurious is 255 on qemu and 15 on the nehalem..  We actually
-        * can set bits 4-7, and P6s have 0-3 hardwired to 0.  YMMV.
+        * can set bits 4-7, and P6s have 0-3 hardwired to 0.  YMMV.  NxM seems to
+        * say the lower 3 bits are usually 1.  We'll see if the assert trips.
         *
         * The SDM recommends not using the spurious vector for any other IRQs (LVT
         * or IOAPIC RTE), since the handlers don't send an EOI.  However, our check
         * here allows us to use the vector since we can tell the diff btw a
         * spurious and a real IRQ. */
-       uint8_t lapic_spurious = read_mmreg32(LAPIC_SPURIOUS) & 0xff;
+       assert(IdtLAPIC_SPURIOUS == (read_mmreg32(LAPIC_SPURIOUS) & 0xff));
        /* Note the lapic's vectors are not shifted by an offset. */
-       if ((trap_nr == lapic_spurious) && !lapic_get_isr_bit(lapic_spurious)) {
+       if ((trap_nr == IdtLAPIC_SPURIOUS) &&
+            !lapic_get_isr_bit(IdtLAPIC_SPURIOUS)) {
                /* i'm still curious about these */
-               printk("Spurious LAPIC irq %d, core %d!\n", lapic_spurious, core_id());
+               printk("Spurious LAPIC irq %d, core %d!\n", IdtLAPIC_SPURIOUS,
+                      core_id());
                lapic_print_isr();
                return TRUE;
        }
@@ -62,8 +58,8 @@ void lapic_print_isr(void)
 static bool __lapic_get_isrr_bit(unsigned long base, uint8_t vector)
 {
        int which_reg = vector >> 5;    /* 32 bits per reg */
-       uint32_t *lapic_reg = (uint32_t*)(base + which_reg * 0x10);     /* offset 16 */
-       return (*lapic_reg & (1 << (vector % 32)) ? 1 : 0);
+       uintptr_t lapic_reg = base + which_reg * 0x10;  /* offset 16 */
+       return (read_mmreg32(lapic_reg) & (1 << (vector % 32)) ? 1 : 0);
 }
 
 bool lapic_get_isr_bit(uint8_t vector)
@@ -76,6 +72,28 @@ bool lapic_get_irr_bit(uint8_t vector)
        return __lapic_get_isrr_bit(LAPIC_IRR, vector);
 }
 
+void lapic_mask_irq(struct irq_handler *unused, int apic_vector)
+{
+       uintptr_t mm_reg;
+       if (apic_vector < IdtLAPIC || IdtLAPIC + 4 < apic_vector) {
+               warn("Bad apic vector %d\n", apic_vector);
+               return;
+       }
+       mm_reg = LAPIC_BASE + (apic_vector - IdtLAPIC) * 0x10;
+       write_mmreg32(mm_reg, read_mmreg32(mm_reg) | LAPIC_LVT_MASK);
+}
+
+void lapic_unmask_irq(struct irq_handler *unused, int apic_vector)
+{
+       uintptr_t mm_reg;
+       if (apic_vector < IdtLAPIC || IdtLAPIC + 4 < apic_vector) {
+               warn("Bad apic vector %d\n", apic_vector);
+               return;
+       }
+       mm_reg = LAPIC_BASE + 0x320 + (apic_vector - IdtLAPIC) * 0x10;
+       write_mmreg32(mm_reg, read_mmreg32(mm_reg) & ~LAPIC_LVT_MASK);
+}
+
 /* This works for any interrupt that goes through the LAPIC, but not things like
  * ExtInts.  To prevent abuse, we'll use it just for IPIs for now (which only
  * come via the APIC).
@@ -103,7 +121,7 @@ void __lapic_set_timer(uint32_t ticks, uint8_t vec, bool periodic, uint8_t div)
        // clears bottom bit and then set divider
        write_mmreg32(LAPIC_TIMER_DIVIDE, (read_mmreg32(LAPIC_TIMER_DIVIDE) &~0xf) |
                      (div & 0xf));
-       // set LVT with interrupt handling information
+       // set LVT with interrupt handling information.  also unmasks.
        write_mmreg32(LAPIC_LVT_TIMER, vec | (periodic << 17));
        write_mmreg32(LAPIC_TIMER_INIT, ticks);
        // For debugging when we expand this