Only destroy pages up to PHYS_BASE.
[pintos-anon] / src / userprog / pagedir.c
1 #include "userprog/pagedir.h"
2 #include <stdbool.h>
3 #include <stddef.h>
4 #include <string.h>
5 #include "threads/init.h"
6 #include "threads/mmu.h"
7 #include "threads/palloc.h"
8
9 uint32_t *
10 pagedir_create (void) 
11 {
12   uint32_t *pd = palloc_get (0);
13   memcpy (pd, base_page_dir, PGSIZE);
14   return pd;
15 }
16
17 void
18 pagedir_destroy (uint32_t *pd) 
19 {
20   uint32_t *pde;
21
22   for (pde = pd; pde < pd + pd_no (PHYS_BASE); pde++)
23     if (*pde & PG_P) 
24       {
25         uint32_t *pt = pde_get_pt (*pde);
26         uint32_t *pte;
27         
28         for (pte = pt; pte < pt + PGSIZE / sizeof *pte; pte++)
29           if (*pte & PG_P) 
30             palloc_free (pte_get_page (*pte));
31         palloc_free (pt);
32       }
33   palloc_free (pd);
34 }
35
36 static uint32_t *
37 lookup_page (uint32_t *pd, void *upage, bool create)
38 {
39   uint32_t *pt;
40   uint32_t *pde;
41
42   ASSERT (pd != NULL);
43   ASSERT (pg_ofs (upage) == 0);
44   ASSERT (upage < PHYS_BASE);
45
46   /* Check for a page table for UPAGE.
47      If one is missing, create one if requested. */
48   pde = pd + pd_no (upage);
49   if (*pde == 0) 
50     {
51       if (create)
52         {
53           pt = palloc_get (PAL_ZERO);
54           if (pt == NULL) 
55             return NULL; 
56       
57           *pde = pde_create (pt);
58         }
59       else
60         return NULL;
61     }
62
63   /* Return the page table entry. */
64   pt = pde_get_pt (*pde);
65   return &pt[pt_no (upage)];
66 }
67
68 bool
69 pagedir_set_page (uint32_t *pd, void *upage, void *kpage,
70                   bool writable) 
71 {
72   uint32_t *pte;
73
74   ASSERT (pg_ofs (kpage) == 0);
75
76   pte = lookup_page (pd, upage, true);
77   if (pte != NULL) 
78     {
79       *pte = pte_create_user (kpage, writable);
80       return true;
81     }
82   else
83     return false;
84 }
85
86 void *
87 pagedir_get_page (uint32_t *pd, void *upage) 
88 {
89   uint32_t *pte = lookup_page (pd, upage, false);
90   return pte != NULL && *pte != 0 ? pte_get_page (*pte) : NULL;
91 }
92
93 void
94 pagedir_clear_page (uint32_t *pd, void *upage)
95 {
96   uint32_t *pte = lookup_page (pd, upage, false);
97   if (pte != NULL)
98     *pte = 0;
99 }
100
101 void
102 pagedir_activate (uint32_t *pd) 
103 {
104   if (pd == NULL)
105     pd = base_page_dir;
106   asm volatile ("movl %0,%%cr3" :: "r" (vtop (pd)));
107 }