Make pagedir_destroy(NULL) a no-op.
[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   if (pd == NULL)
23     return;
24
25   for (pde = pd; pde < pd + pd_no (PHYS_BASE); pde++)
26     if (*pde & PG_P) 
27       {
28         uint32_t *pt = pde_get_pt (*pde);
29         uint32_t *pte;
30         
31         for (pte = pt; pte < pt + PGSIZE / sizeof *pte; pte++)
32           if (*pte & PG_P) 
33             palloc_free (pte_get_page (*pte));
34         palloc_free (pt);
35       }
36   palloc_free (pd);
37 }
38
39 static uint32_t *
40 lookup_page (uint32_t *pd, void *upage, bool create)
41 {
42   uint32_t *pt;
43   uint32_t *pde;
44
45   ASSERT (pd != NULL);
46   ASSERT (upage < PHYS_BASE);
47
48   /* Check for a page table for UPAGE.
49      If one is missing, create one if requested. */
50   pde = pd + pd_no (upage);
51   if (*pde == 0) 
52     {
53       if (create)
54         {
55           pt = palloc_get (PAL_ZERO);
56           if (pt == NULL) 
57             return NULL; 
58       
59           *pde = pde_create (pt);
60         }
61       else
62         return NULL;
63     }
64
65   /* Return the page table entry. */
66   pt = pde_get_pt (*pde);
67   return &pt[pt_no (upage)];
68 }
69
70 bool
71 pagedir_set_page (uint32_t *pd, void *upage, void *kpage,
72                   bool writable) 
73 {
74   uint32_t *pte;
75
76   ASSERT (pg_ofs (kpage) == 0);
77
78   pte = lookup_page (pd, upage, true);
79   if (pte != NULL) 
80     {
81       *pte = pte_create_user (kpage, writable);
82       return true;
83     }
84   else
85     return false;
86 }
87
88 void *
89 pagedir_get_page (uint32_t *pd, const void *upage) 
90 {
91   uint32_t *pte = lookup_page (pd, (void *) upage, false);
92   return pte != NULL && *pte != 0 ? pte_get_page (*pte) : NULL;
93 }
94
95 void
96 pagedir_clear_page (uint32_t *pd, void *upage)
97 {
98   uint32_t *pte = lookup_page (pd, upage, false);
99   if (pte != NULL)
100     *pte = 0;
101 }
102
103 void
104 pagedir_activate (uint32_t *pd) 
105 {
106   if (pd == NULL)
107     pd = base_page_dir;
108   asm volatile ("movl %0,%%cr3" :: "r" (vtop (pd)));
109 }