summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--kernel/Makefile2
-rw-r--r--kernel/cpu.c19
-rw-r--r--kernel/cpu.h2
-rw-r--r--kernel/exceptions.S55
-rw-r--r--kernel/exceptions.h7
-rw-r--r--kernel/memory.c14
-rw-r--r--rules.mk4
7 files changed, 96 insertions, 7 deletions
diff --git a/kernel/Makefile b/kernel/Makefile
index 1e6ce69..da4591d 100644
--- a/kernel/Makefile
+++ b/kernel/Makefile
@@ -19,7 +19,7 @@ LOADLIBES := -lgcc
SOBJS :=
GOBJS := entry_efi.o kprint.o serial.o port.o main.o memory.o \
- memset.o memcpy.o memmove.o memcmp.o cpu.o
+ memset.o memcpy.o memmove.o memcmp.o cpu.o exceptions.o
IOBJS :=
$(SOBJS): CFLAGS += -fPIC
diff --git a/kernel/cpu.c b/kernel/cpu.c
index db4108f..ed1a04e 100644
--- a/kernel/cpu.c
+++ b/kernel/cpu.c
@@ -1,4 +1,5 @@
#include "cpu.h"
+#include "exceptions.h"
#include <stdint.h>
@@ -140,6 +141,7 @@ static void gdt_init(void)
"mov %w2, %%es\n"
"mov %w2, %%fs\n"
"mov %w2, %%gs\n"
+ "mov %w2, %%ss\n"
// make a far return frame on the stack
// [ss] @rsp+8
// [rip] @rsp
@@ -183,11 +185,24 @@ void cpu_init(void)
{
gdt_init();
idt_init();
+ exceptions_init();
}
-void isr_install(int vec, void *isr, int ist)
+void exceptions_init(void)
{
- set_idt(vec, CODE_SEG_INDEX << 3, (uint64_t)isr, INT64_GATE);
+ isr_install(PAGE_FAULT_VECTOR, &page_fault_isr, 0, 0);
+}
+
+void isr_install(int vec, void (*isr)(void), int trap, int ist)
+{
+ enum gate_descriptor_type type = INT64_GATE;
+
+ if (trap)
+ {
+ type = TRAP64_GATE;
+ }
+
+ set_idt(vec, CODE_SEG_INDEX << 3, (uint64_t)isr, type);
if (ist)
{
set_ist(vec, ist);
diff --git a/kernel/cpu.h b/kernel/cpu.h
index 15cf44a..56a4073 100644
--- a/kernel/cpu.h
+++ b/kernel/cpu.h
@@ -2,7 +2,7 @@
void cpu_init(void);
-void isr_install(int vec, void *isr, int ist);
+void isr_install(int vec, void (*isr)(void), int ist, int trap);
void ist_install(int ist, void *stack);
void int_enable(void);
diff --git a/kernel/exceptions.S b/kernel/exceptions.S
new file mode 100644
index 0000000..03402f2
--- /dev/null
+++ b/kernel/exceptions.S
@@ -0,0 +1,55 @@
+.extern page_fault_handler
+
+.global page_fault_isr
+.type page_fault_isr, @function
+page_fault_isr:
+ /* just in case something tried to be clever before */
+ cld
+ /* push param registers */
+ push %rdi
+ push %rsi
+ push %rdx
+ push %rcx
+ push %r8
+ push %r9
+ /* collect parameters for page fault handler */
+ mov 48(%rsp), %rdi /* error code is first parameter */
+ mov %cr2, %rsi /* PFLA is next parameter */
+ /* caller-saved registers */
+ push %rax
+ push %r10
+ push %r11
+ /* callee-saved registers */
+ push %rbx
+ push %rbp
+ push %r12
+ push %r13
+ push %r14
+ push %r15
+ /* stack has to be aligned */
+ mov %rsp, %rbp
+ and $-16, %rsp
+ call page_fault_handler
+ mov %rbp, %rsp
+ /* TODO: test for error code here and panic() */
+ pop %r15
+ pop %r14
+ pop %r13
+ pop %r12
+ pop %rbp
+ pop %rbx
+ pop %r11
+ pop %r10
+ pop %rax
+ pop %r9
+ pop %r8
+ pop %rcx
+ pop %rdx
+ pop %rsi
+ pop %rdi
+ /* unwind the error code from the stack */
+ add $8, %rsp
+ /* leave the isr */
+ iretq
+.size page_fault_isr, . - page_fault_isr
+
diff --git a/kernel/exceptions.h b/kernel/exceptions.h
new file mode 100644
index 0000000..5d22284
--- /dev/null
+++ b/kernel/exceptions.h
@@ -0,0 +1,7 @@
+#pragma once
+
+extern void page_fault_isr(void);
+
+#define PAGE_FAULT_VECTOR 0xe
+
+void exceptions_init(void);
diff --git a/kernel/memory.c b/kernel/memory.c
index d9bc8c3..f233b85 100644
--- a/kernel/memory.c
+++ b/kernel/memory.c
@@ -1,4 +1,5 @@
#include "memory.h"
+#include "kprint.h"
#include <kernel/memory/paging.h>
@@ -326,11 +327,10 @@ void kernel_unmap_page(void *vaddr)
phys_addr_t page_alloc(void)
{
- int index;
+ int index = first_free_page_index;
- if (first_free_page_index > 0)
+ if (index > 0)
{
- index = first_free_page_index;
page_array[index].used = 1;
first_free_page_index = page_array[index].next;
}
@@ -361,3 +361,11 @@ static uint64_t *get_kernel_pm2e(void *vaddr)
{
return &kernel_pm2[kpm2_index(vaddr)];
}
+
+int page_fault_handler(uint32_t code, void *address)
+{
+ (void)code;
+ (void)address;
+ kputs("page faulmt\n");
+ return 0;
+}
diff --git a/rules.mk b/rules.mk
index 4ac15a4..2115028 100644
--- a/rules.mk
+++ b/rules.mk
@@ -29,6 +29,10 @@ COMPILE.info = $(info $$(CC) $@)
$(COMPILE.info)
@$(COMPILE.cpp) -MMD -MP
+%.o: %.S
+ $(COMPILE.info)
+ @$(COMPILE.S) -MMD -MP
+
clean:
$(info $$(RM) $(CLEANLIST))
-@$(RM) $(CLEANLIST)