diff --git a/kernel/src/arch/CPU.h b/kernel/src/arch/CPU.h index f446a0a0..e705bf0e 100644 --- a/kernel/src/arch/CPU.h +++ b/kernel/src/arch/CPU.h @@ -22,6 +22,9 @@ namespace CPU void disable_interrupts(); void wait_for_interrupt(); + bool save_interrupts(); + void restore_interrupts(bool saved); + void get_stack_trace(void (*callback)(u64, void*), void* arg); void print_stack_trace(); void get_stack_trace_at(Registers* regs, void (*callback)(u64, void*), void* arg); @@ -30,6 +33,7 @@ namespace CPU u16 get_processor_id(); bool register_interrupt(u8 interrupt, void (*handler)(Registers*, void*), void* context); + void sync_interrupts(); void pause(); } diff --git a/kernel/src/arch/x86_64/CPU.cpp b/kernel/src/arch/x86_64/CPU.cpp index 4c719eb3..d7733861 100644 --- a/kernel/src/arch/x86_64/CPU.cpp +++ b/kernel/src/arch/x86_64/CPU.cpp @@ -22,6 +22,7 @@ extern "C" void enable_nx(); extern void setup_gdt(); extern void remap_pic(); +extern void change_pic_masks(u8 pic1_mask, u8 pic2_mask); extern void pic_eoi(unsigned char irq); extern void pic_eoi(Registers* regs); extern void setup_idt(); @@ -268,6 +269,8 @@ namespace CPU .expect_value("Could not create the IO background thread!"); remap_pic(); + + sync_interrupts(); } void enable_interrupts() @@ -280,6 +283,20 @@ namespace CPU asm volatile("cli"); } + bool save_interrupts() + { + u64 flags; + asm volatile("pushfq; pop %0" : "=r"(flags)); + return flags & 0x200; + } + + void restore_interrupts(bool saved) + { + if (saved) enable_interrupts(); + else + disable_interrupts(); + } + void wait_for_interrupt() { asm volatile("hlt"); @@ -387,8 +404,28 @@ namespace CPU irq_handlers[interrupt] = { handler, context }; + sync_interrupts(); + return true; } + + void sync_interrupts() + { + u8 pic1_mask, pic2_mask; + pic1_mask = pic2_mask = 0b11111111; + for (int i = 0; i < 8; i++) + { + if (irq_handlers[i].function) pic1_mask &= (u8)(~(1 << i)); + if (irq_handlers[i + 8].function) pic2_mask &= (u8)(~(1 << i)); + } + + if (pic2_mask != 0b11111111) pic1_mask &= 0b11111011; + + auto val = CPU::save_interrupts(); + CPU::disable_interrupts(); + change_pic_masks(pic1_mask, pic2_mask); + CPU::restore_interrupts(val); + } } // called by kernel_yield diff --git a/kernel/src/arch/x86_64/init/IDT.cpp b/kernel/src/arch/x86_64/init/IDT.cpp index 22ea980a..a226ff43 100644 --- a/kernel/src/arch/x86_64/init/IDT.cpp +++ b/kernel/src/arch/x86_64/init/IDT.cpp @@ -84,6 +84,20 @@ INT(20); INT(21); INT(32); INT(33); +INT(34); +INT(35); +INT(36); +INT(37); +INT(38); +INT(39); +INT(40); +INT(41); +INT(42); +INT(43); +INT(44); +INT(45); +INT(46); +INT(47); INT(66); void setup_idt() @@ -112,6 +126,20 @@ void setup_idt() TRAP(21); IRQ(32); IRQ(33); + IRQ(34); + IRQ(35); + IRQ(36); + IRQ(37); + IRQ(38); + IRQ(39); + IRQ(40); + IRQ(41); + IRQ(42); + IRQ(43); + IRQ(44); + IRQ(45); + IRQ(46); + IRQ(47); SYS(66); static IDTR idtr; diff --git a/kernel/src/arch/x86_64/init/PIC.cpp b/kernel/src/arch/x86_64/init/PIC.cpp index e24a23a1..35ca6481 100644 --- a/kernel/src/arch/x86_64/init/PIC.cpp +++ b/kernel/src/arch/x86_64/init/PIC.cpp @@ -36,9 +36,18 @@ void remap_pic() IO::outb(PIC2_DATA, ICW4_8086); io_delay(); - IO::outb(PIC1_DATA, 0b11111100); + IO::outb(PIC1_DATA, 0b11111111); io_delay(); IO::outb(PIC2_DATA, 0b11111111); + io_delay(); +} + +void change_pic_masks(u8 pic1_mask, u8 pic2_mask) +{ + IO::outb(PIC1_DATA, pic1_mask); + io_delay(); + IO::outb(PIC2_DATA, pic2_mask); + io_delay(); } void pic_eoi(unsigned char irq)