From 2ce0f8af51dae9e7d591ff5fd038f89d6ca9dbbe Mon Sep 17 00:00:00 2001 From: Danny Holman Date: Sat, 24 Feb 2024 14:44:38 -0600 Subject: 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 --- arch/i386/boot/gdt.c | 58 ------------- arch/i386/boot/idt.c | 162 ------------------------------------ arch/i386/boot/isr.s | 129 ---------------------------- arch/i386/include/kernel/asm.h | 84 +++++++++++++++++++ arch/i386/include/kernel/idt.h | 1 - arch/i386/include/kernel/isr.h | 78 ----------------- arch/i386/include/kernel/keyboard.h | 3 +- arch/i386/include/kernel/paging.h | 18 +--- arch/i386/include/kernel/pic.h | 17 +--- arch/i386/include/kernel/syscall.h | 8 +- arch/i386/include/kernel/timer.h | 4 +- arch/i386/kernel/gdt.c | 58 +++++++++++++ arch/i386/kernel/idt.c | 152 +++++++++++++++++++++++++++++++++ arch/i386/kernel/isr.s | 129 ++++++++++++++++++++++++++++ arch/i386/kernel/keyboard.c | 8 +- arch/i386/kernel/paging.c | 78 ++++++++--------- arch/i386/kernel/pic.c | 16 ++-- arch/i386/kernel/syscall.c | 48 ++++++----- arch/i386/kernel/timer.c | 6 +- arch/i386/make.config | 6 +- 20 files changed, 515 insertions(+), 548 deletions(-) delete mode 100644 arch/i386/boot/gdt.c delete mode 100644 arch/i386/boot/idt.c delete mode 100644 arch/i386/boot/isr.s delete mode 100644 arch/i386/include/kernel/isr.h create mode 100644 arch/i386/kernel/gdt.c create mode 100644 arch/i386/kernel/idt.c create mode 100644 arch/i386/kernel/isr.s (limited to 'arch') diff --git a/arch/i386/boot/gdt.c b/arch/i386/boot/gdt.c deleted file mode 100644 index c0cf127..0000000 --- a/arch/i386/boot/gdt.c +++ /dev/null @@ -1,58 +0,0 @@ -#include -#include -#include - -struct gdt_entry desc[6]; -struct gdt_ptr gp; -struct tss_entry tss_entry; - -void gdt_set_gate(int num, uint32_t base, uint32_t limit, uint8_t access, uint8_t gran) { - desc[num].base_low = (base & 0xFFFF); - desc[num].base_middle = (base >> 16) & 0xFF; - desc[num].base_high = (base >> 24) & 0xFF; - - desc[num].limit_low = (limit & 0xFFFF); - desc[num].gran = (limit >> 16) & 0x0F; - desc[num].gran |= (gran & 0xF0); - desc[num].access = access; -} - -void write_tss(int num, uint32_t ss0, uint32_t esp0) { - uint32_t base = (uint32_t)&tss_entry; - uint32_t limit = base + sizeof(struct tss_entry); - - gdt_set_gate(num, base, limit, 0x89, 0x00); - memset(&tss_entry, 0x0, sizeof(tss_entry)); - - tss_entry.ss0 = ss0; - tss_entry.esp0 = esp0; - tss_entry.cs = 0x0B; - tss_entry.ss = 0x13; - tss_entry.ds = 0x13; - tss_entry.es = 0x13; - tss_entry.fs = 0x13; - tss_entry.gs = 0x13; - tss_entry.iomap_base = sizeof(tss_entry); -} - -void set_kernel_esp(uint32_t esp) { - tss_entry.esp0 = esp; -} - -void gdt_install(void) { - gp.limit = (sizeof(struct gdt_entry) * 6) - 1; - gp.base = (uint32_t)&desc; - - gdt_set_gate(0, 0, 0, 0, 0); - gdt_set_gate(1, 0, 0xFFFFF, 0x9A, 0xCF); - gdt_set_gate(2, 0, 0xFFFFF, 0x92, 0xCF); - gdt_set_gate(3, 0, 0xFFFFF, 0xFA, 0xCF); - gdt_set_gate(4, 0, 0xFFFFF, 0xF2, 0xCF); - - uint32_t esp; - __asm__ volatile("movl %%esp, %0" : "=r"(esp)); - write_tss(5, 0x10, esp); - - flush_gdt(); - flush_tss(); -} diff --git a/arch/i386/boot/idt.c b/arch/i386/boot/idt.c deleted file mode 100644 index 7b9401d..0000000 --- a/arch/i386/boot/idt.c +++ /dev/null @@ -1,162 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -__attribute__((aligned(0x10))) -struct idt_entry idt[256]; -struct idt_ptr idtr; - -const 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 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) { - case 0x00: - panic("Division by zero in kernel address space"); - halt_catch_fire(frame); - case 0x06: - panic("Invalid opcode in kernel address space"); - halt_catch_fire(frame); - case 0x08: - panic("Double fault in interrupt handler"); - halt_catch_fire(frame); - case 0x0D: - panic("Protection fault in kernel address space"); - halt_catch_fire(frame); - case 0x0E: - page_fault_handler(frame); - 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); - } else { - switch (frame.vector) { - case 0x80: - handle_syscall(&frame); - break; - default: - panic("Unmapped interrupt"); - 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); - desc->reserved = 0; - desc->kernel_cs = cs; - desc->flags = flags; -} - -void idt_install(void) { - idtr.limit = (uint16_t)sizeof(struct idt_entry) * 256 - 1; - idtr.base = (uint32_t)idt; - - idt_set_gate(0x0, isr_stub_0, 0x08, IDT_EXCEPTION); - idt_set_gate(0x1, isr_stub_1, 0x08, IDT_EXCEPTION); - idt_set_gate(0x2, isr_stub_2, 0x08, IDT_EXCEPTION); - idt_set_gate(0x3, isr_stub_3, 0x08, IDT_EXCEPTION); - idt_set_gate(0x4, isr_stub_4, 0x08, IDT_EXCEPTION); - idt_set_gate(0x5, isr_stub_5, 0x08, IDT_EXCEPTION); - idt_set_gate(0x6, isr_stub_6, 0x08, IDT_EXCEPTION); - idt_set_gate(0x7, isr_stub_7, 0x08, IDT_EXCEPTION); - idt_set_gate(0x8, isr_stub_8, 0x08, IDT_EXCEPTION); - idt_set_gate(0x9, isr_stub_9, 0x08, IDT_EXCEPTION); - idt_set_gate(0xA, isr_stub_10, 0x08, IDT_EXCEPTION); - idt_set_gate(0xB, isr_stub_11, 0x08, IDT_EXCEPTION); - idt_set_gate(0xC, isr_stub_12, 0x08, IDT_EXCEPTION); - idt_set_gate(0xD, isr_stub_13, 0x08, IDT_EXCEPTION); - idt_set_gate(0xE, isr_stub_14, 0x08, IDT_EXCEPTION); - idt_set_gate(0xF, isr_stub_15, 0x08, IDT_EXCEPTION); - idt_set_gate(0x10, isr_stub_16, 0x08, IDT_EXCEPTION); - idt_set_gate(0x11, isr_stub_17, 0x08, IDT_EXCEPTION); - idt_set_gate(0x12, isr_stub_18, 0x08, IDT_EXCEPTION); - idt_set_gate(0x13, isr_stub_19, 0x08, IDT_EXCEPTION); - idt_set_gate(0x14, isr_stub_20, 0x08, IDT_EXCEPTION); - idt_set_gate(0x15, isr_stub_21, 0x08, IDT_EXCEPTION); - idt_set_gate(0x16, isr_stub_22, 0x08, IDT_EXCEPTION); - idt_set_gate(0x17, isr_stub_23, 0x08, IDT_EXCEPTION); - idt_set_gate(0x18, isr_stub_24, 0x08, IDT_EXCEPTION); - idt_set_gate(0x19, isr_stub_25, 0x08, IDT_EXCEPTION); - idt_set_gate(0x1A, isr_stub_26, 0x08, IDT_EXCEPTION); - idt_set_gate(0x1B, isr_stub_27, 0x08, IDT_EXCEPTION); - idt_set_gate(0x1C, isr_stub_28, 0x08, IDT_EXCEPTION); - idt_set_gate(0x1D, isr_stub_29, 0x08, IDT_EXCEPTION); - idt_set_gate(0x1E, isr_stub_30, 0x08, IDT_EXCEPTION); - idt_set_gate(0x1F, isr_stub_31, 0x08, IDT_EXCEPTION); - - idt_set_gate(0x20, irq_stub_0, 0x08, IDT_INTERRUPT); - idt_set_gate(0x21, irq_stub_1, 0x08, IDT_INTERRUPT); - idt_set_gate(0x22, irq_stub_2, 0x08, IDT_INTERRUPT); - idt_set_gate(0x23, irq_stub_3, 0x08, IDT_INTERRUPT); - idt_set_gate(0x24, irq_stub_4, 0x08, IDT_INTERRUPT); - idt_set_gate(0x25, irq_stub_5, 0x08, IDT_INTERRUPT); - idt_set_gate(0x26, irq_stub_6, 0x08, IDT_INTERRUPT); - idt_set_gate(0x27, irq_stub_7, 0x08, IDT_INTERRUPT); - idt_set_gate(0x28, irq_stub_8, 0x08, IDT_INTERRUPT); - idt_set_gate(0x29, irq_stub_9, 0x08, IDT_INTERRUPT); - idt_set_gate(0x2A, irq_stub_10, 0x08, IDT_INTERRUPT); - idt_set_gate(0x2B, irq_stub_11, 0x08, IDT_INTERRUPT); - idt_set_gate(0x2C, irq_stub_12, 0x08, IDT_INTERRUPT); - idt_set_gate(0x2D, irq_stub_13, 0x08, IDT_INTERRUPT); - idt_set_gate(0x2E, irq_stub_14, 0x08, IDT_INTERRUPT); - idt_set_gate(0x2F, irq_stub_15, 0x08, IDT_INTERRUPT); - - idt_set_gate(0x80, syscall_stub, 0x08, IDT_INTERRUPT); - - __asm__ volatile("lidt %0" : : "memory"(idtr)); -} diff --git a/arch/i386/boot/isr.s b/arch/i386/boot/isr.s deleted file mode 100644 index 55db35e..0000000 --- a/arch/i386/boot/isr.s +++ /dev/null @@ -1,129 +0,0 @@ -.section .text - -.macro isr_err_stub num -.global isr_stub_\num -.type isr_stub_\num, @function -isr_stub_\num: - cli - pushl $\num - jmp isr_frame_asm -.endm -.macro isr_no_err_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+32 - jmp isr_frame_asm -.endm - -.global syscall_stub -syscall_stub: - cli - pushl $0 - pushl $0x80 - jmp isr_frame_asm - -isr_frame_asm: - pushl %eax - pushl %ebx - pushl %ecx - pushl %edx - pushl %esi - pushl %edi - - movl %cr0, %eax - pushl %eax - movl %cr2, %eax - pushl %eax - movl %cr3, %eax - pushl %eax - movl %cr4, %eax - pushl %eax - - pushl %esp - call set_kernel_esp - addl $4, %esp - - cld - call interrupt_handler - - popl %eax - movl %eax, %cr4 - popl %eax - movl %eax, %cr3 - popl %eax - movl %eax, %cr2 - popl %eax - movl %eax, %cr0 - - popl %edi - popl %esi - popl %edx - popl %ecx - popl %ebx - popl %eax - addl $8, %esp - - iret - -isr_no_err_stub 0 -isr_no_err_stub 1 -isr_no_err_stub 2 -isr_no_err_stub 3 -isr_no_err_stub 4 -isr_no_err_stub 5 -isr_no_err_stub 6 -isr_no_err_stub 7 -isr_err_stub 8 -isr_no_err_stub 9 -isr_err_stub 10 -isr_err_stub 11 -isr_err_stub 12 -isr_err_stub 13 -isr_err_stub 14 -isr_no_err_stub 15 -isr_no_err_stub 16 -isr_err_stub 17 -isr_no_err_stub 18 -isr_no_err_stub 19 -isr_no_err_stub 20 -isr_err_stub 21 -isr_no_err_stub 22 -isr_no_err_stub 23 -isr_no_err_stub 24 -isr_no_err_stub 25 -isr_no_err_stub 26 -isr_no_err_stub 27 -isr_no_err_stub 28 -isr_err_stub 29 -isr_err_stub 30 -isr_no_err_stub 31 - -irq_stub 0 -irq_stub 1 -irq_stub 2 -irq_stub 3 -irq_stub 4 -irq_stub 5 -irq_stub 6 -irq_stub 7 -irq_stub 8 -irq_stub 9 -irq_stub 10 -irq_stub 11 -irq_stub 12 -irq_stub 13 -irq_stub 14 -irq_stub 15 diff --git a/arch/i386/include/kernel/asm.h b/arch/i386/include/kernel/asm.h index 33ec3d7..615da74 100644 --- a/arch/i386/include/kernel/asm.h +++ b/arch/i386/include/kernel/asm.h @@ -1,6 +1,90 @@ #ifndef I386_ASM_H #define I386_ASM_H +#include + +struct regs { + uint32_t cr4; + uint32_t cr3; + uint32_t cr2; + uint32_t cr0; + + uint32_t edi; + uint32_t esi; + uint32_t edx; + uint32_t ecx; + uint32_t ebx; + uint32_t eax; + + uint32_t isr_vector; + uint32_t isr_err; + uint32_t eip; + uint32_t cs; + uint32_t eflags; +} __attribute__((packed)); + +void isr_stub_0(void); +void isr_stub_1(void); +void isr_stub_2(void); +void isr_stub_3(void); +void isr_stub_4(void); +void isr_stub_5(void); +void isr_stub_6(void); +void isr_stub_7(void); +void isr_stub_8(void); +void isr_stub_9(void); +void isr_stub_10(void); +void isr_stub_11(void); +void isr_stub_12(void); +void isr_stub_13(void); +void isr_stub_14(void); +void isr_stub_15(void); +void isr_stub_16(void); +void isr_stub_17(void); +void isr_stub_18(void); +void isr_stub_19(void); +void isr_stub_20(void); +void isr_stub_21(void); +void isr_stub_22(void); +void isr_stub_23(void); +void isr_stub_24(void); +void isr_stub_25(void); +void isr_stub_26(void); +void isr_stub_27(void); +void isr_stub_28(void); +void isr_stub_29(void); +void isr_stub_30(void); +void isr_stub_31(void); + +void irq_stub_0(void); +void irq_stub_1(void); +void irq_stub_2(void); +void irq_stub_3(void); +void irq_stub_4(void); +void irq_stub_5(void); +void irq_stub_6(void); +void irq_stub_7(void); +void irq_stub_8(void); +void irq_stub_9(void); +void irq_stub_10(void); +void irq_stub_11(void); +void irq_stub_12(void); +void irq_stub_13(void); +void irq_stub_14(void); +void irq_stub_15(void); + +void syscall_stub(void); + +static inline void outb(uint16_t port, uint8_t value) { + __asm__ volatile("outb %0, %1" : : "a"(value), "Nd"(port)); +} + +static inline uint8_t inb(uint16_t port) { + uint8_t ret; + __asm__ volatile("inb %1, %0" : "=a"(ret) : "Nd"(port)); + return ret; +} + static inline void enable_ints(void) { __asm__ volatile("sti"); return; diff --git a/arch/i386/include/kernel/idt.h b/arch/i386/include/kernel/idt.h index 6873a3b..29ec39f 100644 --- a/arch/i386/include/kernel/idt.h +++ b/arch/i386/include/kernel/idt.h @@ -3,7 +3,6 @@ #include -// IDT Flags #define SEGMENT_PRESENT 0x80 #define SEGMENT_RING0 0x00 #define SEGMENT_RING3 0x60 diff --git a/arch/i386/include/kernel/isr.h b/arch/i386/include/kernel/isr.h deleted file mode 100644 index 4e21f8f..0000000 --- a/arch/i386/include/kernel/isr.h +++ /dev/null @@ -1,78 +0,0 @@ -#ifndef I386_ISR_H -#define I386_ISR_H - -#include - -struct isr_frame { - uint32_t cr4; - uint32_t cr3; - uint32_t cr2; - uint32_t cr0; - - uint32_t edi; - uint32_t esi; - uint32_t edx; - uint32_t ecx; - uint32_t ebx; - uint32_t eax; - - uint32_t vector; - uint32_t errno; - uint32_t eip; - uint32_t cs; - uint32_t eflags; -} __attribute__((packed)); - -extern void isr_stub_0(void); -extern void isr_stub_1(void); -extern void isr_stub_2(void); -extern void isr_stub_3(void); -extern void isr_stub_4(void); -extern void isr_stub_5(void); -extern void isr_stub_6(void); -extern void isr_stub_7(void); -extern void isr_stub_8(void); -extern void isr_stub_9(void); -extern void isr_stub_10(void); -extern void isr_stub_11(void); -extern void isr_stub_12(void); -extern void isr_stub_13(void); -extern void isr_stub_14(void); -extern void isr_stub_15(void); -extern void isr_stub_16(void); -extern void isr_stub_17(void); -extern void isr_stub_18(void); -extern void isr_stub_19(void); -extern void isr_stub_20(void); -extern void isr_stub_21(void); -extern void isr_stub_22(void); -extern void isr_stub_23(void); -extern void isr_stub_24(void); -extern void isr_stub_25(void); -extern void isr_stub_26(void); -extern void isr_stub_27(void); -extern void isr_stub_28(void); -extern void isr_stub_29(void); -extern void isr_stub_30(void); -extern void isr_stub_31(void); - -extern void irq_stub_0(void); -extern void irq_stub_1(void); -extern void irq_stub_2(void); -extern void irq_stub_3(void); -extern void irq_stub_4(void); -extern void irq_stub_5(void); -extern void irq_stub_6(void); -extern void irq_stub_7(void); -extern void irq_stub_8(void); -extern void irq_stub_9(void); -extern void irq_stub_10(void); -extern void irq_stub_11(void); -extern void irq_stub_12(void); -extern void irq_stub_13(void); -extern void irq_stub_14(void); -extern void irq_stub_15(void); - -extern void syscall_stub(void); - -#endif diff --git a/arch/i386/include/kernel/keyboard.h b/arch/i386/include/kernel/keyboard.h index 8f39a70..7b63993 100644 --- a/arch/i386/include/kernel/keyboard.h +++ b/arch/i386/include/kernel/keyboard.h @@ -1,7 +1,6 @@ #ifndef I386_KEYBOARD_H #define I386_KEYBOARD_H -#include #include #define KB_STAT 0x64 @@ -28,6 +27,6 @@ #define KB_DEL 0xE9 char keyboard_getchar(void); -void keyboard_handler(struct isr_frame *frame); +void keyboard_handler(void); #endif diff --git a/arch/i386/include/kernel/paging.h b/arch/i386/include/kernel/paging.h index bb79d09..7f820e8 100644 --- a/arch/i386/include/kernel/paging.h +++ b/arch/i386/include/kernel/paging.h @@ -1,7 +1,7 @@ #ifndef I386_PAGING_H #define I386_PAGING_H -#include +#include #include #include #include @@ -25,21 +25,11 @@ #define PAGE_SIZE 4096 -#define DMA_BITMAP_SZ 128 -#define BDY_BITMAP_SZ 32640 - -struct pfa_buddy { - uintptr_t start; - uintptr_t *bitmap; - uint8_t size; - struct list_head list; -}; - -void load_page_dir(uintptr_t pd_addr); -void enable_paging(void); +uint32_t* init_page_table(uint32_t flags); +void enable_paging(uintptr_t pd_addr); void paging_init(void); -void page_fault_handler(struct isr_frame *frame); +void page_fault_handler(struct regs *regs); uint32_t get_vaddr(uintptr_t paddr); diff --git a/arch/i386/include/kernel/pic.h b/arch/i386/include/kernel/pic.h index ca3cc99..2b757ee 100644 --- a/arch/i386/include/kernel/pic.h +++ b/arch/i386/include/kernel/pic.h @@ -1,8 +1,7 @@ #ifndef I386_PIC_H #define I386_PIC_H -#include -#include +#include #include #define PIC1 0x20 @@ -27,16 +26,6 @@ #define PIC_READ_IRR 0x0A #define PIC_READ_ISR 0x0B -static inline void outb(uint16_t port, uint8_t value) { - __asm__ volatile("outb %0, %1" : : "a"(value), "Nd"(port)); -} - -static inline uint8_t inb(uint16_t port) { - uint8_t ret; - __asm__ volatile("inb %1, %0" : "=a"(ret) : "Nd"(port)); - return ret; -} - static inline void io_wait(void) { outb(0x80, 0); } @@ -46,8 +35,8 @@ void pic_remap(void); uint16_t pic_get_irr(void); uint16_t pic_get_isr(void); -void register_irq_handler(uint8_t irq, void (*handler)(struct isr_frame *frame)); -void irq_dispatch(struct isr_frame *frame); +void register_irq_handler(uint8_t irq, void (*handler)(struct regs *regs)); +void irq_dispatch(struct regs *regs); void irq_set_mask(uint8_t irq); void irq_clear_mask(uint8_t irq); diff --git a/arch/i386/include/kernel/syscall.h b/arch/i386/include/kernel/syscall.h index 788e5da..88ee59a 100644 --- a/arch/i386/include/kernel/syscall.h +++ b/arch/i386/include/kernel/syscall.h @@ -1,7 +1,8 @@ #ifndef I386_SYSCALL_H #define I386_SYSCALL_H -#include +#include +#include #include // Unix standard calls @@ -23,11 +24,10 @@ #define SYS_LINK 16 #define SYS_MKDIR 17 #define SYS_CLOSE 18 +#define SYS_EXEC 19 #define SYS_REBOOT 88 -int handle_syscall(struct isr_frame *frame); -void dump_reg(struct isr_frame *frame); -void dump_stack(uintptr_t esp, size_t len); +int handle_syscall(struct regs *regs); #endif diff --git a/arch/i386/include/kernel/timer.h b/arch/i386/include/kernel/timer.h index 0d90369..1bc2855 100644 --- a/arch/i386/include/kernel/timer.h +++ b/arch/i386/include/kernel/timer.h @@ -1,9 +1,9 @@ #ifndef I386_TIMER_H #define I386_TIMER_H -#include +#include -void timer_handler(struct isr_frame *frame); +void timer_handler(struct regs *regs); void timer_init(void); #endif diff --git a/arch/i386/kernel/gdt.c b/arch/i386/kernel/gdt.c new file mode 100644 index 0000000..c0cf127 --- /dev/null +++ b/arch/i386/kernel/gdt.c @@ -0,0 +1,58 @@ +#include +#include +#include + +struct gdt_entry desc[6]; +struct gdt_ptr gp; +struct tss_entry tss_entry; + +void gdt_set_gate(int num, uint32_t base, uint32_t limit, uint8_t access, uint8_t gran) { + desc[num].base_low = (base & 0xFFFF); + desc[num].base_middle = (base >> 16) & 0xFF; + desc[num].base_high = (base >> 24) & 0xFF; + + desc[num].limit_low = (limit & 0xFFFF); + desc[num].gran = (limit >> 16) & 0x0F; + desc[num].gran |= (gran & 0xF0); + desc[num].access = access; +} + +void write_tss(int num, uint32_t ss0, uint32_t esp0) { + uint32_t base = (uint32_t)&tss_entry; + uint32_t limit = base + sizeof(struct tss_entry); + + gdt_set_gate(num, base, limit, 0x89, 0x00); + memset(&tss_entry, 0x0, sizeof(tss_entry)); + + tss_entry.ss0 = ss0; + tss_entry.esp0 = esp0; + tss_entry.cs = 0x0B; + tss_entry.ss = 0x13; + tss_entry.ds = 0x13; + tss_entry.es = 0x13; + tss_entry.fs = 0x13; + tss_entry.gs = 0x13; + tss_entry.iomap_base = sizeof(tss_entry); +} + +void set_kernel_esp(uint32_t esp) { + tss_entry.esp0 = esp; +} + +void gdt_install(void) { + gp.limit = (sizeof(struct gdt_entry) * 6) - 1; + gp.base = (uint32_t)&desc; + + gdt_set_gate(0, 0, 0, 0, 0); + gdt_set_gate(1, 0, 0xFFFFF, 0x9A, 0xCF); + gdt_set_gate(2, 0, 0xFFFFF, 0x92, 0xCF); + gdt_set_gate(3, 0, 0xFFFFF, 0xFA, 0xCF); + gdt_set_gate(4, 0, 0xFFFFF, 0xF2, 0xCF); + + uint32_t esp; + __asm__ volatile("movl %%esp, %0" : "=r"(esp)); + write_tss(5, 0x10, esp); + + flush_gdt(); + flush_tss(); +} diff --git a/arch/i386/kernel/idt.c b/arch/i386/kernel/idt.c new file mode 100644 index 0000000..5c0766c --- /dev/null +++ b/arch/i386/kernel/idt.c @@ -0,0 +1,152 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +__attribute__((aligned(0x10))) +struct idt_entry idt[256]; +struct idt_ptr idtr; + +const 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" +}; + +void exception_handler(struct regs *regs) { + switch (regs->isr_vector) { + case 0x00: + panic("Division by zero in kernel address space"); + break; + case 0x06: + panic("Invalid opcode in kernel address space"); + break; + case 0x08: + panic("Double fault in interrupt handler"); + break; + case 0x0D: + panic("Protection fault in kernel address space"); + break; + case 0x0E: + page_fault_handler(regs); + break; + default: + panic("Unhandled exception"); + } +} + +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 (regs.isr_vector) { + case 0x80: + handle_syscall(®s); + break; + default: + panic("Unmapped interrupt"); + } + } +} + +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); + desc->reserved = 0; + desc->kernel_cs = cs; + desc->flags = flags; +} + +void idt_install(void) { + idtr.limit = (uint16_t)sizeof(struct idt_entry) * 256 - 1; + idtr.base = (uint32_t)idt; + + idt_set_gate(0x0, isr_stub_0, 0x08, IDT_EXCEPTION); + idt_set_gate(0x1, isr_stub_1, 0x08, IDT_EXCEPTION); + idt_set_gate(0x2, isr_stub_2, 0x08, IDT_EXCEPTION); + idt_set_gate(0x3, isr_stub_3, 0x08, IDT_EXCEPTION); + idt_set_gate(0x4, isr_stub_4, 0x08, IDT_EXCEPTION); + idt_set_gate(0x5, isr_stub_5, 0x08, IDT_EXCEPTION); + idt_set_gate(0x6, isr_stub_6, 0x08, IDT_EXCEPTION); + idt_set_gate(0x7, isr_stub_7, 0x08, IDT_EXCEPTION); + idt_set_gate(0x8, isr_stub_8, 0x08, IDT_EXCEPTION); + idt_set_gate(0x9, isr_stub_9, 0x08, IDT_EXCEPTION); + idt_set_gate(0xA, isr_stub_10, 0x08, IDT_EXCEPTION); + idt_set_gate(0xB, isr_stub_11, 0x08, IDT_EXCEPTION); + idt_set_gate(0xC, isr_stub_12, 0x08, IDT_EXCEPTION); + idt_set_gate(0xD, isr_stub_13, 0x08, IDT_EXCEPTION); + idt_set_gate(0xE, isr_stub_14, 0x08, IDT_EXCEPTION); + idt_set_gate(0xF, isr_stub_15, 0x08, IDT_EXCEPTION); + idt_set_gate(0x10, isr_stub_16, 0x08, IDT_EXCEPTION); + idt_set_gate(0x11, isr_stub_17, 0x08, IDT_EXCEPTION); + idt_set_gate(0x12, isr_stub_18, 0x08, IDT_EXCEPTION); + idt_set_gate(0x13, isr_stub_19, 0x08, IDT_EXCEPTION); + idt_set_gate(0x14, isr_stub_20, 0x08, IDT_EXCEPTION); + idt_set_gate(0x15, isr_stub_21, 0x08, IDT_EXCEPTION); + idt_set_gate(0x16, isr_stub_22, 0x08, IDT_EXCEPTION); + idt_set_gate(0x17, isr_stub_23, 0x08, IDT_EXCEPTION); + idt_set_gate(0x18, isr_stub_24, 0x08, IDT_EXCEPTION); + idt_set_gate(0x19, isr_stub_25, 0x08, IDT_EXCEPTION); + idt_set_gate(0x1A, isr_stub_26, 0x08, IDT_EXCEPTION); + idt_set_gate(0x1B, isr_stub_27, 0x08, IDT_EXCEPTION); + idt_set_gate(0x1C, isr_stub_28, 0x08, IDT_EXCEPTION); + idt_set_gate(0x1D, isr_stub_29, 0x08, IDT_EXCEPTION); + idt_set_gate(0x1E, isr_stub_30, 0x08, IDT_EXCEPTION); + idt_set_gate(0x1F, isr_stub_31, 0x08, IDT_EXCEPTION); + + idt_set_gate(0x20, irq_stub_0, 0x08, IDT_INTERRUPT); + idt_set_gate(0x21, irq_stub_1, 0x08, IDT_INTERRUPT); + idt_set_gate(0x22, irq_stub_2, 0x08, IDT_INTERRUPT); + idt_set_gate(0x23, irq_stub_3, 0x08, IDT_INTERRUPT); + idt_set_gate(0x24, irq_stub_4, 0x08, IDT_INTERRUPT); + idt_set_gate(0x25, irq_stub_5, 0x08, IDT_INTERRUPT); + idt_set_gate(0x26, irq_stub_6, 0x08, IDT_INTERRUPT); + idt_set_gate(0x27, irq_stub_7, 0x08, IDT_INTERRUPT); + idt_set_gate(0x28, irq_stub_8, 0x08, IDT_INTERRUPT); + idt_set_gate(0x29, irq_stub_9, 0x08, IDT_INTERRUPT); + idt_set_gate(0x2A, irq_stub_10, 0x08, IDT_INTERRUPT); + idt_set_gate(0x2B, irq_stub_11, 0x08, IDT_INTERRUPT); + idt_set_gate(0x2C, irq_stub_12, 0x08, IDT_INTERRUPT); + idt_set_gate(0x2D, irq_stub_13, 0x08, IDT_INTERRUPT); + idt_set_gate(0x2E, irq_stub_14, 0x08, IDT_INTERRUPT); + idt_set_gate(0x2F, irq_stub_15, 0x08, IDT_INTERRUPT); + + idt_set_gate(0x80, syscall_stub, 0x08, IDT_INTERRUPT); + + __asm__ volatile("lidt %0" : : "memory"(idtr)); +} diff --git a/arch/i386/kernel/isr.s b/arch/i386/kernel/isr.s new file mode 100644 index 0000000..55db35e --- /dev/null +++ b/arch/i386/kernel/isr.s @@ -0,0 +1,129 @@ +.section .text + +.macro isr_err_stub num +.global isr_stub_\num +.type isr_stub_\num, @function +isr_stub_\num: + cli + pushl $\num + jmp isr_frame_asm +.endm +.macro isr_no_err_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+32 + jmp isr_frame_asm +.endm + +.global syscall_stub +syscall_stub: + cli + pushl $0 + pushl $0x80 + jmp isr_frame_asm + +isr_frame_asm: + pushl %eax + pushl %ebx + pushl %ecx + pushl %edx + pushl %esi + pushl %edi + + movl %cr0, %eax + pushl %eax + movl %cr2, %eax + pushl %eax + movl %cr3, %eax + pushl %eax + movl %cr4, %eax + pushl %eax + + pushl %esp + call set_kernel_esp + addl $4, %esp + + cld + call interrupt_handler + + popl %eax + movl %eax, %cr4 + popl %eax + movl %eax, %cr3 + popl %eax + movl %eax, %cr2 + popl %eax + movl %eax, %cr0 + + popl %edi + popl %esi + popl %edx + popl %ecx + popl %ebx + popl %eax + addl $8, %esp + + iret + +isr_no_err_stub 0 +isr_no_err_stub 1 +isr_no_err_stub 2 +isr_no_err_stub 3 +isr_no_err_stub 4 +isr_no_err_stub 5 +isr_no_err_stub 6 +isr_no_err_stub 7 +isr_err_stub 8 +isr_no_err_stub 9 +isr_err_stub 10 +isr_err_stub 11 +isr_err_stub 12 +isr_err_stub 13 +isr_err_stub 14 +isr_no_err_stub 15 +isr_no_err_stub 16 +isr_err_stub 17 +isr_no_err_stub 18 +isr_no_err_stub 19 +isr_no_err_stub 20 +isr_err_stub 21 +isr_no_err_stub 22 +isr_no_err_stub 23 +isr_no_err_stub 24 +isr_no_err_stub 25 +isr_no_err_stub 26 +isr_no_err_stub 27 +isr_no_err_stub 28 +isr_err_stub 29 +isr_err_stub 30 +isr_no_err_stub 31 + +irq_stub 0 +irq_stub 1 +irq_stub 2 +irq_stub 3 +irq_stub 4 +irq_stub 5 +irq_stub 6 +irq_stub 7 +irq_stub 8 +irq_stub 9 +irq_stub 10 +irq_stub 11 +irq_stub 12 +irq_stub 13 +irq_stub 14 +irq_stub 15 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 -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 +#include +#include +#include +#include #include #include -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); diff --git a/arch/i386/make.config b/arch/i386/make.config index 9d74c33..91b665d 100644 --- a/arch/i386/make.config +++ b/arch/i386/make.config @@ -4,9 +4,9 @@ KERNEL_ARCH_LDFLAGS= KERNEL_ARCH_LIBS= KERNEL_ARCH_OBJS=$(ARCHDIR)/boot/boot.o \ - $(ARCHDIR)/boot/isr.o \ - $(ARCHDIR)/boot/idt.o \ - $(ARCHDIR)/boot/gdt.o \ + $(ARCHDIR)/kernel/idt.o \ + $(ARCHDIR)/kernel/gdt.o \ + $(ARCHDIR)/kernel/isr.o \ $(ARCHDIR)/kernel/framebuffer.o \ $(ARCHDIR)/kernel/multiboot.o \ $(ARCHDIR)/kernel/keyboard.o \ -- cgit v1.2.3