diff options
author | Danny Holman <dholman@gymli.org> | 2024-02-24 14:44:38 -0600 |
---|---|---|
committer | Danny Holman <dholman@gymli.org> | 2024-02-24 14:44:38 -0600 |
commit | 2ce0f8af51dae9e7d591ff5fd038f89d6ca9dbbe (patch) | |
tree | 314f6105fc2996923070ed7f82c3acc8d5b2b20c /arch/i386/kernel | |
parent | arch: i386: move jump_userspace to its own file (diff) | |
download | box-2ce0f8af51dae9e7d591ff5fd038f89d6ca9dbbe.tar.gz box-2ce0f8af51dae9e7d591ff5fd038f89d6ca9dbbe.tar.zst box-2ce0f8af51dae9e7d591ff5fd038f89d6ca9dbbe.zip |
arch: i386: cleanup everything and reorganize
Clean up everything in the i386 arch directory. This code has been in
dire need of refactoring for a long while. All the inline assembly
functions and the data structures related to the architecture should be
placed into their own header file. Now the scheduler can access
registers and ISRs without having to deal with arch-specific code.
Signed-off-by: Danny Holman <dholman@gymli.org>
Diffstat (limited to '')
-rw-r--r-- | arch/i386/kernel/gdt.c (renamed from arch/i386/boot/gdt.c) | 0 | ||||
-rw-r--r-- | arch/i386/kernel/idt.c (renamed from arch/i386/boot/idt.c) | 42 | ||||
-rw-r--r-- | arch/i386/kernel/isr.s (renamed from arch/i386/boot/isr.s) | 0 | ||||
-rw-r--r-- | arch/i386/kernel/keyboard.c | 8 | ||||
-rw-r--r-- | arch/i386/kernel/paging.c | 78 | ||||
-rw-r--r-- | arch/i386/kernel/pic.c | 16 | ||||
-rw-r--r-- | arch/i386/kernel/syscall.c | 48 | ||||
-rw-r--r-- | arch/i386/kernel/timer.c | 6 |
8 files changed, 91 insertions, 107 deletions
diff --git a/arch/i386/boot/gdt.c b/arch/i386/kernel/gdt.c index c0cf127..c0cf127 100644 --- a/arch/i386/boot/gdt.c +++ b/arch/i386/kernel/gdt.c diff --git a/arch/i386/boot/idt.c b/arch/i386/kernel/idt.c index 7b9401d..5c0766c 100644 --- a/arch/i386/boot/idt.c +++ b/arch/i386/kernel/idt.c @@ -1,7 +1,8 @@ +#include <kernel/idt.h> #include <kernel/syscall.h> #include <kernel/panic.h> #include <kernel/gdt.h> -#include <kernel/isr.h> +#include <kernel/asm.h> #include <kernel/io.h> #include <kernel/pic.h> #include <kernel/string.h> @@ -44,51 +45,40 @@ const char* exceptions[] = { "RESERVED" }; -__attribute__((noreturn)) -void halt_catch_fire(struct isr_frame *frame) { - dump_reg(frame); - kprintf("ERRNO=%x\n", frame->errno); - __asm__ volatile("cli;hlt"); - while (1); -} - -void exception_handler(struct isr_frame *frame) { - switch (frame->vector) { +void exception_handler(struct regs *regs) { + switch (regs->isr_vector) { case 0x00: panic("Division by zero in kernel address space"); - halt_catch_fire(frame); + break; case 0x06: panic("Invalid opcode in kernel address space"); - halt_catch_fire(frame); + break; case 0x08: panic("Double fault in interrupt handler"); - halt_catch_fire(frame); + break; case 0x0D: panic("Protection fault in kernel address space"); - halt_catch_fire(frame); + break; case 0x0E: - page_fault_handler(frame); + page_fault_handler(regs); break; default: panic("Unhandled exception"); - halt_catch_fire(frame); } } -void interrupt_handler(struct isr_frame frame) { - if (frame.vector < 32) { - exception_handler(&frame); - } else if (frame.vector < 48) { - irq_dispatch(&frame); +void interrupt_handler(struct regs regs) { + if (regs.isr_vector < 32) { + exception_handler(®s); + } else if (regs.isr_vector < 48) { + irq_dispatch(®s); } else { - switch (frame.vector) { + switch (regs.isr_vector) { case 0x80: - handle_syscall(&frame); + handle_syscall(®s); break; default: panic("Unmapped interrupt"); - halt_catch_fire(&frame); - __asm__ volatile("cli;hlt"); } } } diff --git a/arch/i386/boot/isr.s b/arch/i386/kernel/isr.s index 55db35e..55db35e 100644 --- a/arch/i386/boot/isr.s +++ b/arch/i386/kernel/isr.s diff --git a/arch/i386/kernel/keyboard.c b/arch/i386/kernel/keyboard.c index 4e4bc9b..96aea3a 100644 --- a/arch/i386/kernel/keyboard.c +++ b/arch/i386/kernel/keyboard.c @@ -100,6 +100,9 @@ static uint8_t* keymaps[4] = { keymap_control, }; +char keyboard_buffer[4096]; +int kbuf_pos = 0; + char keyboard_getchar(void) { static int shift = 0; uint8_t st = inb(KB_STAT); @@ -133,10 +136,9 @@ char keyboard_getchar(void) { return c; } -void keyboard_handler(struct isr_frame *frame) { +void keyboard_handler(void) { char c = keyboard_getchar(); - // TODO: actually put this in a buffer if (c != -1) - fb_putchar(c); + keyboard_buffer[kbuf_pos++]; return; } diff --git a/arch/i386/kernel/paging.c b/arch/i386/kernel/paging.c index 54539ac..b2a1392 100644 --- a/arch/i386/kernel/paging.c +++ b/arch/i386/kernel/paging.c @@ -10,63 +10,42 @@ static uintptr_t kend = (uintptr_t)&_kernel_end - 0xC0000000; static uintptr_t page_directory[1024] __attribute__((aligned(PAGE_SIZE))); static uintptr_t first_page_table[1024] __attribute__((aligned(PAGE_SIZE))); +static uintptr_t second_page_table[1024] __attribute__((aligned(PAGE_SIZE))); static int paging_enabled = 0; -static uint32_t dma_zone_bitmap[DMA_BITMAP_SZ]; -static uint32_t buddy_bitmap[BDY_BITMAP_SZ]; -static struct pfa_buddy first_buddy; - -static void _pfa_init(void) { - first_buddy.start = 0x01000000; - first_buddy.bitmap = buddy_bitmap; +uint32_t* init_page_table(uint32_t flags) { + uint32_t *ret = kmalloc(sizeof(uint32_t)*1024); + for (int i = 0; i < 1024; i++) + ret[i] = flags; } -static void _pfa_alloc(uintptr_t paddr) { - uintptr_t index = (paddr & 0xFFFFF000) / 4096 / 32; - uintptr_t bit = (paddr & 0xFFFFF000) / 4096 % 32; - uint32_t *bitmap; - if (paddr < 0x01000000) - bitmap = dma_zone_bitmap; - else - bitmap = first_buddy.bitmap; - - bitmap[index] |= (1 << bit); -} - -static void _pfa_free(uintptr_t paddr) { - uintptr_t index = (paddr & 0xFFFFF000) / 4096 / 32; - uintptr_t bit = (paddr & 0xFFFFF000) / 4096 % 32; - uint32_t *bitmap; - if (paddr < 0x01000000) - bitmap = dma_zone_bitmap; - else - bitmap = first_buddy.bitmap; - - bitmap[index] &= ~(1 << bit); +uint32_t* init_page_dir(uint32_t flags) { + uint32_t *ret = init_page_table(flags); + ret[0] = ((uintptr_t)&first_page_table - 0xC0000000) | 3; + ret[768] = ((uintptr_t)&second_page_table - 0xC0000000) | 3; } void paging_init(void) { - _pfa_init(); - for (int i = 0; i < 1024; i++) - page_directory[i] = 0x00000002; + for (int i = 0; i < 1024; i++) { + page_directory[i] = PD_RW; + first_page_table[i] = PD_RW; + second_page_table[i] = PD_RW; + } page_directory[1023] = ((uintptr_t)&page_directory - 0xC0000000) | 3; page_directory[0] = ((uintptr_t)&first_page_table - 0xC0000000) | 3; - page_directory[768] = ((uintptr_t)&first_page_table - 0xC0000000) | 3; - for (uintptr_t i = kstart; i < kend; i += 4096) { - _pfa_alloc(get_vaddr(i)); - map_page(page_directory, i, get_vaddr(i), 0x003); - } + page_directory[768] = ((uintptr_t)&second_page_table - 0xC0000000) | 3; + for (uintptr_t i = kstart; i < kend; i += PAGE_SIZE) + map_page(page_directory, i, i + 0xC0000000, 0x003); - load_page_dir(((uintptr_t)&page_directory) - 0xC0000000); - enable_paging(); + enable_paging(((uintptr_t)&page_directory) - 0xC0000000); paging_enabled = 1; return; } -void page_fault_handler(struct isr_frame *frame) { - uintptr_t errno = frame->errno; +void page_fault_handler(struct regs *regs) { + uintptr_t errno = regs->isr_err; uintptr_t fault_addr; __asm__ volatile("movl %%cr2, %0" : "=r"(fault_addr)); @@ -76,9 +55,9 @@ void page_fault_handler(struct isr_frame *frame) { int reserved = errno & ERR_RESERVED; int ifetch = errno & ERR_INST; + uintptr_t first_free; if (!present) - _pfa_alloc(fault_addr); - map_page(NULL, fault_addr, fault_addr, 0x003); + map_page(regs->cr3, fault_addr, fault_addr, PD_PRES | PD_RW | PD_USR); if (user) panic("Usermode attempted to read supervisor page"); if (rw) @@ -89,8 +68,17 @@ void page_fault_handler(struct isr_frame *frame) { panic("Task paging instruction fetch failure"); } -uintptr_t get_vaddr(uintptr_t paddr) { - return paddr + 0xC0000000; +uintptr_t get_paddr(uintptr_t vaddr) { + uint32_t pdindex = (uint32_t)vaddr >> 22; + uint32_t ptindex = (uint32_t)vaddr >> 12 & 0x03FF; + + uint32_t *pd = (uint32_t*)0xFFFFF000; + if (*pd & PD_PRES != 1) + return NULL; + uint32_t *pt = ((uint32_t*)0xFFC00000) + (0x400 * pdindex); + if (*pt & PD_PRES != 1) + return NULL; + return (uintptr_t)((pt[ptindex] & ~0xFFF) + ((uint32_t)vaddr & 0xFFF)); } void map_page(uint32_t *pd, uintptr_t paddr, uintptr_t vaddr, uint32_t flags) { diff --git a/arch/i386/kernel/pic.c b/arch/i386/kernel/pic.c index 7a51763..3cf1d94 100644 --- a/arch/i386/kernel/pic.c +++ b/arch/i386/kernel/pic.c @@ -1,6 +1,6 @@ #include <kernel/pic.h> -static void (*irq_handlers[16])(struct isr_frame *frame); +static void (*irq_handlers[16])(struct regs *regs); void pic_eoi(uint8_t irq) { if (irq >= 8) @@ -24,27 +24,27 @@ void pic_remap(void) { outb(PIC2_DATA, a2); } -static uint16_t __pic_get_irq_reg(int ocw3) { +static uint16_t _pic_get_irq_reg(int ocw3) { outb(PIC1_COMMAND, ocw3); outb(PIC2_COMMAND, ocw3); return (inb(PIC2_COMMAND) << 8) | inb(PIC1_COMMAND); } uint16_t pic_get_irr(void) { - return __pic_get_irq_reg(PIC_READ_IRR); + return _pic_get_irq_reg(PIC_READ_IRR); } uint16_t pic_get_isr(void) { - return __pic_get_irq_reg(PIC_READ_ISR); + return _pic_get_irq_reg(PIC_READ_ISR); } -void register_irq_handler(uint8_t irq, void (*handler)(struct isr_frame *frame)) { +void register_irq_handler(uint8_t irq, void (*handler)(struct regs *regs)) { irq_handlers[irq] = handler; } -void irq_dispatch(struct isr_frame *frame) { - (*irq_handlers[frame->vector-32])(frame); - pic_eoi(frame->vector-32); +void irq_dispatch(struct regs *regs) { + (*irq_handlers[regs->isr_vector-32])(regs); + pic_eoi(regs->isr_vector-32); return; } diff --git a/arch/i386/kernel/syscall.c b/arch/i386/kernel/syscall.c index 7bdb24b..27e1c60 100644 --- a/arch/i386/kernel/syscall.c +++ b/arch/i386/kernel/syscall.c @@ -1,32 +1,36 @@ #include <kernel/syscall.h> +#include <kernel/panic.h> +#include <kernel/framebuffer.h> +#include <kernel/keyboard.h> +#include <kernel/string.h> #include <kernel/io.h> #include <stddef.h> -int handle_syscall(struct isr_frame *frame) { - switch (frame->eax) { - case SYS_REBOOT: - kprintf("REBOOT NOT SUPPORTED\n"); - break; - default: - kprintf("Error: Invalid system call number: %d\n", frame->eax); - halt_catch_fire(frame); +extern char *keyboard_buffer; +extern uint32_t kbuf_pos; + +void sys_read(struct regs *regs) { + if (regs->ebx == 1) { + while (kbuf_pos > regs->edx); + memcpy((char*)regs->ecx, keyboard_buffer, regs->edx); } - return 0; } -void dump_reg(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("\tEIP = %x\n", frame->eip); - kprintf("Current code selector: %x\n", frame->cs); +void sys_write(struct regs *regs) { + if (regs->ebx == 0) + fb_write((char*)regs->ecx, regs->edx); } -void dump_stack(uint32_t esp, size_t len) { - for (uint32_t i = 0; i < len; i++) - kprintf("%x:\t%x\n", esp+i, *(uint32_t*)(esp+i)); +int handle_syscall(struct regs *regs) { + switch (regs->eax) { + case SYS_READ: + sys_read(regs); + break; + case SYS_WRITE: + sys_write(regs); + break; + default: + panic("Invalid system call number"); + } + return 0; } diff --git a/arch/i386/kernel/timer.c b/arch/i386/kernel/timer.c index 9e53fbd..4aafed1 100644 --- a/arch/i386/kernel/timer.c +++ b/arch/i386/kernel/timer.c @@ -5,7 +5,7 @@ static uint32_t num_ticks = 0; -void timer_handler(struct isr_frame *frame) { +void timer_handler(struct regs *regs) { num_ticks++; if (num_ticks == 3) { num_ticks = 0; @@ -14,12 +14,12 @@ void timer_handler(struct isr_frame *frame) { } void timer_init(void) { - asm __volatile__("cli"); + disable_ints(); int divisor = 1193182 / 100; outb(0x43, 0x34); outb(0x40, divisor && 0xFF); outb(0x40, divisor && 0xFF00 >> 8); - asm __volatile__("sti"); + enable_ints(); //uint8_t read = 0; //outb(0x43, 0xE2); |