diff options
Diffstat (limited to 'kernel/cpu')
-rw-r--r-- | kernel/cpu/arch_inst.h | 11 | ||||
-rw-r--r-- | kernel/cpu/arch_inst.s | 60 | ||||
-rw-r--r-- | kernel/cpu/gdt.c | 4 | ||||
-rw-r--r-- | kernel/cpu/idt.c | 19 |
4 files changed, 80 insertions, 14 deletions
diff --git a/kernel/cpu/arch_inst.h b/kernel/cpu/arch_inst.h new file mode 100644 index 0000000..54faffb --- /dev/null +++ b/kernel/cpu/arch_inst.h @@ -0,0 +1,11 @@ +#include <stdint.h> +uintptr_t get_current_sp(void); +uintptr_t get_current_sbp(void); +__attribute__((__noreturn__)) void halt(void); +uintptr_t get_cr2(void); +void flush_tlb(void); +void set_sp(uintptr_t); +void set_sbp(uintptr_t); +void set_cr3(uintptr_t); +uintptr_t get_cr3(void); +void enable_paging(void); diff --git a/kernel/cpu/arch_inst.s b/kernel/cpu/arch_inst.s new file mode 100644 index 0000000..aaf34b6 --- /dev/null +++ b/kernel/cpu/arch_inst.s @@ -0,0 +1,60 @@ +.intel_syntax noprefix +.global get_current_sp +.global get_current_sbp +.global halt +.global get_cr2 +.global set_sp +.global set_sbp +.global flush_tlb +.global set_cr3 +.global get_cr3 +.global enable_paging + +get_current_sp: + mov eax, esp + sub eax, 4 + ret + +get_current_sbp: + mov eax, ebp + ret + +set_sp: + mov ecx, [esp] # store the return address in ecx + mov eax, [esp + 4] + mov esp, eax + jmp ecx # jump to the return address instead of doing a ret as the stack values may have changed + +set_sbp: + mov eax, [esp + 4] + mov ebp, eax + ret + +halt: + hlt + jmp $ + ret + +get_cr2: + mov eax, cr2 + ret + +flush_tlb: + mov eax, cr3 + mov cr3, eax + ret + +set_cr3: + mov eax, [esp + 4] + mov cr3, eax + ret + +get_cr3: + mov eax, cr3 + ret + +enable_paging: + mov eax, cr0 + or eax, 0b10000000000000000000000000000000 + mov cr0, eax + ret diff --git a/kernel/cpu/gdt.c b/kernel/cpu/gdt.c index 2f9f90b..d91abed 100644 --- a/kernel/cpu/gdt.c +++ b/kernel/cpu/gdt.c @@ -1,4 +1,5 @@ #include "gdt.h" +#include <cpu/arch_inst.h> #include <interrupts.h> extern void flush_tss(void); @@ -39,8 +40,7 @@ void write_tss(struct GDT_Entry *gdt_entry) { memset(&tss_entry, 0, sizeof tss_entry); tss_entry.ss0 = GDT_KERNEL_DATA_SEGMENT * GDT_ENTRY_SIZE; - register u32 esp asm("esp"); - tss_entry.esp0 = esp; + tss_entry.esp0 = get_current_sp(); } void gdt_init() { diff --git a/kernel/cpu/idt.c b/kernel/cpu/idt.c index 3d866e5..ec7ca63 100644 --- a/kernel/cpu/idt.c +++ b/kernel/cpu/idt.c @@ -1,4 +1,6 @@ +#include <cpu/arch_inst.h> #include <cpu/idt.h> +#include <interrupts.h> #include <sched/scheduler.h> #include <stdio.h> @@ -52,25 +54,20 @@ void general_protection_fault(reg_t *regs) { kprintf(" Error Code: %x\n", regs->error_code); kprintf("Instruction Pointer: %x\n", regs->eip); dump_backtrace(12); - asm("hlt"); - for (;;) - ; + halt(); EOI(0xD - 8); } void double_fault(registers_t *regs) { (void)regs; klog("DOUBLE FAULT", LOG_ERROR); - asm("hlt"); - for (;;) - ; + halt(); } void page_fault(reg_t *regs) { - volatile uint32_t cr2; - asm volatile("mov %%cr2, %0" : "=r"(cr2)); + uint32_t cr2 = get_cr2(); if (0xDEADC0DE == cr2) { - asm("cli"); + disable_interrupts(); EOI(0xB); process_pop_restore_context(NULL, regs); return; @@ -105,9 +102,7 @@ void page_fault(reg_t *regs) { } dump_backtrace(12); - asm("hlt"); - for (;;) - ; + halt(); } static inline void io_wait(void) { |