/
vm.c
123 lines (97 loc) · 2.26 KB
/
vm.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
#include "u.h"
#include "defs.h"
#include "mem.h"
#include "proc.h"
void
checkalign(void *a, int alignment, char *msg, ...)
{
uintptr aa = (uintptr)a;
va_list ap;
if (aa & (alignment-1)) {
va_start(ap, msg);
vpanic(msg, ap);
va_end(ap);
}
}
Pte *
copyuvm(Pte *oldmap, usize sz)
{
uintptr a;
Pte *newmap;
Pte *pte;
byte *oldmem, *newmem;
u32 flags;
newmap = allocpgmap();
if (newmap == nil)
return nil;
for (a = 0; a < sz; a += PGSIZE) {
pte = walkpgmap(oldmap, (void *)a, 0);
if (pte == nil)
panic("copyuvm - nil pte");
if (!(*pte & PTE_P))
panic("copyuvm - page not present");
oldmem = p2v(pte_addr(*pte));
flags = pte_flags(*pte);
newmem = kalloc();
if (newmem == nil)
goto bad;
memmove(newmem, oldmem, PGSIZE);
if (mappages(newmap, (void *)a, PGSIZE, v2p(newmem), flags) < 0)
goto bad;
}
return newmap;
bad:
freeuvm(newmap);
return nil;
}
void
freeuvm(Pte *pgmap)
{
cprintf("freeuvm not implemented yet!\n");
// todo
}
usize
allocuvm(Pte *pgmap, usize oldsz, usize newsz)
{
void *mem;
usize a;
if (newsz >= USERTOP)
return 0;
if (newsz < oldsz)
return oldsz;
a = (usize)pgceil((void *)oldsz);
for (; a < newsz; a += PGSIZE) {
mem = kalloc();
if (mem == nil) {
cprintf("allocuvm -- oom (should dealloc here)\n");
return 0;
}
memzero(mem, PGSIZE);
if (mappages(pgmap, (char *)a, PGSIZE, v2p(mem), uvmperm()) < 0) {
cprintf("allocuvm -- oom 2 (should dealloc here)\n");
kfree(mem);
return 0;
}
}
return newsz;
}
void
loaduvm(Pte *pgmap, char *addr, byte *data, u64 sz)
{
Pte *pte;
u64 i;
usize n;
char *pg;
checkalign(addr, PGSIZE, "loaduvm - addr not page aligned");
for (i = 0; i < sz; i+= PGSIZE) {
pte = walkpgmap(pgmap, addr+i, 0);
if (pte == nil)
panic("loaduvm - addr not mapped");
pg = p2v(pte_addr(*pte));
if (sz - i < PGSIZE)
n = sz - i;
else
n = PGSIZE;
memmove(pg, data + i, n);
}
}