[Krafton Jungle] PintOS 2.0.0
크래프톤 정글 PintOS
 
Loading...
Searching...
No Matches
mmu.c File Reference
#include <stdbool.h>
#include <stddef.h>
#include <string.h>
#include "threads/init.h"
#include "threads/pte.h"
#include "threads/palloc.h"
#include "threads/thread.h"
#include "threads/mmu.h"
#include "intrinsic.h"
Include dependency graph for mmu.c:

Functions

static uint64_tpgdir_walk (uint64_t *pdp, const uint64_t va, int create)
 
static uint64_tpdpe_walk (uint64_t *pdpe, const uint64_t va, int create)
 
uint64_tpml4e_walk (uint64_t *pml4e, const uint64_t va, int create)
 
uint64_tpml4_create (void)
 
static bool pt_for_each (uint64_t *pt, pte_for_each_func *func, void *aux, unsigned pml4_index, unsigned pdp_index, unsigned pdx_index)
 
static bool pgdir_for_each (uint64_t *pdp, pte_for_each_func *func, void *aux, unsigned pml4_index, unsigned pdp_index)
 
static bool pdp_for_each (uint64_t *pdp, pte_for_each_func *func, void *aux, unsigned pml4_index)
 
bool pml4_for_each (uint64_t *pml4, pte_for_each_func *func, void *aux)
 
static void pt_destroy (uint64_t *pt)
 
static void pgdir_destroy (uint64_t *pdp)
 
static void pdpe_destroy (uint64_t *pdpe)
 
void pml4_destroy (uint64_t *pml4)
 
void pml4_activate (uint64_t *pml4)
 
void * pml4_get_page (uint64_t *pml4, const void *uaddr)
 
bool pml4_set_page (uint64_t *pml4, void *upage, void *kpage, bool rw)
 
void pml4_clear_page (uint64_t *pml4, void *upage)
 
bool pml4_is_dirty (uint64_t *pml4, const void *vpage)
 
void pml4_set_dirty (uint64_t *pml4, const void *vpage, bool dirty)
 
bool pml4_is_accessed (uint64_t *pml4, const void *vpage)
 
void pml4_set_accessed (uint64_t *pml4, const void *vpage, bool accessed)
 

Function Documentation

◆ pdp_for_each()

static bool pdp_for_each ( uint64_t pdp,
pte_for_each_func func,
void *  aux,
unsigned  pml4_index 
)
static
135 {
136 for (unsigned i = 0; i < PGSIZE / sizeof(uint64_t *); i++) {
137 uint64_t *pde = ptov((uint64_t *) pdp[i]);
138 if (((uint64_t) pde) & PTE_P)
139 if (!pgdir_for_each ((uint64_t *) PTE_ADDR (pde), func,
140 aux, pml4_index, i))
141 return false;
142 }
143 return true;
144}
static bool pgdir_for_each(uint64_t *pdp, pte_for_each_func *func, void *aux, unsigned pml4_index, unsigned pdp_index)
Definition: mmu.c:121
#define PTE_ADDR(pte)
Definition: pte.h:29
#define PTE_P
Definition: pte.h:39
unsigned long long int uint64_t
Definition: stdint.h:29
#define PGSIZE
Definition: vaddr.h:20
#define ptov(paddr)
Definition: vaddr.h:49
Here is the call graph for this function:
Here is the caller graph for this function:

◆ pdpe_destroy()

static void pdpe_destroy ( uint64_t pdpe)
static
179 {
180 for (unsigned i = 0; i < PGSIZE / sizeof(uint64_t *); i++) {
181 uint64_t *pde = ptov((uint64_t *) pdpe[i]);
182 if (((uint64_t) pde) & PTE_P)
183 pgdir_destroy ((void *) PTE_ADDR (pde));
184 }
185 palloc_free_page ((void *) pdpe);
186}
static void pgdir_destroy(uint64_t *pdp)
Definition: mmu.c:169
void palloc_free_page(void *)
Definition: palloc.c:333
Here is the call graph for this function:
Here is the caller graph for this function:

◆ pdpe_walk()

