diff options
| author | Kimplul <kimi.h.kuparinen@gmail.com> | 2021-12-23 17:47:46 +0200 |
|---|---|---|
| committer | Kimplul <kimi.h.kuparinen@gmail.com> | 2021-12-23 17:47:46 +0200 |
| commit | 64ef02c4baa0a1181a28e2e1b1517de3ba4907be (patch) | |
| tree | 71da34495e878d24fb06cbc2051e65b50ec53531 | |
| parent | 272e1889ce14aaea9e3431a93c406d347f5b3c54 (diff) | |
| download | kmi-64ef02c4baa0a1181a28e2e1b1517de3ba4907be.tar.gz kmi-64ef02c4baa0a1181a28e2e1b1517de3ba4907be.zip | |
map_fill_region can now utilize higher order pages
| -rw-r--r-- | arch/riscv/kernel/vmem.c | 2 | ||||
| -rw-r--r-- | common/vmem.c | 33 | ||||
| -rw-r--r-- | include/apos/utils.h | 8 | ||||
| -rw-r--r-- | include/apos/vmem.h | 2 |
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 |
