From 19d58ec71da2fd05f0bbfc21bdc6375f75bb7b0f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Lov=C3=A9n?= Date: Wed, 28 Feb 2018 22:02:20 +0100 Subject: [PATCH] Functions for copying stuff between kernel and user space --- src/kernel/boot/kmain.c | 5 ++-- src/kernel/include/memory.h | 2 ++ src/kernel/memory/vmm.c | 46 +++++++++++++++++++++++++++++++++++++ 3 files changed, 50 insertions(+), 3 deletions(-) diff --git a/src/kernel/boot/kmain.c b/src/kernel/boot/kmain.c index bbd10a8..0b7f20e 100644 --- a/src/kernel/boot/kmain.c +++ b/src/kernel/boot/kmain.c @@ -29,9 +29,8 @@ void kmain(uint64_t multiboot_magic, void *multiboot_data) cpu_init(); struct process *p1 = new_process((void (*)(void))0x10000); - uint64_t page = pmm_alloc(); - vmm_set_page(p1->P4, 0x10000, page, PAGE_WRITE | PAGE_PRESENT | PAGE_USER); - memcpy(P2V(page), (void *)(uintptr_t)thread_function, PAGE_SIZE); + vmm_set_page(p1->P4, 0x10000, pmm_calloc(), PAGE_WRITE | PAGE_PRESENT | PAGE_USER); + memcpy_k2u(p1->P4, (void *)0x10000, (void *)(uintptr_t)thread_function, 100); ready(p1); diff --git a/src/kernel/include/memory.h b/src/kernel/include/memory.h index 13e8035..849cd9f 100644 --- a/src/kernel/include/memory.h +++ b/src/kernel/include/memory.h @@ -45,6 +45,8 @@ uint64_t vmm_get_page(uint64_t P4, uint64_t addr); #define PAGE_EXIST(p) ((p) != (uint64_t)-1) int vmm_set_page(uint64_t P4, uint64_t addr, uint64_t page, uint16_t flags); void vmm_clear_page(uint64_t P4, uint64_t addr, int free); +size_t memcpy_k2u(uint64_t P4, void *dst, void *src, size_t n); +size_t memcpy_u2k(void *dst, uint64_t P4, void *src, size_t n); extern union PTE BootP4; extern int kernel_start, kernel_end; diff --git a/src/kernel/memory/vmm.c b/src/kernel/memory/vmm.c index eae6c17..b13abd1 100644 --- a/src/kernel/memory/vmm.c +++ b/src/kernel/memory/vmm.c @@ -1,4 +1,5 @@ #include +#include #define FLAGS_MASK (PAGE_SIZE-1) #define MASK_FLAGS(addr) ((uint64_t)addr & ~FLAGS_MASK) @@ -101,3 +102,48 @@ void vmm_clear_page(uint64_t P4, uint64_t addr, int free) pmm_free(MASK_FLAGS(P4E)); P4E = 0; } + +#define min(a,b) (((a) < (b))?(a):(b)) +#define offset(p) ((uintptr_t)(p) % PAGE_SIZE) +#define remaining(p) (PAGE_SIZE - offset(p)) +size_t memcpy_k2u(uint64_t P4, void *dst, void *src, size_t n) +{ + size_t copied = 0; + while(n) + { + size_t bytes = min(remaining(dst), n); + uintptr_t page = vmm_get_page(P4, (uintptr_t)dst); + if(!PAGE_EXIST(page)) + return copied; + + void *to = P2V(MASK_FLAGS(page) + offset(dst)); + memcpy(to, src, bytes); + + copied += bytes; + n -= bytes; + dst = incptr(dst, bytes); + src = incptr(src, bytes); + } + return copied; +} + +size_t memcpy_u2k(void *dst, uint64_t P4, void *src, size_t n) +{ + size_t copied = 0; + while(n) + { + size_t bytes = min(remaining(src), n); + uintptr_t page = vmm_get_page(P4, (uintptr_t)src); + if(!PAGE_EXIST(page)) + return copied; + + void *from = P2V(MASK_FLAGS(page) + offset(src)); + memcpy(dst, from, bytes); + + copied += bytes; + n -= bytes; + dst = incptr(dst, bytes); + src = incptr(src, bytes); + } + return copied; +}