static uint64_t * pdpe_walk ( uint64_t pdpe,
const uint64_t  va,
int  create 
)
static
32 {
33 uint64_t *pte = NULL;
34 int idx = PDPE (va);
35 int allocated = 0;
36 if (pdpe) {
37 uint64_t *pde = (uint64_t *) pdpe[idx];
38 if (!((uint64_t) pde & PTE_P)) {
39 if (create) {
40 uint64_t *new_page = palloc_get_page (PAL_ZERO);
41 if (new_page) {
42 pdpe[idx] = vtop (new_page) | PTE_U | PTE_W | PTE_P;
43 allocated = 1;
44 } else
45 return NULL;
46 } else
47 return NULL;
48 }
49 pte = pgdir_walk (ptov (PTE_ADDR (pdpe[idx])), va, create);
50 }
51 if (pte == NULL && allocated) {
52 palloc_free_page ((void *) ptov (PTE_ADDR (pdpe[idx])));
53 pdpe[idx] = 0;
54 }
55 return pte;
56}
bool create(const char *file, unsigned initial_size)
파일을 생성하는 시스템 콜
Definition: syscall.c:233
static uint64_t * pgdir_walk(uint64_t *pdp, const uint64_t va, int create)
Definition: mmu.c:12
@ PAL_ZERO
Definition: palloc.h:10
void * palloc_get_page(enum palloc_flags)
Definition: palloc.c:301
#define PTE_W
Definition: pte.h:40
#define PDPE(la)
Definition: pte.h:26
#define PTE_U
Definition: pte.h:41
#define NULL
Definition: stddef.h:4
#define vtop(vaddr)
Definition: vaddr.h:53
Here is the call graph for this function:
Here is the caller graph for this function:

◆ pgdir_destroy()

static void pgdir_destroy ( uint64_t pdp)
static
169 {
170 for (unsigned i = 0; i < PGSIZE / sizeof(uint64_t *); i++) {
171 uint64_t *pte = ptov((uint64_t *) pdp[i]);
172 if (((uint64_t) pte) & PTE_P)
173 pt_destroy (PTE_ADDR (pte));
174 }
175 palloc_free_page ((void *) pdp);
176}
static void pt_destroy(uint64_t *pt)
Definition: mmu.c:159
Here is the call graph for this function:
Here is the caller graph for this function:

◆ pgdir_for_each()

static bool pgdir_for_each ( uint64_t pdp,
pte_for_each_func func,
void *  aux,
unsigned  pml4_index,
unsigned  pdp_index 
)
static
122 {
123 for (unsigned i = 0; i < PGSIZE / sizeof(uint64_t *); i++) {
124 uint64_t *pte = ptov((uint64_t *) pdp[i]);
125 if (((uint64_t) pte) & PTE_P)
126 if (!pt_for_each ((uint64_t *) PTE_ADDR (pte), func, aux,
127 pml4_index, pdp_index, i))
128 return false;
129 }
130 return true;
131}
static bool pt_for_each(uint64_t *pt, pte_for_each_func *func, void *aux, unsigned pml4_index, unsigned pdp_index, unsigned pdx_index)
Definition: mmu.c:104
Here is the call graph for this function:
Here is the caller graph for this function:

◆ pgdir_walk()

static uint64_t * pgdir_walk ( uint64_t pdp,
const uint64_t  va,
int  create 
)
static
12 {
13 int idx = PDX (va);
14 if (pdp) {
15 uint64_t *pte = (uint64_t *) pdp[idx];
16 if (!((uint64_t) pte & PTE_P)) {
17 if (create) {
18 uint64_t *new_page = palloc_get_page (PAL_ZERO);
19 if (new_page)
20 pdp[idx] = vtop (new_page) | PTE_U | PTE_W | PTE_P;
21 else
22 return NULL;
23 } else
24 return NULL;
25 }
26 return (uint64_t *) ptov (PTE_ADDR (pdp[idx]) + 8 * PTX (va));
27 }
28 return NULL;
29}
#define PDX(la)
Definition: pte.h:27
#define PTX(la)
Definition: pte.h:28
Here is the call graph for this function:
Here is the caller graph for this function:

◆ pml4_activate()

void pml4_activate ( uint64_t pml4)
205 {
206 lcr3 (vtop (pml4 ? pml4 : base_pml4));
207}
uint64_t * base_pml4
Definition: init.c:42
Here is the caller graph for this function:

◆ pml4_clear_page()

