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
124
125
126
127
128
129
130
131
132
|
/* This file implements the methods of physically contiguous anonymous memory. */
#include <assert.h>
#include "proto.h"
#include "vm.h"
#include "region.h"
#include "glo.h"
static int anon_contig_reference(struct phys_region *, struct phys_region *);
static int anon_contig_unreference(struct phys_region *pr);
static int anon_contig_pagefault(struct vmproc *vmp, struct vir_region *region,
struct phys_region *ph, int write, vfs_callback_t cb, void *state,
int len, int *io);
static int anon_contig_sanitycheck(struct phys_region *pr, const char *file, int line);
static int anon_contig_writable(struct phys_region *pr);
static void anon_contig_split(struct vmproc *vmp, struct vir_region *vr,
struct vir_region *r1, struct vir_region *r2);
static int anon_contig_resize(struct vmproc *vmp, struct vir_region *vr, vir_bytes l);
static int anon_contig_new(struct vir_region *vr);
static int anon_contig_pt_flags(struct vir_region *vr);
struct mem_type mem_type_anon_contig = {
.name = "anonymous memory (physically contiguous)",
.ev_new = anon_contig_new,
.ev_reference = anon_contig_reference,
.ev_unreference = anon_contig_unreference,
.ev_pagefault = anon_contig_pagefault,
.ev_resize = anon_contig_resize,
.ev_split = anon_contig_split,
.ev_sanitycheck = anon_contig_sanitycheck,
.writable = anon_contig_writable,
.pt_flags = anon_contig_pt_flags,
};
static int anon_contig_pt_flags(struct vir_region *vr){
#if defined(__arm__)
return ARM_VM_PTE_DEVICE;
#else
return 0;
#endif
}
static int anon_contig_pagefault(struct vmproc *vmp, struct vir_region *region,
struct phys_region *ph, int write, vfs_callback_t cb, void *state,
int len, int *io)
{
panic("anon_contig_pagefault: pagefault cannot happen");
}
static int anon_contig_new(struct vir_region *region)
{
u32_t allocflags;
phys_bytes new_pages, new_page_cl, cur_ph;
phys_bytes p, pages;
allocflags = vrallocflags(region->flags);
pages = region->length/VM_PAGE_SIZE;
assert(physregions(region) == 0);
for(p = 0; p < pages; p++) {
struct phys_block *pb = pb_new(MAP_NONE);
struct phys_region *pr = NULL;
if(pb)
pr = pb_reference(pb, p * VM_PAGE_SIZE, region, &mem_type_anon_contig);
if(!pr) {
if(pb) pb_free(pb);
map_free(region);
return ENOMEM;
}
}
assert(physregions(region) == pages);
if((new_page_cl = alloc_mem(pages, allocflags)) == NO_MEM) {
map_free(region);
return ENOMEM;
}
cur_ph = new_pages = CLICK2ABS(new_page_cl);
for(p = 0; p < pages; p++) {
struct phys_region *pr = physblock_get(region, p * VM_PAGE_SIZE);
assert(pr);
assert(pr->ph);
assert(pr->ph->phys == MAP_NONE);
assert(pr->offset == p * VM_PAGE_SIZE);
pr->ph->phys = cur_ph + pr->offset;
}
return OK;
}
static int anon_contig_resize(struct vmproc *vmp, struct vir_region *vr, vir_bytes l)
{
printf("VM: cannot resize physically contiguous memory.\n");
return ENOMEM;
}
static int anon_contig_reference(struct phys_region *pr,
struct phys_region *newpr)
{
printf("VM: cannot fork with physically contig memory.\n");
return ENOMEM;
}
/* Methods inherited from the anonymous memory methods. */
static int anon_contig_unreference(struct phys_region *pr)
{
return mem_type_anon.ev_unreference(pr);
}
static int anon_contig_sanitycheck(struct phys_region *pr, const char *file, int line)
{
return mem_type_anon.ev_sanitycheck(pr, file, line);
}
static int anon_contig_writable(struct phys_region *pr)
{
return mem_type_anon.writable(pr);
}
static void anon_contig_split(struct vmproc *vmp, struct vir_region *vr,
struct vir_region *r1, struct vir_region *r2)
{
return;
}
|