diff options
author | Jon Santmyer <jon@jonsantmyer.com> | 2025-09-26 13:17:41 -0400 |
---|---|---|
committer | Jon Santmyer <jon@jonsantmyer.com> | 2025-09-26 13:17:41 -0400 |
commit | 2dadbfc899df4179ca70c4ea04f74a5e190c2ae7 (patch) | |
tree | b166aaa9af42406cd07fbaf150f93aefeb2fbe33 | |
parent | ddc4fbc15223e362896a9f42beca73f05f48e664 (diff) | |
download | jove-kernel-2dadbfc899df4179ca70c4ea04f74a5e190c2ae7.tar.gz jove-kernel-2dadbfc899df4179ca70c4ea04f74a5e190c2ae7.tar.bz2 jove-kernel-2dadbfc899df4179ca70c4ea04f74a5e190c2ae7.zip |
fix usermode interrupts. add ability to define custom interrupt handlersmain
-rw-r--r-- | arch/x86_64/device/processor.c | 4 | ||||
-rw-r--r-- | arch/x86_64/gdt.c | 16 | ||||
-rw-r--r-- | arch/x86_64/idt.c | 16 | ||||
-rw-r--r-- | arch/x86_64/init.c | 2 | ||||
-rw-r--r-- | arch/x86_64/ivt.s | 21 | ||||
-rw-r--r-- | arch/x86_64/lgdt.s | 4 | ||||
-rw-r--r-- | arch/x86_64/memory/pml4.c | 24 | ||||
-rw-r--r-- | arch/x86_64/panic.c | 3 | ||||
-rw-r--r-- | arch/x86_64/syscall/invoke-mapping.c | 11 | ||||
-rw-r--r-- | arch/x86_64/syscall/syscall.c | 24 | ||||
-rw-r--r-- | arch/x86_64/tasking/tcb.c | 6 | ||||
-rw-r--r-- | arch/x86_64/usermode.c | 1 | ||||
-rw-r--r-- | config.mk | 1 | ||||
-rw-r--r-- | device/initrd.c | 1 | ||||
-rw-r--r-- | device/portio_uart.c | 2 | ||||
-rw-r--r-- | include/api/init.h | 15 | ||||
-rw-r--r-- | include/arch/x86_64/idt.h | 22 | ||||
-rw-r--r-- | include/arch/x86_64/processor.h | 5 | ||||
-rw-r--r-- | include/init.h | 14 | ||||
-rw-r--r-- | syscall/invoke-untyped.c | 2 | ||||
-rw-r--r-- | syscall/invoke_objdir.c | 5 |
21 files changed, 142 insertions, 57 deletions
diff --git a/arch/x86_64/device/processor.c b/arch/x86_64/device/processor.c index ff920c8..1b3daa2 100644 --- a/arch/x86_64/device/processor.c +++ b/arch/x86_64/device/processor.c @@ -44,7 +44,7 @@ typedef union msr_star uint32_t eip; uint16_t kcs; uint16_t ucs; - }; + }__attribute__((packed)); uint32_t v[2]; } msr_star_t; @@ -65,7 +65,7 @@ s_enable_sce(void) msr_star_t star; star.kcs = GDT_OFFSET_KERNEL_CODE; - star.ucs = GDT_OFFSET_USER_CODE; + star.ucs = GDT_OFFSET_USER_NULL; wrmsr(MSR_STAR, star.v[0], star.v[1]); extern void _syscall_entry(void); diff --git a/arch/x86_64/gdt.c b/arch/x86_64/gdt.c index 3756d21..9c172d2 100644 --- a/arch/x86_64/gdt.c +++ b/arch/x86_64/gdt.c @@ -57,9 +57,7 @@ static segment_descriptor_t s_gdt[] = { .limit_0_15 = 0, .base_0_15 = 0, .base_16_23 = 0, - .type_flags = GDT_SEGMENT_TYPE_TSS_AVAIL | - GDT_SEGMENT_FLAG_DPL(0) | - GDT_SEGMENT_FLAG_P, + .type_flags = 0x89, .limit_16_19_avlx = 0, .base_24_31 = 0 }, @@ -71,29 +69,25 @@ void gdt_setup(processor_t *processor) { 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.base = (uintptr_t)&processor->gdt; 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); + size_t tssl = sizeof(tss_t) - 1; 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; - - tss_lo->limit_16_19_avlx = (tssl >> 16) & 0xF; + *(uint32_t*)tss_hi = (tssb >> 32) & 0xFFFFFFFF; processor->tss.iopb = tssl; - + extern void gdt_load(void*); gdt_load(&processor->gdtr); diff --git a/arch/x86_64/idt.c b/arch/x86_64/idt.c index 1080f92..2eebf41 100644 --- a/arch/x86_64/idt.c +++ b/arch/x86_64/idt.c @@ -1,12 +1,20 @@ #include "arch/x86_64/tables.h" #include "arch/x86_64/idt.h" +#include "print.h" __attribute__((aligned(0x10))) -interrupt_gate_t s_idtd[256]; +static interrupt_gate_t s_idtd[256]; + +kernel_isr_handler_t kernel_isr_handles[256]; void isr_handle(ivt_state_t* state) { + kernel_isr_handler_t kernel_handle = kernel_isr_handles[state->num]; + if(kernel_handle) { + kernel_handle(state); + return; + } kpanic_state(state, "Unhandled interrupt %i", state->num); } @@ -34,6 +42,8 @@ idt_setup(processor_t *processor) processor->idtr.base = (uintptr_t)&s_idtd; processor->idtr.length = sizeof(s_idtd) - 1; - extern void idt_load(void* idtr); - idt_load(&processor->idtr); + klogf("%X\n", s_idtd[0].type_flags); + + __asm__ volatile("lidt %0":: "m"(processor->idtr)); + __asm__ volatile("cli"); } diff --git a/arch/x86_64/init.c b/arch/x86_64/init.c index 7a2f67d..9e32898 100644 --- a/arch/x86_64/init.c +++ b/arch/x86_64/init.c @@ -1,6 +1,7 @@ #include "init.h" #include "bootargs.h" #include "device/initrd.h" +#include "api/init.h" #include "arch/x86_64/page.h" #include "arch/x86_64/processor.h" #include "device/processor.h" @@ -180,5 +181,6 @@ init_load(void) extern tcb_t *_init_tcb; _init_tcb->sp = (uintptr_t)usermode_sp; + extern void usermode(void*, void*); usermode((void*)init_ehdr->e_entry, usermode_sp); } diff --git a/arch/x86_64/ivt.s b/arch/x86_64/ivt.s index a64f6b7..a1592be 100644 --- a/arch/x86_64/ivt.s +++ b/arch/x86_64/ivt.s @@ -1,14 +1,13 @@ .section .text -.global idt_load -.type idt_load @function -idt_load: - lidt (%rdi) - sti - retq -.size idt_load, . - idt_load - .include "arch/x86_64/savestate.s" +.macro swapgs_if_necessary + cmp $0x08, 0x8(%rsp) + je 1f + swapgs +1: +.endm + .extern isr_handle .type __isr_head @function __isr_head: @@ -20,14 +19,13 @@ __isr_head: popall addq $16, %rsp + swapgs_if_necessary iretq -.extern __isr_err -.extern __isr_num - .macro defn_isr_err num:req .type __isr\num @function __isr\num: + swapgs_if_necessary pushq $\num jmp __isr_head .size __isr\num, . - __isr\num @@ -36,6 +34,7 @@ __isr\num: .macro defn_isr num:req .type __isr\num @function __isr\num: + swapgs_if_necessary pushq $0 pushq $\num jmp __isr_head diff --git a/arch/x86_64/lgdt.s b/arch/x86_64/lgdt.s index 55e37b5..ccafe42 100644 --- a/arch/x86_64/lgdt.s +++ b/arch/x86_64/lgdt.s @@ -4,9 +4,9 @@ gdt_load: lgdt (%rdi) .reload_segments: pushq $0x8 - leaq .reload_cs, %rax + leaq .reload_cs(%rip), %rax pushq %rax - lretq + retfq .reload_cs: movw $0x10, %ax movw %ax, %ds diff --git a/arch/x86_64/memory/pml4.c b/arch/x86_64/memory/pml4.c index d5fb56b..b42ce06 100644 --- a/arch/x86_64/memory/pml4.c +++ b/arch/x86_64/memory/pml4.c @@ -1,5 +1,6 @@ #include "arch/x86_64/page.h" #include "arch/x86_64/processor.h" +#include "arch/x86_64/idt.h" #include "device/processor.h" #include "memory.h" #include "boot.h" @@ -7,6 +8,7 @@ #include "init.h" #include "string.h" #include "jove.h" +#include "print.h" #include "api/error.h" #include <stdint.h> @@ -81,6 +83,27 @@ pml4_try_map(pmle_t *pml4, uintptr_t pptr, uintptr_t vptr) return KE_OK; } +static void +s_handle_pagefault(ivt_state_t *state) +{ + int eflags = state->err; + bool e_present = eflags & 1; + bool e_write = (eflags & 2) > 0; + bool e_user = (eflags & 4) > 0; + bool e_insf = (eflags & 16) > 0; + + uintptr_t faultaddr; + __asm__ volatile("movq %%cr2, %0": "=r"(faultaddr)); + + kprintf("\n%s %s %s page for %s\n", + e_user ? "User" : "Kernel", + e_write ? "wrote to" : "read from", + e_present ? "present" : "non-present", + e_insf ? "instruction" : "memory"); + kprintf("Faulting address: %p\n", faultaddr); + kpanic_state(state, "Unhandled page fault"); +} + __attribute__((aligned(0x1000))) pmle_t s_kernel_pml4[512]; // Page L4 __attribute__((aligned(0x1000))) pmle_t s_kernel_pml3[512]; // Page L3 __attribute__((aligned(0x1000))) pmle_t s_kernel_pml2[512]; // Page directory @@ -139,6 +162,7 @@ pml4_setup_init(void) } __asm__ volatile("mov %0, %%cr3":: "r"(kernel_pml4_base)); + kernel_isr_handles[EXCEPTION_PF] = s_handle_pagefault; //Add page mapping object to init directory. _initDirectory.entries[INIT_OBJECT_PAGEMAP] = (objdir_entry_t) { diff --git a/arch/x86_64/panic.c b/arch/x86_64/panic.c index 2e34500..522550f 100644 --- a/arch/x86_64/panic.c +++ b/arch/x86_64/panic.c @@ -25,12 +25,13 @@ kpanic_state(ivt_state_t *state, const char *fmt, ...) kprintf("R12 %p | R13 %p | R14 %p | R15 %p\n", state->r12, state->r13, state->r14, state->r15); kprintf("RIP %p\n", state->rip); + /* kprintf("\nStack trace:\n"); struct stackFrame *frame = (struct stackFrame*)state->rbp; for(size_t framei = 0; frame && framei < 64; ++framei) { kprintf("%i %p : %p\n", framei, frame, frame->eip); frame = frame->ebp; - } + }*/ hcf(); } diff --git a/arch/x86_64/syscall/invoke-mapping.c b/arch/x86_64/syscall/invoke-mapping.c index 186b420..e470034 100644 --- a/arch/x86_64/syscall/invoke-mapping.c +++ b/arch/x86_64/syscall/invoke-mapping.c @@ -1,5 +1,5 @@ #include "arch/x86_64/syscall/wrappers.h" -#include "arch/x86_64/syscall.h" +#include "arch/x86_64/api/syscall.h" #include "arch/x86_64/page.h" #include <stddef.h> #include "api/error.h" @@ -20,7 +20,9 @@ s_handle_invoke_mapping_exists( pmle_t *target_pml; uint8_t target_depth; SYSCALL_PAYLOAD_TAKEPML(payload, payload_at, pml4, target_depth, target_pml); - if(target_pml == NULL || !target_pml->p) return KE_DNE; + if(target_pml == NULL || !target_pml->p) { + return KE_DNE; + } #ifdef DBG_SYSCALL klogf("pml d%i %p from %p exists\n", target_depth, target_pml, pml4); @@ -46,7 +48,9 @@ s_handle_invoke_mapping_map( 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) { @@ -69,6 +73,7 @@ s_handle_invoke_mapping_map( memset(untyped, 0, 0x1000); } untyped_entry->type = KO_NONE; + untyped_entry->data = 0; #ifdef DBG_SYSCALL klogf("map %p[%i] to %p[%i]\n", untyped_phys, target_depth, target_pml, ((uintptr_t)target_pml & 0xFFF) / 8); #endif diff --git a/arch/x86_64/syscall/syscall.c b/arch/x86_64/syscall/syscall.c index 7ddd179..1ed991d 100644 --- a/arch/x86_64/syscall/syscall.c +++ b/arch/x86_64/syscall/syscall.c @@ -35,18 +35,36 @@ __attribute__((naked)) void _syscall_entry(void) { __asm__ volatile(" \ - pushq %%r11; \ - pushq %%rcx; \ swapgs; \ movq %%gs:%c[tcb], %%rax; \ movq %%rsp, %c[sp](%%rax); \ movq %c[ksp](%%rax), %%rsp; \ pushq %c[sp](%%rax); \ + pushq %%r11; \ + pushq %%rcx; \ + pushq %%rbx; \ + pushq %%rbp; \ + pushq %%r12; \ + pushq %%r13; \ + pushq %%r14; \ + pushq %%r15; \ callq _syscall_handler; \ swapgs; \ - popq %%rsp; \ + popq %%r15; \ + popq %%r14; \ + popq %%r13; \ + popq %%r12; \ + popq %%rbp; \ + popq %%rbx; \ + xorq %%rdx, %%rdx; \ + xorq %%rsi, %%rsi; \ + xorq %%rdi, %%rdi; \ + xorq %%r8, %%r8; \ + xorq %%r9, %%r9; \ + xorq %%r10, %%r10; \ popq %%rcx; \ popq %%r11; \ + popq %%rsp; \ sysretq;" :: [tcb] "i"(offsetof(processor_t, tcb)), diff --git a/arch/x86_64/tasking/tcb.c b/arch/x86_64/tasking/tcb.c index 9877455..3cae29f 100644 --- a/arch/x86_64/tasking/tcb.c +++ b/arch/x86_64/tasking/tcb.c @@ -24,8 +24,10 @@ tcb_init(void *task_main) .type = KO_TCB, .data = vptr_tophys_koff((uintptr_t)_init_tcb) }; - - ((processor_t*)processor_current())->tcb = _init_tcb; + + processor_t* proc = processor_current(); + proc->tcb = _init_tcb; + proc->tss.rsp0 = _init_tcb->ksp; __asm__ volatile("\ movq %0, %%rsp; \ diff --git a/arch/x86_64/usermode.c b/arch/x86_64/usermode.c index 24a31a1..0285e7d 100644 --- a/arch/x86_64/usermode.c +++ b/arch/x86_64/usermode.c @@ -6,7 +6,6 @@ void usermode(void *ip, void *sp) __asm__ volatile("mov %0, %%rsp; \ movq %1, %%rcx; \ movq $0x202, %%r11; \ - cli; \ swapgs; \ sysretq":: "r"(sp), "r"(ip): "memory"); @@ -17,6 +17,7 @@ CFLAGS = \ -fno-pie \ -fno-pic \ -g \ + -MD \ -D__$(TARGET_MACHINE)__ \ -D__$(TARGET_BOOTLOADER)__ \ -DPROCESSORS_MAX=$(PROCESSORS_MAX) \ diff --git a/device/initrd.c b/device/initrd.c index b57687c..e9b3533 100644 --- a/device/initrd.c +++ b/device/initrd.c @@ -5,6 +5,7 @@ #include "device/initrd.h" #include "boot.h" #include "object.h" +#include "api/init.h" #include "init.h" #include "bootargs.h" #include "print.h" diff --git a/device/portio_uart.c b/device/portio_uart.c index 9cc76f8..b049257 100644 --- a/device/portio_uart.c +++ b/device/portio_uart.c @@ -1,5 +1,6 @@ #ifdef ENABLE_PORTIO_UART #include "init.h" +#include "api/init.h" #include "device/portio_uart.h" #include "device/portio.h" @@ -59,6 +60,7 @@ void portio_uart_write(uint64_t dev, const char *s, int n) { for(int i = 0; i < n; i++) { + while((port_inb(dev + 5) & 0x20) == 0); port_outb(dev, s[i]); } } diff --git a/include/api/init.h b/include/api/init.h new file mode 100644 index 0000000..e17d8fd --- /dev/null +++ b/include/api/init.h @@ -0,0 +1,15 @@ +#ifndef _JOVE_API_INIT_H +#define _JOVE_API_INIT_H 1 + +enum { + INIT_OBJECT_ROOTDIR = 0, + INIT_OBJECT_TCB, + INIT_OBJECT_PAGEMAP, + INIT_OBJECT_PROCESSOR_DIR, + INIT_OBJECT_UNTYPED_DIR, + INIT_OBJECT_INITRD_DIR, + INIT_OBJECT_MESSAGE, + INIT_OBJECT_LOG +}; + +#endif diff --git a/include/arch/x86_64/idt.h b/include/arch/x86_64/idt.h index 4ca820f..fe544cb 100644 --- a/include/arch/x86_64/idt.h +++ b/include/arch/x86_64/idt.h @@ -11,6 +11,28 @@ typedef struct jove_IVTState uint64_t rip, cs, rflags, rsp, ss; } ivt_state_t; +enum +{ + EXCEPTION_DIVISION = 0, + EXCEPTION_DEBUG, + EXCEPTION_NMI, + EXCEPTION_BREAKPOINT, + EXCEPTION_OVERFLOW, + EXCEPTION_BRE, + EXCEPTION_INVLOP, + EXCEPTION_DEVNA, + EXCEPTION_DOUBLE, + EXCEPTION_CSO, + EXCEPTION_INVALID_TSS, + EXCEPTION_SEG_MISSING, + EXCEPTION_SS, + EXCEPTION_GPF, + EXCEPTION_PF +}; + +typedef void (*kernel_isr_handler_t)(ivt_state_t*); +extern kernel_isr_handler_t kernel_isr_handles[256]; + void kpanic_state(ivt_state_t *state, const char *fmt, ...); void ivt_setup(void); diff --git a/include/arch/x86_64/processor.h b/include/arch/x86_64/processor.h index 7363c41..5e878b9 100644 --- a/include/arch/x86_64/processor.h +++ b/include/arch/x86_64/processor.h @@ -51,6 +51,7 @@ enum #define GDT_OFFSET_KERNEL_CODE (GDT_ENTRY_KERNEL_CODE * sizeof(segment_descriptor_t)) #define GDT_OFFSET_KERNEL_DATA (GDT_ENTRY_KERNEL_DATA * sizeof(segment_descriptor_t)) +#define GDT_OFFSET_USER_NULL (GDT_ENTRY_USER_NULL * sizeof(segment_descriptor_t)) #define GDT_OFFSET_USER_DATA (GDT_ENTRY_USER_DATA * sizeof(segment_descriptor_t)) #define GDT_OFFSET_USER_CODE (GDT_ENTRY_USER_CODE * sizeof(segment_descriptor_t)) #define GDT_OFFSET_TSS (GDT_ENTRY_TSS_LOW * sizeof(segment_descriptor_t)) @@ -60,7 +61,9 @@ typedef struct jove_Processor physptr_t pdir; struct jove_ObjectDirectory *odir; + __attribute__((aligned(0x10))) segment_descriptor_t gdt[GDT_ENTRY_COUNT]; + struct { uint16_t length; uint64_t base; @@ -70,7 +73,9 @@ typedef struct jove_Processor uint64_t base; } __attribute__((packed)) idtr; + __attribute__((aligned(0x10))) tss_t tss; + tcb_t *tcb; } processor_t; diff --git a/include/init.h b/include/init.h index 2821926..f21afa6 100644 --- a/include/init.h +++ b/include/init.h @@ -1,20 +1,8 @@ #ifndef _JOVE_INIT_H #define _JOVE_INIT_H 1 -#include <stdint.h> - -enum { - INIT_OBJECT_ROOTDIR = 0, - INIT_OBJECT_TCB, - INIT_OBJECT_PAGEMAP, - INIT_OBJECT_PROCESSOR_DIR, - INIT_OBJECT_UNTYPED_DIR, - INIT_OBJECT_INITRD_DIR, - INIT_OBJECT_MESSAGE, - INIT_OBJECT_LOG -}; - #include "object.h" +#include "api/init.h" extern objdir_t _initDirectory; void init_load(void); diff --git a/syscall/invoke-untyped.c b/syscall/invoke-untyped.c index ae9482f..1168d77 100644 --- a/syscall/invoke-untyped.c +++ b/syscall/invoke-untyped.c @@ -70,7 +70,7 @@ s_handle_invoke_untyped_split( }; size_t *split = ko_entry_data(dest_entry); -*untyped -= dest_bytes; + *untyped -= dest_bytes; *split = dest_bytes; #ifdef DBG_SYSCALL diff --git a/syscall/invoke_objdir.c b/syscall/invoke_objdir.c index 8f0a923..86dc40c 100644 --- a/syscall/invoke_objdir.c +++ b/syscall/invoke_objdir.c @@ -36,9 +36,6 @@ s_handle_invoke_objdir_lastmemb( size_t payload_at ) { - path_byte_t *dest; - SYSCALL_PAYLOAD_TAKEP(payload, payload_at, dest, path_byte_t); - uint8_t lastfull = 0; for(int i = 1; i < 256; i++) { if(target_dir->entries[i].type != KO_NONE) lastfull = i; @@ -47,7 +44,7 @@ s_handle_invoke_objdir_lastmemb( #ifdef DBG_SYSCALL klogf("%i\n", lastfull); #endif - *dest = lastfull; + payload[0] = lastfull; return 0; } |