X-Git-Url: https://scm.lunaixsky.com/lunaix-os.git/blobdiff_plain/45e1f8b055043e54be35462852ab6649d634da7c..HEAD:/lunaix-os/kernel/mm/vmap.c diff --git a/lunaix-os/kernel/mm/vmap.c b/lunaix-os/kernel/mm/vmap.c index ad1a832..349f1fb 100644 --- a/lunaix-os/kernel/mm/vmap.c +++ b/lunaix-os/kernel/mm/vmap.c @@ -1,65 +1,94 @@ -#include -#include +#include +#include #include +#include -#define VMAP_START PG_MOUNT_BASE + MEM_4MB -#define VMAP_END VMS_SELF +#include -static ptr_t start = VMAP_START; +static ptr_t start = VMAP; +static volatile ptr_t prev_va = 0; -void* -vmm_vmap(ptr_t paddr, size_t size, pt_attr attr) +void +vmap_set_start(ptr_t start_addr) { + start = start_addr; +} + +static pte_t* +__alloc_contig_ptes(pte_t* ptep, size_t base_sz, int n) { - // next fit - assert_msg((paddr & 0xfff) == 0, "vmap: bad alignment"); - size = ROUNDUP(size, PG_SIZE); - - ptr_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), j = 0; - for (; i < PG_MAX_ENTRIES && examed_size < size; i++, j++) { - if (!ptd->entry[i]) { - examed_size += PG_SIZE; - } else if (examed_size) { - // found a discontinuity, start from beginning - examed_size = 0; - j++; - break; - } - } - current_addr += j << 12; - } + int _n = 0; + size_t sz = L0T_SIZE; + ptr_t va = page_addr(ptep_pfn(ptep)); - if (examed_size >= size) { - goto done; + ptep = mkl0tep(ptep); + + while (_n < n && va < VMAP_END) { + pte_t pte = *ptep; + if (pte_isnull(pte)) { + _n += sz / base_sz; + } + else if ((sz / LEVEL_SIZE) < base_sz) { + _n = 0; + } + else { + sz = sz / LEVEL_SIZE; + ptep = ptep_step_into(ptep); + continue; } - if (current_addr >= VMAP_END) { - wrapped = 1; - examed_size = 0; - current_addr = VMAP_START; + if (ptep_vfn(ptep) + 1 == LEVEL_SIZE) { + ptep = ptep_step_out(++ptep); + va += sz; + + sz = sz * LEVEL_SIZE; + continue; } + + va += sz; + ptep++; } - return NULL; + if (va >= VMAP_END) { + return NULL; + } + + va -= base_sz * _n; + + prev_va = va; + return mkptep_va(ptep_vm_mnt(ptep), va); +} -done: - ptr_t alloc_begin = current_addr - examed_size; - for (size_t i = 0; i < size; i += PG_SIZE) { - vmm_set_mapping(VMS_SELF, alloc_begin + i, paddr + i, PG_PREM_RW, 0); - pmm_ref_page(KERNEL_PID, paddr + i); +ptr_t +vmap_ptes_at(pte_t pte, size_t lvl_size, int n) +{ + pte_t* ptep = mkptep_va(VMS_SELF, start); + ptep = __alloc_contig_ptes(ptep, lvl_size, n); + + if (!ptep) { + return 0; } - start = alloc_begin + size; - return (void*)alloc_begin; + vmm_set_ptes_contig(ptep, pte, lvl_size, n); + + ptr_t va = page_addr(ptep_pfn(ptep)); + + tlb_flush_kernel_ranged(va, n); + + return va; +} + +void +vunmap(ptr_t ptr, struct leaflet* leaflet) +{ + pte_t* ptep; + unsigned int npages; + + assert(start <= ptr && ptr <= VMAP_END); + + npages = leaflet_nfold(leaflet); + ptep = mkptep_va(VMS_SELF, ptr); + + vmm_unset_ptes(ptep, npages); + + tlb_flush_kernel_ranged(ptr, npages); } \ No newline at end of file