SMP boot cleanup
authorBarret Rhoden <brho@cs.berkeley.edu>
Thu, 28 May 2009 00:58:21 +0000 (17:58 -0700)
committerBarret Rhoden <brho@cs.berkeley.edu>
Thu, 28 May 2009 01:02:14 +0000 (18:02 -0700)
Deallocates the *page table* used by the smp_boot mapping, which was
being copied into every processes address space, which caused problems.

Need to take a look at UTOP and ULIM and add a check in env_vm_setup to
check for these things in the future.  Do this when gutting UPAGES.

include/pmap.h
include/ros/env.h
kern/src/env.c
kern/src/pmap.c
kern/src/smp.c

index 223be06..20b4abe 100644 (file)
@@ -86,6 +86,7 @@ void  page_free(page_t *pp);
 int    page_insert(pde_t *pgdir, page_t *pp, void *va, int perm);
 void   page_remove(pde_t *pgdir, void *va);
 page_t *page_lookup(pde_t *pgdir, void *va, pte_t **pte_store);
+error_t        pagetable_remove(pde_t *pgdir, void *va);
 void   page_decref(page_t *pp);
 
 void setup_default_mtrrs(barrier_t* smp_barrier);
@@ -121,7 +122,7 @@ static inline physaddr_t page2pa(page_t *pp)
 static inline page_t* pa2page(physaddr_t pa)
 {
        if (PPN(pa) >= npage)
-               warn("pa2page called with pa larger than npage");
+               warn("pa2page called with pa (0x%08x) larger than npage", pa);
        return &pages[PPN(pa)];
 }
 
index 6a374bf..3744046 100644 (file)
@@ -42,9 +42,9 @@ typedef int32_t envid_t;
 #define ENV_DYING                      4
 
 struct Env {
+       LIST_ENTRY(env_t) env_link;     // Free list link pointers
        uint32_t lock;
        trapframe_t env_tf;                     // Saved registers
-       LIST_ENTRY(env_t) env_link;     // Free list link pointers
        envid_t env_id;                         // Unique environment identifier
        envid_t env_parent_id;          // env_id of this env's parent
        unsigned env_status;            // Status of the environment
index 85799d3..f25dd48 100644 (file)
@@ -202,6 +202,8 @@ env_alloc(env_t **newenv_store, envid_t parent_id)
 
        if (!(e = LIST_FIRST(&env_free_list)))
                return -E_NO_FREE_ENV;
+       
+       memset((void*)e + sizeof(e->env_link), 0, sizeof(*e) - sizeof(e->env_link));
 
        // Allocate and set up the page directory for this environment.
        if ((r = env_setup_vm(e)) < 0)
index f73b75d..a50d611 100644 (file)
@@ -785,6 +785,28 @@ page_free(page_t *pp)
        }
 }
 
+/* 
+ * Remove the second level page table associated with virtual address va.
+ * Will 0 out the PDE for that page table.
+ * Panics if the page table has any present entries.
+ * This should be called rarely and with good cause.
+ * Currently errors if the PDE is jumbo or not present.
+ */
+error_t        pagetable_remove(pde_t *pgdir, void *va)
+{
+       pde_t* the_pde = &pgdir[PDX(va)];
+
+       if (!(*the_pde & PTE_P) || (*the_pde & PTE_PS))
+               return -E_FAULT;
+       pte_t* page_table = (pde_t*)KADDR(PTE_ADDR(*the_pde));
+       for (int i = 0; i < NPTENTRIES; i++) 
+               if (page_table[i] & PTE_P)
+                       panic("Page table not empty during attempted removal!");
+       *the_pde = 0;
+       page_decref(pa2page(PADDR(page_table)));
+       return 0;
+}
+
 //
 // Decrement the reference count on a page,
 // freeing it if there are no more refs.
index f3e84e2..dcab5d3 100644 (file)
@@ -116,6 +116,8 @@ void smp_boot(void)
        // TODO after we parse ACPI tables
        if (num_cpus == 8) // TODO - ghetto coded for our 8 way SMPs
                page_decref(pa2page(trampoline_pg));
+       // Remove the page table used for that mapping
+       pagetable_remove(boot_pgdir, (void*)trampoline_pg);
        // Dealloc the temp shared stack
        page_decref(smp_stack);