feature: start to implement keyboard handler and better isrs/irqs

This commit is contained in:
0x35c 2024-10-09 17:54:29 +02:00
parent 0812a06350
commit 4fb51d4356
11 changed files with 451 additions and 141 deletions

7
headers/drivers.h Normal file
View File

@ -0,0 +1,7 @@
#pragma once
#include "interrupts.h"
void load_drivers(void);
void keyboard_handler(struct registers *regs);
void clock_handler(struct registers *regs);

View File

@ -1,5 +1,7 @@
#pragma once #pragma once
#include <stdint.h>
// doc : https://wiki.osdev.org/Interrupt_Descriptor_Table#IDTR // doc : https://wiki.osdev.org/Interrupt_Descriptor_Table#IDTR
struct idt_descriptor { struct idt_descriptor {
uint16_t size; uint16_t size;

View File

@ -2,5 +2,19 @@
#include <stdint.h> #include <stdint.h>
void exception_handler(void); struct registers {
// data segment selector
uint32_t ds;
// general purpose registers pushed by pusha
uint32_t edi, esi, ebp, esp, ebx, edx, ecx, eax;
// pushed by isr procedure
uint32_t int_no, err_code;
// pushed by CPU automatically
uint32_t eip, cs, eflags, useresp, ss;
};
typedef void (*isr_t)(struct registers *);
void isr_handler(struct registers *regs);
void pic_send_eoi(uint8_t irq); void pic_send_eoi(uint8_t irq);
void register_interrupt_handler(int index, isr_t handler);

8
src/drivers/clock.c Normal file
View File

@ -0,0 +1,8 @@
#include "interrupts.h"
#include "kprintf.h"
void clock_handler(struct registers *regs)
{
(void)regs;
kprintf("test\n");
}

8
src/drivers/drivers.c Normal file
View File

@ -0,0 +1,8 @@
#include "drivers.h"
#include "interrupts.h"
void load_drivers(void)
{
register_interrupt_handler(1, keyboard_handler);
register_interrupt_handler(0, clock_handler);
}

10
src/drivers/keyboard.c Normal file
View File

@ -0,0 +1,10 @@
#include "interrupts.h"
#include "kprintf.h"
#include "terminal.h"
#include <stdint.h>
void keyboard_handler(struct registers *regs)
{
(void)regs;
terminal_putchar(terminal_getkey().c);
}

View File

@ -3,8 +3,8 @@
#include "kprintf.h" #include "kprintf.h"
#include "utils.h" #include "utils.h"
#include <stddef.h>
#include <stdint.h> #include <stdint.h>
#define NTMFDP 0
const char *faults[] = { const char *faults[] = {
"division by zero", "division by zero",
@ -29,36 +29,29 @@ const char *faults[] = {
"SIMD floating point exception", "SIMD floating point exception",
}; };
void exception_handler(void) static isr_t interrupt_handlers[16];
void isr_handler(struct registers *regs)
{ {
int8_t index = -1;
__asm__ volatile("movb %%bl, %0" ::"m"(index));
if (index == -1) {
kprintf(KERN_ERR "interrupt triggered without a code\n");
return;
}
uint8_t i = 0; uint8_t i = 0;
while (i < ARRAY_SIZE(faults)) { while (i < ARRAY_SIZE(faults)) {
if (i == index) if (i == regs->int_no)
kpanic("interrupt: %s\n", faults[i]); kpanic("interrupt: %s\n", faults[i]);
i++; i++;
} }
kprintf(KERN_ERR "interrupt triggered with no matching code\n"); kprintf(KERN_ERR "interrupt triggered with no matching code\n");
} }
void irq_handler(void) void register_interrupt_handler(int i, isr_t handler)
{ {
int8_t index = -1; interrupt_handlers[i] = handler;
__asm__ volatile("movb %%bl, %0" ::"m"(index)); }
pic_send_eoi(index); void irq_handler(struct registers *regs)
if (index == -1) { {
kprintf(KERN_ERR "interrupt triggered without a code\n"); if (regs->int_no != 0) {
return; isr_t handler = interrupt_handlers[regs->int_no];
handler(regs);
} }
if (index == 0) pic_send_eoi(regs->int_no);
return;
kpanic("%d\n", index);
} }

View File

@ -1,4 +1,3 @@
#include "sys/io.h"
#include <stdbool.h> #include <stdbool.h>
#include <stdint.h> #include <stdint.h>

View File

@ -1,45 +1,137 @@
.intel_syntax noprefix .intel_syntax noprefix
.extern irq_handler .extern irq_handler
.macro irq_common_stub nb irq_common_stub:
irq_stub_\nb: // push general purpose registers
mov bl, \nb pusha
call irq_handler
iret
.endm
irq_common_stub 0 // push data segment selector
irq_common_stub 1 mov ax, ds
irq_common_stub 2 push eax
irq_common_stub 3
irq_common_stub 4 // use kernel data segment
irq_common_stub 5 mov ax, 0x10
irq_common_stub 6 mov ds, ax
irq_common_stub 7 mov es, ax
irq_common_stub 8 mov fs, ax
irq_common_stub 9 mov gs, ax
irq_common_stub 10 // hand over stack to C function
irq_common_stub 11 push esp
irq_common_stub 12 // and call it
irq_common_stub 13 call irq_handler
irq_common_stub 14 // pop stack pointer again
irq_common_stub 15 pop eax
// restore original segment pointers segment
pop eax
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
// restore registers
popa
// remove int_no and err_code from stack
add esp, 8
iret
irq0:
push 0
push 32
jmp irq_common_stub
irq1:
push 1
push 33
jmp irq_common_stub
irq2:
push 2
push 34
jmp irq_common_stub
irq3:
push 3
push 35
jmp irq_common_stub
irq4:
push 4
push 36
jmp irq_common_stub
irq5:
push 5
push 37
jmp irq_common_stub
irq6:
push 6
push 38
jmp irq_common_stub
irq7:
push 7
push 39
jmp irq_common_stub
irq8:
push 8
push 40
jmp irq_common_stub
irq9:
push 9
push 41
jmp irq_common_stub
irq10:
push 10
push 42
jmp irq_common_stub
irq11:
push 11
push 43
jmp irq_common_stub
irq12:
push 12
push 44
jmp irq_common_stub
irq13:
push 13
push 45
jmp irq_common_stub
irq14:
push 14
push 46
jmp irq_common_stub
irq15:
push 15
push 47
jmp irq_common_stub
.global irq_stub_table .global irq_stub_table
irq_stub_table: irq_stub_table:
.long irq_stub_0 .long irq0
.long irq_stub_1 .long irq1
.long irq_stub_2 .long irq2
.long irq_stub_3 .long irq3
.long irq_stub_4 .long irq4
.long irq_stub_5 .long irq5
.long irq_stub_6 .long irq6
.long irq_stub_7 .long irq7
.long irq_stub_8 .long irq8
.long irq_stub_9 .long irq9
.long irq_stub_10 .long irq10
.long irq_stub_11 .long irq11
.long irq_stub_12 .long irq12
.long irq_stub_13 .long irq13
.long irq_stub_14 .long irq14
.long irq_stub_15 .long irq15

View File

@ -1,84 +1,257 @@
.intel_syntax noprefix .intel_syntax noprefix
.extern exception_handler .extern isr_handler
isr_common_stub:
// push general purpose registers
pusha
// push data segment selector
mov ax, ds
push eax
// use kernel data segment
mov ax, 0x10
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
// hand over stack to C function
push esp
// and call it
call isr_handler
// pop stack pointer again
pop eax
// restore original segment pointers segment
pop eax
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
// restore registers
popa
// remove int_no and err_code from stack
add esp, 8
.macro isr_err_stub nb
isr_stub_\nb:
mov bl, \nb
call exception_handler
iret iret
.endm
.macro isr_no_err_stub nb // 0: Divide By Zero Exception
isr_stub_\nb: isr0:
mov bl, \nb push 0
call exception_handler push 0
iret jmp isr_common_stub
.endm
isr_no_err_stub 0 // 1: Debug Exception
isr_no_err_stub 1 isr1:
isr_no_err_stub 2 push 0
isr_no_err_stub 3 push 1
isr_no_err_stub 4 jmp isr_common_stub
isr_no_err_stub 5
isr_no_err_stub 6 // 2: Non Maskable Interrupt Exception
isr_no_err_stub 7 isr2:
isr_err_stub 8 push 0
isr_no_err_stub 9 push 2
isr_err_stub 10 jmp isr_common_stub
isr_err_stub 11
isr_err_stub 12 // 3: Int 3 Exception
isr_err_stub 13 isr3:
isr_err_stub 14 push 0
isr_no_err_stub 15 push 3
isr_no_err_stub 16 jmp isr_common_stub
isr_err_stub 17
isr_no_err_stub 18 // 4: INTO Exception
isr_no_err_stub 19 isr4:
isr_no_err_stub 20 push 0
isr_no_err_stub 21 push 4
isr_no_err_stub 22 jmp isr_common_stub
isr_no_err_stub 23
isr_no_err_stub 24 // 5: Out of Bounds Exception
isr_no_err_stub 25 isr5:
isr_no_err_stub 26 push 0
isr_no_err_stub 27 push 5
isr_no_err_stub 28 jmp isr_common_stub
isr_no_err_stub 29
isr_err_stub 30 // 6: Invalid Opcode Exception
isr_no_err_stub 31 isr6:
push 0
push 6
jmp isr_common_stub
// 7: Coprocessor Not Available Exception
isr7:
push 0
push 7
jmp isr_common_stub
// 8: Double Fault Exception (With Error Code!)
isr8:
push 8
jmp isr_common_stub
// 9: Coprocessor Segment Overrun Exception
isr9:
push 0
push 9
jmp isr_common_stub
// 10: Bad TSS Exception (With Error Code!)
isr10:
push 10
jmp isr_common_stub
// 11: Segment Not Present Exception (With Error Code!)
isr11:
push 11
jmp isr_common_stub
// 12: Stack Fault Exception (With Error Code!)
isr12:
push 12
jmp isr_common_stub
// 13: General Protection Fault Exception (With Error Code!)
isr13:
push 13
jmp isr_common_stub
// 14: Page Fault Exception (With Error Code!)
isr14:
push 14
jmp isr_common_stub
// 15: Reserved Exception
isr15:
push 0
push 15
jmp isr_common_stub
// 16: Floating Point Exception
isr16:
push 0
push 16
jmp isr_common_stub
// 17: Alignment Check Exception
isr17:
push 17
jmp isr_common_stub
// 18: Machine Check Exception
isr18:
push 0
push 18
jmp isr_common_stub
// 19: Reserved
isr19:
push 0
push 19
jmp isr_common_stub
// 20: Reserved
isr20:
push 0
push 20
jmp isr_common_stub
// 21: Reserved
isr21:
push 21
jmp isr_common_stub
// 22: Reserved
isr22:
push 0
push 22
jmp isr_common_stub
// 23: Reserved
isr23:
push 0
push 23
jmp isr_common_stub
// 24: Reserved
isr24:
push 0
push 24
jmp isr_common_stub
// 25: Reserved
isr25:
push 0
push 25
jmp isr_common_stub
// 26: Reserved
isr26:
push 0
push 26
jmp isr_common_stub
// 27: Reserved
isr27:
push 0
push 27
jmp isr_common_stub
// 28: Reserved
isr28:
push 0
push 28
jmp isr_common_stub
// 29: Reserved
isr29:
push 0
push 29
jmp isr_common_stub
// 30: Reserved
isr30:
push 0
push 30
jmp isr_common_stub
// 31: Reserved
isr31:
push 0
push 31
jmp isr_common_stub
.global isr_stub_table .global isr_stub_table
isr_stub_table: isr_stub_table:
.long isr_stub_0 .long isr0
.long isr_stub_1 .long isr1
.long isr_stub_2 .long isr2
.long isr_stub_3 .long isr3
.long isr_stub_4 .long isr4
.long isr_stub_5 .long isr5
.long isr_stub_6 .long isr6
.long isr_stub_7 .long isr7
.long isr_stub_8 .long isr8
.long isr_stub_9 .long isr9
.long isr_stub_10 .long isr10
.long isr_stub_11 .long isr11
.long isr_stub_12 .long isr12
.long isr_stub_13 .long isr13
.long isr_stub_14 .long isr14
.long isr_stub_15 .long isr15
.long isr_stub_16 .long isr16
.long isr_stub_17 .long isr17
.long isr_stub_18 .long isr18
.long isr_stub_19 .long isr19
.long isr_stub_20 .long isr20
.long isr_stub_21 .long isr21
.long isr_stub_22 .long isr22
.long isr_stub_23 .long isr23
.long isr_stub_24 .long isr24
.long isr_stub_25 .long isr25
.long isr_stub_26 .long isr26
.long isr_stub_27 .long isr27
.long isr_stub_28 .long isr28
.long isr_stub_29 .long isr29
.long isr_stub_30 .long isr30
.long isr_stub_31 .long isr31

View File

@ -1,3 +1,4 @@
#include "drivers.h"
#include "gdt.h" #include "gdt.h"
#include "idt.h" #include "idt.h"
#include "kprintf.h" #include "kprintf.h"
@ -27,5 +28,8 @@ void kernel_main(void)
init_gdt(); init_gdt();
init_idt(); init_idt();
init_memory(); init_memory();
/* load_drivers(); */
/* while (42) */
/* ; */
shell_init(); shell_init();
} }