+ uint32_t *pte;
+
+ ASSERT (is_user_vaddr (uaddr));
+
+ pte = lookup_page (pd, uaddr, false);
+ if (pte != NULL && (*pte & PTE_P) != 0)
+ return pte_get_page (*pte) + pg_ofs (uaddr);
+ else
+ return NULL;
+}
+
+/* Marks user virtual page UPAGE "not present" in page
+ directory PD. Later accesses to the page will fault. Other
+ bits in the page table entry are preserved.
+ UPAGE need not be mapped. */
+void
+pagedir_clear_page (uint32_t *pd, void *upage)
+{
+ uint32_t *pte;
+
+ ASSERT (pg_ofs (upage) == 0);
+ ASSERT (is_user_vaddr (upage));
+
+ pte = lookup_page (pd, upage, false);
+ if (pte != NULL && (*pte & PTE_P) != 0)
+ {
+ *pte &= ~PTE_P;
+ invalidate_pagedir (pd);
+ }
+}
+
+/* Returns true if the PTE for virtual page VPAGE in PD is dirty,
+ that is, if the page has been modified since the PTE was
+ installed.
+ Returns false if PD contains no PTE for VPAGE. */
+bool
+pagedir_is_dirty (uint32_t *pd, const void *vpage)
+{
+ uint32_t *pte = lookup_page (pd, vpage, false);
+ return pte != NULL && (*pte & PTE_D) != 0;
+}
+
+/* Set the dirty bit to DIRTY in the PTE for virtual page VPAGE
+ in PD. */
+void
+pagedir_set_dirty (uint32_t *pd, const void *vpage, bool dirty)
+{
+ uint32_t *pte = lookup_page (pd, vpage, false);
+ if (pte != NULL)
+ {
+ if (dirty)
+ *pte |= PTE_D;
+ else
+ {
+ *pte &= ~(uint32_t) PTE_D;
+ invalidate_pagedir (pd);
+ }
+ }
+}
+
+/* Returns true if the PTE for virtual page VPAGE in PD has been
+ accessed recently, that is, between the time the PTE was
+ installed and the last time it was cleared. Returns false if
+ PD contains no PTE for VPAGE. */
+bool
+pagedir_is_accessed (uint32_t *pd, const void *vpage)
+{
+ uint32_t *pte = lookup_page (pd, vpage, false);
+ return pte != NULL && (*pte & PTE_A) != 0;
+}
+
+/* Sets the accessed bit to ACCESSED in the PTE for virtual page
+ VPAGE in PD. */
+void
+pagedir_set_accessed (uint32_t *pd, const void *vpage, bool accessed)
+{
+ uint32_t *pte = lookup_page (pd, vpage, false);
+ if (pte != NULL)
+ {
+ if (accessed)
+ *pte |= PTE_A;
+ else
+ {
+ *pte &= ~(uint32_t) PTE_A;
+ invalidate_pagedir (pd);
+ }
+ }