1 #include "libcflat.h" 2 #include "apic.h" 3 #include "vm.h" 4 #include "smp.h" 5 #include "desc.h" 6 #include "isr.h" 7 8 #define EDGE_TRIGGERED 0 9 #define LEVEL_TRIGGERED 1 10 11 static void set_ioapic_redir(unsigned line, unsigned vec, unsigned trig_mode) 12 { 13 ioapic_redir_entry_t e = { 14 .vector = vec, 15 .delivery_mode = 0, 16 .trig_mode = trig_mode, 17 }; 18 19 ioapic_write_redir(line, e); 20 } 21 22 static void set_irq_line(unsigned line, int val) 23 { 24 asm volatile("out %0, %1" : : "a"((u8)val), "d"((u16)(0x2000 + line))); 25 } 26 27 static void toggle_irq_line(unsigned line) 28 { 29 set_irq_line(line, 1); 30 set_irq_line(line, 0); 31 } 32 33 static volatile int g_isr_77; 34 35 static void ioapic_isr_77(isr_regs_t *regs) 36 { 37 ++g_isr_77; 38 eoi(); 39 } 40 41 static void test_ioapic_intr(void) 42 { 43 handle_irq(0x77, ioapic_isr_77); 44 set_ioapic_redir(0x0e, 0x77, EDGE_TRIGGERED); 45 toggle_irq_line(0x0e); 46 asm volatile ("nop"); 47 report("ioapic interrupt", g_isr_77 == 1); 48 } 49 50 static int g_78, g_66, g_66_after_78; 51 static ulong g_66_rip, g_78_rip; 52 53 static void ioapic_isr_78(isr_regs_t *regs) 54 { 55 ++g_78; 56 g_78_rip = regs->rip; 57 eoi(); 58 } 59 60 static void ioapic_isr_66(isr_regs_t *regs) 61 { 62 ++g_66; 63 if (g_78) 64 ++g_66_after_78; 65 g_66_rip = regs->rip; 66 eoi(); 67 } 68 69 static void test_ioapic_simultaneous(void) 70 { 71 handle_irq(0x78, ioapic_isr_78); 72 handle_irq(0x66, ioapic_isr_66); 73 set_ioapic_redir(0x0e, 0x78, EDGE_TRIGGERED); 74 set_ioapic_redir(0x0f, 0x66, EDGE_TRIGGERED); 75 irq_disable(); 76 toggle_irq_line(0x0f); 77 toggle_irq_line(0x0e); 78 irq_enable(); 79 asm volatile ("nop"); 80 report("ioapic simultaneous interrupt", 81 g_66 && g_78 && g_66_after_78 && g_66_rip == g_78_rip); 82 } 83 84 int main(void) 85 { 86 setup_vm(); 87 smp_init(); 88 setup_idt(); 89 90 mask_pic_interrupts(); 91 enable_apic(); 92 93 irq_enable(); 94 95 test_ioapic_intr(); 96 test_ioapic_simultaneous(); 97 98 return report_summary(); 99 } 100