summaryrefslogtreecommitdiffstats
path: root/arch/x86_64
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86_64')
-rw-r--r--arch/x86_64/elf.d2
-rw-r--r--arch/x86_64/gdt.c42
-rw-r--r--arch/x86_64/gdt.d2
-rw-r--r--arch/x86_64/idt.c19
-rw-r--r--arch/x86_64/idt.d2
-rw-r--r--arch/x86_64/int.S3
-rw-r--r--arch/x86_64/interrupt.h11
-rw-r--r--arch/x86_64/loadgdt.S4
-rw-r--r--arch/x86_64/paging.c35
-rw-r--r--arch/x86_64/paging.d2
-rw-r--r--arch/x86_64/serial.d2
-rw-r--r--arch/x86_64/syscall.d1
-rw-r--r--arch/x86_64/syscall_setup.S21
-rw-r--r--arch/x86_64/tables.d1
-rw-r--r--arch/x86_64/tables.h2
-rw-r--r--arch/x86_64/tasking.c93
-rw-r--r--arch/x86_64/thread.c85
-rw-r--r--arch/x86_64/thread.d3
-rw-r--r--arch/x86_64/tss.h6
19 files changed, 201 insertions, 135 deletions
diff --git a/arch/x86_64/elf.d b/arch/x86_64/elf.d
deleted file mode 100644
index f57bbe6..0000000
--- a/arch/x86_64/elf.d
+++ /dev/null
@@ -1,2 +0,0 @@
-arch/x86_64/elf.o: arch/x86_64/elf.c arch/x86_64/elf.h lib/string.h \
- usr/elf.h io/log.h mem/memory.h mem/slab.h
diff --git a/arch/x86_64/gdt.c b/arch/x86_64/gdt.c
index d996dcb..07a8097 100644
--- a/arch/x86_64/gdt.c
+++ b/arch/x86_64/gdt.c
@@ -25,14 +25,15 @@ static struct SegmentDescriptor s_gdtd[GDT_SEGMENT_COUNT] =
.limit_0_15 = 0xFFFF,
.base_0_15 = 0,
.base_16_23 = 0,
- .type = CD_SEGMENT_TYPE_CODE | CD_SEGMENT_TYPE_CODE_CONFORMING,
+ .type = CD_SEGMENT_TYPE_CODE | CD_SEGMENT_TYPE_WRITEABLE,
.s = 1,
.dpl = 0,
.p = 1,
.limit_16_19 = 0xF,
+ .avl = 0,
.l = 1,
.d_b = 0,
- .g = 0,
+ .g = 1,
.base_24_31 = 0
},
{ /* Kernel Data (64-bit RW DPL0) */
@@ -44,9 +45,10 @@ static struct SegmentDescriptor s_gdtd[GDT_SEGMENT_COUNT] =
.dpl = 0,
.p = 1,
.limit_16_19 = 0xF,
- .l = 1,
- .d_b = 0,
- .g = 0,
+ .avl = 0,
+ .l = 0,
+ .d_b = 1,
+ .g = 1,
.base_24_31 = 0
},
{ 0 }, /* User NULL */
@@ -59,36 +61,38 @@ static struct SegmentDescriptor s_gdtd[GDT_SEGMENT_COUNT] =
.dpl = 3,
.p = 1,
.limit_16_19 = 0xF,
- .l = 1,
- .d_b = 0,
- .g = 0,
+ .avl = 0,
+ .l = 0,
+ .d_b = 1,
+ .g = 1,
.base_24_31 = 0,
},
{ /* User Code (64-bit RO EX DPL3)*/
.limit_0_15 = 0xFFFF,
.base_0_15 = 0,
.base_16_23 = 0,
- .type = CD_SEGMENT_TYPE_CODE | CD_SEGMENT_TYPE_CODE_CONFORMING,
+ .type = CD_SEGMENT_TYPE_CODE | CD_SEGMENT_TYPE_WRITEABLE,
.s = 1,
.dpl = 3,
.p = 1,
.limit_16_19 = 0xF,
+ .avl = 0,
.l = 1,
.d_b = 0,
- .g = 0,
+ .g = 1,
.base_24_31 = 0,
},
{ /* TSS Low */
- .limit_0_15 = sizeof(struct TSS),
+ .limit_0_15 = 0,
.base_0_15 = 0,
.base_16_23 = 0,
.type = S_SEGMENT_TYPE_TSS_AVAIL,
- .avl = 1,
+ .avl = 0,
.s = 0,
.dpl = 0,
.p = 1,
.limit_16_19 = 0,
- .l = 1,
+ .l = 0,
.d_b = 0,
.g = 0,
.base_24_31 = 0,
@@ -118,8 +122,20 @@ x86_64_load_gdt(void)
tss_lo->base_24_31 = (tssb >> 24) & 0xFF;
tss_hi->limit_0_15 = (tssb >> 32) & 0xFFFF;
tss_hi->base_0_15 = (tssb >> 48) & 0xFFFF;
+
+ size_t tssl = sizeof(struct TSS) - 1;
+ tss_lo->limit_0_15 = tssl & 0xFFFF;
+ tss_lo->limit_16_19 = (tssl >> 16) & 0xF;
+
+ s_tss.iobp = sizeof(struct TSS);
}
x86_64_lgdt(&s_gdtr);
x86_64_flush_tss();
}
+
+void tss_set_rsp(uint8_t dpl, uintptr_t rsp)
+{
+ s_tss.rsp[dpl][0] = rsp & 0xFFFFFFFF;
+ s_tss.rsp[dpl][1] = (rsp >> 32) & 0xFFFFFFFF;
+}
diff --git a/arch/x86_64/gdt.d b/arch/x86_64/gdt.d
deleted file mode 100644
index 7b43bdb..0000000
--- a/arch/x86_64/gdt.d
+++ /dev/null
@@ -1,2 +0,0 @@
-arch/x86_64/gdt.o: arch/x86_64/gdt.c arch/x86_64/tables.h \
- arch/x86_64/tss.h
diff --git a/arch/x86_64/idt.c b/arch/x86_64/idt.c
index 567dead..05dcf43 100644
--- a/arch/x86_64/idt.c
+++ b/arch/x86_64/idt.c
@@ -5,7 +5,7 @@
PAGEALIGN
static struct InterruptTrapGate s_idtd[48];
-static struct InterruptState *(*s_int_handlers[48])(struct Registers*);
+static struct Registers *(*s_int_handlers[48])(struct Registers*);
static struct XDTR s_idtr = {
.length = sizeof(s_idtd) - 1,
.address = (uintptr_t)&s_idtd
@@ -14,13 +14,19 @@ static struct XDTR s_idtr = {
uint64_t __isr_err;
uint64_t __isr_num;
+void
+int_set_handler(uint8_t code, struct Registers *(*handler)(struct Registers*))
+{
+ if(code >= 48) return;
+ s_int_handlers[code] = handler;
+}
+
struct Registers*
irq_handle(struct Registers *state)
{
if(__isr_num < 48) {
if(s_int_handlers[__isr_num] != NULL) {
- s_int_handlers[__isr_num](state);
- return state;
+ return s_int_handlers[__isr_num](state);
}
}
klogf("Interrupt %i\nerror code %#016X\n", __isr_num, __isr_err);
@@ -52,10 +58,9 @@ x86_64_load_idt(void)
for(int i = 0; i < 22; i++)
{
uintptr_t base = __isr_stubs[i];
- klogf("INT %2i : %#016X\n", i, base);
s_idtd[i] = (struct InterruptTrapGate){
.base_0_15 = (base & 0xFFFF),
- .segment_selector = 0x10,
+ .segment_selector = 0x8,
.ist = 0,
.zero_0 = 0,
.type = 0xE,
@@ -63,8 +68,10 @@ x86_64_load_idt(void)
.dpl = 0,
.p = 1,
.base_16_31 = (base >> 16) & 0xFFFF,
- .base_32_63 = (base >> 32) & 0xFFFFFFFF
+ .base_32_63 = (base >> 32) & 0xFFFFFFFF,
+ .resv = 0
};
+ klogf("INT %2i : %#016X (%016X)\n", i, base, s_idtd[i]);
}
x86_64_lidt(&s_idtr);
}
diff --git a/arch/x86_64/idt.d b/arch/x86_64/idt.d
deleted file mode 100644
index 7e976e7..0000000
--- a/arch/x86_64/idt.d
+++ /dev/null
@@ -1,2 +0,0 @@
-arch/x86_64/idt.o: arch/x86_64/idt.c arch/x86_64/tables.h \
- arch/x86_64/cpu.h lib/jove.h io/log.h
diff --git a/arch/x86_64/int.S b/arch/x86_64/int.S
index 96c62d9..e00760a 100644
--- a/arch/x86_64/int.S
+++ b/arch/x86_64/int.S
@@ -3,6 +3,7 @@
.type x86_64_lidt @function
x86_64_lidt:
lidt (%rdi)
+ sti
retq
.macro irq_preserve
@@ -54,7 +55,6 @@ irq_stub:
movq %rax, %rsp
irq_restore
- addq $128, %rsp
iretq
.extern __isr_err
@@ -63,7 +63,6 @@ irq_stub:
.macro isr_error num:req
.type __isr\num @function
isr\num:
- subq $128, %rsp
pushq %rbx
movq 8(%rsp), %rbx
movq %rbx, __isr_err
diff --git a/arch/x86_64/interrupt.h b/arch/x86_64/interrupt.h
new file mode 100644
index 0000000..9ae63f9
--- /dev/null
+++ b/arch/x86_64/interrupt.h
@@ -0,0 +1,11 @@
+#ifndef JOVE_ARCH_INTERRUPT_H
+#define JOVE_ARCH_INTERRUPT_H 1
+
+#include "cpu.h"
+
+/**Register a handler for a specified interrupt code.
+ * @param code interrupt to handle.
+ * @param handler to call.*/
+void int_set_handler(unsigned char code, struct Registers *(*handler)(struct Registers*));
+
+#endif
diff --git a/arch/x86_64/loadgdt.S b/arch/x86_64/loadgdt.S
index e183850..a293bae 100644
--- a/arch/x86_64/loadgdt.S
+++ b/arch/x86_64/loadgdt.S
@@ -6,7 +6,7 @@ x86_64_lgdt:
pushq $0x8
leaq .reload_cs, %rax
pushq %rax
- retfq
+ lretq
.reload_cs:
movw $0x10, %ax
movw %ax, %ds
@@ -15,6 +15,7 @@ x86_64_lgdt:
movw %ax, %gs
movw %ax, %ss
retq
+.size x86_64_lgdt, . - x86_64_lgdt
.global x86_64_flush_tss
.type x86_64_flush_tss @function
@@ -22,3 +23,4 @@ x86_64_flush_tss:
movw $0x30, %ax
ltr %ax
retq
+.size x86_64_flush_tss, . - x86_64_flush_tss
diff --git a/arch/x86_64/paging.c b/arch/x86_64/paging.c
index 76b5735..29c4863 100644
--- a/arch/x86_64/paging.c
+++ b/arch/x86_64/paging.c
@@ -1,4 +1,5 @@
#include "paging.h"
+#include "interrupt.h"
#include <stddef.h>
#include "lib/jove.h"
#include "io/log.h"
@@ -129,9 +130,15 @@ mem_pd_ensure_range(struct PageDirectory *pd, uintptr_t from, uintptr_t to, uint
}
void
+mem_ensure_range_for(void *pd, uintptr_t from, uintptr_t to, bool rw, bool user)
+{
+ mem_pd_ensure_range((struct PageDirectory*)pd, from, to, 1 | (rw << 1) | (user << 2));
+}
+
+void
mem_ensure_range(uintptr_t from, uintptr_t to, bool rw, bool user)
{
- mem_pd_ensure_range(mem_current_pd, from, to, 1 | (rw << 1) | (user << 2));
+ mem_ensure_range_for(mem_current_pd, from, to, rw, user);
}
void mem_pd_new(struct PageDirectory *pd)
@@ -152,10 +159,33 @@ void mem_pd_clone(struct PageDirectory *pd, struct PageDirectory *parent)
{
mem_pd_new(pd);
for(size_t i = 0; i < 256; i++) {
-
+ //TODO: Impl pd cloning
}
}
+struct Registers*
+s_pagefault_handler(struct Registers *state)
+{
+ extern uint64_t __isr_err;
+
+ uintptr_t fault_addr = 0;
+ __asm__ volatile("movq %%cr2, %0": "=r"(fault_addr));
+
+ bool present = __isr_err & 1;
+ bool write = __isr_err & 2;
+ bool user = __isr_err & 4;
+ bool fetch = __isr_err & 16;
+
+ klogf("Page fault at %016X\n", fault_addr);
+ klogf("%s %s from a %s address\n",
+ user ? "user" : "kernel",
+ write ? "wrote" : "read",
+ present ? "present" : "non-present");
+
+ kpanic("Unhandled page fault at %016X\n", state->ip);
+ return state;
+}
+
void
mem_paging_setup(void)
{
@@ -198,5 +228,6 @@ mem_paging_setup(void)
s_kernel_initial_pml1[0][i] = (i * PAGESIZE) + boot_kernel_physical_address | 3;
}
+ int_set_handler(14, s_pagefault_handler);
__asm__ volatile("mov %0, %%cr3":: "r"(s_kernel_initial_pd.pml4_paddr));
}
diff --git a/arch/x86_64/paging.d b/arch/x86_64/paging.d
deleted file mode 100644
index bb3ea83..0000000
--- a/arch/x86_64/paging.d
+++ /dev/null
@@ -1,2 +0,0 @@
-arch/x86_64/paging.o: arch/x86_64/paging.c arch/x86_64/paging.h \
- mem/memory.h mem/slab.h lib/jove.h io/log.h lib/string.h boot/boot.h
diff --git a/arch/x86_64/serial.d b/arch/x86_64/serial.d
deleted file mode 100644
index a0b0756..0000000
--- a/arch/x86_64/serial.d
+++ /dev/null
@@ -1,2 +0,0 @@
-arch/x86_64/serial.o: arch/x86_64/serial.c arch/x86_64/serial.h \
- arch/x86_64/uart.h lib/jove.h io/log.h
diff --git a/arch/x86_64/syscall.d b/arch/x86_64/syscall.d
deleted file mode 100644
index bb8f166..0000000
--- a/arch/x86_64/syscall.d
+++ /dev/null
@@ -1 +0,0 @@
-arch/x86_64/syscall.o: arch/x86_64/syscall.c usr/umode.h
diff --git a/arch/x86_64/syscall_setup.S b/arch/x86_64/syscall_setup.S
index cbd3220..972e345 100644
--- a/arch/x86_64/syscall_setup.S
+++ b/arch/x86_64/syscall_setup.S
@@ -1,11 +1,12 @@
-.extern _kernel_thread_sp
+.extern _kernel_task_sp
.extern syscall_handler
.global syscall_entry
.type syscall_entry @function
syscall_entry:
+ swapgs
movq %rsp, %rax
- movq (_kernel_thread_bp), %rsp
+ movq (_kernel_task_bp), %rsp
pushq %rax
pushq %rbp
pushq %rcx
@@ -16,22 +17,26 @@ syscall_entry:
popq %rcx
popq %rbp
popq %rsp
+ swapgs
sysretq
.global syscall_setup_syscall
.type syscall_setup_syscall @function
syscall_setup_syscall:
- movq $0xc0000082, %rcx
- leaq syscall_entry, %rdx
- mov %edx, %eax
- shr $32, %rdx
- wrmsr
movq $0xc0000080, %rcx
rdmsr
or $1, %eax
wrmsr
+
movq $0xc0000081, %rcx
rdmsr
- mov $0x00180008, %edx
+ mov $0x001b0008, %edx
+ wrmsr
+
+ movq $0xc0000082, %rcx
+ leaq syscall_entry, %rdx
+ mov %edx, %eax
+ shr $32, %rdx
wrmsr
+
retq
diff --git a/arch/x86_64/tables.d b/arch/x86_64/tables.d
deleted file mode 100644
index 6b10ebe..0000000
--- a/arch/x86_64/tables.d
+++ /dev/null
@@ -1 +0,0 @@
-arch/x86_64/tables.o: arch/x86_64/tables.c arch/x86_64/tables.h
diff --git a/arch/x86_64/tables.h b/arch/x86_64/tables.h
index 8e43bec..e160c66 100644
--- a/arch/x86_64/tables.h
+++ b/arch/x86_64/tables.h
@@ -45,7 +45,7 @@ struct InterruptTrapGate
uint8_t p : 1;
uint16_t base_16_31;
uint32_t base_32_63;
-
+ uint32_t resv;
}__attribute__((packed));
struct XDTR /* Generic table descriptor struct */
diff --git a/arch/x86_64/tasking.c b/arch/x86_64/tasking.c
new file mode 100644
index 0000000..fe6ecdb
--- /dev/null
+++ b/arch/x86_64/tasking.c
@@ -0,0 +1,93 @@
+#include "tsk/tasking.h"
+#include "mem/memory.h"
+#include "io/log.h"
+#include "lib/hashtable.h"
+#include "lib/string.h"
+#include "paging.h"
+#include "cpu.h"
+#include "tss.h"
+
+struct TaskBody {
+ struct Task base;
+ struct PageDirectory *pd;
+ struct Registers state;
+};
+
+struct Task *task_current;
+uintptr_t _kernel_task_bp = 0;
+
+//static struct SLinkedList s_tasks;
+static struct HashTable s_tasks;
+
+static struct SlabCache s_task_cache;
+static struct SlabCache s_kbp_cache;
+
+static tid_t s_task_id_next = 1;
+
+static size_t
+s_task_hash_func(const void* tid, size_t _)
+{
+ return (tid_t)tid;
+}
+
+void
+tasking_setup(void)
+{
+ hashtable_new(&s_tasks, struct TaskBody*, tid_t);
+ s_tasks.hash_function = s_task_hash_func;
+
+ mem_slabcache_new(&s_task_cache, "tasks", sizeof(struct TaskBody));
+ mem_slabcache_new(&s_kbp_cache, "kernel stacks", 4096);
+
+ struct TaskBody *ktask = mem_slab_alloc(&s_task_cache);
+ *ktask = (struct TaskBody){
+ .base.id = s_task_id_next++,
+ .base.kbp = ((uintptr_t)mem_slab_alloc(&s_kbp_cache)) + 0xFF0,
+ .base.perm = (size_t)-1,
+ .pd = mem_current_pd
+ };
+ hashtable_insert(&s_tasks, 0, ktask);
+
+ task_current = (struct Task*)ktask;
+ tss_set_rsp(0, task_current->kbp);
+ _kernel_task_bp = task_current->kbp;
+}
+
+struct Task*
+task_new(struct Task *parent)
+{
+ struct TaskBody *new = mem_slab_alloc(&s_task_cache);
+ memcpy(new, parent, sizeof(struct TaskBody));
+ new->base.id = s_task_id_next++;
+
+ uintptr_t ksp_base = (uintptr_t)mem_slab_alloc(&s_kbp_cache);
+ new->base.kbp = ksp_base + 0xFFF;
+ new->base.perm = parent->perm;
+
+ hashtable_insert(&s_tasks, (void*)new->base.id, new);
+ return (struct Task*)new;
+}
+
+struct Task*
+task_get(tid_t id)
+{
+ struct Task **task = hashtable_get(&s_tasks, (void*)id, struct Task*);
+ if(task == NULL) return NULL;
+ return *task;
+}
+
+void
+task_free(struct Task *task)
+{
+ struct TaskBody *body = (struct TaskBody*)task;
+ body->pd->references--;
+ task->kbp -= 0xFFF;
+ mem_slab_free(&s_kbp_cache, (void*)(task->kbp));
+ klogf("Need impl for task_free\n");
+}
+
+void*
+task_get_pd(struct Task *task)
+{
+ return ((struct TaskBody*)task)->pd;
+}
diff --git a/arch/x86_64/thread.c b/arch/x86_64/thread.c
deleted file mode 100644
index da20067..0000000
--- a/arch/x86_64/thread.c
+++ /dev/null
@@ -1,85 +0,0 @@
-#include "tsk/tasking.h"
-#include "mem/memory.h"
-#include "io/log.h"
-#include "lib/hashtable.h"
-#include "lib/string.h"
-#include "paging.h"
-#include "cpu.h"
-
-struct ThreadBody {
- struct Thread base;
- struct PageDirectory pd;
- struct Registers state;
-};
-
-struct Thread *thread_current;
-uintptr_t _kernel_thread_bp = 0;
-
-//static struct SLinkedList s_threads;
-static struct HashTable s_threads;
-
-static struct SlabCache s_thread_cache;
-static struct SlabCache s_kbp_cache;
-
-static tid_t s_thread_id_next = 1;
-
-static size_t
-s_thread_hash_func(const void* tid, size_t _)
-{
- return (tid_t)tid;
-}
-
-void
-tasking_setup(void)
-{
- hashtable_new(&s_threads, struct ThreadBody*, tid_t);
- s_threads.hash_function = s_thread_hash_func;
-
- mem_slabcache_new(&s_thread_cache, "threads", sizeof(struct ThreadBody));
- mem_slabcache_new(&s_kbp_cache, "kernel stacks", 4096);
-
- struct ThreadBody *kthread = mem_slab_alloc(&s_thread_cache);
- *kthread = (struct ThreadBody){
- .base.id = s_thread_id_next++,
- .base.kbp = ((uintptr_t)mem_slab_alloc(&s_kbp_cache)) + 0xFFF,
- .base.perm = (size_t)-1,
- .pd = *mem_current_pd
- };
- hashtable_insert(&s_threads, 0, kthread);
-
- thread_current = (struct Thread*)kthread;
- _kernel_thread_bp = thread_current->kbp;
-}
-
-struct Thread*
-thread_new(struct Thread *parent)
-{
- struct ThreadBody *new = mem_slab_alloc(&s_thread_cache);
- memcpy(new, parent, sizeof(struct ThreadBody));
- new->base.id = s_thread_id_next++;
-
- uintptr_t ksp_base = (uintptr_t)mem_slab_alloc(&s_kbp_cache);
- new->base.kbp = ksp_base + 0xFFF;
- new->base.perm = parent->perm;
-
- hashtable_insert(&s_threads, (void*)new->base.id, new);
- return (struct Thread*)new;
-}
-
-struct Thread*
-thread_get(tid_t id)
-{
- struct Thread **thread = hashtable_get(&s_threads, (void*)id, struct Thread*);
- if(thread == NULL) return NULL;
- return *thread;
-}
-
-void
-thread_free(struct Thread *thread)
-{
- struct ThreadBody *body = (struct ThreadBody*)thread;
- body->pd.references--;
- thread->kbp -= 0xFFF;
- mem_slab_free(&s_kbp_cache, (void*)(thread->kbp));
- klogf("Need impl for thread_free\n");
-}
diff --git a/arch/x86_64/thread.d b/arch/x86_64/thread.d
deleted file mode 100644
index c78e4a9..0000000
--- a/arch/x86_64/thread.d
+++ /dev/null
@@ -1,3 +0,0 @@
-arch/x86_64/thread.o: arch/x86_64/thread.c tsk/tasking.h mem/memory.h \
- mem/slab.h io/log.h lib/hashtable.h lib/linkedlist.h lib/string.h \
- arch/x86_64/paging.h arch/x86_64/cpu.h
diff --git a/arch/x86_64/tss.h b/arch/x86_64/tss.h
index 34ec444..dcdd01c 100644
--- a/arch/x86_64/tss.h
+++ b/arch/x86_64/tss.h
@@ -7,12 +7,14 @@
struct TSS
{
uint32_t resv0;
- uint64_t rsp[3];
+ uint32_t rsp[3][2];
uint64_t resv1;
- uint64_t ist[8];
+ uint32_t ist[8][2];
uint64_t resv2;
uint16_t resv3;
uint16_t iobp;
};
+void tss_set_rsp(uint8_t dpl, uintptr_t rsp);
+
#endif