aboutsummaryrefslogtreecommitdiff
path: root/common/vmem.c
diff options
context:
space:
mode:
authorKimplul <kimi.h.kuparinen@gmail.com>2021-12-23 17:47:46 +0200
committerKimplul <kimi.h.kuparinen@gmail.com>2021-12-23 17:47:46 +0200
commit64ef02c4baa0a1181a28e2e1b1517de3ba4907be (patch)
tree71da34495e878d24fb06cbc2051e65b50ec53531 /common/vmem.c
parent272e1889ce14aaea9e3431a93c406d347f5b3c54 (diff)
downloadkmi-64ef02c4baa0a1181a28e2e1b1517de3ba4907be.tar.gz
kmi-64ef02c4baa0a1181a28e2e1b1517de3ba4907be.zip
map_fill_region can now utilize higher order pages
Diffstat (limited to 'common/vmem.c')
-rw-r--r--common/vmem.c33
1 files changed, 27 insertions, 6 deletions
diff --git a/common/vmem.c b/common/vmem.c
index eee85a0..3795d0b 100644
--- a/common/vmem.c
+++ b/common/vmem.c
@@ -1,6 +1,6 @@
-#include <vmem.h>
#include <apos/vmem.h>
#include <apos/mem_nodes.h>
+#include <vmem.h>
#define mark_region_used(r) ((r) = 1)
#define mark_region_unused(r) ((r) = 0)
@@ -342,14 +342,35 @@ size_t uvmem_size()
return __uvmem_size;
}
-/* TODO: add in ability to notice when a page can be mapped to a higher order */
+/* assuming start is chosen to start on an aligned border, this should choose
+ * the 'optimal' fit for the mapping.
+ *
+ * NOTE: not actually optimal, this doesn't bother to go through possible
+ * permutations etc. which would be slow and I don't want to implement it.
+ */
vm_t map_fill_region(struct vm_branch_t *b, vm_t start, size_t bytes, uint8_t flags)
{
- size_t pages = bytes / BASE_PAGE_SIZE;
pm_t offset = 0;
- for(size_t i = 0; i < pages; ++i){
- offset = alloc_page(BASE_PAGE, offset);
- map_vmem(b, offset, start + i * BASE_PAGE_SIZE, flags, BASE_PAGE);
+ pm_t runner = start;
+ size_t pages = __pages(bytes);
+ enum mm_order_t top = __mm_max_order;
+
+ for(; pages; top--){
+ size_t o_size = __o_size(top);
+ size_t o_pages = __pages(o_size);
+
+ if(!aligned(runner, o_size))
+ continue;
+
+ while(pages > o_pages){
+ offset = alloc_page(top, offset);
+ if(!offset)
+ break;
+
+ map_vmem(b, offset, runner, flags, top);
+ pages -= o_pages;
+ runner += o_size;
+ }
}
return start;