Boot framework rework (#45)
[lunaix-os.git] / lunaix-os / kernel / mm / vmm.c
index a076a976cbbe2fa9f495bc9cafcc6af932f7b328..24fa4227999a410bd9737c584e0b0f53422b6169 100644 (file)
-#include <libc/string.h>
+#include <klibc/string.h>
 #include <lunaix/mm/page.h>
 #include <lunaix/mm/page.h>
-#include <lunaix/mm/pmm.h>
-#include <lunaix/mm/vmm.h>
+#include <lunaix/spike.h>
+#include <lunaix/syslog.h>
 
 
-// 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 <sys/cpu.h>
+#include <sys/mm/mm_defs.h>
 
 
-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()
 {
 
 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
 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
 }
\ No newline at end of file