1
2 /* This file implements the methods of physically contiguous anonymous memory. */
3
4 #include <assert.h>
5
6 #include "proto.h"
7 #include "vm.h"
8 #include "region.h"
9 #include "glo.h"
10
11 static int anon_contig_reference(struct phys_region *, struct phys_region *);
12 static int anon_contig_unreference(struct phys_region *pr);
13 static int anon_contig_pagefault(struct vmproc *vmp, struct vir_region *region,
14 struct phys_region *ph, int write, vfs_callback_t cb, void *state,
15 int len, int *io);
16 static int anon_contig_sanitycheck(struct phys_region *pr, const char *file, int line);
17 static int anon_contig_writable(struct phys_region *pr);
18 static void anon_contig_split(struct vmproc *vmp, struct vir_region *vr,
19 struct vir_region *r1, struct vir_region *r2);
20 static int anon_contig_resize(struct vmproc *vmp, struct vir_region *vr, vir_bytes l);
21 static int anon_contig_new(struct vir_region *vr);
22 static int anon_contig_pt_flags(struct vir_region *vr);
23
24 struct mem_type mem_type_anon_contig = {
25 .name = "anonymous memory (physically contiguous)",
26 .ev_new = anon_contig_new,
27 .ev_reference = anon_contig_reference,
28 .ev_unreference = anon_contig_unreference,
29 .ev_pagefault = anon_contig_pagefault,
30 .ev_resize = anon_contig_resize,
31 .ev_split = anon_contig_split,
32 .ev_sanitycheck = anon_contig_sanitycheck,
33 .writable = anon_contig_writable,
34 .pt_flags = anon_contig_pt_flags,
35 };
36
anon_contig_pt_flags(struct vir_region * vr)37 static int anon_contig_pt_flags(struct vir_region *vr){
38 #if defined(__arm__)
39 return ARM_VM_PTE_DEVICE;
40 #else
41 return 0;
42 #endif
43 }
44
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)45 static int anon_contig_pagefault(struct vmproc *vmp, struct vir_region *region,
46 struct phys_region *ph, int write, vfs_callback_t cb, void *state,
47 int len, int *io)
48 {
49 panic("anon_contig_pagefault: pagefault cannot happen");
50 }
51
anon_contig_new(struct vir_region * region)52 static int anon_contig_new(struct vir_region *region)
53 {
54 u32_t allocflags;
55 phys_bytes new_pages, new_page_cl, cur_ph;
56 phys_bytes p, pages;
57
58 allocflags = vrallocflags(region->flags);
59
60 pages = region->length/VM_PAGE_SIZE;
61
62 assert(physregions(region) == 0);
63
64 for(p = 0; p < pages; p++) {
65 struct phys_block *pb = pb_new(MAP_NONE);
66 struct phys_region *pr = NULL;
67 if(pb)
68 pr = pb_reference(pb, p * VM_PAGE_SIZE, region, &mem_type_anon_contig);
69 if(!pr) {
70 if(pb) pb_free(pb);
71 map_free(region);
72 return ENOMEM;
73 }
74 }
75
76 assert(physregions(region) == pages);
77
78 if((new_page_cl = alloc_mem(pages, allocflags)) == NO_MEM) {
79 map_free(region);
80 return ENOMEM;
81 }
82
83 cur_ph = new_pages = CLICK2ABS(new_page_cl);
84
85 for(p = 0; p < pages; p++) {
86 struct phys_region *pr = physblock_get(region, p * VM_PAGE_SIZE);
87 assert(pr);
88 assert(pr->ph);
89 assert(pr->ph->phys == MAP_NONE);
90 assert(pr->offset == p * VM_PAGE_SIZE);
91 pr->ph->phys = cur_ph + pr->offset;
92 }
93
94 return OK;
95 }
96
anon_contig_resize(struct vmproc * vmp,struct vir_region * vr,vir_bytes l)97 static int anon_contig_resize(struct vmproc *vmp, struct vir_region *vr, vir_bytes l)
98 {
99 printf("VM: cannot resize physically contiguous memory.\n");
100 return ENOMEM;
101 }
102
anon_contig_reference(struct phys_region * pr,struct phys_region * newpr)103 static int anon_contig_reference(struct phys_region *pr,
104 struct phys_region *newpr)
105 {
106 printf("VM: cannot fork with physically contig memory.\n");
107 return ENOMEM;
108 }
109
110 /* Methods inherited from the anonymous memory methods. */
111
anon_contig_unreference(struct phys_region * pr)112 static int anon_contig_unreference(struct phys_region *pr)
113 {
114 return mem_type_anon.ev_unreference(pr);
115 }
116
anon_contig_sanitycheck(struct phys_region * pr,const char * file,int line)117 static int anon_contig_sanitycheck(struct phys_region *pr, const char *file, int line)
118 {
119 return mem_type_anon.ev_sanitycheck(pr, file, line);
120 }
121
anon_contig_writable(struct phys_region * pr)122 static int anon_contig_writable(struct phys_region *pr)
123 {
124 return mem_type_anon.writable(pr);
125 }
126
anon_contig_split(struct vmproc * vmp,struct vir_region * vr,struct vir_region * r1,struct vir_region * r2)127 static void anon_contig_split(struct vmproc *vmp, struct vir_region *vr,
128 struct vir_region *r1, struct vir_region *r2)
129 {
130 return;
131 }
132
133