#include "threads/mmu.h"
#include "threads/palloc.h"
+/* Creates a new page directory that has mappings for kernel
+ virtual addresses, but none for user virtual addresses.
+ Returns the new page directory, or a null pointer if memory
+ allocation fails. */
uint32_t *
pagedir_create (void)
{
return pd;
}
+/* Destroys page directory PD, freeing all the pages it
+ references. */
void
pagedir_destroy (uint32_t *pd)
{
palloc_free (pd);
}
+/* Returns the mapping of user virtual address UADDR in page
+ directory PD into a kernel virtual address.
+ If UADDR is unmapped, behavior varies based on CREATE:
+ if CREATE is true, then a new, zeroed page is created and a
+ pointer into it is returned,
+ otherwise a null pointer is returned. */
static uint32_t *
-lookup_page (uint32_t *pd, void *upage, bool create)
+lookup_page (uint32_t *pd, void *uaddr, bool create)
{
- uint32_t *pt;
- uint32_t *pde;
+ uint32_t *pt, *pde;
ASSERT (pd != NULL);
- ASSERT (upage < PHYS_BASE);
+ ASSERT (uaddr < PHYS_BASE);
- /* Check for a page table for UPAGE.
+ /* Check for a page table for UADDR.
If one is missing, create one if requested. */
- pde = pd + pd_no (upage);
+ pde = pd + pd_no (uaddr);
if (*pde == 0)
{
if (create)
/* Return the page table entry. */
pt = pde_get_pt (*pde);
- return &pt[pt_no (upage)];
+ return &pt[pt_no (uaddr)];
}
+/* Adds a mapping from user virtual address UPAGE to kernel
+ virtual address KPAGE in page directory PD.
+ UPAGE must not already be mapped.
+ If WRITABLE is true, the new page is read/write;
+ otherwise it is read-only.
+ Returns true if successful, false if memory allocation
+ failed. */
bool
pagedir_set_page (uint32_t *pd, void *upage, void *kpage,
bool writable)
{
uint32_t *pte;
+ ASSERT (pg_ofs (upage) == 0);
ASSERT (pg_ofs (kpage) == 0);
+ ASSERT (lookup_page (pd, upage, false) == NULL);
pte = lookup_page (pd, upage, true);
if (pte != NULL)
return false;
}
+/* Returns the kernel virtual address that user virtual address
+ UADDR is mapped to in PD, or a null pointer if there is no
+ mapping. */
void *
-pagedir_get_page (uint32_t *pd, const void *upage)
+pagedir_get_page (uint32_t *pd, const void *uaddr)
{
- uint32_t *pte = lookup_page (pd, (void *) upage, false);
+ uint32_t *pte = lookup_page (pd, (void *) uaddr, false);
return pte != NULL && *pte != 0 ? pte_get_page (*pte) : NULL;
}
-void
-pagedir_clear_page (uint32_t *pd, void *upage)
-{
- uint32_t *pte = lookup_page (pd, upage, false);
- if (pte != NULL)
- *pte = 0;
-}
-
+/* Loads page directory PD into the CPU's page directory base
+ register. */
void
pagedir_activate (uint32_t *pd)
{
#include <stdint.h>
uint32_t *pagedir_create (void);
-void pagedir_destroy (uint32_t *);
-bool pagedir_set_page (uint32_t *pagedir, void *upage, void *kpage,
- bool writable);
-void *pagedir_get_page (uint32_t *pagedir, const void *upage);
-void pagedir_clear_page (uint32_t *pagedir, void *upage);
-
-void pagedir_activate (uint32_t *pagedir);
+void pagedir_destroy (uint32_t *pd);
+bool pagedir_set_page (uint32_t *pd, void *upage, void *kpage, bool rw);
+void *pagedir_get_page (uint32_t *pd, const void *upage);
+void pagedir_activate (uint32_t *pd);
#endif /* userprog/pagedir.h */