Remove PDX and NPDENTRIES
[akaros.git] / kern / include / pmap.h
index e7c4710..cabf615 100644 (file)
@@ -73,7 +73,7 @@ extern uintptr_t boot_freelimit;
 extern struct page *pages;
 
 extern physaddr_t RO boot_cr3;
-extern pde_t *CT(NPDENTRIES) RO boot_pgdir;
+extern pgdir_t boot_pgdir;
 
 bool enable_pse(void);
 void vm_init(void);
@@ -83,20 +83,24 @@ void *boot_alloc(size_t amt, size_t align);
 void *boot_zalloc(size_t amt, size_t align);
 
 void page_check(void);
-int     page_insert(pde_t *pgdir, struct page *page, void *SNT va, int perm);
-void page_remove(pde_t *COUNT(NPDENTRIES) pgdir, void *SNT va);
-page_t*COUNT(1) page_lookup(pde_t SSOMELOCK*COUNT(NPDENTRIES) pgdir, void *SNT va, pte_t **pte_store);
-error_t        pagetable_remove(pde_t *COUNT(NPDENTRIES) pgdir, void *SNT va);
+int     page_insert(pgdir_t pgdir, struct page *page, void *SNT va,
+                       int perm);
+void page_remove(pgdir_t pgdir, void *SNT va);
+page_t* page_lookup(pgdir_t pgdir, void *va, pte_t *pte_store);
+error_t        pagetable_remove(pgdir_t pgdir, void *SNT va);
 void   page_decref(page_t *COUNT(1) pp);
 
-void   tlb_invalidate(pde_t *COUNT(NPDENTRIES) pgdir, void *SNT va);
+void   tlb_invalidate(pgdir_t pgdir, void *SNT va);
 void tlb_flush_global(void);
 bool regions_collide_unsafe(uintptr_t start1, uintptr_t end1, 
                             uintptr_t start2, uintptr_t end2);
 
 /* Arch specific implementations for these */
-pte_t *pgdir_walk(pde_t *COUNT(NPDENTRIES) pgdir, const void *SNT va, int create);
-int get_va_perms(pde_t *COUNT(NPDENTRIES) pgdir, const void *SNT va);
+pte_t pgdir_walk(pgdir_t pgdir, const void *va, int create);
+int get_va_perms(pgdir_t pgdir, const void *va);
+int arch_pgdir_setup(pgdir_t boot_copy, pgdir_t *new_pd);
+physaddr_t arch_pgdir_get_cr3(pgdir_t pd);
+void arch_pgdir_clear(pgdir_t *pd);
 
 static inline page_t *SAFE ppn2page(size_t ppn)
 {
@@ -152,4 +156,114 @@ static inline bool is_kaddr(void *addr)
        return (uintptr_t)addr >= KERNBASE;
 }
 
+static inline unsigned long nr_pages(size_t nr_bytes)
+{
+       return (nr_bytes >> PGSHIFT) + (PGOFF(nr_bytes) ? 1 : 0);
+}
+
+static inline bool pte_walk_okay(pte_t pte)
+{
+       return pte ? TRUE : FALSE;
+}
+
+/* PTE states:
+ *  - present: the PTE is involved in a valid page table walk, with the physaddr
+ *  part pointing to a physical page.
+ *
+ *     - mapped: the PTE is involved in some sort of mapping, e.g. a VMR.  We're
+ *     storing something in the PTE, but it is isn't necessarily present and
+ *     pointing to an actual physical page.  All present are mapped, but not vice
+ *     versa.  Mapped could also include paged-out, if we support that later.
+ *
+ *     - unmapped: completely unused. (0 value) */
+static inline bool pte_is_present(pte_t pte)
+{
+       return *(kpte_t*)pte & PTE_P ? TRUE : FALSE;
+}
+
+static inline bool pte_is_unmapped(pte_t pte)
+{
+       return PAGE_UNMAPPED(*(kpte_t*)pte);
+}
+
+static inline bool pte_is_mapped(pte_t pte)
+{
+       return !PAGE_UNMAPPED(*(kpte_t*)pte);
+}
+
+static inline bool pte_is_paged_out(pte_t pte)
+{
+       return PAGE_PAGED_OUT(*(kpte_t*)pte);
+}
+
+static inline bool pte_is_dirty(pte_t pte)
+{
+       return *(kpte_t*)pte & PTE_D ? TRUE : FALSE;
+}
+
+static inline bool pte_is_accessed(pte_t pte)
+{
+       return *(kpte_t*)pte & PTE_A ? TRUE : FALSE;
+}
+
+/* Used in debugging code - want something better involving the walk */
+static inline bool pte_is_jumbo(pte_t pte)
+{
+       return *(kpte_t*)pte & PTE_PS ? TRUE : FALSE;
+}
+
+static inline physaddr_t pte_get_paddr(pte_t pte)
+{
+       return PTE_ADDR(*(kpte_t*)pte);
+}
+
+/* Returns the PTE in an unsigned long, for debugging mostly. */
+static inline unsigned long pte_print(pte_t pte)
+{
+       return *(kpte_t*)pte;
+}
+
+static inline void pte_write(pte_t pte, physaddr_t pa, int perm)
+{
+       *(kpte_t*)pte = PTE(pa2ppn(pa), perm);
+}
+
+static inline void pte_clear_present(pte_t pte)
+{
+       *(kpte_t*)pte &= ~PTE_P;
+}
+
+static inline void pte_clear(pte_t pte)
+{
+       *(kpte_t*)pte = 0;
+}
+
+/* These are used by memcpy_*_user, but are very dangerous (and possibly used
+ * incorrectly there).  These aren't the overall perms for a VA.  For U and W,
+ * we need the intersection of the PTEs along the walk and not just the last
+ * one.  It just so happens that the W is only cleared on the last PTE, so the
+ * check works for that.  But if there was a page under ULIM that wasn't U due
+ * to an intermediate PTE, we'd miss that. */
+static inline bool pte_has_perm_ur(pte_t pte)
+{
+       return *(kpte_t*)pte & PTE_USER_RO ? TRUE : FALSE;
+}
+
+static inline bool pte_has_perm_urw(pte_t pte)
+{
+       return *(kpte_t*)pte & PTE_USER_RW ? TRUE : FALSE;
+}
+
+/* return the arch-independent format for prots - whatever you'd expect to
+ * receive for pte_write.  Careful with the ret, since a valid type is 0. */
+static inline int pte_get_perm(pte_t pte)
+{
+       return *(kpte_t*)pte & PTE_PERM;
+}
+
+static inline void pte_replace_perm(pte_t pte, int perm)
+{
+       *(kpte_t*)pte = (*(kpte_t*)pte & ~PTE_PERM) | perm;
+}
+
 #endif /* !ROS_KERN_PMAP_H */