70 lines
1.8 KiB
C
70 lines
1.8 KiB
C
#include <stdint.h>
|
|
#include <stddef.h>
|
|
#include <sys/idt.h>
|
|
#include <sys/cpu.h>
|
|
#include <sys/pic.h>
|
|
#include <sys/lapic.h>
|
|
#include <mm/pmm.h>
|
|
#include <lib/blib.h>
|
|
|
|
static struct idt_entry *dummy_idt = NULL;
|
|
|
|
void dummy_isr(void);
|
|
|
|
void init_flush_irqs(void) {
|
|
size_t dummy_idt_size = 256 * sizeof(struct idt_entry);
|
|
dummy_idt = ext_mem_alloc(dummy_idt_size);
|
|
|
|
for (size_t i = 0; i < 256; i++) {
|
|
dummy_idt[i].offset_lo = (uint16_t)(uintptr_t)dummy_isr;
|
|
dummy_idt[i].type_attr = 0x8e;
|
|
#if defined (__i386__)
|
|
dummy_idt[i].selector = 0x18;
|
|
dummy_idt[i].offset_hi = (uint16_t)((uintptr_t)dummy_isr >> 16);
|
|
#elif defined (__x86_64__)
|
|
dummy_idt[i].selector = 0x28;
|
|
dummy_idt[i].offset_mid = (uint16_t)((uintptr_t)dummy_isr >> 16);
|
|
dummy_idt[i].offset_hi = (uint32_t)((uintptr_t)dummy_isr >> 32);
|
|
#endif
|
|
}
|
|
|
|
pmm_free(dummy_idt, dummy_idt_size);
|
|
}
|
|
|
|
int irq_flush_type = IRQ_NO_FLUSH;
|
|
|
|
void flush_irqs(void) {
|
|
switch (irq_flush_type) {
|
|
case IRQ_PIC_ONLY_FLUSH:
|
|
pic_flush();
|
|
// FALLTHRU
|
|
case IRQ_NO_FLUSH:
|
|
return;
|
|
case IRQ_PIC_APIC_FLUSH:
|
|
break;
|
|
default:
|
|
panic(false, "Invalid IRQ flush type");
|
|
}
|
|
|
|
struct idtr old_idt;
|
|
asm volatile ("sidt %0" : "=m"(old_idt) :: "memory");
|
|
|
|
struct idtr new_idt = {
|
|
256 * sizeof(struct idt_entry) - 1,
|
|
(uintptr_t)dummy_idt
|
|
};
|
|
asm volatile ("lidt %0" :: "m"(new_idt) : "memory");
|
|
|
|
// Flush the legacy PIC so we know the remaining ints come from the LAPIC
|
|
pic_flush();
|
|
|
|
asm volatile ("sti" ::: "memory");
|
|
|
|
// Delay a while to make sure we catch ALL pending IRQs
|
|
delay(10000000);
|
|
|
|
asm volatile ("cli" ::: "memory");
|
|
|
|
asm volatile ("lidt %0" :: "m"(old_idt) : "memory");
|
|
}
|