X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fthreads%2Fpaging.c;h=ca5f4b49ac0e56ea4c1bad738230f26f9c83e69e;hb=f6580e9ad405b519dbe85027691bf3c66074b0a4;hp=9fd568caf894107e02b09edda8dff05d9d060d9e;hpb=a98578bf3b6b5c946713654b404a886a7199dbee;p=pintos-anon diff --git a/src/threads/paging.c b/src/threads/paging.c index 9fd568c..ca5f4b4 100644 --- a/src/threads/paging.c +++ b/src/threads/paging.c @@ -2,35 +2,28 @@ #include #include #include "init.h" -#include "lib.h" #include "mmu.h" #include "palloc.h" +#include "lib/lib.h" static uint32_t *base_page_dir; -static uint32_t -make_pde (uint32_t *pagetab) -{ - ASSERT (pg_ofs (pagetab) == 0); - - return vtop (pagetab) | PG_U | PG_P | PG_W; +static uint32_t make_pde (uint32_t *pt) { + ASSERT (pg_ofs (pt) == 0); + return vtop (pt) | PG_U | PG_P | PG_W; } -static uint32_t -make_pte (uint32_t *page, bool writable) -{ - uint32_t entry; - +static uint32_t make_kernel_pte (uint32_t *page, bool writable) { ASSERT (pg_ofs (page) == 0); - - entry = vtop (page) | PG_U | PG_P; - if (writable) - entry |= PG_W; - return entry; + return vtop (page) | PG_P | (writable ? PG_W : 0); +} + +static uint32_t make_user_pte (uint32_t *page, bool writable) { + return make_kernel_pte (page, writable) | PG_U; } static uint32_t * -pde_get_pagetab (uint32_t pde) +pde_get_pt (uint32_t pde) { ASSERT (pde & PG_P); @@ -50,9 +43,9 @@ pte_get_page (uint32_t pte) new page directory. At the time this function is called, the active page table - only maps the first 4 MB of RAM, so it should not try to use - extravagant amounts of memory. Fortunately, there is no need - to do so. */ + (set up by loader.S) only maps the first 4 MB of RAM, so we + should not try to use extravagant amounts of memory. + Fortunately, there is no need to do so. */ void paging_init (void) { @@ -74,11 +67,10 @@ paging_init (void) pd[pde_idx] = make_pde (pt); } - pt[pte_idx] = make_pte (vaddr, true); + pt[pte_idx] = make_kernel_pte (vaddr, true); } - /* Set the page table. */ - asm volatile ("movl %0,%%cr3" :: "r" (vtop (pd))); + pagedir_activate (pd); } uint32_t * @@ -93,57 +85,73 @@ void pagedir_destroy (uint32_t *pd) { void *kpage, *upage; + unsigned pde_idx; + /* Destroy user pages. */ for (kpage = pagedir_first (pd, &upage); kpage != NULL; kpage = pagedir_next (pd, &upage)) palloc_free (kpage); + + /* Destroy page table pages. */ + for (pde_idx = 0; pde_idx < pd_no (PHYS_BASE); pde_idx++) + { + uint32_t pde = pd[pde_idx]; + + if (pde != 0) + { + uint32_t *pt = pde_get_pt (pde); + palloc_free (pt); + } + } + + /* Destroy page directory. */ palloc_free (pd); } static uint32_t * -lookup_page (uint32_t *pagedir, void *upage, bool create) +lookup_page (uint32_t *pd, void *upage, bool create) { - uint32_t *pagetab; + uint32_t *pt; uint32_t *pde; - ASSERT (pagedir != NULL); + ASSERT (pd != NULL); ASSERT (pg_ofs (upage) == 0); ASSERT (upage < PHYS_BASE); /* Check for a page table for UPAGE. If one is missing, create one if requested. */ - pde = pagedir + pd_no (upage); + pde = pd + pd_no (upage); if (*pde == 0) { if (create) { - pagetab = palloc_get (PAL_ZERO); - if (pagetab == NULL) + pt = palloc_get (PAL_ZERO); + if (pt == NULL) return NULL; - *pde = make_pde (pagetab); + *pde = make_pde (pt); } else return NULL; } /* Return the page table entry. */ - pagetab = pde_get_pagetab (*pde); - return &pagetab[pt_no (upage)]; + pt = pde_get_pt (*pde); + return &pt[pt_no (upage)]; } bool -pagedir_set_page (uint32_t *pagedir, void *upage, void *kpage, +pagedir_set_page (uint32_t *pd, void *upage, void *kpage, bool writable) { uint32_t *pte; ASSERT (pg_ofs (kpage) == 0); - pte = lookup_page (pagedir, upage, true); + pte = lookup_page (pd, upage, true); if (pte != NULL) { - *pte = make_pte (kpage, writable); + *pte = make_user_pte (kpage, writable); return true; } else @@ -151,16 +159,16 @@ pagedir_set_page (uint32_t *pagedir, void *upage, void *kpage, } void * -pagedir_get_page (uint32_t *pagedir, void *upage) +pagedir_get_page (uint32_t *pd, void *upage) { - uint32_t *pte = lookup_page (pagedir, upage, false); + uint32_t *pte = lookup_page (pd, upage, false); return pte != NULL && *pte != 0 ? pte_get_page (*pte) : NULL; } void -pagedir_clear_page (uint32_t *pagedir, void *upage) +pagedir_clear_page (uint32_t *pd, void *upage) { - uint32_t *pte = lookup_page (pagedir, upage, false); + uint32_t *pte = lookup_page (pd, upage, false); if (pte != NULL) *pte = 0; } @@ -195,7 +203,7 @@ scan_pd (uint32_t *pd, unsigned pde_idx, void **upage) if (pde != 0) { - void *kpage = scan_pt (pde_get_pagetab (pde), pde_idx, 0, upage); + void *kpage = scan_pt (pde_get_pt (pde), pde_idx, 0, upage); if (kpage != NULL) return kpage; } @@ -205,9 +213,9 @@ scan_pd (uint32_t *pd, unsigned pde_idx, void **upage) } void * -pagedir_first (uint32_t *pagedir, void **upage) +pagedir_first (uint32_t *pd, void **upage) { - return scan_pd (pagedir, 0, upage); + return scan_pd (pd, 0, upage); } void * @@ -218,11 +226,17 @@ pagedir_next (uint32_t *pd, void **upage) pde_idx = pd_no (*upage); pte_idx = pt_no (*upage); - kpage = scan_pt (pde_get_pagetab (pd[pde_idx]), + kpage = scan_pt (pde_get_pt (pd[pde_idx]), pde_idx, pte_idx + 1, upage); if (kpage == NULL) kpage = scan_pd (pd, pde_idx + 1, upage); return kpage; } -void pagedir_activate (uint32_t *pagedir); +void +pagedir_activate (uint32_t *pd) +{ + if (pd == NULL) + pd = base_page_dir; + asm volatile ("movl %0,%%cr3" :: "r" (vtop (pd))); +}