From 548506392b789f58b1556a6ffca917441e1d89fd Mon Sep 17 00:00:00 2001 From: Jon Santmyer Date: Tue, 13 Oct 2026 22:31:43 -0400 Subject: ipc functions. work on process spawning --- arch/x86_64/hal/obj.h | 4 +- arch/x86_64/hal/paging.c | 112 +++++++++++++++++++++++++++++++++---------- arch/x86_64/hal/paging.h | 7 ++- arch/x86_64/hal/smp.c | 3 ++ arch/x86_64/hal/smp.h | 6 ++- arch/x86_64/proc/init.c | 20 ++++---- arch/x86_64/proc/process.c | 41 ++++++++++++++++ arch/x86_64/proc/process.h | 8 ++-- arch/x86_64/proc/scheduler.c | 30 +++++++++++- arch/x86_64/proc/switch.s | 10 ---- arch/x86_64/sys/link.c | 69 ++++++++++++++++++++------ arch/x86_64/sys/link.h | 15 ++++++ 12 files changed, 252 insertions(+), 73 deletions(-) create mode 100644 arch/x86_64/sys/link.h (limited to 'arch/x86_64') diff --git a/arch/x86_64/hal/obj.h b/arch/x86_64/hal/obj.h index 4364348..b939406 100644 --- a/arch/x86_64/hal/obj.h +++ b/arch/x86_64/hal/obj.h @@ -15,8 +15,8 @@ enum typedef union jove_obj { struct { - uint8_t type; atomic_flag lock; + uint8_t type; /*Raw value or pointer to a data-structure located in identity memory.*/ uint64_t value : 48; }; @@ -33,7 +33,5 @@ typedef struct jove_locked_obj /*Object directories are always 1 page wide. Since an object inside the directory * in this arch is a pointer width, that is 512 entries per directory.*/ -#define JOVE_OBJDIR_SIZE 0x1000 -#define JOVE_OBJDIR_ENTRIES (JOVE_OBJDIR_SIZE / sizeof(jove_obj_t)) #endif diff --git a/arch/x86_64/hal/paging.c b/arch/x86_64/hal/paging.c index 535d5b2..d5bcee3 100644 --- a/arch/x86_64/hal/paging.c +++ b/arch/x86_64/hal/paging.c @@ -22,6 +22,14 @@ PAGEALIGN page_t _kernel_pml1[512]; PAGEALIGN static page_t ident_pml3[IDENT_MASSIVEPAGES][512]; PAGEALIGN static page_t ident_pml2[IDENT_GIANTPAGES][512]; +virtaddr_t __syscall_stack_guard; +virtaddr_t __syscall_stack; +virtaddr_t __interrupt_stack_guard; +virtaddr_t __interrupt_stack; + +virtaddr_t *__syscall_stack_mapping; +virtaddr_t *__interrupt_stack_mapping; + void* phys_tovirt(uintptr_t phys) { @@ -95,7 +103,7 @@ s_pagedir_get_pml1(page_t *pml4, uintptr_t vptr) return 0; } - #define PML_TBL(tbl, i) (page_t*)(((uintptr_t)tbl[i].paddr << 12) | IDENT_VIRT_BASE) + #define PML_TBL(tbl, i) (page_t*)(((uintptr_t)tbl[i].pfn << 12) | IDENT_VIRT_BASE) page_t *pml3 = PML_TBL(pml4, pml4i); size_t pml3i = PML3I(vptr); @@ -137,18 +145,48 @@ uintptr_t *pagedir_get_mapping(jove_owned_obj_t *pagedir, uintptr_t vptr) return (uintptr_t*)mapping; } -uintptr_t +size_t +pagedir_mapping_get_pfn(virtaddr_t *mapping) +{ + return ((page_t*)mapping)->pfn; +} + +virtaddr_t pagedir_ident_from_mapping(uintptr_t *mapping) { - return (((page_t*)mapping)->paddr << 12) | IDENT_VIRT_BASE; + return (((page_t*)mapping)->pfn << 12) | IDENT_VIRT_BASE; +} + +inline bool pagedir_mapping_is_present(virtaddr_t *mapping) +{ + return ((page_t*)mapping)->p; +} + +inline void pagedir_mapping_set_pfn(virtaddr_t *mapping, size_t pfn) +{ + ((page_t*)mapping)->pfn = pfn; } -void -pagedir_mapping_set_present(uintptr_t *mapping, bool present) +inline void pagedir_mapping_set_present(virtaddr_t *mapping, bool present) { ((page_t*)mapping)->p = present; } +inline void pagedir_mapping_set_writeable(virtaddr_t *mapping, bool rw) +{ + ((page_t*)mapping)->rw = rw; +} + +inline void pagedir_mapping_set_user(virtaddr_t *mapping, bool user) +{ + ((page_t*)mapping)->u = user; +} + +inline void pagedir_mapping_set_type(virtaddr_t *mapping, int type) +{ + ((page_t*)mapping)->mapping_type = type; +} + int pagedir_map_frame(page_t *pml4, uintptr_t pptr, uintptr_t vptr, uintmax_t flg) @@ -165,11 +203,11 @@ int pagedir_map_frame(page_t *pml4, return 0; } -int pagedir_map_shmem(page_t *pml4, +int pagedir_map_frame_type(page_t *pml4, uintptr_t pptr, uintptr_t vptr, - struct syscall_pagedir_flags flg) + struct syscall_pagedir_flags flg, int type) { - uintmax_t real_flg = PAGE_USER | PAGE_SHMEM; + uintmax_t real_flg = PAGE_USER | (type << PAGE_SHL_TYPE); if(flg.writeable) { real_flg |= PAGE_WRITEABLE; } @@ -191,9 +229,7 @@ int pagedir_map_untyped_frame( } uintptr_t frame = obj_getvalue(untyped->obj); - return pagedir_map_frame(pml4, frame, vptr, PAGE_USER | - (flg.writeable ? PAGE_WRITEABLE : 0) | - (flg.executable ? 0 : PAGE_XD)); + return pagedir_map_frame_type(pml4, frame, vptr, flg, JOVE_MAPPING_TYPE_UNTYPED); } int pagedir_map_table(page_t *pml4, @@ -209,7 +245,7 @@ int pagedir_map_table(page_t *pml4, goto map_table; } - page_t *pml3 = (page_t*)(((uintptr_t)pml4[pml4i].paddr << 12) + page_t *pml3 = (page_t*)(((uintptr_t)pml4[pml4i].pfn << 12) | IDENT_VIRT_BASE); size_t pml3i = PML3I(vptr); if(!pml3[pml3i].p) { @@ -217,7 +253,7 @@ int pagedir_map_table(page_t *pml4, goto map_table; } - page_t *pml2 = (page_t*)(((uintptr_t)pml3[pml3i].paddr << 12) + page_t *pml2 = (page_t*)(((uintptr_t)pml3[pml3i].pfn << 12) | IDENT_VIRT_BASE); size_t pml2i = PML2I(vptr); if(!pml2[pml2i].p) { @@ -265,9 +301,7 @@ int pagedir_map_shmem_frame( uintptr_t frame = value & ~0xFF; frame += (uintmax_t)page_offset << 12; - return pagedir_map_frame(pml4, frame, vptr, PAGE_USER | - (flg.writeable ? PAGE_WRITEABLE : 0) | - (flg.executable ? 0 : PAGE_XD)); + return pagedir_map_frame_type(pml4, frame, vptr, flg, JOVE_MAPPING_TYPE_SHMEM); } int pagedir_unmap_untyped_frame( @@ -276,13 +310,14 @@ int pagedir_unmap_untyped_frame( page_t *pml4 = obj_deref(tgt); size_t pml4i = PML4I(vptr); - if(!pml4[pml4i].p) return ENOMAP; + if(!pml4[pml4i].p) return -ENOMAP; page_t *pml1 = s_pagedir_get_pml1(pml4, vptr); size_t pml1i = PML1I(vptr); - if(!pml1[pml1i].p) return ENOMAP; + if(!pml1[pml1i].p) return -ENOMAP; - uintptr_t untyped_pptr = (pml1[pml1i].paddr << 12); + if(pml1[pml1i].mapping_type != JOVE_MAPPING_TYPE_UNTYPED) return -ENOMAP; + uintptr_t untyped_pptr = (pml1[pml1i].pfn << 12); obj_settype(dst, JOVE_OBJ_UNTYPED); obj_setvalue(dst, untyped_pptr); @@ -294,6 +329,26 @@ int pagedir_unmap_untyped_frame( return 0; } +int pagedir_unmap_shmem_frame( + jove_owned_obj_t *tgt, uintptr_t vptr) +{ + page_t *pml4 = obj_deref(tgt); + + size_t pml4i = PML4I(vptr); + if(!pml4[pml4i].p) return -ENOMAP; + + page_t *pml1 = s_pagedir_get_pml1(pml4, vptr); + size_t pml1i = PML1I(vptr); + if(!pml1[pml1i].p) return -ENOMAP; + + if(pml1[pml1i].mapping_type != JOVE_MAPPING_TYPE_UNTYPED) return -ENOMAP; + + pml1[pml1i].p = 0; + pagedir_invlpg(vptr); + + return 0; +} + int pagedir_unmap_untyped_table( jove_owned_obj_t *tgt, jove_owned_obj_t *dst, uintptr_t vptr) { @@ -304,12 +359,12 @@ int pagedir_unmap_untyped_table( //trying to unmap the entire address space. We don't support this. size_t pml4i = PML4I(vptr); if(!pml4[pml4i].p) { - return ENOMAP; + return -ENOMAP; } target_table = &pml4[pml4i]; //Try to unmap the pml4 entry if the pml3 entry does not exist. - page_t *pml3 = (page_t*)(((uintptr_t)pml4[pml4i].paddr << 12) | IDENT_VIRT_BASE); + page_t *pml3 = (page_t*)(((uintptr_t)pml4[pml4i].pfn << 12) | IDENT_VIRT_BASE); size_t pml3i = PML3I(vptr); if(!pml3[pml3i].p) { goto unmap_table; @@ -317,7 +372,7 @@ int pagedir_unmap_untyped_table( target_table = &pml3[pml3i]; //Try to unmap the pml3 entry if the pml2 entry does not exist. - page_t *pml2 = (page_t*)(((uintptr_t)pml3[pml3i].paddr << 12) | IDENT_VIRT_BASE); + page_t *pml2 = (page_t*)(((uintptr_t)pml3[pml3i].pfn << 12) | IDENT_VIRT_BASE); size_t pml2i = PML2I(vptr); if(!pml2[pml2i].p) { goto unmap_table; @@ -327,13 +382,13 @@ int pagedir_unmap_untyped_table( unmap_table: { - uintptr_t frame = target_table->paddr << 12; + uintptr_t frame = target_table->pfn << 12; page_t *target_vals = (page_t*)(frame | IDENT_VIRT_BASE); //Check that the page table at our target entry is empty. //If it's not, we return an error saying that the entry contains a map. for(size_t i = 0; i < 512; i++) { - if(target_vals[i].p) return EHASMAP; + if(target_vals[i].p) return -EHASMAP; } //Populate the none object with an untyped object at the free'd page frame. @@ -421,6 +476,15 @@ paging_pml4_init(void) | PAGE_PRESENT | PAGE_WRITEABLE | PAGE_GLOBAL | PAGE_XD; } + size_t kernel_stack_off = kernel_data_off + kernel_data_pages; + __syscall_stack_guard = ((kernel_stack_off) << 12) + KERNEL_VIRT_BASE; + __syscall_stack = __syscall_stack_guard + 0x1000; + __interrupt_stack_guard = __syscall_stack + 0x1000; + __interrupt_stack = __interrupt_stack_guard + 0x1000; + + __syscall_stack_mapping = (virtaddr_t*)&_kernel_pml1[kernel_stack_off + 1]; + __interrupt_stack_mapping = (virtaddr_t*)&_kernel_pml1[kernel_stack_off + 3]; + /*Identity pages are mapped as huge pages starting at the 256'th PML3 entry. *We want to support any range of physical memory up to several TiB, so *the mapper has to consider multiple heirarchies of huge pages.*/ diff --git a/arch/x86_64/hal/paging.h b/arch/x86_64/hal/paging.h index becf353..6edac0c 100644 --- a/arch/x86_64/hal/paging.h +++ b/arch/x86_64/hal/paging.h @@ -17,10 +17,9 @@ typedef union page_table_entry uint8_t d : 1; uint8_t ps : 1; uint8_t g : 1; - uint8_t shm : 1; - uint8_t ign_0 : 1; + uint8_t mapping_type : 2; uint8_t r : 1; - uint64_t paddr : 35; + uint64_t pfn : 35; uint8_t ign_1 : 4; uint8_t pkey : 4; uint8_t xd : 1; @@ -37,7 +36,7 @@ typedef union page_table_entry #define PAGE_DIRTY 0b1000000 #define PAGE_PS 0b10000000 #define PAGE_GLOBAL 0b100000000 -#define PAGE_SHMEM 0b1000000000 +#define PAGE_SHL_TYPE 9 #define PAGE_XD (1ULL << 63) extern void *_kernel_physptr; diff --git a/arch/x86_64/hal/smp.c b/arch/x86_64/hal/smp.c index 392e68f..7d94340 100644 --- a/arch/x86_64/hal/smp.c +++ b/arch/x86_64/hal/smp.c @@ -1,4 +1,5 @@ #include "smp.h" +#include "hal/memory.h" #include "proc/init.h" #include "config.h" #include "jove.h" @@ -57,6 +58,8 @@ smp_init_bsp(void) idt_init(); paging_pml4_init(); + + bsp->tss.rsp[0] = __interrupt_stack; } inline processor_t *processor_current(void) diff --git a/arch/x86_64/hal/smp.h b/arch/x86_64/hal/smp.h index b26d4ac..0f0fc40 100644 --- a/arch/x86_64/hal/smp.h +++ b/arch/x86_64/hal/smp.h @@ -1,6 +1,7 @@ #ifndef _JOVE_x86_64_HAL_SMP_H #define _JOVE_x86_64_HAL_SMP_H 1 +#include "arch/x86_64/hal/paging.h" #include "arch/x86_64/proc/process.h" #include "gdt.h" #include "hal/obj.h" @@ -11,7 +12,10 @@ typedef struct processor struct gdt_entry gdt[GDT_TSS_HI+1]; struct tss tss; uint8_t iopb[0x2000]; - + + page_t syscall_page; + page_t interrupt_page; + jove_owned_obj_t *pcb_obj; pcb_t *pcb; } processor_t; diff --git a/arch/x86_64/proc/init.c b/arch/x86_64/proc/init.c index 155cff6..8003a6d 100644 --- a/arch/x86_64/proc/init.c +++ b/arch/x86_64/proc/init.c @@ -5,6 +5,7 @@ #include "jove.h" #include "hal/obj.h" #include "lib/string.h" +#include "sys/message.h" #include "sys/objdir.h" #include "panic/panic.h" #include "lib/printf.h" @@ -126,20 +127,19 @@ init_setup(void) //Map the syscall message. last_base = (last_base + 0xFFF) & ~0xFFF; jove_owned_obj_t message_frame = init_pop_alloc(); - pagedir_map_frame(pml4, obj_getvalue(&message_frame), last_base, - PAGE_WRITEABLE | PAGE_USER | PAGE_XD); + jove_owned_obj_t *message_obj = objdir_getlocal(_rootdir_obj, INIT_ROOTDIR_MESSAGE_I); + + message_new(&message_frame); + objdir_swapobj(message_obj, &message_frame); + message_map(message_obj, init_pagedir, last_base); + + obj_release(init_pagedir); - extern struct init_payload _init_payload; _init_payload.brk = last_base + 0x1000; + //Copy init payload into syscall message. + extern struct init_payload _init_payload; memcpy((void*)last_base, &_init_payload, sizeof(struct init_payload)); - - jove_owned_obj_t *message_obj = objdir_getlocal(_rootdir_obj, INIT_ROOTDIR_MESSAGE_I); - obj_settype(message_obj, JOVE_OBJ_MESSAGE); - obj_setvalue(message_obj, last_base | 1); - obj_release(message_obj); - - obj_release(init_pagedir); //Enable syscalls extern void _syscall_entry(void); diff --git a/arch/x86_64/proc/process.c b/arch/x86_64/proc/process.c index 5935303..b10d538 100644 --- a/arch/x86_64/proc/process.c +++ b/arch/x86_64/proc/process.c @@ -40,3 +40,44 @@ processing_setup(void (*process_main)) scheduler_init(init_pcb_obj, process_main); } + +inline physaddr_t +pcb_get_syscall_stack(pcb_t *pcb) +{ + return pcb->syscall_page.pfn << 12; +} + +inline physaddr_t +pcb_get_interrupt_stack(pcb_t *pcb) +{ + return pcb->interrupt_page.pfn << 12; +} + +physaddr_t +pcb_set_syscall_stack(pcb_t *pcb, physaddr_t page) +{ + physaddr_t old_page = pcb_get_syscall_stack(pcb); + pcb->syscall_page.pfn = page >> 12; + pcb->syscall_page.p = 1; + pcb->syscall_page.rw = 1; + return old_page; +} +physaddr_t +pcb_set_interrupt_stack(pcb_t *pcb, physaddr_t page) +{ + physaddr_t old_page = pcb_get_interrupt_stack(pcb); + pcb->interrupt_page.pfn = page >> 12; + pcb->interrupt_page.p = 1; + pcb->interrupt_page.rw = 1; + return old_page; +} + +inline void pcb_map_syscall_stack(pcb_t *pcb) +{ + *__syscall_stack_mapping = pcb->syscall_page.value; +} + +inline void pcb_map_interrupt_stack(pcb_t *pcb) +{ + *__interrupt_stack_mapping = pcb->interrupt_page.value; +} diff --git a/arch/x86_64/proc/process.h b/arch/x86_64/proc/process.h index 5004b49..866184b 100644 --- a/arch/x86_64/proc/process.h +++ b/arch/x86_64/proc/process.h @@ -3,16 +3,16 @@ #include "proc/process.h" #include "lib/rbtree.h" +#include "arch/x86_64/hal/paging.h" typedef struct process_control_block { struct pcb_header header; jove_obj_t *iopb; - - char kstack[]; -} pcb_t; -#define PCB_KSTACK_SIZE (0x1000 - sizeof(pcb_t)) + page_t syscall_page; + page_t interrupt_page; +} pcb_t; #endif diff --git a/arch/x86_64/proc/scheduler.c b/arch/x86_64/proc/scheduler.c index 23e54af..49a0c4d 100644 --- a/arch/x86_64/proc/scheduler.c +++ b/arch/x86_64/proc/scheduler.c @@ -1,14 +1,16 @@ #include "proc/scheduler.h" #include "arch/x86_64/hal/gdt.h" +#include "lib/string.h" #include "process.h" #include "../hal/smp.h" -#include +#include "../proc/process.h" void _scheduler_switch_pcb_arch(pcb_t *target) { processor_t *proc = processor_current(); - proc->tss.rsp[0] = (uintptr_t)target->header.ksp; + proc->syscall_page = target->interrupt_page; + proc->interrupt_page = target->interrupt_page; if(target->iopb) { proc->tss.iopb = sizeof(struct tss); @@ -18,3 +20,27 @@ _scheduler_switch_pcb_arch(pcb_t *target) proc->tss.iopb = 0xff; } } + +__attribute__((naked)) +void scheduler_switch(void *this_sp, void *other_sp, void *new_cr3) +{ + __asm__ volatile("\ + movq %%rsp, (%%rdi); \ + movq %%rsi, %%rsp; \ + movq %%cr3, %%rax; \ + cmp %%rax, %%rdx; \ + je .nocr3swap; \ + movq %%rdx, %%cr3; \ + .nocr3swap: \ + movq %%gs:%c[syscall_page], %%rax; \ + movq %%rax, __syscall_stack_mapping; \ + movq (__syscall_stack), %%rax; \ + invlpg (%%rax); \ + movq %%gs:%c[interrupt_page], %%rax; \ + movq %%rax, __interrupt_stack_mapping; \ + movq (__interrupt_stack), %%rax; \ + invlpg (%%rax); \ + retq":: + [syscall_page] "i"(offsetof(processor_t, syscall_page)), + [interrupt_page] "i"(offsetof(processor_t, interrupt_page))); +} diff --git a/arch/x86_64/proc/switch.s b/arch/x86_64/proc/switch.s index 16b2198..028a949 100644 --- a/arch/x86_64/proc/switch.s +++ b/arch/x86_64/proc/switch.s @@ -1,13 +1,3 @@ -.global scheduler_switch -.type scheduler_switch @function - -scheduler_switch: - movq %rsp, (%rdi) - movq %rsi, %rsp - retq - -.size scheduler_switch, . - scheduler_switch - .global scheduler_savestate .type scheduler_savestate @function diff --git a/arch/x86_64/sys/link.c b/arch/x86_64/sys/link.c index 96f8eeb..c8b08ec 100644 --- a/arch/x86_64/sys/link.c +++ b/arch/x86_64/sys/link.c @@ -1,19 +1,58 @@ #include "sys/link.h" +#include "api/obj.h" +#include "arch/x86_64/hal/paging.h" +#include "hal/memory.h" +#include "hal/obj.h" +#include "jove.h" +#include "sys/lock.h" -jove_obj_t -link_unlink(jove_owned_obj_t *link) +int link_new(jove_owned_obj_t *target_obj, jove_owned_obj_t *untyped_obj, uint8_t permissions) { - struct obj_link *linkval = obj_deref(link); - if(--linkval->refcount == 1) { - jove_obj_t held_obj = linkval->obj; - link->locked = held_obj; - return (jove_obj_t) { - .lock = 0, - .type = JOVE_OBJ_UNTYPED, - .value = (uintptr_t)linkval - }; - }else{ - obj_settype(link, JOVE_OBJ_NONE); - } - return (jove_obj_t) { 0 }; + jove_untyped_t *untyped = obj_deref(untyped_obj); + if(untyped->limit != sizeof(jove_link_obj_t)) return -EBADSIZE; + + jove_link_obj_t *link = (jove_link_obj_t*)untyped; + release_mutex(&link->lock); + link->permissions = permissions; + link->refcount = 2; + link->obj = target_obj->locked; + + obj_setvalue(target_obj, (uintptr_t)link); + obj_setvalue(untyped_obj, (uintptr_t)link); + + obj_settype(target_obj, JOVE_OBJ_LINK); + obj_settype(untyped_obj, JOVE_OBJ_LINK); + + return 0; +} + +int link_dup(jove_owned_obj_t *link_obj, jove_owned_obj_t *dest_obj) +{ + jove_link_obj_t *link = obj_deref(link_obj); + obj_settype(dest_obj, JOVE_OBJ_LINK); + obj_setvalue(dest_obj, obj_getvalue(link_obj)); + link->refcount++; + return 0; +} + +inline jove_owned_obj_t* +link_deref(jove_link_obj_t *link) +{ + return obj_take(&link->obj); } + +inline jove_owned_obj_t* +link_try_deref(jove_link_obj_t *link) +{ + return obj_trytake(&link->obj); +} + +inline void link_lock(jove_link_obj_t *link) +{ take_mutex(&link->lock); } +inline void link_unlock(jove_link_obj_t *link) +{ release_mutex(&link->lock); } + +inline uint8_t link_getperm(jove_link_obj_t *link) +{ return link->permissions; } +inline void link_setperm(jove_link_obj_t *link, uint8_t perm) +{ link->permissions = perm; } diff --git a/arch/x86_64/sys/link.h b/arch/x86_64/sys/link.h new file mode 100644 index 0000000..e826dc3 --- /dev/null +++ b/arch/x86_64/sys/link.h @@ -0,0 +1,15 @@ +#ifndef _JOVE_ARCH_SYS_LINK_H +#define _JOVE_ARCH_SYS_LINK_H 1 + +#include +#include "hal/obj.h" + +typedef struct link_obj +{ + jove_obj_t obj; + uint32_t refcount; + uint8_t permissions; + atomic_flag lock; +} jove_link_obj_t; + +#endif -- cgit v1.2.3