diff options
| author | Anton Kling <anton@kling.gg> | 2024-05-05 15:50:33 +0200 | 
|---|---|---|
| committer | Anton Kling <anton@kling.gg> | 2024-05-05 15:51:44 +0200 | 
| commit | 9d4ed1393d163514b317654cda736987b476f8a3 (patch) | |
| tree | b133537ec0531941b705436add2aaa437b70d76d /kernel/cpu | |
| parent | c750b444c7f5c2f21be74922c711f2929359afbe (diff) | |
Kernel: Mask interrupts until they have a handler
Diffstat (limited to 'kernel/cpu')
| -rw-r--r-- | kernel/cpu/idt.c | 35 | 
1 files changed, 23 insertions, 12 deletions
| diff --git a/kernel/cpu/idt.c b/kernel/cpu/idt.c index acede33..a1f78f9 100644 --- a/kernel/cpu/idt.c +++ b/kernel/cpu/idt.c @@ -68,6 +68,13 @@ void double_fault(registers_t *regs) {    halt();  } +void invalid_opcode(reg_t *regs) { +  klog("Invalid opcode", LOG_ERROR); +  kprintf("Instruction Pointer: %x\n", regs->eip); +  dump_backtrace(8); +  halt(); +} +  void page_fault(reg_t *regs) {    uint32_t cr2 = get_cr2();    if (0xDEADC0DE == cr2) { @@ -128,7 +135,7 @@ static inline void io_wait(void) {  #define ICW4_BUF_MASTER 0x0C /* Buffered mode/master */  #define ICW4_SFNM 0x10       /* Special fully nested (not) */ -void PIC_remap(int offset) { +void pic_remap(int offset) {    unsigned char a1, a2;    a1 = inb(MASTER_PIC_DATA_PORT);    a2 = inb(SLAVE_PIC_DATA_PORT); @@ -164,14 +171,14 @@ void PIC_remap(int offset) {    outb(SLAVE_PIC_DATA_PORT, a2);  } -void IRQ_set_mask(unsigned char IRQline) { +void irq_set_mask(unsigned char irq_line) {    u16 port;    u8 value; -  port = (IRQline < 8) ? MASTER_PIC_DATA_PORT : SLAVE_PIC_DATA_PORT; -  if (IRQline >= 8) { -    IRQline -= 8; +  port = (irq_line < 8) ? MASTER_PIC_DATA_PORT : SLAVE_PIC_DATA_PORT; +  if (irq_line >= 8) { +    irq_line -= 8;    } -  value = inb(port) | (1 << IRQline); +  value = inb(port) | (1 << irq_line);    outb(port, value);  } @@ -252,11 +259,21 @@ void install_handler(interrupt_handler handler_function, u16 type_attribute,    format_descriptor((u32)isr_list[entry], KERNEL_CODE_SEGMENT_OFFSET,                      type_attribute, &IDT_Entry[entry]);    list_of_handlers[entry] = (interrupt_handler)handler_function; +  if (entry >= 0x20 && entry < 0x20 + 0xA) { +    IRQ_clear_mask(entry - 0x20); +  }  }  void idt_init(void) {    memset(list_of_handlers, 0, sizeof(void *) * 256); +  pic_remap(0x20); +  for (int i = 0; i < 16; i++) { +    irq_set_mask(i); +  } + +  install_handler((interrupt_handler)invalid_opcode, INT_32_INTERRUPT_GATE(0x0), +                  0x6);    install_handler((interrupt_handler)page_fault, INT_32_INTERRUPT_GATE(0x0),                    0xE);    install_handler((interrupt_handler)double_fault, INT_32_INTERRUPT_GATE(0x0), @@ -264,12 +281,6 @@ void idt_init(void) {    install_handler((interrupt_handler)general_protection_fault,                    INT_32_INTERRUPT_GATE(0x0), 0xD); -  PIC_remap(0x20); -  IRQ_clear_mask(0xb); -  IRQ_set_mask(0xe); -  IRQ_set_mask(0xf); -  IRQ_clear_mask(2); -    idtr.interrupt_table = (struct IDT_Descriptor **)&IDT_Entry;    idtr.size = (sizeof(struct IDT_Descriptor) * IDT_MAX_ENTRY) - 1;    load_idtr(&idtr); |