Changes pde_t* -> pgdir_t
authorBarret Rhoden <brho@cs.berkeley.edu>
Mon, 16 Mar 2015 19:35:23 +0000 (15:35 -0400)
committerBarret Rhoden <brho@cs.berkeley.edu>
Tue, 17 Mar 2015 14:56:00 +0000 (10:56 -0400)
Just like pte_t, the nature of the pgdir is arch-dependent.  For now,
it's all the same under the hood, thanks to various casts.

14 files changed:
kern/arch/riscv/arch.h
kern/arch/riscv/cpuinfo.c
kern/arch/riscv/pmap.c
kern/arch/riscv/ros/mmu.h
kern/arch/x86/arch.h
kern/arch/x86/cpuinfo.c
kern/arch/x86/pmap64.c
kern/arch/x86/ros/mmu64.h
kern/include/env.h
kern/include/pmap.h
kern/src/env.c
kern/src/monitor.c
kern/src/pmap.c
kern/src/process.c

index a0e767a..77dbf9e 100644 (file)
@@ -12,7 +12,7 @@
 #define ARCH_CL_SIZE 64
 
 void print_cpuinfo(void);
-void show_mapping(pde_t *pgdir, uintptr_t start, size_t size);
+void show_mapping(pgdir_t pgdir, uintptr_t start, size_t size);
 void backtrace(void);
 
 static __inline void breakpoint(void)
index 6766761..ba71bc1 100644 (file)
@@ -24,7 +24,8 @@ print_cpuinfo(void)
        cprintf("CPU Info: RISC-V %s\n", name);
 }
 
