9 static uint32_t *base_page_dir;
12 make_pde (uint32_t *pagetab)
14 ASSERT (PGOFS ((uintptr_t) pagetab) == 0);
16 return vtop (pagetab) | PG_U | PG_P | PG_W;
20 make_pte (uint32_t *page, bool writable)
24 ASSERT (PGOFS ((uintptr_t) page) == 0);
26 entry = vtop (page) | PG_U | PG_P;
33 pde_get_pagetab (uint32_t pde)
37 return ptov (PGROUNDDOWN (pde));
41 pte_get_page (uint32_t pte)
45 return ptov (PGROUNDDOWN (pte));
48 /* Populates the base page directory and page table with the
49 kernel virtual mapping, and then sets up the CPU to use the
52 At the time this function is called, the active page table
53 only maps the first 4 MB of RAM, so it should not try to use
54 extravagant amounts of memory. Fortunately, there is no need
62 pd = base_page_dir = palloc_get (PAL_ASSERT | PAL_ZERO);
64 for (page = 0; page < ram_pages; page++)
66 uintptr_t paddr = page * NBPG;
67 void *vaddr = ptov (paddr);
68 size_t pde_idx = PDENO ((uintptr_t) vaddr);
69 size_t pte_idx = PTENO ((uintptr_t) vaddr);
73 pt = palloc_get (PAL_ASSERT | PAL_ZERO);
74 pd[pde_idx] = make_pde (pt);
77 pt[pte_idx] = make_pte (vaddr, true);
80 /* Set the page table. */
81 asm volatile ("movl %0,%%cr3" :: "r" (vtop (pd)));
87 uint32_t *pd = palloc_get (0);
88 memcpy (pd, base_page_dir, NBPG);
93 pagedir_destroy (uint32_t *pd)
97 for (kpage = pagedir_first (pd, &upage); kpage != NULL;
98 kpage = pagedir_next (pd, &upage))
104 lookup_page (uint32_t *pagedir, void *upage, bool create)
109 ASSERT (pagedir != NULL);
110 ASSERT (PGOFS ((uintptr_t) upage) == 0);
111 ASSERT ((uintptr_t) upage < PHYS_BASE);
113 /* Check for a page table for UPAGE.
114 If one is missing, create one if requested. */
115 pde = pagedir + PDENO ((uint32_t) upage);
120 pagetab = palloc_get (PAL_ZERO);
124 *pde = make_pde (pagetab);
130 /* Return the page table entry. */
131 pagetab = pde_get_pagetab (*pde);
132 return &pagetab[PTENO ((uintptr_t) upage)];
136 pagedir_set_page (uint32_t *pagedir, void *upage, void *kpage,
141 ASSERT (PGOFS ((uintptr_t) kpage) == 0);
143 pte = lookup_page (pagedir, upage, true);
146 *pte = make_pte (kpage, writable);
154 pagedir_get_page (uint32_t *pagedir, void *upage)
156 uint32_t *pte = lookup_page (pagedir, upage, false);
157 return pte != NULL && *pte != 0 ? pte_get_page (*pte) : NULL;
161 pagedir_clear_page (uint32_t *pagedir, void *upage)
163 uint32_t *pte = lookup_page (pagedir, upage, false);
169 scan_pt (uint32_t *pt, unsigned pde_idx, unsigned pte_idx, void **upage)
171 for (; pte_idx < NBPG / sizeof *pt; pte_idx++)
173 uint32_t pte = pt[pte_idx];
177 void *kpage = pte_get_page (pte);
180 *upage = (void *) ((pde_idx << PDSHIFT)
181 | (pte_idx << PGSHIFT));
191 scan_pd (uint32_t *pd, unsigned pde_idx, void **upage)
193 for (; pde_idx < PDENO (PHYS_BASE); pde_idx++)
195 uint32_t pde = pd[pde_idx];
199 void *kpage = scan_pt (pde_get_pagetab (pde), pde_idx, 0, upage);
209 pagedir_first (uint32_t *pagedir, void **upage)
211 return scan_pd (pagedir, 0, upage);
215 pagedir_next (uint32_t *pd, void **upage)
217 unsigned pde_idx, pte_idx;
220 pde_idx = PDENO (*upage);
221 pte_idx = PTENO (*upage);
222 kpage = scan_pt (pde_get_pagetab (pd[pde_idx]),
223 pde_idx, pte_idx + 1, upage);
225 kpage = scan_pd (pd, pde_idx + 1, upage);
229 void pagedir_activate (uint32_t *pagedir);