kernel: Actually register interrupt handlers properly

This commit is contained in:
apio 2023-05-14 15:24:46 +02:00
parent ac040f6252
commit 81bf3740a1
Signed by: apio
GPG Key ID: B8A7D06E42258954
4 changed files with 79 additions and 1 deletions

View File

@ -22,6 +22,9 @@ namespace CPU
void disable_interrupts(); void disable_interrupts();
void wait_for_interrupt(); void wait_for_interrupt();
bool save_interrupts();
void restore_interrupts(bool saved);
void get_stack_trace(void (*callback)(u64, void*), void* arg); void get_stack_trace(void (*callback)(u64, void*), void* arg);
void print_stack_trace(); void print_stack_trace();
void get_stack_trace_at(Registers* regs, void (*callback)(u64, void*), void* arg); void get_stack_trace_at(Registers* regs, void (*callback)(u64, void*), void* arg);
@ -30,6 +33,7 @@ namespace CPU
u16 get_processor_id(); u16 get_processor_id();
bool register_interrupt(u8 interrupt, void (*handler)(Registers*, void*), void* context); bool register_interrupt(u8 interrupt, void (*handler)(Registers*, void*), void* context);
void sync_interrupts();
void pause(); void pause();
} }

View File

@ -22,6 +22,7 @@ extern "C" void enable_nx();
extern void setup_gdt(); extern void setup_gdt();
extern void remap_pic(); 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(unsigned char irq);
extern void pic_eoi(Registers* regs); extern void pic_eoi(Registers* regs);
extern void setup_idt(); extern void setup_idt();
@ -268,6 +269,8 @@ namespace CPU
.expect_value("Could not create the IO background thread!"); .expect_value("Could not create the IO background thread!");
remap_pic(); remap_pic();
sync_interrupts();
} }
void enable_interrupts() void enable_interrupts()
@ -280,6 +283,20 @@ namespace CPU
asm volatile("cli"); 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() void wait_for_interrupt()
{ {
asm volatile("hlt"); asm volatile("hlt");
@ -387,8 +404,28 @@ namespace CPU
irq_handlers[interrupt] = { handler, context }; irq_handlers[interrupt] = { handler, context };
sync_interrupts();
return true; 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 // called by kernel_yield

View File

@ -84,6 +84,20 @@ INT(20);
INT(21); INT(21);
INT(32); INT(32);
INT(33); 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); INT(66);
void setup_idt() void setup_idt()
@ -112,6 +126,20 @@ void setup_idt()
TRAP(21); TRAP(21);
IRQ(32); IRQ(32);
IRQ(33); 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); SYS(66);
static IDTR idtr; static IDTR idtr;

View File

@ -36,9 +36,18 @@ void remap_pic()
IO::outb(PIC2_DATA, ICW4_8086); IO::outb(PIC2_DATA, ICW4_8086);
io_delay(); io_delay();
IO::outb(PIC1_DATA, 0b11111100); IO::outb(PIC1_DATA, 0b11111111);
io_delay(); io_delay();
IO::outb(PIC2_DATA, 0b11111111); 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) void pic_eoi(unsigned char irq)