1 #include "userprog/pagedir.h"
5 #include "threads/init.h"
6 #include "threads/mmu.h"
7 #include "threads/palloc.h"
9 /* Creates a new page directory that has mappings for kernel
10 virtual addresses, but none for user virtual addresses.
11 Returns the new page directory, or a null pointer if memory
16 uint32_t *pd = palloc_get (0);
17 memcpy (pd, base_page_dir, PGSIZE);
21 /* Destroys page directory PD, freeing all the pages it
24 pagedir_destroy (uint32_t *pd)
31 for (pde = pd; pde < pd + pd_no (PHYS_BASE); pde++)
34 uint32_t *pt = pde_get_pt (*pde);
37 for (pte = pt; pte < pt + PGSIZE / sizeof *pte; pte++)
39 palloc_free (pte_get_page (*pte));
45 /* Returns the mapping of user virtual address UADDR in page
46 directory PD into a kernel virtual address.
47 If UADDR is unmapped, behavior varies based on CREATE:
48 if CREATE is true, then a new, zeroed page is created and a
49 pointer into it is returned,
50 otherwise a null pointer is returned. */
52 lookup_page (uint32_t *pd, void *uaddr, bool create)
57 ASSERT (uaddr < PHYS_BASE);
59 /* Check for a page table for UADDR.
60 If one is missing, create one if requested. */
61 pde = pd + pd_no (uaddr);
66 pt = palloc_get (PAL_ZERO);
70 *pde = pde_create (pt);
76 /* Return the page table entry. */
77 pt = pde_get_pt (*pde);
78 return &pt[pt_no (uaddr)];
81 /* Adds a mapping from user virtual address UPAGE to kernel
82 virtual address KPAGE in page directory PD.
83 UPAGE must not already be mapped.
84 If WRITABLE is true, the new page is read/write;
85 otherwise it is read-only.
86 Returns true if successful, false if memory allocation
89 pagedir_set_page (uint32_t *pd, void *upage, void *kpage,
94 ASSERT (pg_ofs (upage) == 0);
95 ASSERT (pg_ofs (kpage) == 0);
96 ASSERT (lookup_page (pd, upage, false) == NULL);
98 pte = lookup_page (pd, upage, true);
101 *pte = pte_create_user (kpage, writable);
108 /* Returns the kernel virtual address that user virtual address
109 UADDR is mapped to in PD, or a null pointer if there is no
112 pagedir_get_page (uint32_t *pd, const void *uaddr)
114 uint32_t *pte = lookup_page (pd, (void *) uaddr, false);
115 return pte != NULL && *pte != 0 ? pte_get_page (*pte) : NULL;
118 /* Loads page directory PD into the CPU's page directory base
121 pagedir_activate (uint32_t *pd)
125 asm volatile ("movl %0,%%cr3" :: "r" (vtop (pd)));