summaryrefslogtreecommitdiff
path: root/src/kernel/arch
diff options
context:
space:
mode:
authordzwdz2022-05-26 21:45:34 +0200
committerdzwdz2022-05-26 21:45:34 +0200
commit2dfecbfa898c7db2f5039c81c23a8475966ecfef (patch)
tree74d809b4315f49070c1e780355abdcc909294172 /src/kernel/arch
parent0604552310847fd695e9cf62fcddb8e18720fc3b (diff)
syscalls/memflag: FINDFREE flag
Diffstat (limited to 'src/kernel/arch')
-rw-r--r--src/kernel/arch/generic.h2
-rw-r--r--src/kernel/arch/i386/pagedir.c20
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;
+}