X-Git-Url: https://scm.lunaixsky.com/lunaix-os.git/blobdiff_plain/c1811aecaae88bc006ce20bd301a6519dd89abda..bffa3430fbbaaad29bec0b5bee9c1f0bfc7fd068:/lunaix-os/kernel/mm/vmm.c?ds=inline diff --git a/lunaix-os/kernel/mm/vmm.c b/lunaix-os/kernel/mm/vmm.c index a076a97..24fa422 100644 --- a/lunaix-os/kernel/mm/vmm.c +++ b/lunaix-os/kernel/mm/vmm.c @@ -1,154 +1,94 @@ -#include +#include #include -#include -#include +#include +#include -// TODO: Move these nasty inline asm stuff into hal -// These should be arch dependent -ptd_t* -get_pd() -{ - ptd_t* pd; -#ifdef __ARCH_IA32 - __asm__("movl %%cr3, %0\n" - "andl $0xfffff000, %0" - : "=r"(pd)); -#endif - return (ptd_t*)P2V(pd); -} +#include +#include -void -set_pd(ptd_t* pd) -{ -#ifdef __ARCH_IA32 - __asm__("movl %0, %%eax\n" - "andl $0xfffff000, %%eax\n" - "movl %%eax, %%cr3\n" - : - : "r"(pd)); -#endif -} +LOG_MODULE("VM") void vmm_init() { - // TODO: something here? + // XXX: something here? } -ptd_t* -vmm_init_pd() +pte_t +vmm_tryptep(pte_t* ptep, size_t lvl_size) { - ptd_t* dir = pmm_alloc_page(); - for (size_t i = 0; i < 1024; i++) { - dir[i] = 0; - } + ptr_t va = ptep_va(ptep, lvl_size); + pte_t* _ptep = mkl0tep(ptep); + pte_t pte; - // 自己映射自己,方便我们在软件层面进行查表地址转换 - dir[1023] = PDE(T_SELF_REF_PERM, dir); + if (pte_isnull(pte = *_ptep) || _ptep == ptep) + return pte; - return dir; +#if LnT_ENABLED(1) + _ptep = getl1tep(_ptep, va); + if (_ptep == ptep || pte_isnull(pte = *_ptep)) + return pte; +#endif +#if LnT_ENABLED(2) + _ptep = getl2tep(_ptep, va); + if (_ptep == ptep || pte_isnull(pte = *_ptep)) + return pte; +#endif +#if LnT_ENABLED(3) + _ptep = getl3tep(_ptep, va); + if (_ptep == ptep || pte_isnull(pte = *_ptep)) + return pte; +#endif + _ptep = getlftep(_ptep, va); + return *_ptep; } -void* -vmm_map_page(void* va, void* pa, pt_attr dattr, pt_attr tattr) +ptr_t +vms_mount(ptr_t mnt, ptr_t vms_root) { - // 显然,对空指针进行映射没有意义。 - if (!pa || !va) { - return NULL; - } - - uintptr_t pd_offset = PD_INDEX(va); - uintptr_t pt_offset = PT_INDEX(va); - ptd_t* ptd = (ptd_t*)PTD_BASE_VADDR; - - // 在页表与页目录中找到一个可用的空位进行映射(位于va或其附近) - ptd_t pde = ptd[pd_offset]; - pt_t* pt = (pt_t*)PT_VADDR(pd_offset); - while (pde && pd_offset < 1024) { - if (pt_offset == 1024) { - pd_offset++; - pt_offset = 0; - pde = ptd[pd_offset]; - pt = (pt_t*)PT_VADDR(pd_offset); - } - // 页表有空位,只需要开辟一个新的 PTE - if (pt && !pt[pt_offset]) { - pt[pt_offset] = PTE(tattr, pa); - return (void*)V_ADDR(pd_offset, pt_offset, PG_OFFSET(va)); - } - pt_offset++; - } + assert(vms_root); - // 页目录与所有页表已满! - if (pd_offset > 1024) { - return NULL; - } - - // 页目录有空位,需要开辟一个新的 PDE - uint8_t* new_pt_pa = pmm_alloc_page(); - - // 物理内存已满! - if (!new_pt_pa) { - return NULL; - } - - ptd[pd_offset] = PDE(dattr, new_pt_pa); - - memset((void*)PT_VADDR(pd_offset), 0, PM_PAGE_SIZE); - pt[pt_offset] = PTE(tattr, pa); - - return (void*)V_ADDR(pd_offset, pt_offset, PG_OFFSET(va)); + pte_t* ptep = mkl0tep_va(VMS_SELF, mnt); + set_pte(ptep, mkpte(vms_root, KERNEL_PGTAB)); + tlb_flush_kernel(mnt); + return mnt; } -void* -vmm_alloc_page(void* vpn, pt_attr dattr, pt_attr tattr) +ptr_t +vms_unmount(ptr_t mnt) { - void* pp = pmm_alloc_page(); - void* result = vmm_map_page(vpn, pp, dattr, tattr); - if (!result) { - pmm_free_page(pp); - } - return result; + pte_t* ptep = mkl0tep_va(VMS_SELF, mnt); + set_pte(ptep, null_pte); + tlb_flush_kernel(mnt); + return mnt; } + void -vmm_unmap_page(void* vpn) +ptep_alloc_hierarchy(pte_t* ptep, ptr_t va, pte_attr_t prot) { - uintptr_t pd_offset = PD_INDEX(vpn); - uintptr_t pt_offset = PT_INDEX(vpn); - ptd_t* self_pde = (ptd_t*)PTD_BASE_VADDR; - - ptd_t pde = self_pde[pd_offset]; + pte_t* _ptep; + + _ptep = mkl0tep(ptep); + if (_ptep == ptep) { + return; + } - if (pde) { - pt_t* pt = (pt_t*)PT_VADDR(pd_offset); - uint32_t pte = pt[pt_offset]; - if (IS_CACHED(pte) && pmm_free_page((void*)pte)) { -// 刷新TLB -#ifdef __ARCH_IA32 - __asm__("invlpg (%0)" ::"r"((uintptr_t)vpn) : "memory"); -#endif - } - pt[pt_offset] = 0; + _ptep = mkl1t(_ptep, va, prot); + if (_ptep == ptep) { + return; } -} -void* -vmm_v2p(void* va) -{ - uintptr_t pd_offset = PD_INDEX(va); - uintptr_t pt_offset = PT_INDEX(va); - uintptr_t po = PG_OFFSET(va); - ptd_t* self_pde = (ptd_t*)PTD_BASE_VADDR; + _ptep = mkl2t(_ptep, va, prot); + if (_ptep == ptep) { + return; + } - ptd_t pde = self_pde[pd_offset]; - if (pde) { - pt_t pte = ((pt_t*)PT_VADDR(pd_offset))[pt_offset]; - if (pte) { - uintptr_t ppn = pte >> 12; - return (void*)P_ADDR(ppn, po); - } + _ptep = mkl3t(_ptep, va, prot); + if (_ptep == ptep) { + return; } - return NULL; + _ptep = mklft(_ptep, va, prot); + assert(_ptep == ptep); } \ No newline at end of file