void pml4_clear_page ( uint64_t pml4,
void *  upage 
)
258 {
259 uint64_t *pte;
260 ASSERT (pg_ofs (upage) == 0);
261 ASSERT (is_user_vaddr (upage));
262
263 pte = pml4e_walk (pml4, (uint64_t) upage, false);
264
265 if (pte != NULL && (*pte & PTE_P) != 0) {
266 *pte &= ~PTE_P;
267 if (rcr3 () == vtop (pml4))
268 invlpg ((uint64_t) upage);
269 }
270}
#define ASSERT(CONDITION)
Definition: debug.h:30
uint64_t * pml4e_walk(uint64_t *pml4e, const uint64_t va, int create)
Definition: mmu.c:65
#define is_user_vaddr(vaddr)
Definition: vaddr.h:41
#define pg_ofs(va)
Definition: vaddr.h:24
Here is the call graph for this function:
Here is the caller graph for this function:

◆ pml4_create()

uint64_t * pml4_create ( void  )
96 {
97 uint64_t *pml4 = palloc_get_page (0);
98 if (pml4)
99 memcpy (pml4, base_pml4, PGSIZE);
100 return pml4;
101}
void * memcpy(void *, const void *, size_t)
Definition: string.c:7
Here is the call graph for this function:
Here is the caller graph for this function:

◆ pml4_destroy()

void pml4_destroy ( uint64_t pml4)
190 {
191 if (pml4 == NULL)
192 return;
193 ASSERT (pml4 != base_pml4);
194
195 /* if PML4 (vaddr) >= 1, it's kernel space by define. */
196 uint64_t *pdpe = ptov ((uint64_t *) pml4[0]);
197 if (((uint64_t) pdpe) & PTE_P)
198 pdpe_destroy ((void *) PTE_ADDR (pdpe));
199 palloc_free_page ((void *) pml4);
200}
static void pdpe_destroy(uint64_t *pdpe)
Definition: mmu.c:179
Here is the call graph for this function:
Here is the caller graph for this function:

◆ pml4_for_each()

bool pml4_for_each ( uint64_t pml4,
pte_for_each_func func,
void *  aux 
)
148 {
149 for (unsigned i = 0; i < PGSIZE / sizeof(uint64_t *); i++) {
150 uint64_t *pdpe = ptov((uint64_t *) pml4[i]);
151 if (((uint64_t) pdpe) & PTE_P)
152 if (!pdp_for_each ((uint64_t *) PTE_ADDR (pdpe), func, aux, i))
153 return false;
154 }
155 return true;
156}
static bool pdp_for_each(uint64_t *pdp, pte_for_each_func *func, void *aux, unsigned pml4_index)
Definition: mmu.c:134
Here is the call graph for this function:
Here is the caller graph for this function:

◆ pml4_get_page()

void * pml4_get_page ( uint64_t pml4,
const void *  uaddr 
)
214 {
215 ASSERT (is_user_vaddr (uaddr));
216
217 uint64_t *pte = pml4e_walk (pml4, (uint64_t) uaddr, 0);
218
219 if (pte && (*pte & PTE_P))
220 return ptov (PTE_ADDR (*pte)) + pg_ofs (uaddr);
221 return NULL;
222}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ pml4_is_accessed()

bool pml4_is_accessed ( uint64_t pml4,
const void *  vpage 
)
303 {
304 uint64_t *pte = pml4e_walk (pml4, (uint64_t) vpage, false);
305 return pte != NULL && (*pte & PTE_A) != 0;
306}
#define PTE_A
Definition: pte.h:42
Here is the call graph for this function:
Here is the caller graph for this function:

◆ pml4_is_dirty()

bool pml4_is_dirty ( uint64_t pml4,
const void *  vpage 
)
277 {
278 uint64_t *pte = pml4e_walk (pml4, (uint64_t) vpage, false);
279 return pte != NULL && (*pte & PTE_D) != 0;
280}
#define PTE_D
Definition: pte.h:43
Here is the call graph for this function:
Here is the caller graph for this function:

◆ pml4_set_accessed()

