X-Git-Url: https://scm.lunaixsky.com/lunaix-os.git/blobdiff_plain/e141fd4dcd5effc2dbe59a498d7ea274b7199147..bffa3430fbbaaad29bec0b5bee9c1f0bfc7fd068:/lunaix-os/kernel/mm/vmm.c?ds=sidebyside diff --git a/lunaix-os/kernel/mm/vmm.c b/lunaix-os/kernel/mm/vmm.c index 364332e..24fa422 100644 --- a/lunaix-os/kernel/mm/vmm.c +++ b/lunaix-os/kernel/mm/vmm.c @@ -1,143 +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 P2V(pd); -} +#include +#include + +LOG_MODULE("VM") -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 +void +vmm_init() +{ + // XXX: something here? } -void vmm_init() { - // TODO: something here? +pte_t +vmm_tryptep(pte_t* ptep, size_t lvl_size) +{ + ptr_t va = ptep_va(ptep, lvl_size); + pte_t* _ptep = mkl0tep(ptep); + pte_t pte; + + if (pte_isnull(pte = *_ptep) || _ptep == ptep) + return pte; + +#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; } -ptd_t* vmm_init_pd() { - ptd_t* dir = pmm_alloc_page(); - for (size_t i = 0; i < 1024; i++) - { - dir[i] = 0; - } - - // 自己映射自己,方便我们在软件层面进行查表地址转换 - dir[1023] = PDE(T_SELF_REF_PERM, dir); +ptr_t +vms_mount(ptr_t mnt, ptr_t vms_root) +{ + assert(vms_root); - return dir; + pte_t* ptep = mkl0tep_va(VMS_SELF, mnt); + set_pte(ptep, mkpte(vms_root, KERNEL_PGTAB)); + tlb_flush_kernel(mnt); + return mnt; } -void* vmm_map_page(void* va, void* pa, pt_attr dattr, pt_attr tattr) { - // 显然,对空指针进行映射没有意义。 - if (!pa || !va) { - return NULL; - } +ptr_t +vms_unmount(ptr_t mnt) +{ + pte_t* ptep = mkl0tep_va(VMS_SELF, mnt); + set_pte(ptep, null_pte); + tlb_flush_kernel(mnt); + return mnt; +} - 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 = (uintptr_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 V_ADDR(pd_offset, pt_offset, PG_OFFSET(va)); - } - pt_offset++; - } +void +ptep_alloc_hierarchy(pte_t* ptep, ptr_t va, pte_attr_t prot) +{ + pte_t* _ptep; - // 页目录与所有页表已满! - if (pd_offset > 1024) { - return NULL; + _ptep = mkl0tep(ptep); + if (_ptep == ptep) { + return; } - // 页目录有空位,需要开辟一个新的 PDE - uint8_t* new_pt_pa = pmm_alloc_page(); - - // 物理内存已满! - if (!new_pt_pa) { - return NULL; + _ptep = mkl1t(_ptep, va, prot); + if (_ptep == ptep) { + return; } - - 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 V_ADDR(pd_offset, pt_offset, PG_OFFSET(va)); -} - -void* vmm_alloc_page(void* vpn, pt_attr dattr, pt_attr tattr) { - void* pp = pmm_alloc_page(); - void* result = vmm_map_page(vpn, pp, dattr, tattr); - if (!result) { - pmm_free_page(pp); + _ptep = mkl2t(_ptep, va, prot); + if (_ptep == ptep) { + return; } - return result; -} - -void vmm_unmap_page(void* vpn) { - uintptr_t pd_offset = PD_INDEX(vpn); - uintptr_t pt_offset = PT_INDEX(vpn); - ptd_t* self_pde = PTD_BASE_VADDR; - - ptd_t pde = self_pde[pd_offset]; - - if (pde) { - pt_t* pt = (pt_t*)PT_VADDR(pd_offset); - uint32_t pte = pt[pt_offset]; - if (IS_CACHED(pte) && pmm_free_page(pte)) { - // 刷新TLB - #ifdef __ARCH_IA32 - __asm__("invlpg (%0)" :: "r"((uintptr_t)vpn) : "memory"); - #endif - } - pt[pt_offset] = 0; - } -} - -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_BASE_VADDR; - 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