aboutsummaryrefslogtreecommitdiff
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
parent272e1889ce14aaea9e3431a93c406d347f5b3c54 (diff)
downloadkmi-64ef02c4baa0a1181a28e2e1b1517de3ba4907be.tar.gz
kmi-64ef02c4baa0a1181a28e2e1b1517de3ba4907be.zip
map_fill_region can now utilize higher order pages
-rw-r--r--arch/riscv/kernel/vmem.c2
-rw-r--r--common/vmem.c33
-rw-r--r--include/apos/utils.h8
-rw-r--r--include/apos/vmem.h2
4 files changed, 38 insertions, 7 deletions
diff --git a/arch/riscv/kernel/vmem.c b/arch/riscv/kernel/vmem.c
index d1d77a1..80644bd 100644
--- a/arch/riscv/kernel/vmem.c
+++ b/arch/riscv/kernel/vmem.c
@@ -83,7 +83,7 @@ static void __destroy_branch(struct vm_branch_t *b)
return;
for(size_t i = 0; i < BASE_PAGE_SIZE / sizeof(pm_t); ++i){
- if(is_branch(b->leaf[i]));
+ if(is_branch(b->leaf[i]))
__destroy_branch((struct vm_branch_t *)pte_addr(b->leaf[i]));
free_page(MM_KPAGE, (pm_t)pte_addr(b->leaf[i]));
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;
diff --git a/include/apos/utils.h b/include/apos/utils.h
index 318ba0a..b973d49 100644
--- a/include/apos/utils.h
+++ b/include/apos/utils.h
@@ -54,6 +54,14 @@ static inline size_t align_down(size_t val, size_t a)
return val - (val % a);
}
+static inline bool aligned(size_t val, size_t a)
+{
+ if (!a)
+ return true;
+
+ return val % a == 0;
+}
+
static inline size_t asciinum(char c)
{
if(c >= '0' && c <= '9')
diff --git a/include/apos/vmem.h b/include/apos/vmem.h
index fd1a165..4cc4895 100644
--- a/include/apos/vmem.h
+++ b/include/apos/vmem.h
@@ -30,6 +30,8 @@ struct sp_mem {
#define __pa(x) (((char *)(x)) + RAM_BASE - VM_DMAP)
#define __page(x) ((x) / BASE_PAGE_SIZE)
#define __addr(x) ((x) * BASE_PAGE_SIZE)
+#define __pages(x) (__page(x))
+#define __bytes(x) (__addr(x))
/* general overview of the different functions:
* internally they all work with pages, but they are called and return usable