diff options
author | dzwdz | 2021-09-12 14:59:47 +0200 |
---|---|---|
committer | dzwdz | 2021-09-12 14:59:47 +0200 |
commit | 1bf901c803bff3393d0cc9dfe76fc9f025cecb1c (patch) | |
tree | 10f0c1c5d64496c3b300a4d691d640a7da73c772 | |
parent | d7a91165004baf67b645b5604934ec89402d034b (diff) |
barebones `memflag()` implementation - letting the user allocate pages
-rw-r--r-- | src/init/main.c | 6 | ||||
-rw-r--r-- | src/init/syscalls.c | 4 | ||||
-rw-r--r-- | src/kernel/syscalls.c | 22 | ||||
-rw-r--r-- | src/shared/flags.h | 5 | ||||
-rw-r--r-- | src/shared/syscalls.h | 4 |
5 files changed, 41 insertions, 0 deletions
diff --git a/src/init/main.c b/src/init/main.c index 06e59a2..dc5a975 100644 --- a/src/init/main.c +++ b/src/init/main.c @@ -1,4 +1,5 @@ #include <init/types.h> +#include <shared/flags.h> #include <shared/syscalls.h> #include <stdint.h> @@ -8,6 +9,8 @@ __attribute__((section("text"))) int tty_fd; +int test; + void fs_test(void); int main(void) { @@ -16,6 +19,9 @@ int main(void) { _syscall_exit(argify("couldn't open tty")); log(" opened /tty "); + _syscall_memflag(&test, sizeof(int), MEMFLAG_PRESENT); + test = 0; // would cause a pagefault without the memflag call + fs_test(); _syscall_exit(argify("my job here is done.")); } diff --git a/src/init/syscalls.c b/src/init/syscalls.c index e63f911..8d5ecf2 100644 --- a/src/init/syscalls.c +++ b/src/init/syscalls.c @@ -44,3 +44,7 @@ handle_t _syscall_fs_create(handle_t __user *back) { int _syscall_fs_wait(handle_t back, char __user *buf, int __user *len) { return _syscall(_SYSCALL_FS_WAIT, back, (int)buf, (int)len); } + +int _syscall_memflag(void __user *addr, size_t len, int flags) { + return _syscall(_SYSCALL_MEMFLAG, (int)addr, len, flags); +} diff --git a/src/kernel/syscalls.c b/src/kernel/syscalls.c index 21c1b72..1180197 100644 --- a/src/kernel/syscalls.c +++ b/src/kernel/syscalls.c @@ -5,6 +5,7 @@ #include <kernel/proc.h> #include <kernel/types.h> #include <kernel/vfs/path.h> +#include <shared/flags.h> #include <shared/syscalls.h> #include <stdint.h> @@ -221,6 +222,25 @@ int _syscall_fs_wait(handle_t back, char __user *buf, int __user *len) { } } +int _syscall_memflag(void __user *addr, size_t len, int flags) { + userptr_t goal = addr + len; + struct pagedir *pages = process_current->pages; + if (flags != MEMFLAG_PRESENT) panic(); // currently only allocation is implemented + + addr = (userptr_t)((int)addr & ~PAGE_MASK); // align to page boundary + for (; addr < goal; addr += PAGE_SIZE) { + if (pagedir_virt2phys(pages, addr, false, false)) { + // allocated page, currently a no-op + // if you'll be changing this - remember to check if the pages are owned by the kernel! + } else { + // allocate the new pages + pagedir_map(pages, addr, page_alloc(1), true, true); + } + } + + return -1; +} + int syscall_handler(int num, int a, int b, int c) { switch (num) { case _SYSCALL_EXIT: @@ -243,6 +263,8 @@ int syscall_handler(int num, int a, int b, int c) { return _syscall_fs_create((userptr_t)a); case _SYSCALL_FS_WAIT: return _syscall_fs_wait(a, (userptr_t)b, (userptr_t)c); + case _SYSCALL_MEMFLAG: + return _syscall_memflag((userptr_t)a, b, c); default: tty_const("unknown syscall "); panic(); diff --git a/src/shared/flags.h b/src/shared/flags.h new file mode 100644 index 0000000..9ab8d9d --- /dev/null +++ b/src/shared/flags.h @@ -0,0 +1,5 @@ +#pragma once + +enum { + MEMFLAG_PRESENT = 1 << 0, +}; diff --git a/src/shared/syscalls.h b/src/shared/syscalls.h index a746ade..d96c8a7 100644 --- a/src/shared/syscalls.h +++ b/src/shared/syscalls.h @@ -22,6 +22,8 @@ enum { _SYSCALL_FS_CREATE, _SYSCALL_FS_WAIT, + + _SYSCALL_MEMFLAG, }; /** Kills the current process. @@ -53,3 +55,5 @@ int _syscall_close(handle_t); handle_t _syscall_fs_create(handle_t __user *back); int _syscall_fs_wait(handle_t back, char __user *buf, int __user *len); + +int _syscall_memflag(void __user *addr, size_t len, int flags); |