summaryrefslogtreecommitdiffstats
path: root/arch/x86_64
diff options
context:
space:
mode:
authorJon Santmyer <jon@jonsantmyer.com>2025-08-17 14:16:55 -0400
committerJon Santmyer <jon@jonsantmyer.com>2025-08-17 14:16:55 -0400
commit7ee9347560768641096df68c545ac085a20233e4 (patch)
tree5b567f2e98cd9e6aeee33eeecd7fbf6f2fafdeab /arch/x86_64
parentf466364b8a3858e7b3f19258d142851cb4a7e6d6 (diff)
downloadjove-kernel-7ee9347560768641096df68c545ac085a20233e4.tar.gz
jove-kernel-7ee9347560768641096df68c545ac085a20233e4.tar.bz2
jove-kernel-7ee9347560768641096df68c545ac085a20233e4.zip
working usermode pager. fix usermode interrupts
Diffstat (limited to 'arch/x86_64')
-rw-r--r--arch/x86_64/gdt.c93
-rw-r--r--arch/x86_64/idt.c15
-rw-r--r--arch/x86_64/ivt.s12
-rw-r--r--arch/x86_64/lgdt.s3
-rw-r--r--arch/x86_64/processor.c4
-rw-r--r--arch/x86_64/syscall-invoke-mapping.c58
-rw-r--r--arch/x86_64/usermode.c9
7 files changed, 100 insertions, 94 deletions
diff --git a/arch/x86_64/gdt.c b/arch/x86_64/gdt.c
index e8ca912..3756d21 100644
--- a/arch/x86_64/gdt.c
+++ b/arch/x86_64/gdt.c
@@ -1,105 +1,96 @@
#include "arch/x86_64/tables.h"
#include "arch/x86_64/processor.h"
#include "string.h"
+#include "print.h"
static segment_descriptor_t s_gdt[] = {
+ [GDT_ENTRY_KERNEL_NULL] =
{ 0 }, //Kernel NULL
+ [GDT_ENTRY_KERNEL_CODE] =
{ //Kernel Code
.limit_0_15 = 0xFFFF,
.base_0_15 = 0x0,
- .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 = 1,
+ .type_flags = CD_SEGMENT_TYPE_CODE | CD_SEGMENT_TYPE_WRITEABLE |
+ GDT_SEGMENT_FLAG_S |
+ GDT_SEGMENT_FLAG_DPL(0) |
+ GDT_SEGMENT_FLAG_P,
+ .limit_16_19_avlx = 0xF | GDT_SEGMENT_AVLX_L | GDT_SEGMENT_AVLX_G,
.base_24_31 = 0x0
},
+ [GDT_ENTRY_KERNEL_DATA] =
{ //Kernel Data
.limit_0_15 = 0xFFFF,
.base_0_15 = 0x0,
- .type = CD_SEGMENT_TYPE_WRITEABLE,
- .s = 1,
- .dpl = 0,
- .p = 1,
- .limit_16_19 = 0xF,
- .avl = 0,
- .l = 0,
- .d_b = 1,
- .g = 1,
+ .type_flags = CD_SEGMENT_TYPE_WRITEABLE |
+ GDT_SEGMENT_FLAG_S |
+ GDT_SEGMENT_FLAG_DPL(0) |
+ GDT_SEGMENT_FLAG_P,
+ .limit_16_19_avlx = 0xF | GDT_SEGMENT_AVLX_L | GDT_SEGMENT_AVLX_G,
.base_24_31 = 0x0
},
+ [GDT_ENTRY_USER_NULL] =
{ 0 }, //User NULL
+ [GDT_ENTRY_USER_DATA] =
{ //User Data
.limit_0_15 = 0xFFFF,
.base_0_15 = 0x0,
- .type = CD_SEGMENT_TYPE_WRITEABLE,
- .s = 1,
- .dpl = 3,
- .p = 1,
- .limit_16_19 = 0xF,
- .avl = 0,
- .l = 0,
- .d_b = 1,
- .g = 1,
+ .type_flags = CD_SEGMENT_TYPE_WRITEABLE |
+ GDT_SEGMENT_FLAG_S |
+ GDT_SEGMENT_FLAG_DPL(3) |
+ GDT_SEGMENT_FLAG_P,
+ .limit_16_19_avlx = 0xF | GDT_SEGMENT_AVLX_L | GDT_SEGMENT_AVLX_G,
.base_24_31 = 0x0
},
+ [GDT_ENTRY_USER_CODE] =
{ //User Code
.limit_0_15 = 0xFFFF,
.base_0_15 = 0x0,
- .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 = 1,
+ .type_flags = CD_SEGMENT_TYPE_CODE | CD_SEGMENT_TYPE_WRITEABLE |
+ GDT_SEGMENT_FLAG_S |
+ GDT_SEGMENT_FLAG_DPL(3) |
+ GDT_SEGMENT_FLAG_P,
+ .limit_16_19_avlx = 0xF | GDT_SEGMENT_AVLX_L | GDT_SEGMENT_AVLX_G,
.base_24_31 = 0x0
},
+ [GDT_ENTRY_TSS_LOW] =
{ //TSS Low
.limit_0_15 = 0,
.base_0_15 = 0,
.base_16_23 = 0,
- .type = S_SEGMENT_TYPE_TSS_AVAIL,
- .avl = 0,
- .s = 0,
- .dpl = 0,
- .p = 1,
- .limit_16_19 = 0,
- .l = 0,
- .d_b = 0,
- .g = 0,
+ .type_flags = GDT_SEGMENT_TYPE_TSS_AVAIL |
+ GDT_SEGMENT_FLAG_DPL(0) |
+ GDT_SEGMENT_FLAG_P,
+ .limit_16_19_avlx = 0,
.base_24_31 = 0
},
+ [GDT_ENTRY_TSS_HIGH] =
{ 0 } //TSS High
};
void
gdt_setup(processor_t *processor)
{
- memcpy(processor->gdt, s_gdt, sizeof(s_gdt));
+ size_t gdtw = GDT_ENTRY_COUNT * sizeof(segment_descriptor_t);
+ klogf("%X\n", gdtw);
+ memcpy(processor->gdt, &s_gdt, gdtw);
processor->gdtr.base = (uintptr_t)&s_gdt;
- processor->gdtr.length = sizeof(s_gdt) - 1;
+ processor->gdtr.length = gdtw - 1;
segment_descriptor_t *tss_lo = &processor->gdt[GDT_ENTRY_TSS_LOW];
segment_descriptor_t *tss_hi = &processor->gdt[GDT_ENTRY_TSS_HIGH];
uintptr_t tssb = (uintptr_t)&processor->tss;
+ size_t tssl = sizeof(tss_t);
+
+ tss_lo->limit_0_15 = tssl & 0xFF;
tss_lo->base_0_15 = tssb & 0xFFFF;
tss_lo->base_16_23 = (tssb >> 16) & 0xFF;
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(tss_t);
- tss_lo->limit_0_15 = tssl & 0xFFFF;
- tss_lo->limit_16_19 = (tssl >> 16) & 0xF;
+ tss_lo->limit_16_19_avlx = (tssl >> 16) & 0xF;
processor->tss.iopb = tssl;
@@ -107,5 +98,5 @@ gdt_setup(processor_t *processor)
gdt_load(&processor->gdtr);
extern void tss_flush(uint16_t);
- tss_flush(GDT_ENTRY_TSS_LOW * sizeof(segment_descriptor_t));
+ tss_flush(GDT_OFFSET_TSS);
}
diff --git a/arch/x86_64/idt.c b/arch/x86_64/idt.c
index 99e1da1..1080f92 100644
--- a/arch/x86_64/idt.c
+++ b/arch/x86_64/idt.c
@@ -1,16 +1,13 @@
#include "arch/x86_64/tables.h"
#include "arch/x86_64/idt.h"
-__attribute__((aligned(4096)))
+__attribute__((aligned(0x10)))
interrupt_gate_t s_idtd[256];
-int64_t __isr_err;
-int64_t __isr_num;
-
void
isr_handle(ivt_state_t* state)
{
- kpanic_state(state, "Unhandled interrupt %i", __isr_num);
+ kpanic_state(state, "Unhandled interrupt %i", state->num);
}
void
@@ -21,13 +18,9 @@ ivt_setup(void)
uintptr_t base = __ivt[i];
s_idtd[i] = (interrupt_gate_t) {
.base_0_15 = (base & 0xFFFF),
- .segment_selector = 0x8,
+ .cs = GDT_OFFSET_KERNEL_CODE,
.ist = 0,
- .zero_0 = 0,
- .type = 0xE,
- .zero_1 = 0,
- .dpl = 0,
- .p = 1,
+ .type_flags = IDT_TYPE_INT_GATE | IDT_FLAG_DPL(0) | IDT_FLAG_P,
.base_16_31 = (base >> 16) & 0xFFFF,
.base_32_63 = (base >> 32) & 0xFFFFFFFF,
.resv = 0
diff --git a/arch/x86_64/ivt.s b/arch/x86_64/ivt.s
index d2d504b..0005686 100644
--- a/arch/x86_64/ivt.s
+++ b/arch/x86_64/ivt.s
@@ -18,6 +18,8 @@ __isr_head:
call isr_handle
popall
+
+ addq $16, %rsp
iretq
.extern __isr_err
@@ -26,12 +28,7 @@ __isr_head:
.macro defn_isr_err num:req
.type __isr\num @function
__isr\num:
- pushq %rbx
- movq 8(%rsp), %rbx
- movq %rbx, __isr_err
- popq %rbx
- addq $8, %rsp
- movq $\num, __isr_num
+ pushq $\num
jmp __isr_head
.size __isr\num, . - __isr\num
.endm
@@ -39,7 +36,8 @@ __isr\num:
.macro defn_isr num:req
.type __isr\num @function
__isr\num:
- movq $\num, __isr_num
+ pushq $0
+ pushq $\num
jmp __isr_head
.size __isr\num, . - __isr\num
.endm
diff --git a/arch/x86_64/lgdt.s b/arch/x86_64/lgdt.s
index 7122ef9..55e37b5 100644
--- a/arch/x86_64/lgdt.s
+++ b/arch/x86_64/lgdt.s
@@ -20,7 +20,6 @@ gdt_load:
.global tss_flush
.type tss_flush @function
tss_flush:
- movw %di, %ax
- ltr %ax
+ ltr %di
retq
.size tss_flush, . - tss_flush
diff --git a/arch/x86_64/processor.c b/arch/x86_64/processor.c
index 3ebf1ee..f7e5cac 100644
--- a/arch/x86_64/processor.c
+++ b/arch/x86_64/processor.c
@@ -66,8 +66,8 @@ s_enable_sce(void)
wrmsr(MSR_EFER, feat.v[0], feat.v[1]);
msr_star_t star;
- star.kcs = GDT_ENTRY_KERNEL_CODE * sizeof(segment_descriptor_t);
- star.ucs = GDT_ENTRY_USER_CODE * sizeof(segment_descriptor_t);
+ star.kcs = GDT_OFFSET_KERNEL_CODE;
+ star.ucs = GDT_OFFSET_USER_CODE;
wrmsr(MSR_STAR, star.v[0], star.v[1]);
extern void _syscall_entry(void);
diff --git a/arch/x86_64/syscall-invoke-mapping.c b/arch/x86_64/syscall-invoke-mapping.c
index efecbdf..5b79239 100644
--- a/arch/x86_64/syscall-invoke-mapping.c
+++ b/arch/x86_64/syscall-invoke-mapping.c
@@ -4,6 +4,9 @@
#include <stddef.h>
#include "error.h"
#include "lock.h"
+#include "string.h"
+#include "memory.h"
+#include "print.h"
static int
s_handle_invoke_mapping_release(
@@ -13,6 +16,9 @@ s_handle_invoke_mapping_release(
size_t payload_at
)
{
+#ifdef DBG_SYSCALL
+ klogf("release mapping %p\n", target_entry);
+#endif
target_entry->data = 0;
target_entry->type = KO_NONE;
return 0;
@@ -29,25 +35,29 @@ s_handle_invoke_mapping_get(
pmli_t pmli;
SYSCALL_PAYLOAD_TAKEL(payload, payload_at, pmli, pmli_t);
- if(pmli > 511) return -KE_OOB;
+ if(pmli > 511) return KE_OOB;
uint8_t level = target_entry->data & 3;
pmle_t *target_pml = (pmle_t*)vmem_phys_tovirt(target_entry->data & ~3ULL);
- if(level == 3 && pmli > 255) return -KE_OOB;
- if(level == 0) return -KE_BADOBJ;
-
+ if(level == 3 && pmli > 255) return KE_OOB;
+ if(level < 0) return KE_BADOBJ;
+
size_t dest_pathw;
objdir_entry_t *dest_entry;
SYSCALL_PAYLOAD_TAKEOBJ(payload, payload_at, dest_pathw, dest_entry);
- if(dest_entry->type != KO_NONE) return -KE_FULL;
+
+ if(dest_entry->type != KO_NONE) return KE_FULL;
pmle_t pmle = target_pml[pmli];
- if(!pmle.p) return -KE_DNE;
+ if(!pmle.p) return KE_DNE;
*dest_entry = (objdir_entry_t) {
.type = KO_MEMORY_MAPPING,
.data = (((uintptr_t)target_pml[pmli].paddr) << 12ULL) | (level - 1)
};
+#ifdef DBG_SYSCALL
+ klogf("Get pml%i %p[%i] -> %p\n", level, target_pml, pmli, dest_entry->data & ~3ULL);
+#endif
return 0;
}
@@ -65,37 +75,47 @@ s_handle_invoke_mapping_map(
pmli_t pmli;
SYSCALL_PAYLOAD_TAKEL(payload, payload_at, pmli, pmli_t);
- if(pmli > 511) return -KE_OOB;
- if(level == 3 && pmli > 255) return -KE_OOB;
+ if(pmli > 511) return KE_OOB;
+ if(level == 3 && pmli > 255) return KE_OOB;
+ if(level < 0) return KE_BADOBJ;
size_t untyped_pathw;
objdir_entry_t *untyped_entry;
SYSCALL_PAYLOAD_TAKEOBJ(payload, payload_at, untyped_pathw, untyped_entry);
- if(untyped_entry->type != KO_MEMORY_UNTYPED) return -KE_BADOBJ;
+ if(untyped_entry->type != KO_MEMORY_UNTYPED) return KE_BADOBJ;
mtx_acquire(&untyped_entry->lock);
if((untyped_entry->data & 0xFFF) != 0) {
mtx_release(&untyped_entry->lock);
- return -KE_ALIGN;
+ return KE_ALIGN;
}
- size_t *untyped_data = (size_t*)untyped_entry->data;
- size_t untyped_size = *untyped_data;
+
+ uintptr_t untyped_phys = untyped_entry->data;
+ size_t *untyped = ko_entry_data(untyped_entry);
+ size_t untyped_size = *untyped;
if(untyped_size != 0x1000) {
mtx_release(&untyped_entry->lock);
- return -KE_BADSIZE;
+ return KE_BADSIZE;
}
pmle_t pmle = target_pml[pmli];
if(pmle.p) {
mtx_release(&untyped_entry->lock);
- return -KE_OCCUPIED;
+ return KE_OCCUPIED;
}
- target_pml[pmli].value = vmem_ident_tophys((void*)untyped_entry->data) | PAGE_RW | PAGE_US | PAGE_PRESENT;
+ target_pml[pmli].value = untyped_phys | PAGE_RW | PAGE_US | PAGE_PRESENT;
+ if(level != 0) {
+ memset(untyped, 0, 0x1000);
+ }
untyped_entry->type = KO_MEMORY_MAPPING;
untyped_entry->data |= level - 1;
+#ifdef DBG_SYSCALL
+ klogf("map %p[%p] to pml%i %p[%i]\n", untyped_entry, untyped_phys, level, target_pml, pmli);
+#endif
+
mtx_release(&untyped_entry->lock);
return 0;
}
@@ -119,6 +139,10 @@ syscall_handle_invoke_mapping(
uint8_t funcid;
SYSCALL_PAYLOAD_TAKEL(payload, payload_at, funcid, uint8_t);
- if(funcid >= s_invoke_handles_count) return -KE_BADFUNC;
- return s_invoke_handles[funcid](root_dir, target, payload, payload_at);
+ if(funcid >= s_invoke_handles_count) return KE_BADFUNC;
+ int r = s_invoke_handles[funcid](root_dir, target, payload, payload_at);
+#ifdef DBG_SYSCALL
+ klogf("Call returns %i\n", r);
+#endif
+ return r;
}
diff --git a/arch/x86_64/usermode.c b/arch/x86_64/usermode.c
index 68cb45a..99ee128 100644
--- a/arch/x86_64/usermode.c
+++ b/arch/x86_64/usermode.c
@@ -7,6 +7,7 @@
#include "string.h"
#include "device/processor.h"
#include "arch/x86_64/page.h"
+#include "print.h"
static tcb_t s_init_tcb;
@@ -99,7 +100,7 @@ init_load(void)
_initDirectory.entries[INIT_OBJECT_TCB] = (objdir_entry_t) {
.type = KO_TCB,
- .data = (uintptr_t)&s_init_tcb
+ .data = vmem_tophys_koff((uintptr_t)&s_init_tcb)
};
objdir_t *untyped_dir = (objdir_t*)_initDirectory.entries[INIT_OBJECT_UNTYPED_DIR].data;
@@ -123,11 +124,12 @@ init_load(void)
uintptr_t sp = stack_base + 0xFF0;
//Create a kernel stack for the init TCB
- uintptr_t ksp_base = (uintptr_t)s_init_tcb.kstack;
+ uintptr_t ksp_base = (uintptr_t)&s_init_tcb.kstack;
s_init_tcb.ksp = ksp_base + 0xFF0;
processor_t *proc = (processor_t*)processor_current();
- proc->tss.rsp[0] = ksp_base;
+ proc->tss.rsp0 = s_init_tcb.ksp;
+ klogf("RSP0 %p\n", s_init_tcb.ksp);
//Create a message object for init
uintptr_t message_base = init_base + (init_pages << 12);
@@ -145,6 +147,5 @@ init_load(void)
//Setup usermode and jump
proc->tcb = &s_init_tcb;
- proc->tss.rsp[0] = s_init_tcb.ksp;
s_enter_usermode((void*)init_base, (void*)sp);
}