This repository has been archived by the owner on Apr 26, 2024. It is now read-only.
/
vmspace.c
80 lines (62 loc) · 2.09 KB
/
vmspace.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
/* vmspace.c - Virtual memory address space manager for Mink.
*
* Portions copyright (c)2012 James Molloy.
*
* Copyright (c)2013 Ross Bamford. See LICENSE for details.
*/
#include "assert.h"
#include "hal.h"
#include "vmspace.h"
int vmspace_init(vmspace_t *vms, uintptr_t addr, uintptr_t sz) {
/* FIXME: Assert starts and finishes on a page boundary! */
range_t r;
r.start = addr;
r.extent = sz;
vms->start = addr;
vms->size = sz;
spinlock_init(&vms->lock);
size_t overhead = round_to_page_size(buddy_calc_overhead(r));
size_t npages = overhead >> get_page_shift();
uintptr_t start = r.start + r.extent - overhead;
int ok = map(start,
alloc_pages(PAGE_REQ_NONE, npages), npages,
PAGE_WRITE);
assert(ok == 0 && "map() failed in vmspace_init!");
r.extent -= overhead;
buddy_init(&vms->allocator, (uint8_t*)start, r, /*start_freed=*/0);
buddy_free_range(&vms->allocator, r);
return 0;
}
uintptr_t vmspace_alloc(vmspace_t *vms, unsigned sz, int alloc_phys) {
/* FIXME: Assert sz is page aligned. */
spinlock_acquire(&vms->lock);
uint64_t addr = buddy_alloc(&vms->allocator, sz);
if (alloc_phys && addr != ~0ULL) {
size_t npages = sz >> get_page_shift();
uintptr_t phys_pages = alloc_pages(PAGE_REQ_NONE, npages);
#if CPUBITS == 64
assert(phys_pages != ~0UL && phys_pages != ~0ULL && "Out of memory!");
#elif CPUBITS == 32
assert(phys_pages != ~0UL && "Out of memory!");
#endif
int ok = map(addr, phys_pages, npages, alloc_phys);
assert(ok == 0 && "vmspace_alloc: map failed!");
}
spinlock_release(&vms->lock);
return addr;
}
void vmspace_free(vmspace_t *vms, unsigned sz, uintptr_t addr, int free_phys) {
spinlock_acquire(&vms->lock);
if (free_phys) {
unsigned pgsz = get_page_size();
for (unsigned i = 0; i < sz; i += pgsz) {
uint64_t p = get_mapping(addr + i, NULL);
assert(p != ~0ULL &&
"vmspace_free asked to free_phys but mapping did not exist!");
free_page(p);
unmap(addr + i, 1);
}
}
buddy_free(&vms->allocator, addr, sz);
spinlock_release(&vms->lock);
}