xref: /minix3/minix/servers/vm/mem_shared.c (revision 433d6423c39e34ec4b79c950597bb2d236f886be)
1 
2 /* This file implements the methods of shared 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 /* These functions are static so as to not pollute the
12  * global namespace, and are accessed through their function
13  * pointers.
14  */
15 
16 static int shared_unreference(struct phys_region *pr);
17 static int shared_pagefault(struct vmproc *vmp, struct vir_region *region,
18 	struct phys_region *ph, int write, vfs_callback_t cb, void *state,
19 	int len, int *io);
20 static int shared_sanitycheck(struct phys_region *pr, const char *file, int line);
21 static int shared_writable(struct phys_region *pr);
22 static void shared_delete(struct vir_region *region);
23 static u32_t shared_regionid(struct vir_region *region);
24 static int shared_copy(struct vir_region *vr, struct vir_region *newvr);
25 static int shared_refcount(struct vir_region *vr);
26 static int shared_pt_flags(struct vir_region *vr);
27 
28 struct mem_type mem_type_shared = {
29 	.name = "shared memory",
30 	.ev_copy = shared_copy,
31 	.ev_unreference = shared_unreference,
32 	.ev_pagefault = shared_pagefault,
33 	.ev_sanitycheck = shared_sanitycheck,
34 	.ev_delete = shared_delete,
35 	.regionid = shared_regionid,
36 	.refcount = shared_refcount,
37 	.writable = shared_writable,
38 	.pt_flags = shared_pt_flags,
39 };
40 
41 static int shared_pt_flags(struct vir_region *vr){
42 #if defined(__arm__)
43 	return ARM_VM_PTE_CACHED;
44 #else
45 	return 0;
46 #endif
47 }
48 
49 static int shared_unreference(struct phys_region *pr)
50 {
51 	return mem_type_anon.ev_unreference(pr);
52 }
53 
54 static int getsrc(struct vir_region *region,
55 	struct vmproc **vmp, struct vir_region **r)
56 {
57 	int srcproc;
58 
59 	if(region->def_memtype != &mem_type_shared) {
60 		printf("shared region hasn't shared type but %s.\n",
61 			region->def_memtype->name);
62 		return EINVAL;
63 	}
64 
65 	if(!region->param.shared.ep || !region->param.shared.vaddr) {
66 		printf("shared region has not defined source region.\n");
67 		util_stacktrace();
68 		return EINVAL;
69 	}
70 
71         if(vm_isokendpt((endpoint_t) region->param.shared.ep, &srcproc) != OK) {
72 		printf("VM: shared memory with missing source process.\n");
73 		util_stacktrace();
74                 return EINVAL;
75 	}
76 
77 	*vmp = &vmproc[srcproc];
78 
79 	if(!(*r=map_lookup(*vmp, region->param.shared.vaddr, NULL))) {
80 		printf("VM: shared memory with missing vaddr 0x%lx.\n",
81 			region->param.shared.vaddr);
82                 return EINVAL;
83 	}
84 
85 	if((*r)->def_memtype != &mem_type_anon) {
86 		printf("source region hasn't anon type but %s.\n",
87 			(*r)->def_memtype->name);
88 		return EINVAL;
89 	}
90 
91 	if(region->param.shared.id != (*r)->id) {
92 		printf("source region has no matching id\n");
93 		return EINVAL;
94 	}
95 
96 	return OK;
97 }
98 
99 static u32_t shared_regionid(struct vir_region *vr)
100 {
101 	struct vir_region *src_region;
102 	struct vmproc *src_vmp;
103 
104 	if(getsrc(vr, &src_vmp, &src_region) != OK)
105 		return 0;
106 
107 	return src_region->id;
108 }
109 
110 static void shared_delete(struct vir_region *region)
111 {
112 	struct vir_region *src_region;
113 	struct vmproc *src_vmp;
114 
115 	if(getsrc(region, &src_vmp, &src_region) != OK)
116 		return;
117 
118 	assert(src_region->remaps > 0);
119 	src_region->remaps--;
120 }
121 
122 static int shared_pagefault(struct vmproc *vmp, struct vir_region *region,
123 	struct phys_region *ph, int write, vfs_callback_t cb,
124 	void *state, int statelen, int *io)
125 {
126 	struct vir_region *src_region;
127 	struct vmproc *src_vmp;
128 	struct phys_region *pr;
129 
130 	if(getsrc(region, &src_vmp, &src_region) != OK) {
131 		return EINVAL;
132 	}
133 
134 	assert(ph->ph->phys == MAP_NONE);
135 	pb_free(ph->ph);
136 
137 	if(!(pr = physblock_get(src_region, ph->offset))) {
138 		int r;
139 		if((r=map_pf(src_vmp, src_region, ph->offset, write,
140 			NULL, NULL, 0, io)) != OK)
141 			return r;
142 		if(!(pr = physblock_get(src_region, ph->offset))) {
143 			panic("missing region after pagefault handling");
144 		}
145 	}
146 
147 	pb_link(ph, pr->ph, ph->offset, region);
148 
149 	return OK;
150 }
151 
152 static int shared_sanitycheck(struct phys_region *pr, const char *file, int line)
153 {
154 	return OK;
155 }
156 
157 static int shared_writable(struct phys_region *pr)
158 {
159 	assert(pr->ph->refcount > 0);
160 	return pr->ph->phys != MAP_NONE;
161 }
162 
163 void shared_setsource(struct vir_region *vr, endpoint_t ep,
164 	struct vir_region *src_vr)
165 {
166 	struct vmproc *vmp;
167 	struct vir_region *srcvr;
168 	int id = src_vr->id;
169 	vir_bytes vaddr = src_vr->vaddr;
170 
171 	assert(vr->def_memtype == &mem_type_shared);
172 
173 	if(!ep || !vaddr || !id) {
174 		printf("VM: shared_setsource: zero ep/vaddr/id - ignoring\n");
175 		return;
176 	}
177 
178 	vr->param.shared.ep = ep;
179 	vr->param.shared.vaddr = vaddr;
180 	vr->param.shared.id = id;
181 
182 	if(getsrc(vr, &vmp, &srcvr) != OK)
183 		panic("initial getsrc failed");
184 
185 	assert(srcvr == src_vr);
186 
187 	srcvr->remaps++;
188 }
189 
190 static int shared_copy(struct vir_region *vr, struct vir_region *newvr)
191 {
192 	struct vmproc *vmp;
193 	struct vir_region *srcvr;
194 
195 	if(getsrc(vr, &vmp, &srcvr) != OK)
196 		panic("copy: original getsrc failed");
197 
198 	shared_setsource(newvr, vr->param.shared.ep, srcvr);
199 
200 	return OK;
201 }
202 
203 static int shared_refcount(struct vir_region *vr)
204 {
205 	return 1 + vr->remaps;
206 }
207 
208