| 1 | #if defined (__x86_64__) || defined (__i386__) |
| 2 | |
| 3 | #include <stdint.h> |
| 4 | #include <stddef.h> |
| 5 | #include <sys/idt.h> |
| 6 | #include <sys/cpu.h> |
| 7 | #include <sys/pic.h> |
| 8 | #include <sys/lapic.h> |
| 9 | #include <mm/pmm.h> |
| 10 | #include <lib/misc.h> |
| 11 | |
| 12 | static struct idt_entry *dummy_idt = NULL; |
| 13 | |
| 14 | void dummy_isr(void); |
| 15 | |
| 16 | void init_flush_irqs(void) { |
| 17 | size_t dummy_idt_size = 256 * sizeof(struct idt_entry); |
| 18 | dummy_idt = ext_mem_alloc(dummy_idt_size); |
| 19 | |
| 20 | for (size_t i = 0; i < 256; i++) { |
| 21 | dummy_idt[i].offset_lo = (uint16_t)(uintptr_t)dummy_isr; |
| 22 | dummy_idt[i].type_attr = 0x8e; |
| 23 | #if defined (__i386__) |
| 24 | dummy_idt[i].selector = 0x18; |
| 25 | dummy_idt[i].offset_hi = (uint16_t)((uintptr_t)dummy_isr >> 16); |
| 26 | #elif defined (__x86_64__) |
| 27 | dummy_idt[i].selector = 0x28; |
| 28 | dummy_idt[i].offset_mid = (uint16_t)((uintptr_t)dummy_isr >> 16); |
| 29 | dummy_idt[i].offset_hi = (uint32_t)((uintptr_t)dummy_isr >> 32); |
| 30 | #endif |
| 31 | } |
| 32 | } |
| 33 | |
| 34 | int irq_flush_type = IRQ_NO_FLUSH; |
| 35 | |
| 36 | void flush_irqs(void) { |
| 37 | switch (irq_flush_type) { |
| 38 | case IRQ_PIC_ONLY_FLUSH: |
| 39 | pic_flush(); |
| 40 | // FALLTHRU |
| 41 | case IRQ_NO_FLUSH: |
| 42 | return; |
| 43 | case IRQ_PIC_APIC_FLUSH: |
| 44 | break; |
| 45 | default: |
| 46 | panic(false, "Invalid IRQ flush type"); |
| 47 | } |
| 48 | |
| 49 | struct idtr old_idt; |
| 50 | asm volatile ("sidt %0" : "=m"(old_idt) :: "memory"); |
| 51 | |
| 52 | struct idtr new_idt = { |
| 53 | 256 * sizeof(struct idt_entry) - 1, |
| 54 | (uintptr_t)dummy_idt |
| 55 | }; |
| 56 | asm volatile ("lidt %0" :: "m"(new_idt) : "memory"); |
| 57 | |
| 58 | // Flush the legacy PIC so we know the remaining ints come from the LAPIC |
| 59 | pic_flush(); |
| 60 | |
| 61 | asm volatile ("sti" ::: "memory"); |
| 62 | |
| 63 | // Delay a while to make sure we catch ALL pending IRQs |
| 64 | stall(10000); |
| 65 | |
| 66 | asm volatile ("cli" ::: "memory"); |
| 67 | |
| 68 | asm volatile ("lidt %0" :: "m"(old_idt) : "memory"); |
| 69 | } |
| 70 | |
| 71 | #endif |