void pml4_set_accessed ( uint64_t pml4,
const void *  vpage,
bool  accessed 
)
311 {
312 uint64_t *pte = pml4e_walk (pml4, (uint64_t) vpage, false);
313 if (pte) {
314 if (accessed)
315 *pte |= PTE_A;
316 else
317 *pte &= ~(uint32_t) PTE_A;
318
319 if (rcr3 () == vtop (pml4))
320 invlpg ((uint64_t) vpage);
321 }
322}
unsigned int uint32_t
Definition: stdint.h:26
Here is the call graph for this function:
Here is the caller graph for this function:

◆ pml4_set_dirty()

void pml4_set_dirty ( uint64_t pml4,
const void *  vpage,
bool  dirty 
)
285 {
286 uint64_t *pte = pml4e_walk (pml4, (uint64_t) vpage, false);
287 if (pte) {
288 if (dirty)
289 *pte |= PTE_D;
290 else
291 *pte &= ~(uint32_t) PTE_D;
292
293 if (rcr3 () == vtop (pml4))
294 invlpg ((uint64_t) vpage);
295 }
296}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ pml4_set_page()

bool pml4_set_page ( uint64_t pml4,
void *  upage,
void *  kpage,
bool  rw 
)
240 {
241 ASSERT (pg_ofs (upage) == 0);
242 ASSERT (pg_ofs (kpage) == 0);
243 ASSERT (is_user_vaddr (upage));
244 ASSERT (pml4 != base_pml4);
245
246 uint64_t *pte = pml4e_walk (pml4, (uint64_t) upage, 1);
247
248 if (pte)
249 *pte = vtop (kpage) | PTE_P | (rw ? PTE_W : 0) | PTE_U;
250 return pte != NULL;
251}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ pml4e_walk()

uint64_t * pml4e_walk ( uint64_t pml4e,
const uint64_t  va,
int  create 
)
65 {
66 uint64_t *pte = NULL;
67 int idx = PML4 (va);
68 int allocated = 0;
69 if (pml4e) {
70 uint64_t *pdpe = (uint64_t *) pml4e[idx];
71 if (!((uint64_t) pdpe & PTE_P)) {
72 if (create) {
73 uint64_t *new_page = palloc_get_page (PAL_ZERO);
74 if (new_page) {
75 pml4e[idx] = vtop (new_page) | PTE_U | PTE_W | PTE_P;
76 allocated = 1;
77 } else
78 return NULL;
79 } else
80 return NULL;
81 }
82 pte = pdpe_walk (ptov (PTE_ADDR (pml4e[idx])), va, create);
83 }
84 if (pte == NULL && allocated) {
85 palloc_free_page ((void *) ptov (PTE_ADDR (pml4e[idx])));
86 pml4e[idx] = 0;
87 }
88 return pte;
89}
static uint64_t * pdpe_walk(uint64_t *pdpe, const uint64_t va, int create)
Definition: mmu.c:32
#define PML4(la)
Definition: pte.h:25
Here is the call graph for this function:
Here is the caller graph for this function:

◆ pt_destroy()

static void pt_destroy ( uint64_t pt)
static
159 {
160 for (unsigned i = 0; i < PGSIZE / sizeof(uint64_t *); i++) {
161 uint64_t *pte = ptov((uint64_t *) pt[i]);
162 if (((uint64_t) pte) & PTE_P)
163 palloc_free_page ((void *) PTE_ADDR (pte));
164 }
165 palloc_free_page ((void *) pt);
166}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ pt_for_each()

static bool pt_for_each ( uint64_t pt,
pte_for_each_func func,
void *  aux,
unsigned  pml4_index,
unsigned  pdp_index,
unsigned  pdx_index 
)
static
105 {
106 for (unsigned i = 0; i < PGSIZE / sizeof(uint64_t *); i++) {
107 uint64_t *pte = &pt[i];
108 if (((uint64_t) *pte) & PTE_P) {
109 void *va = (void *) (((uint64_t) pml4_index << PML4SHIFT) |
110 ((uint64_t) pdp_index << PDPESHIFT) |
111 ((uint64_t) pdx_index << PDXSHIFT) |
112 ((uint64_t) i << PTXSHIFT));
113 if (!func (pte, va, aux))
114 return false;
115 }
116 }
117 return true;
118}
#define PTXSHIFT
Definition: pte.h:23
#define PML4SHIFT
Definition: pte.h:20
#define PDXSHIFT
Definition: pte.h:22
#define PDPESHIFT
Definition: pte.h:21
Here is the caller graph for this function: