diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/x86_64/device/processor.c (renamed from arch/x86_64/processor.c) | 0 | ||||
-rw-r--r-- | arch/x86_64/ivt.s | 2 | ||||
-rw-r--r-- | arch/x86_64/page-mapping.c | 15 | ||||
-rw-r--r-- | arch/x86_64/page_directory.c | 2 | ||||
-rw-r--r-- | arch/x86_64/syscall/invoke-mapping.c (renamed from arch/x86_64/syscall-invoke-mapping.c) | 126 | ||||
-rw-r--r-- | arch/x86_64/syscall/syscall.c (renamed from arch/x86_64/syscall.c) | 0 | ||||
-rw-r--r-- | arch/x86_64/syscall/wrappers.h | 14 |
7 files changed, 93 insertions, 66 deletions
diff --git a/arch/x86_64/processor.c b/arch/x86_64/device/processor.c index f7e5cac..f7e5cac 100644 --- a/arch/x86_64/processor.c +++ b/arch/x86_64/device/processor.c diff --git a/arch/x86_64/ivt.s b/arch/x86_64/ivt.s index 0005686..a64f6b7 100644 --- a/arch/x86_64/ivt.s +++ b/arch/x86_64/ivt.s @@ -13,9 +13,9 @@ idt_load: .type __isr_head @function __isr_head: pushall - movq %rsp, %rdi cld + movq %rsp, %rdi call isr_handle popall diff --git a/arch/x86_64/page-mapping.c b/arch/x86_64/page-mapping.c new file mode 100644 index 0000000..0de5bfa --- /dev/null +++ b/arch/x86_64/page-mapping.c @@ -0,0 +1,15 @@ +#include "arch/x86_64/page-mapping.h" +#include "arch/x86_64/page.h" +#include <stddef.h> + +pmle_t* +page_mapping_traverse(pmle_t *pml4, uint8_t depth, uint16_t *path) +{ + uint16_t pathi = path[0]; + + pmle_t *pmle = &pml4[pathi]; + pmle_t *pmle_table = vmem_phys_tovirt(pmle->paddr << 12); + if(depth == 0) return pmle; + if(!pmle->p) return NULL; + return page_mapping_traverse(pmle_table, depth - 1, path + 1); +} diff --git a/arch/x86_64/page_directory.c b/arch/x86_64/page_directory.c index 494cab5..7030b05 100644 --- a/arch/x86_64/page_directory.c +++ b/arch/x86_64/page_directory.c @@ -114,6 +114,6 @@ vmem_setup(void) //Add page mapping object to init directory. _initDirectory.entries[INIT_OBJECT_PAGEMAP] = (objdir_entry_t) { .type = KO_MEMORY_MAPPING, - .data = kernel_pml4_base | 3 + .data = kernel_pml4_base }; } diff --git a/arch/x86_64/syscall-invoke-mapping.c b/arch/x86_64/syscall/invoke-mapping.c index 5b79239..be401d6 100644 --- a/arch/x86_64/syscall-invoke-mapping.c +++ b/arch/x86_64/syscall/invoke-mapping.c @@ -1,4 +1,4 @@ -#include "syscall/handles.h" +#include "arch/x86_64/syscall/wrappers.h" #include "arch/x86_64/syscall.h" #include "arch/x86_64/page.h" #include <stddef.h> @@ -9,54 +9,21 @@ #include "print.h" static int -s_handle_invoke_mapping_release( - objdir_t *root_dir, - objdir_entry_t *target_entry, - uint8_t *payload, - 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; -} - -static int -s_handle_invoke_mapping_get( +s_handle_invoke_mapping_exists( 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; + pmle_t *pml4 = (pmle_t*)vmem_phys_tovirt(target_entry->data); + 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; - 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) - }; #ifdef DBG_SYSCALL - klogf("Get pml%i %p[%i] -> %p\n", level, target_pml, pmli, dest_entry->data & ~3ULL); + klogf("pml d%i %p from %p exists\n", target_depth, target_pml, pml4); #endif return 0; } @@ -69,15 +36,11 @@ s_handle_invoke_mapping_map( 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; - if(level < 0) return KE_BADOBJ; + pmle_t *pml4 = (pmle_t*)vmem_phys_tovirt(target_entry->data); + pmle_t *target_pml; + uint8_t target_depth; + SYSCALL_PAYLOAD_TAKEPML(payload, payload_at, pml4, target_depth, target_pml); + if(target_pml == NULL) return KE_DNE; size_t untyped_pathw; objdir_entry_t *untyped_entry; @@ -98,32 +61,67 @@ s_handle_invoke_mapping_map( 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 = untyped_phys | PAGE_RW | PAGE_US | PAGE_PRESENT; - if(level != 0) { + target_pml->value = untyped_phys | PAGE_RW | PAGE_US | PAGE_PRESENT; + __asm__ volatile("invlpg (%0)":: "r"(untyped): "memory"); + + if(target_depth != 3) { memset(untyped, 0, 0x1000); } - untyped_entry->type = KO_MEMORY_MAPPING; - untyped_entry->data |= level - 1; - + untyped_entry->type = KO_NONE; #ifdef DBG_SYSCALL - klogf("map %p[%p] to pml%i %p[%i]\n", untyped_entry, untyped_phys, level, target_pml, pmli); + klogf("map %p[%i] to %p[%i]\n", untyped_phys, target_depth, target_pml, ((uintptr_t)target_pml & 0xFFF) / 8); #endif mtx_release(&untyped_entry->lock); return 0; } +static int +s_handle_invoke_mapping_unmap( + objdir_t *root_dir, + objdir_entry_t *target_entry, + uint8_t *payload, + size_t payload_at + ) +{ + pmle_t *pml4 = (pmle_t*)vmem_phys_tovirt(target_entry->data); + 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_depth != 3) { + for(pmli_t i = 0; i < 512; i++) { + if(target_pml[i].p) return KE_FULL; + } + } + + target_pml->p = false; + + objdir_entry_t *dest_entry; + size_t dest_pathw; + SYSCALL_PAYLOAD_TAKEOBJ(payload, payload_at, dest_pathw, dest_entry); + + if(dest_entry->type != KO_NONE) return KE_FULL; + uintptr_t pmle_addr = target_pml->paddr << 12; + size_t *untyped = vmem_phys_tovirt(pmle_addr); + __asm__ volatile("invlpg (%0)":: "r"(untyped): "memory"); + + *untyped = 0x1000; + dest_entry->type = KO_MEMORY_UNTYPED; + dest_entry->data = pmle_addr; + +#ifdef DBG_SYSCALL + klogf("unmap %p[%i] to untyped %p\n", target_pml, 3 - target_depth, pmle_addr); +#endif + 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_EXISTS] = s_handle_invoke_mapping_exists, [INVOKE_MAPPING_MAP] = s_handle_invoke_mapping_map, + [INVOKE_MAPPING_UNMAP] = s_handle_invoke_mapping_unmap }; static size_t s_invoke_handles_count = sizeof(s_invoke_handles) / sizeof(void*); diff --git a/arch/x86_64/syscall.c b/arch/x86_64/syscall/syscall.c index 5582336..5582336 100644 --- a/arch/x86_64/syscall.c +++ b/arch/x86_64/syscall/syscall.c diff --git a/arch/x86_64/syscall/wrappers.h b/arch/x86_64/syscall/wrappers.h new file mode 100644 index 0000000..a6fdf88 --- /dev/null +++ b/arch/x86_64/syscall/wrappers.h @@ -0,0 +1,14 @@ +#ifndef _JOVE_ARCH_x86_64_SYSCALL_WRAPPERS_H +#define _JOVE_ARCH_x86_64_SYSCALL_WRAPPERS_H 1 + +#include "arch/x86_64/page-mapping.h" +#include "syscall/handles.h" + +#define SYSCALL_PAYLOAD_TAKEPML(payload, at, pml4, depth, pml) \ + SYSCALL_PAYLOAD_TAKEL(payload, at, depth, uint8_t); \ + if(((depth + 1) * sizeof(uint16_t)) + at >= KO_MESSAGE_BYTES) return KE_BADMSG; \ + if(depth == 0 && *(uint16_t*)&payload[at] > 255) return KE_OOB; \ + pml = page_mapping_traverse(pml4, depth, (uint16_t*)&payload[at]); \ + at += (depth + 1) * sizeof(uint16_t) + +#endif |