X-Git-Url: https://scm.lunaixsky.com/lunaix-os.git/blobdiff_plain/38965e3e83ba1b03c9c9a0f14cce85c1d0cd8fd8..03944e7734220bf7e7aa7b7113bcbdf9c22808a5:/lunaix-os/kernel/mm/vmap.c diff --git a/lunaix-os/kernel/mm/vmap.c b/lunaix-os/kernel/mm/vmap.c new file mode 100644 index 0000000..0c10610 --- /dev/null +++ b/lunaix-os/kernel/mm/vmap.c @@ -0,0 +1,64 @@ +#include +#include +#include + +#define VMAP_START PG_MOUNT_BASE + MEM_4MB +#define VMAP_END PD_REFERENCED + +static uintptr_t start = VMAP_START; + +void* +vmm_vmap(uintptr_t paddr, size_t size, pt_attr attr, pp_attr_t pattr) +{ + // next fit + assert_msg((paddr & 0xfff) == 0, "vmap: bad alignment"); + size = ROUNDUP(size, PG_SIZE); + + uintptr_t current_addr = start; + size_t examed_size = 0, wrapped = 0; + x86_page_table* pd = (x86_page_table*)L1_BASE_VADDR; + + while (!wrapped || current_addr >= start) { + size_t l1inx = L1_INDEX(current_addr); + if (!(pd->entry[l1inx])) { + // empty 4mb region + examed_size += MEM_4MB; + current_addr = (current_addr & 0xffc00000) + MEM_4MB; + } else { + x86_page_table* ptd = (x86_page_table*)(L2_VADDR(l1inx)); + size_t i = L2_INDEX(current_addr); + for (; i < 1024 && examed_size < size; i++) { + if (!ptd->entry[i]) { + examed_size += PG_SIZE; + } else if (examed_size) { + // found a discontinuity, start from beginning + examed_size = 0; + i++; + break; + } + } + current_addr += i << 12; + } + + if (examed_size >= size) { + goto done; + } + + if (current_addr >= VMAP_END) { + wrapped = 1; + current_addr = VMAP_START; + } + } + panick("vmm: out of memory"); + +done: + uintptr_t alloc_begin = current_addr - examed_size; + for (size_t i = 0; i < size; i += PG_SIZE) { + vmm_set_mapping( + PD_REFERENCED, alloc_begin + i, paddr + i, PG_PREM_RW, 0); + pmm_ref_page(KERNEL_PID, paddr + i); + } + start = alloc_begin + size; + + return (void*)alloc_begin; +} \ No newline at end of file