193
|
1 #include "../../context.h"
|
198
|
2 #include "mmu.h"
|
|
3 #include "memlayout.h"
|
193
|
4 #interface "vm_impl.h"
|
|
5
|
198
|
6 /*
|
|
7 vm_impl* createvm_impl2();
|
|
8 */
|
|
9
|
|
10 __code loaduvm_ptesize_checkvm_impl(struct vm_impl* vm_impl, __code next(...)) {
|
200
|
11 char* addr = vm_impl->addr;
|
198
|
12
|
200
|
13 if ((uint) addr %PTE_SZ != 0) {
|
198
|
14 // goto panic
|
|
15 }
|
|
16
|
|
17 goto loaduvm_loopvm_impl(vm_impl, next(...));
|
193
|
18 }
|
|
19
|
198
|
20 __code loaduvm_loopvm_impl(struct vm_impl* vm_impl, __code next(...)) {
|
200
|
21 uint i = vm_impl->i;
|
|
22 uint sz = vm_impl->sz;
|
198
|
23
|
200
|
24 if (i < sz) {
|
198
|
25 goto loaduvm_check_pgdir(vm_impl, next(...));
|
|
26 }
|
200
|
27
|
198
|
28 goto loaduvm_exit(vm_impl, next(...));
|
193
|
29 }
|
200
|
30
|
|
31
|
198
|
32 static pte_t* walkpgdir (pde_t *pgdir, const void *va, int alloc)
|
|
33 {
|
|
34 pde_t *pde;
|
|
35 pte_t *pgtab;
|
|
36
|
|
37 // pgdir points to the page directory, get the page direcotry entry (pde)
|
|
38 pde = &pgdir[PDE_IDX(va)];
|
|
39
|
|
40 if (*pde & PE_TYPES) {
|
|
41 pgtab = (pte_t*) p2v(PT_ADDR(*pde));
|
|
42
|
|
43 } else {
|
|
44 if (!alloc || (pgtab = (pte_t*) kpt_alloc()) == 0) {
|
|
45 return 0;
|
|
46 }
|
|
47
|
|
48 // Make sure all those PTE_P bits are zero.
|
|
49 memset(pgtab, 0, PT_SZ);
|
|
50
|
|
51 // The permissions here are overly generous, but they can
|
|
52 // be further restricted by the permissions in the page table
|
|
53 // entries, if necessary.
|
|
54 *pde = v2p(pgtab) | UPDE_TYPE;
|
|
55 }
|
|
56
|
|
57 return &pgtab[PTE_IDX(va)];
|
|
58 }
|
|
59
|
|
60
|
|
61 __code loaduvm_check_pgdir(struct vm_impl* vm_impl, __code next(...)) {
|
200
|
62 pte_t* pte = vm_impl->pte;
|
|
63 pde_t* pgdir = vm_impl->pgdir;
|
|
64 uint i = vm_impl->i;
|
|
65 char* addr = vm_impl->addr;
|
|
66 uint pa = vm_impl->pa;
|
|
67
|
|
68 if ((pte = walkpgdir(pgdir, addr + i, 0)) == 0) {
|
198
|
69 // goto panic
|
|
70 }
|
200
|
71 pa = PTE_ADDR(*pte);
|
|
72
|
|
73 vm_impl->pte = pte;
|
|
74 vm_impl->pgdir = pgdir;
|
|
75 vm_impl->addr = addr;
|
|
76 vm_impl->pa = pa;
|
|
77
|
198
|
78 goto loaduvm_check_PTE_SZ(vm_impl, next(...));
|
|
79 }
|
|
80
|
|
81 __code loaduvm_check_PTE_SZ(struct vm_impl* vm_impl, __code next(...)) {
|
200
|
82 uint sz = vm_impl->sz;
|
|
83 uint i = vm_impl->i;
|
|
84 uint n = vm_impl->n;
|
|
85 struct inode* ip = vm_impl->ip;
|
|
86 uint pa = vm_impl->pa;
|
|
87 uint offset = vm_impl->offset;
|
|
88
|
|
89 if (sz - i < PTE_SZ) {
|
|
90 n = sz - i;
|
199
|
91 } else {
|
200
|
92 n = PTE_SZ;
|
199
|
93 }
|
|
94
|
200
|
95 if (readi(ip, p2v(pa), offset + i, n) != n) {
|
199
|
96 // panic
|
|
97 // return -1;
|
|
98 }
|
|
99
|
200
|
100 vm_impl->n = n;
|
|
101
|
198
|
102 goto loaduvm_exit(vm_impl, next(...));
|
|
103 }
|
|
104
|
|
105 __code loaduvm_exit(struct vm_impl* vm_impl, __code next(...)) {
|
|
106
|
|
107 goto next(...);
|
|
108 }
|
202
|
109
|
|
110 __code kpt_alloc_check_impl(struct vm_impl* vm_impl, __code next(...)) {
|
|
111
|
|
112 goto kpt_alloc_check_inital_page(vm_impl, next(...));
|
|
113 }
|
|
114
|
|
115 __code kpt_alloc_check_inital_page(struct vm_impl* vm_impl, __code next(...)) {
|
|
116 goto next((char*)r);
|
|
117 }
|