9 static uint32_t *base_page_dir;
12 make_pde (uint32_t *pagetab)
14 ASSERT (pg_ofs (pagetab) == 0);
16 return vtop (pagetab) | PG_U | PG_P | PG_W;
20 make_pte (uint32_t *page, bool writable)
24 ASSERT (pg_ofs (page) == 0);
26 entry = vtop (page) | PG_U | PG_P;
33 pde_get_pagetab (uint32_t pde)
37 return ptov (pde & ~PGMASK);
41 pte_get_page (uint32_t pte)
45 return ptov (pte & ~PGMASK);
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 * PGSIZE;
67 void *vaddr = ptov (paddr);
68 size_t pde_idx = pd_no (vaddr);
69 size_t pte_idx = pt_no (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, PGSIZE);
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 (pg_ofs (upage) == 0);
111 ASSERT (upage < PHYS_BASE);
113 /* Check for a page table for UPAGE.
114 If one is missing, create one if requested. */
115 pde = pagedir + pd_no (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[pt_no (upage)];
136 pagedir_set_page (uint32_t *pagedir, void *upage, void *kpage,
141 ASSERT (pg_ofs (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 < PGSIZE / sizeof *pt; pte_idx++)
173 uint32_t pte = pt[pte_idx];
177 void *kpage = pte_get_page (pte);
180 *upage = (void *) ((pde_idx << PDSHIFT) | (pte_idx << PTSHIFT));
190 scan_pd (uint32_t *pd, unsigned pde_idx, void **upage)
192 for (; pde_idx < pd_no (PHYS_BASE); pde_idx++)
194 uint32_t pde = pd[pde_idx];
198 void *kpage = scan_pt (pde_get_pagetab (pde), pde_idx, 0, upage);
208 pagedir_first (uint32_t *pagedir, void **upage)
210 return scan_pd (pagedir, 0, upage);
214 pagedir_next (uint32_t *pd, void **upage)
216 unsigned pde_idx, pte_idx;
219 pde_idx = pd_no (*upage);
220 pte_idx = pt_no (*upage);
221 kpage = scan_pt (pde_get_pagetab (pd[pde_idx]),
222 pde_idx, pte_idx + 1, upage);
224 kpage = scan_pd (pd, pde_idx + 1, upage);
228 void pagedir_activate (uint32_t *pagedir);