diff options
Diffstat (limited to 'arch/x86_64')
-rw-r--r-- | arch/x86_64/lock.s | 19 | ||||
-rw-r--r-- | arch/x86_64/memory.c | 16 | ||||
-rw-r--r-- | arch/x86_64/page_directory.c | 11 | ||||
-rw-r--r-- | arch/x86_64/processor.c | 12 | ||||
-rw-r--r-- | arch/x86_64/sse.s | 46 | ||||
-rw-r--r-- | arch/x86_64/syscall-invoke-mapping.c | 124 | ||||
-rw-r--r-- | arch/x86_64/syscall.c | 32 | ||||
-rw-r--r-- | arch/x86_64/untyped_retype_page.c | 13 | ||||
-rw-r--r-- | arch/x86_64/usermode.c | 38 |
9 files changed, 265 insertions, 46 deletions
diff --git a/arch/x86_64/lock.s b/arch/x86_64/lock.s new file mode 100644 index 0000000..b63f078 --- /dev/null +++ b/arch/x86_64/lock.s @@ -0,0 +1,19 @@ +.global _mtx_acquire +.type _mtx_acquire @function +_mtx_acquire: + lock btsw $0, (%rdi) + jc .spin + ret +.spin: + pause + testb $1, (%rdi) + jnz .spin + jmp _mtx_acquire +.size _mtx_acquire, . - _mtx_acquire + +.global _mtx_release +.type _mtx_release @function +_mtx_release: + movb $0, (%rdi) + ret +.size _mtx_release, . - _mtx_release diff --git a/arch/x86_64/memory.c b/arch/x86_64/memory.c new file mode 100644 index 0000000..b32d4e7 --- /dev/null +++ b/arch/x86_64/memory.c @@ -0,0 +1,16 @@ +#include "memory.h" +#include "arch/x86_64/page.h" +#include <stdint.h> + +void* +ko_entry_data(objdir_entry_t *entry) +{ + if((intmax_t)entry->data < 0) return (void*)entry->data; + return vmem_phys_tovirt(entry->data); +} + +uintptr_t +ko_data_toentry(uintptr_t vptr) +{ + return vmem_ident_tophys((void*)vptr); +} diff --git a/arch/x86_64/page_directory.c b/arch/x86_64/page_directory.c index 0506703..bcc71cf 100644 --- a/arch/x86_64/page_directory.c +++ b/arch/x86_64/page_directory.c @@ -6,6 +6,7 @@ #include "object.h" #include "string.h" #include "jove.h" +#include <stdint.h> physptr_t s_kpbase(void); @@ -45,6 +46,12 @@ pmle_get_page(pmle_t entry) return vmem_phys_tovirt(pptr); } +uint8_t +pmle_level(pmle_t entry) +{ + return entry.osflg; +} + __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 @@ -107,8 +114,8 @@ vmem_setup(void) //Add page mapping object to init directory. uint8_t pm_i = _initDirectory.self.data++; _initDirectory.entries[pm_i] = (objdir_entry_t) { - .type = KO_MEMORY_MAPPING_PAGE, - .data = kernel_pml4_base + .type = KO_MEMORY_MAPPING, + .data = kernel_pml4_base | 3 }; _initData.pm_object = pm_i; } diff --git a/arch/x86_64/processor.c b/arch/x86_64/processor.c index b39ba63..666eb3d 100644 --- a/arch/x86_64/processor.c +++ b/arch/x86_64/processor.c @@ -88,9 +88,21 @@ processor_setup(void *_processor) (uint32_t)((uintptr_t)_processor >> 32)); } +void enable_fpu(void); +void enable_sse(void); +void enable_avx(void); + void bsp_setup(void) { +#ifdef ENABLE_SSE + enable_fpu(); + enable_sse(); +#endif +#ifdef ENABLE_AVX + enable_avx(); +#endif + uint64_t pd_i = _initDirectory.self.data++; _initDirectory.entries[pd_i] = (objdir_entry_t) { diff --git a/arch/x86_64/sse.s b/arch/x86_64/sse.s new file mode 100644 index 0000000..8065188 --- /dev/null +++ b/arch/x86_64/sse.s @@ -0,0 +1,46 @@ +.global enable_fpu +.type enable_fpu @function +enable_fpu: + fninit + fldcw [fcw_init] + ret +.size enable_fpu, . - enable_fpu + +.global enable_sse +.type enable_sse @function +enable_sse: + movq %cr0, %rax + //Disable coprocessor emulation + and $0xFFFB, %ax + //Set coprocessor monitoring + or $0x22, %ax + //Save cr0 + movq %rax, %cr0 + movq %cr4, %rax + //Set CR4.OSFXR and CR4.OSXMMEXCEPT + or $3 << 9, %ax + movq %rax, %cr4 + ret +.size enable_sse, . - enable_sse + +.global enable_avx +.type enable_avx, @function +enable_avx: + pushq %rax + pushq %rcx + pushq %rdx + + xorq %rcx, %rcx + xgetbv + or $7, %eax + xsetbv + + popq %rdx + popq %rcx + popq %rax + ret +.size enable_avx, . - enable_avx + +.data +fcw_init: + .word 0x037F diff --git a/arch/x86_64/syscall-invoke-mapping.c b/arch/x86_64/syscall-invoke-mapping.c new file mode 100644 index 0000000..efecbdf --- /dev/null +++ b/arch/x86_64/syscall-invoke-mapping.c @@ -0,0 +1,124 @@ +#include "syscall/handles.h" +#include "arch/x86_64/syscall.h" +#include "arch/x86_64/page.h" +#include <stddef.h> +#include "error.h" +#include "lock.h" + +static int +s_handle_invoke_mapping_release( + objdir_t *root_dir, + objdir_entry_t *target_entry, + uint8_t *payload, + size_t payload_at + ) +{ + target_entry->data = 0; + target_entry->type = KO_NONE; + return 0; +} + +static int +s_handle_invoke_mapping_get( + objdir_t *root_dir, + objdir_entry_t *target_entry, + uint8_t *payload, + size_t payload_at + ) +{ + pmli_t pmli; + SYSCALL_PAYLOAD_TAKEL(payload, payload_at, pmli, pmli_t); + + 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; + + 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; + + pmle_t pmle = target_pml[pmli]; + 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) + }; + return 0; +} + +static int +s_handle_invoke_mapping_map( + objdir_t *root_dir, + objdir_entry_t *target_entry, + uint8_t *payload, + size_t payload_at + ) +{ + uint8_t level = target_entry->data & 3; + pmle_t *target_pml = (pmle_t*)vmem_phys_tovirt(target_entry->data & ~3ULL); + + 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; + + 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; + mtx_acquire(&untyped_entry->lock); + + if((untyped_entry->data & 0xFFF) != 0) { + mtx_release(&untyped_entry->lock); + return -KE_ALIGN; + } + size_t *untyped_data = (size_t*)untyped_entry->data; + size_t untyped_size = *untyped_data; + if(untyped_size != 0x1000) { + mtx_release(&untyped_entry->lock); + return -KE_BADSIZE; + } + + pmle_t pmle = target_pml[pmli]; + if(pmle.p) { + mtx_release(&untyped_entry->lock); + return -KE_OCCUPIED; + } + + target_pml[pmli].value = vmem_ident_tophys((void*)untyped_entry->data) | PAGE_RW | PAGE_US | PAGE_PRESENT; + untyped_entry->type = KO_MEMORY_MAPPING; + untyped_entry->data |= level - 1; + + mtx_release(&untyped_entry->lock); + return 0; +} + +static int (*s_invoke_handles[])(objdir_t*, objdir_entry_t*, uint8_t*, size_t) = { + [INVOKE_MAPPING_RELEASE] = s_handle_invoke_mapping_release, + [INVOKE_MAPPING_GET] = s_handle_invoke_mapping_get, + [INVOKE_MAPPING_MAP] = s_handle_invoke_mapping_map, +}; + +static size_t s_invoke_handles_count = sizeof(s_invoke_handles) / sizeof(void*); + +int +syscall_handle_invoke_mapping( + objdir_t *root_dir, + objdir_entry_t *target, + uint8_t *payload, + size_t payload_at + ) +{ + 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); +} diff --git a/arch/x86_64/syscall.c b/arch/x86_64/syscall.c index a563525..5582336 100644 --- a/arch/x86_64/syscall.c +++ b/arch/x86_64/syscall.c @@ -1,6 +1,36 @@ #include "arch/x86_64/processor.h" +#include "syscall/handles.h" +#include "print.h" +#include "lock.h" +#include "error.h" #include <stddef.h> - + +static inline int +s_invoke_release( + objdir_t *root_dir, + objdir_entry_t *target, + uint8_t *payload, + size_t payload_at, + int (*invoke)(objdir_t*, objdir_entry_t*, uint8_t*, size_t)) +{ + int e = invoke(root_dir, target, payload, payload_at); + mtx_release(&target->lock); + return e; +} + +int +_syscall_handler_arch(objdir_t *root_dir, objdir_entry_t *target, uint8_t *payload, size_t payload_at) +{ + switch(target->type) { + case KO_MEMORY_MAPPING: + return s_invoke_release(root_dir, target, payload, payload_at, syscall_handle_invoke_mapping); + default: + klogf("Missing implementation of invoke for type %i\n", target->type); + mtx_release(&target->lock); + return -KE_BADTYPE; + } +} + __attribute__((naked)) void _syscall_entry(void) { diff --git a/arch/x86_64/untyped_retype_page.c b/arch/x86_64/untyped_retype_page.c index 216d88d..32afe2c 100644 --- a/arch/x86_64/untyped_retype_page.c +++ b/arch/x86_64/untyped_retype_page.c @@ -36,16 +36,3 @@ int untyped_retype_page(objdir_entry_t *untyped_entry, void **dest) #endif return r; } - -int -untyped_retype_kernel_stack(objdir_entry_t *untyped_entry, objdir_entry_t *dest_entry) -{ - int r = s_untyped_retype(untyped_entry, KERNEL_STACK_SIZE, 1, (void**)(&dest_entry->data)); - if(r != 0) return r; - - dest_entry->type = KO_KERNEL_STACK; - #ifdef DBG_MEM - klogf("Untyped block %p retyped to kernel stack at %p\n", untyped_entry->data, dest_entry->data); - #endif - return r; -} diff --git a/arch/x86_64/usermode.c b/arch/x86_64/usermode.c index 9ce5ed3..66a641c 100644 --- a/arch/x86_64/usermode.c +++ b/arch/x86_64/usermode.c @@ -1,12 +1,10 @@ #include "arch/x86_64/object.h" #include "object.h" -#include "memory.h" #include "bootargs.h" #include "device/initrd.h" #include "object.h" #include "panic.h" #include "string.h" -#include "print.h" #include "device/processor.h" #include "arch/x86_64/page.h" @@ -28,23 +26,6 @@ s_new_mapping(objdir_t *untyped_dir) return 0; } -static uintptr_t -s_new_kstack(objdir_t *untyped_dir, objdir_entry_t *dest_entry) -{ - objdir_entry_t *untyped_entry = NULL; - for(int i = 1; i < OBJECT_DIRECTORY_MAX_ENTRIES; i++) { - untyped_entry = &untyped_dir->entries[i]; - if(untyped_entry->type != KO_MEMORY_UNTYPED) continue; - - int err = untyped_retype_kernel_stack(untyped_entry, dest_entry); - if(err != 0) continue; - - uintptr_t ptr = dest_entry->data; - return (uintptr_t)vmem_phys_tovirt(ptr); - } - return 0; -} - static pmle_t* s_ensure_mapping_layer(pmle_t *pml, objdir_t *untyped_dir, uintptr_t addr, uint8_t layer) { @@ -60,13 +41,14 @@ s_ensure_mapping_layer(pmle_t *pml, objdir_t *untyped_dir, uintptr_t addr, uint8 .p = 1, .rw = 1, .us = 1, + .osflg = (layer - 1) & 3, .paddr = table_phys >> 12 }; __asm__ volatile("invlpg (%0)":: "r"(table_phys)); return vmem_phys_tovirt(table_phys); } -static void +static uintptr_t s_map_page(pmle_t *pml4, objdir_t *untyped_dir, uintptr_t addr) { pmle_t *pml3 = s_ensure_mapping_layer(pml4, untyped_dir, addr, 4); @@ -82,9 +64,11 @@ s_map_page(pmle_t *pml4, objdir_t *untyped_dir, uintptr_t addr) .p = 1, .rw = 1, .us = 1, + .osflg = 0, .paddr = pptr >> 12 }; __asm__ volatile("invlpg (%0)":: "r"(addr)); + return pptr; } __attribute__((noreturn)) @@ -114,11 +98,9 @@ init_load(void) } size_t tcb_diri = _initDirectory.self.data++; - size_t kstack_diri = _initDirectory.self.data++; size_t message_diri = _initDirectory.self.data++; _initData.tcb_object = tcb_diri; - _initData.kernel_stack_object = kstack_diri; _initData.message_object = message_diri; _initDirectory.entries[tcb_diri] = (objdir_entry_t) { @@ -130,7 +112,7 @@ init_load(void) objdir_t *untyped_dir = (objdir_t*)_initDirectory.entries[untyped_diri].data; size_t pml4_diri = _initData.pm_object; - pmle_t *pml4 = vmem_phys_tovirt(_initDirectory.entries[pml4_diri].data); + pmle_t *pml4 = vmem_phys_tovirt(_initDirectory.entries[pml4_diri].data & ~3ULL); //Reserve and map pages for init binary size_t init_size = initrd_file_size(init_header); @@ -150,11 +132,7 @@ init_load(void) uintptr_t sp = stack_base + 0xFF0; //Create a kernel stack for the init TCB - uintptr_t ksp_base = (uintptr_t)s_new_kstack(untyped_dir, &_initDirectory.entries[kstack_diri]); - _initDirectory.entries[kstack_diri] = (objdir_entry_t) { - .type = KO_KERNEL_STACK, - .data = ksp_base - }; + uintptr_t ksp_base = (uintptr_t)s_init_tcb.kstack; s_init_tcb.ksp = ksp_base + 0xFF0; processor_t *proc = (processor_t*)processor_current(); @@ -164,10 +142,10 @@ init_load(void) uintptr_t message_base = init_base + (init_pages << 12); message_base += ((~(message_base & 0xFFF)) & 0xFFF) + 1; - s_map_page(pml4, untyped_dir, message_base); + uintptr_t message_phys = s_map_page(pml4, untyped_dir, message_base); _initDirectory.entries[message_diri] = (objdir_entry_t) { .type = KO_MESSAGE, - .data = message_base + .data = (uintptr_t)vmem_phys_tovirt(message_phys) }; _initData.message_object_address = message_base; |