-void show_mapping(pde_t *pt, uintptr_t start, size_t size)
+#warning "convert pgdir* to pgdir_t"
+void show_mapping(pgdir_t *pt, uintptr_t start, size_t size)
 {
        pte_t* pte;
        uintptr_t i;
index 4ce640c..fd05763 100644 (file)
@@ -15,7 +15,8 @@
 #include <kmalloc.h>
 #include <page_alloc.h>
 
-pde_t* boot_pgdir;             // Virtual address of boot time page directory
+#warning "convert pgdir* to pgdir_t"
+pgdir_t* boot_pgdir;           // Virtual address of boot time page directory
 physaddr_t boot_cr3;           // Physical address of boot time page directory
 
 // --------------------------------------------------------------
@@ -46,7 +47,7 @@ vm_init(void)
 // This is boot_pgdir_walk, but using page_alloc() instead of boot_alloc().
 // Unlike boot_pgdir_walk, pgdir_walk can fail.
 pte_t*
-pgdir_walk(pde_t *pgdir, const void *SNT va, int create)
+pgdir_walk(pgdir_t *pgdir, const void *SNT va, int create)
 {
        pte_t* ppte;
        pte_t* pt;
@@ -86,7 +87,7 @@ pgdir_walk(pde_t *pgdir, const void *SNT va, int create)
 
 /* Returns the effective permissions for PTE_U, PTE_W, and PTE_P on a given
  * virtual address. */
-int get_va_perms(pde_t *pgdir, const void *SNT va)
+int get_va_perms(pgdir_t *pgdir, const void *SNT va)
 {
        pte_t* pte = pgdir_walk(pgdir, va, 0);
        return pte == NULL ? 0 : (*pte & (PTE_PERM | PTE_E));
@@ -96,3 +97,26 @@ void
 page_check(void)
 {
 }
+
+int arch_pgdir_setup(pgdir_t boot_copy, pgdir_t *new_pd)
+{
+       pte_t *kpt = kpage_alloc_addr();
+       if (!kpt)
+               return -ENOMEM;
+       memcpy(kpt, (pte_t*)boot_copy, PGSIZE);
+
+       /* TODO: VPT/UVPT mappings */
+
+       *new_pd = (pgdir_t)kpt;
+       return 0;
+}
+
+physaddr_t arch_pgdir_get_cr3(pgdir_t pd)
+{
+       return PADDR((pte_t*)pd);
+}
+
+void arch_pgdir_clear(pgdir_t *pd)
+{
+       *pd = 0;
+}
index 633e87f..943bba4 100644 (file)
 
 #ifndef __ASSEMBLER__
 typedef unsigned long pte_t;
-typedef unsigned long pde_t;
+typedef unsigned long pgdir_t;
 #endif
 
 /* Same as VPT but read-only for users */
index d3dfea5..bf6f85e 100644 (file)
@@ -40,7 +40,7 @@ static inline void prefetchw(void *addr);
 void send_ipi(uint32_t os_coreid, uint8_t vector);
 /* in cpuinfo.c */
 void print_cpuinfo(void);
-void show_mapping(pde_t *pgdir, uintptr_t start, size_t size);
+void show_mapping(pgdir_t pgdir, uintptr_t start, size_t size);
 int vendor_id(char *);
 
 static inline void breakpoint(void)
index f9dbf09..45884e7 100644 (file)
@@ -174,7 +174,7 @@ void print_cpuinfo(void)
 #define BIT_SPACING "        "
 #define BIT_DASHES "----------------"
 
-void show_mapping(pde_t *pgdir, uintptr_t start, size_t size)
+void show_mapping(pgdir_t pgdir, uintptr_t start, size_t size)
 {
        pte_t pte;
        int perm;
index ab1fc48..30a290c 100644 (file)
@@ -32,7 +32,7 @@
 #include <page_alloc.h>
 
 extern char boot_pml4[], gdt64[], gdt64desc[];
-pde_t *boot_pgdir;
+pgdir_t boot_pgdir;
 physaddr_t boot_cr3;
 segdesc_t *gdt;
 pseudodesc_t gdt_pd;
@@ -42,13 +42,19 @@ unsigned int max_jumbo_shift;
 #define PG_WALK_CREATE                         0x0100
 
 kpte_t *pml_walk(kpte_t *pml, uintptr_t va, int flags);
-void map_segment(pde_t *pgdir, uintptr_t va, size_t size, physaddr_t pa,
+void map_segment(pgdir_t pgdir, uintptr_t va, size_t size, physaddr_t pa,
                  int perm, int pml_shift);
 typedef int (*kpte_cb_t)(kpte_t *kpte, uintptr_t kva, int pml_shift,
                         bool visited_subs, void *arg);
 int pml_for_each(kpte_t *pml, uintptr_t start, size_t len, kpte_cb_t callback,
                  void *arg);
-int unmap_segment(pde_t *pgdir, uintptr_t va, size_t size);
+int unmap_segment(pgdir_t pgdir, uintptr_t va, size_t size);
+
+/* Helper: gets the kpte_t pointer which is the base of the PML4 from pgdir */
+static kpte_t *pgdir_get_kpt(pgdir_t pgdir)
+{
+       return (kpte_t*)pgdir;
+}
 
 /* Helper: returns true if we do not need to walk the page table any further.
  *
@@ -233,7 +239,7 @@ static int max_possible_shift(uintptr_t va, uintptr_t pa)
  *
  * Don't use this to set the PAT flag on jumbo pages in perm, unless you are
  * absolultely sure you won't map regular pages.  */
-void map_segment(pde_t *pgdir, uintptr_t va, size_t size, physaddr_t pa,
+void map_segment(pgdir_t pgdir, uintptr_t va, size_t size, physaddr_t pa,
                  int perm, int pml_shift)
 {
        int max_shift_possible;
@@ -253,7 +259,7 @@ void map_segment(pde_t *pgdir, uintptr_t va, size_t size, physaddr_t pa,
        assert((pml_shift == PML1_SHIFT) ||
               (pml_shift == PML2_SHIFT) ||
               (pml_shift == PML3_SHIFT));
-       __map_segment(pgdir, va, size, pa, perm, pml_shift);
+       __map_segment(pgdir_get_kpt(pgdir), va, size, pa, perm, pml_shift);
 }
 
 /* For every PTE in [start, start + len), call callback(kpte, shift,
@@ -322,7 +328,7 @@ int pml_for_each(kpte_t *pml, uintptr_t start, size_t len, kpte_cb_t callback,
 /* Unmaps [va, va + size) from pgdir, freeing any intermediate page tables.
  * This does not free the actual memory pointed to by the page tables, nor does
  * it flush the TLB. */
-int unmap_segment(pde_t *pgdir, uintptr_t va, size_t size)
+int unmap_segment(pgdir_t pgdir, uintptr_t va, size_t size)
 {
        int pt_free_cb(kpte_t *kpte, uintptr_t kva, int shift, bool visited_subs,
                       void *data)
@@ -348,7 +354,7 @@ int unmap_segment(pde_t *pgdir, uintptr_t va, size_t size)
                return 0;
        }
 
-       return pml_for_each(pgdir, va, size, pt_free_cb, 0);
+       return pml_for_each(pgdir_get_kpt(pgdir), va, size, pt_free_cb, 0);
 }
 
 /* Older interface for page table walks - will return the PTE corresponding to
@@ -356,12 +362,12 @@ int unmap_segment(pde_t *pgdir, uintptr_t va, size_t size)
  * PTEs, but only if they already exist.  Otherwise, (with create), it'll walk
  * to the lowest PML.  If the walk fails due to a lack of intermediate tables or
  * memory, this returns 0 (subject to change based on pte_t). */
-pte_t pgdir_walk(pde_t *pgdir, const void *va, int create)
+pte_t pgdir_walk(pgdir_t pgdir, const void *va, int create)
 {
        int flags = PML1_SHIFT;
        if (create == 1)
                flags |= PG_WALK_CREATE;
-       return (pte_t)pml_walk(pgdir, (uintptr_t)va, flags);
+       return (pte_t)pml_walk(pgdir_get_kpt(pgdir), (uintptr_t)va, flags);
 }
 
 static int pml_perm_walk(kpte_t *pml, const void *va, int pml_shift)
@@ -382,9 +388,9 @@ static int pml_perm_walk(kpte_t *pml, const void *va, int pml_shift)
 /* Returns the effective permissions for PTE_U, PTE_W, and PTE_P on a given
  * virtual address.  Note we need to consider the composition of every PTE in
  * the page table walk (we bit-and all of them together) */
-int get_va_perms(pde_t *pgdir, const void *va)
+int get_va_perms(pgdir_t pgdir, const void *va)
 {
-       return pml_perm_walk(pgdir, va, PML4_SHIFT);
+       return pml_perm_walk(pgdir_get_kpt(pgdir), va, PML4_SHIFT);
 }
 
 #define check_sym_va(sym, addr)                                                \
@@ -419,8 +425,10 @@ static void check_syms_va(void)
 void vm_init(void)
 {
        uint32_t edx;
+       kpte_t *boot_kpt = KADDR(get_boot_pml4());
+
        boot_cr3 = get_boot_pml4();
-       boot_pgdir = KADDR(get_boot_pml4());
+       boot_pgdir = (pgdir_t)boot_kpt;
        gdt = KADDR(get_gdt64());
 
        /* We need to limit our mappings on machines that don't support 1GB pages */
@@ -441,9 +449,9 @@ void vm_init(void)
        map_segment(boot_pgdir, IOAPIC_BASE, APIC_SIZE, IOAPIC_PBASE,
                    PTE_PCD | PTE_PWT | PTE_W | PTE_G, max_jumbo_shift);
        /* VPT mapping: recursive PTE inserted at the VPT spot */
-       boot_pgdir[PDX(VPT)] = PADDR(boot_pgdir) | PTE_W | PTE_P;
+       boot_kpt[PDX(VPT)] = PADDR(boot_kpt) | PTE_W | PTE_P;
        /* same for UVPT, accessible by userspace (RO). */
-       boot_pgdir[PDX(UVPT)] = PADDR(boot_pgdir) | PTE_U | PTE_P;
+       boot_kpt[PDX(UVPT)] = PADDR(boot_kpt) | PTE_U | PTE_P;
        /* set up core0s now (mostly for debugging) */
        setup_default_mtrrs(0);
        /* Our current gdt_pd (gdt64desc) is pointing to a physical address for the
@@ -519,7 +527,7 @@ void env_pagetable_free(struct proc *p)
 
 /* Remove the inner page tables along va's walk.  The internals are more
  * powerful.  We'll eventually want better arch-indep VM functions. */
-error_t        pagetable_remove(pde_t *pgdir, void *va)
+error_t        pagetable_remove(pgdir_t pgdir, void *va)
 {
        return unmap_segment(pgdir, (uintptr_t)va, PGSIZE);
 }
@@ -528,6 +536,31 @@ void page_check(void)
 {
 }
 
+int arch_pgdir_setup(pgdir_t boot_copy, pgdir_t *new_pd)
+{
+       kpte_t *kpt = kpage_alloc_addr();
+       if (!kpt)
+               return -ENOMEM;
+       memcpy(kpt, (kpte_t*)boot_copy, PGSIZE);
+
+       /* VPT and UVPT map the proc's page table, with different permissions. */
+       kpt[PDX(VPT)]  = PTE(LA2PPN(PADDR(kpt)), PTE_P | PTE_KERN_RW);
+       kpt[PDX(UVPT)] = PTE(LA2PPN(PADDR(kpt)), PTE_P | PTE_USER_RO);
+
+       *new_pd = (pgdir_t)kpt;
+       return 0;
+}
+
+physaddr_t arch_pgdir_get_cr3(pgdir_t pd)
+{
+       return PADDR((kpte_t*)pd);
+}
+
+void arch_pgdir_clear(pgdir_t *pd)
+{
+       *pd = 0;
+}
+
 /* Debugging */
 static int print_pte(kpte_t *kpte, uintptr_t kva, int shift, bool visited_subs,
                      void *data)
index 189421f..185c0e8 100644 (file)
@@ -9,7 +9,7 @@
 #include <ros/common.h>
 typedef unsigned long kpte_t;
 typedef unsigned long pte_t;
-typedef unsigned long pde_t;
+typedef unsigned long pgdir_t;
 #endif
 
 /* Virtual memory map:                                  Virt Addresses
index 91cd3ce..a2ba844 100644 (file)
@@ -67,7 +67,7 @@ struct proc {
        void* heap_top;
 
        // Address space
-       pde_t *COUNT(NPDENTRIES) env_pgdir;                     // Kernel virtual address of page dir
+       pgdir_t env_pgdir;                      // Kernel virtual address of page dir
        physaddr_t env_cr3;                     // Physical address of page dir
        spinlock_t vmr_lock;            /* Protects VMR tree (mem mgmt) */
        spinlock_t pte_lock;            /* Protects page tables (mem mgmt) */
index 9d9d7a9..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* page_lookup(pde_t *pgdir, void *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 *pgdir, const void *va, int create);
-int get_va_perms(pde_t *pgdir, const void *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)
 {
index b2f02d6..0bd26b4 100644 (file)
@@ -39,42 +39,13 @@ atomic_t num_envs;
 int env_setup_vm(env_t *e)
 WRITES(e->env_pgdir, e->env_cr3, e->procinfo, e->procdata)
 {
-       int i, r;
-       page_t *pgdir = NULL;
+       int i, ret;
        static page_t * RO shared_page = 0;
 
-       /* Get a page for the pgdir.  Storing the ref in pgdir/env_pgdir */
-       r = kpage_alloc(&pgdir);
-       if (r < 0)
-               return r;
-
-       /*
-        * Next, set up the e->env_pgdir and e->env_cr3 pointers to point
-        * to this newly allocated page and clear its contents
-        */
-       memset(page2kva(pgdir), 0, PGSIZE);
-       e->env_pgdir = (pde_t *COUNT(NPDENTRIES)) TC(page2kva(pgdir));
-       e->env_cr3 =   (physaddr_t) TC(page2pa(pgdir));
-
-       /*
-        * Now start filling in the pgdir with mappings required by all newly
-        * created address spaces
-        */
-
-       // Map in the kernel to the top of every address space
-       // should be able to do this so long as boot_pgdir never has
-       // anything put below ULIM
-       // TODO check on this!  had a nasty bug because of it
-       // this is a bit wonky, since if it's not PGSIZE, lots of other things are
-       // screwed up...
-       memcpy(e->env_pgdir, boot_pgdir, NPDENTRIES*sizeof(pde_t));
-
-       // VPT and UVPT map the env's own page table, with
-       // different permissions.
-       #ifndef NOVPT
-       e->env_pgdir[PDX(VPT)]  = PTE(LA2PPN(e->env_cr3), PTE_P | PTE_KERN_RW);
-       e->env_pgdir[PDX(UVPT)] = PTE(LA2PPN(e->env_cr3), PTE_P | PTE_USER_RO);
-       #endif
+       if ((ret = arch_pgdir_setup(boot_pgdir, &e->env_pgdir)))
+               return ret;
+       /* TODO: verify there is nothing below ULIM */
+       e->env_cr3 = arch_pgdir_get_cr3(e->env_pgdir);
 
        /* These need to be contiguous, so the kernel can alias them.  Note the
         * pages return with a refcnt, but it's okay to insert them since we free
index 648dd1d..6765928 100644 (file)
@@ -177,7 +177,7 @@ static int __showmapping(int argc, char **argv, struct hw_trapframe *hw_tf)
        struct proc *p;
        uintptr_t start;
        size_t size;
-       pde_t *pgdir;
+       pgdir_t pgdir;
        pid_t pid;
        if (argc < 3) {
                printk("Shows virtual -> physical mappings for a virt addr range.\n");
index 8659c38..cb8351f 100644 (file)
@@ -209,7 +209,7 @@ void *boot_zalloc(size_t amt, size_t align)
  *                   into which the page should be inserted
  *
  */
-int page_insert(pde_t *pgdir, struct page *page, void *va, int perm) 
+int page_insert(pgdir_t pgdir, struct page *page, void *va, int perm) 
 {
        pte_t pte = pgdir_walk(pgdir, va, 1);
        if (!pte_walk_okay(pte))
@@ -244,7 +244,7 @@ int page_insert(pde_t *pgdir, struct page *page, void *va, int perm)
  * @return PAGE the page mapped at virtual address 'va'
  * @return NULL No mapping exists at virtual address 'va', or it's paged out
  */
-page_t *page_lookup(pde_t *pgdir, void *va, pte_t *pte_store)
+page_t *page_lookup(pgdir_t pgdir, void *va, pte_t *pte_store)
 {
        pte_t pte = pgdir_walk(pgdir, va, 0);
        if (!pte_walk_okay(pte) || !pte_is_present(pte))
@@ -276,7 +276,7 @@ page_t *page_lookup(pde_t *pgdir, void *va, pte_t *pte_store)
  * TODO: consider deprecating this, or at least changing how it works with TLBs.
  * Might want to have the caller need to manage the TLB.  Also note it is used
  * in env_user_mem_free, minus the walk. */
-void page_remove(pde_t *pgdir, void *va)
+void page_remove(pgdir_t pgdir, void *va)
 {
        pte_t pte;
        page_t *page;
@@ -311,7 +311,7 @@ void page_remove(pde_t *pgdir, void *va)
  * @param va    the virtual address associated with the tlb entry
  *              we are trying to invalidate
  */
-void tlb_invalidate(pde_t *pgdir, void *va)
+void tlb_invalidate(pgdir_t pgdir, void *va)
 {
        // Flush the entry only if we're modifying the current address space.
        // For now, there is only one address space, so always invalidate.
index 2332652..5896add 100644 (file)
@@ -503,7 +503,7 @@ static void __proc_free(struct kref *kref)
        free_cont_pages(p->procdata, LOG2_UP(PROCDATA_NUM_PAGES));
 
        env_pagetable_free(p);
-       p->env_pgdir = 0;
+       arch_pgdir_clear(&p->env_pgdir);
        p->env_cr3 = 0;
 
        atomic_dec(&num_envs);