diff options
author | dzwdz | 2022-05-26 21:45:34 +0200 |
---|---|---|
committer | dzwdz | 2022-05-26 21:45:34 +0200 |
commit | 2dfecbfa898c7db2f5039c81c23a8475966ecfef (patch) | |
tree | 74d809b4315f49070c1e780355abdcc909294172 /src/kernel/arch | |
parent | 0604552310847fd695e9cf62fcddb8e18720fc3b (diff) |
syscalls/memflag: FINDFREE flag
Diffstat (limited to 'src/kernel/arch')
-rw-r--r-- | src/kernel/arch/generic.h | 2 | ||||
-rw-r--r-- | src/kernel/arch/i386/pagedir.c | 20 |
2 files changed, 22 insertions, 0 deletions
diff --git a/src/kernel/arch/generic.h b/src/kernel/arch/generic.h index 3e98001..a9e1ac9 100644 --- a/src/kernel/arch/generic.h +++ b/src/kernel/arch/generic.h @@ -35,6 +35,8 @@ void pagedir_map(struct pagedir *dir, void __user *virt, void *phys, bool user, bool writeable); bool pagedir_iskern(struct pagedir *, const void __user *virt); +void __user *pagedir_findfree(struct pagedir *dir, char __user *start, size_t len); + void pagedir_switch(struct pagedir *); // return 0 on failure diff --git a/src/kernel/arch/i386/pagedir.c b/src/kernel/arch/i386/pagedir.c index 28608dc..e607cc7 100644 --- a/src/kernel/arch/i386/pagedir.c +++ b/src/kernel/arch/i386/pagedir.c @@ -184,3 +184,23 @@ void *pagedir_virt2phys(struct pagedir *dir, const void __user *virt, phys |= ((uintptr_t)virt) & 0xFFF; return (void*)phys; } + +void __user *pagedir_findfree(struct pagedir *dir, char __user *start, size_t len) { + struct pagetable_entry *page; + char __user *iter; + start = (userptr_t)(((uintptr_t __force)start + PAGE_MASK) & ~PAGE_MASK); // round up to next page + iter = start; + + while (iter < (char __user *)0xFFF00000) { // TODO better boundary + page = get_entry(dir, iter); + if (page && page->present) { + start = iter + PAGE_SIZE; + } else { + if ((size_t)(iter + PAGE_SIZE - start) >= len) + return start; + } + iter += PAGE_SIZE; + } + + return NULL; +} |