From c83d7bdcb60859f232e0fa6994ffba01509aba2e Mon Sep 17 00:00:00 2001 From: Danny Holman Date: Sat, 15 Jan 2022 16:11:30 -0600 Subject: arch: i386: simplify IDT setup Simplify the interrupt descriptor table setup and frame assembly. Signed-off-by: Danny Holman --- arch/i386/boot/crti.s | 4 +- arch/i386/boot/idt.c | 104 +++++++++++++++++++++++++++++++++++++++-- arch/i386/boot/isr.s | 45 +++++++++--------- arch/i386/include/kernel/idt.h | 1 + arch/i386/include/kernel/isr.h | 5 +- 5 files changed, 128 insertions(+), 31 deletions(-) diff --git a/arch/i386/boot/crti.s b/arch/i386/boot/crti.s index 4e1e4cb..8386b77 100644 --- a/arch/i386/boot/crti.s +++ b/arch/i386/boot/crti.s @@ -1,15 +1,15 @@ .section .init + .global _init .type _init, @function - _init: pushl %ebp movl %esp, %ebp .section .fini + .global _fini .type _fini, @function - _fini: pushl %ebp movl %esp, %ebp diff --git a/arch/i386/boot/idt.c b/arch/i386/boot/idt.c index d741381..dbcfaa2 100644 --- a/arch/i386/boot/idt.c +++ b/arch/i386/boot/idt.c @@ -5,17 +5,113 @@ #include #include +#define SEGMENT_PRESENT 0x80 +#define SEGMENT_RING0 0x00 +#define SEGMENT_RING3 0x60 +#define SEGMENT_STORAGE 0x00 +#define SEGMENT_INTERRUPT 0x0E +#define IDT_EXCEPTION (SEGMENT_PRESENT | SEGMENT_INTERRUPT) +#define IDT_INTERRUPT (SEGMENT_PRESENT | SEGMENT_INTERRUPT) + +#define IDT_MAX_DESCRIPTORS 256 + +struct idt_entry { + uint16_t isr_low; + uint16_t kernel_cs; + uint8_t reserved; + uint8_t flags; + uint16_t isr_high; +} __attribute__((packed)); + +struct idt_ptr { + uint16_t limit; + uint32_t base; +} __attribute__((packed)); + __attribute__((aligned(0x10))) struct idt_entry idt[256]; struct idt_ptr idtr; +char *exceptions[] = { + "Division by zero", + "Debug", + "Non-maskable interrupt", + "Breakpoint", + "Overflow", + "Out-of-bounds", + "Invalid opcode", + "FPU not available", + "Double fault", + "RESERVED", + "Invalid TSS", + "Segment not present", + "Stack fault", + "General protection fault", + "Page fault", + "RESERVED", + "FPU exception", + "Alignment check", + "Machine check", + "FPU-SIMD exception", + "Virtualization exception", + "Control protection" + "RESERVED", + "Hypervisor injection", + "VMM exception", + "Security exception", + "RESERVED", + "Triple fault", + "RESERVED" +}; + __attribute__((noreturn)) -void exception_handler(struct isr_frame *frame) { - kprintf("Error: CPU exception: %d\n", frame->vector); +void halt_catch_fire(struct isr_frame *frame) { + kprintf("Registers at interrupt:\n"); + kprintf("\tEAX = %x\n", frame->eax); + kprintf("\tEBX = %x\n", frame->ebx); + kprintf("\tECX = %x\n", frame->ecx); + kprintf("\tEDX = %x\n", frame->edx); + kprintf("\tESI = %x\n", frame->esi); + kprintf("\tEDI = %x\n", frame->edi); + kprintf("\tESP = %x\n", frame->esp); + kprintf("\tEBP = %x\n", frame->ebp); + kprintf("\tEIP = %x\n", frame->eip); + kprintf("\tEFLAGS = %x\n", frame->eflags); + kprintf("Current code selector: %d\n", frame->cs); __asm__ volatile("cli;hlt"); } -extern void idt_set_gate(uint8_t num, void (*handler)(void), uint16_t cs, uint8_t flags) { +__attribute__((noreturn)) +void exception_handler(struct isr_frame *frame) { + switch (frame->vector) { + default: + kprintf("Unhandled exception: %s\n", exceptions[frame->vector]); + halt_catch_fire(frame); + } +} + +void irq_dispatch(uint8_t irq, struct isr_frame *frame) { + return; +} + +__attribute__((noreturn)) +void interrupt_handler(struct isr_frame *frame) { + if (frame->vector < 32) + exception_handler(frame); + else if (frame->vector > 32 && frame->vector < 48) + irq_dispatch(frame->vector - 16, frame); + switch (frame->vector) { + case 0x80: + syscall_dispatch(frame); + break; + default: + kprintf("Error: Unmapped interrupt: %d\n", frame->vector); + halt_catch_fire(frame); + __asm__ volatile("cli;hlt"); + } +} + +void idt_set_gate(uint8_t num, void (*handler)(void), uint16_t cs, uint8_t flags) { struct idt_entry *desc = &idt[num]; desc->isr_low = (uint16_t)(((uint32_t)handler >> 0) & 0xFFFF); desc->isr_high = (uint16_t)(((uint32_t)handler >> 16) & 0xFFFF); @@ -26,7 +122,7 @@ extern void idt_set_gate(uint8_t num, void (*handler)(void), uint16_t cs, uint8_ void idt_install(void) { idtr.limit = (uint16_t)sizeof(struct idt_entry) * 256 - 1; - idtr.base = (uint32_t)&idt[0]; + idtr.base = (uint32_t)idt; idt_set_gate(0, isr_stub_0, 0x08, IDT_EXCEPTION); idt_set_gate(1, isr_stub_1, 0x08, IDT_EXCEPTION); diff --git a/arch/i386/boot/isr.s b/arch/i386/boot/isr.s index b5f8be5..76afa9f 100644 --- a/arch/i386/boot/isr.s +++ b/arch/i386/boot/isr.s @@ -4,6 +4,7 @@ .global isr_stub_\num .type isr_stub_\num, @function isr_stub_\num: + cli pushl $\num jmp isr_frame_asm .endm @@ -11,18 +12,32 @@ isr_stub_\num: .global isr_stub_\num .type isr_stub_\num, @function isr_stub_\num: + cli pushl $0 pushl $\num jmp isr_frame_asm .endm +.macro irq_stub num +.global irq_stub_\num +.type irq_stub_\num, @function +irq_stub_\num: + cli + pushl $0 + pushl $\num + jmp isr_frame_asm +.endm + +.global syscall_stub +syscall_stub: + pushl $0 + pushl $0x80 + jmp isr_frame_asm + isr_frame_asm: - pushl %ebp - movl %esp, %ebp pushl %eax pushl %ebx pushl %ecx - pushl %ecx pushl %edx pushl %esi pushl %edi @@ -36,22 +51,9 @@ isr_frame_asm: movl %cr4, %eax pushl %eax - movw %ds, %ax - pushl %eax - pushl $0 - movw $0x10, %ax - movw %ax, %ds - movw %ax, %es - movw %ax, %ss - - lea 0xC(%esp), %edi + lea -8(%esp), %edi pushl %edi - call exception_handler - - popl %eax - popl %eax - movw %ax, %ds - movw %ax, %es + call interrupt_handler popl %eax movl %eax, %cr4 @@ -69,8 +71,7 @@ isr_frame_asm: popl %ebx popl %eax - popl %ebp - add $0x10, %esp + addl $4, %esp iret isr_no_err_stub 0 @@ -94,7 +95,7 @@ isr_err_stub 17 isr_no_err_stub 18 isr_no_err_stub 19 isr_no_err_stub 20 -isr_no_err_stub 21 +isr_err_stub 21 isr_no_err_stub 22 isr_no_err_stub 23 isr_no_err_stub 24 @@ -102,6 +103,6 @@ isr_no_err_stub 25 isr_no_err_stub 26 isr_no_err_stub 27 isr_no_err_stub 28 -isr_no_err_stub 29 +isr_err_stub 29 isr_err_stub 30 isr_no_err_stub 31 diff --git a/arch/i386/include/kernel/idt.h b/arch/i386/include/kernel/idt.h index 699eb96..190e15e 100644 --- a/arch/i386/include/kernel/idt.h +++ b/arch/i386/include/kernel/idt.h @@ -10,6 +10,7 @@ #define SEGMENT_STORAGE 0x00 #define SEGMENT_INTERRUPT 0x0E #define IDT_EXCEPTION (SEGMENT_PRESENT | SEGMENT_INTERRUPT) +#define IDT_INTERRUPT (SEGMENT_PRESENT | SEGMENT_INTERRUPT) #define IDT_MAX_DESCRIPTORS 256 diff --git a/arch/i386/include/kernel/isr.h b/arch/i386/include/kernel/isr.h index 61fe22f..9d88958 100644 --- a/arch/i386/include/kernel/isr.h +++ b/arch/i386/include/kernel/isr.h @@ -11,19 +11,18 @@ struct isr_frame { uint32_t edi; uint32_t esi; + uint32_t ebp; + uint32_t esp; uint32_t edx; uint32_t ecx; uint32_t ebx; uint32_t eax; - uint32_t ebp; uint32_t vector; uint32_t errno; uint32_t eip; uint32_t cs; uint32_t eflags; - uint32_t esp; - uint32_t dss; } __attribute__((packed)); extern void isr_stub_0(void); -- cgit v1.2.3