summaryrefslogtreecommitdiff
path: root/kernel/cpu
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/cpu')
-rw-r--r--kernel/cpu/arch_inst.h11
-rw-r--r--kernel/cpu/arch_inst.s60
-rw-r--r--kernel/cpu/gdt.c4
-rw-r--r--kernel/cpu/idt.c19
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) {