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 pagedir_activate (pd);
86 uint32_t *pd = palloc_get (0);
87 memcpy (pd, base_page_dir, PGSIZE);
92 pagedir_destroy (uint32_t *pd)
96 for (kpage = pagedir_first (pd, &upage); kpage != NULL;
97 kpage = pagedir_next (pd, &upage))
103 lookup_page (uint32_t *pagedir, void *upage, bool create)
108 ASSERT (pagedir != NULL);
109 ASSERT (pg_ofs (upage) == 0);
110 ASSERT (upage < PHYS_BASE);
112 /* Check for a page table for UPAGE.
113 If one is missing, create one if requested. */
114 pde = pagedir + pd_no (upage);
119 pagetab = palloc_get (PAL_ZERO);
123 *pde = make_pde (pagetab);
129 /* Return the page table entry. */
130 pagetab = pde_get_pagetab (*pde);
131 return &pagetab[pt_no (upage)];
135 pagedir_set_page (uint32_t *pagedir, void *upage, void *kpage,
140 ASSERT (pg_ofs (kpage) == 0);
142 pte = lookup_page (pagedir, upage, true);
145 *pte = make_pte (kpage, writable);
153 pagedir_get_page (uint32_t *pagedir, void *upage)
155 uint32_t *pte = lookup_page (pagedir, upage, false);
156 return pte != NULL && *pte != 0 ? pte_get_page (*pte) : NULL;
160 pagedir_clear_page (uint32_t *pagedir, void *upage)
162 uint32_t *pte = lookup_page (pagedir, upage, false);
168 scan_pt (uint32_t *pt, unsigned pde_idx, unsigned pte_idx, void **upage)
170 for (; pte_idx < PGSIZE / sizeof *pt; pte_idx++)
172 uint32_t pte = pt[pte_idx];
176 void *kpage = pte_get_page (pte);
179 *upage = (void *) ((pde_idx << PDSHIFT) | (pte_idx << PTSHIFT));
189 scan_pd (uint32_t *pd, unsigned pde_idx, void **upage)
191 for (; pde_idx < pd_no (PHYS_BASE); pde_idx++)
193 uint32_t pde = pd[pde_idx];
197 void *kpage = scan_pt (pde_get_pagetab (pde), pde_idx, 0, upage);
207 pagedir_first (uint32_t *pagedir, void **upage)
209 return scan_pd (pagedir, 0, upage);
213 pagedir_next (uint32_t *pd, void **upage)
215 unsigned pde_idx, pte_idx;
218 pde_idx = pd_no (*upage);
219 pte_idx = pt_no (*upage);
220 kpage = scan_pt (pde_get_pagetab (pd[pde_idx]),
221 pde_idx, pte_idx + 1, upage);
223 kpage = scan_pd (pd, pde_idx + 1, upage);
228 pagedir_activate (uint32_t *pagedir)
230 asm volatile ("movl %0,%%cr3" :: "r" (vtop (pagedir)));