1433d6423SLionel Sambuc
2433d6423SLionel Sambuc /* This file implements the methods of shared memory. */
3433d6423SLionel Sambuc
4433d6423SLionel Sambuc #include <assert.h>
5433d6423SLionel Sambuc
6433d6423SLionel Sambuc #include "proto.h"
7433d6423SLionel Sambuc #include "vm.h"
8433d6423SLionel Sambuc #include "region.h"
9433d6423SLionel Sambuc #include "glo.h"
10433d6423SLionel Sambuc
11433d6423SLionel Sambuc /* These functions are static so as to not pollute the
12433d6423SLionel Sambuc * global namespace, and are accessed through their function
13433d6423SLionel Sambuc * pointers.
14433d6423SLionel Sambuc */
15433d6423SLionel Sambuc
16433d6423SLionel Sambuc static int shared_unreference(struct phys_region *pr);
17433d6423SLionel Sambuc static int shared_pagefault(struct vmproc *vmp, struct vir_region *region,
18433d6423SLionel Sambuc struct phys_region *ph, int write, vfs_callback_t cb, void *state,
19433d6423SLionel Sambuc int len, int *io);
20433d6423SLionel Sambuc static int shared_sanitycheck(struct phys_region *pr, const char *file, int line);
21433d6423SLionel Sambuc static int shared_writable(struct phys_region *pr);
22433d6423SLionel Sambuc static void shared_delete(struct vir_region *region);
23433d6423SLionel Sambuc static u32_t shared_regionid(struct vir_region *region);
24433d6423SLionel Sambuc static int shared_copy(struct vir_region *vr, struct vir_region *newvr);
25433d6423SLionel Sambuc static int shared_refcount(struct vir_region *vr);
26433d6423SLionel Sambuc static int shared_pt_flags(struct vir_region *vr);
27433d6423SLionel Sambuc
28433d6423SLionel Sambuc struct mem_type mem_type_shared = {
29433d6423SLionel Sambuc .name = "shared memory",
30433d6423SLionel Sambuc .ev_copy = shared_copy,
31433d6423SLionel Sambuc .ev_unreference = shared_unreference,
32433d6423SLionel Sambuc .ev_pagefault = shared_pagefault,
33433d6423SLionel Sambuc .ev_sanitycheck = shared_sanitycheck,
34433d6423SLionel Sambuc .ev_delete = shared_delete,
35433d6423SLionel Sambuc .regionid = shared_regionid,
36433d6423SLionel Sambuc .refcount = shared_refcount,
37433d6423SLionel Sambuc .writable = shared_writable,
38433d6423SLionel Sambuc .pt_flags = shared_pt_flags,
39433d6423SLionel Sambuc };
40433d6423SLionel Sambuc
shared_pt_flags(struct vir_region * vr)41433d6423SLionel Sambuc static int shared_pt_flags(struct vir_region *vr){
42433d6423SLionel Sambuc #if defined(__arm__)
43433d6423SLionel Sambuc return ARM_VM_PTE_CACHED;
44433d6423SLionel Sambuc #else
45433d6423SLionel Sambuc return 0;
46433d6423SLionel Sambuc #endif
47433d6423SLionel Sambuc }
48433d6423SLionel Sambuc
shared_unreference(struct phys_region * pr)49433d6423SLionel Sambuc static int shared_unreference(struct phys_region *pr)
50433d6423SLionel Sambuc {
51433d6423SLionel Sambuc return mem_type_anon.ev_unreference(pr);
52433d6423SLionel Sambuc }
53433d6423SLionel Sambuc
getsrc(struct vir_region * region,struct vmproc ** vmp,struct vir_region ** r)54433d6423SLionel Sambuc static int getsrc(struct vir_region *region,
55433d6423SLionel Sambuc struct vmproc **vmp, struct vir_region **r)
56433d6423SLionel Sambuc {
57433d6423SLionel Sambuc int srcproc;
58433d6423SLionel Sambuc
59433d6423SLionel Sambuc if(region->def_memtype != &mem_type_shared) {
60433d6423SLionel Sambuc printf("shared region hasn't shared type but %s.\n",
61433d6423SLionel Sambuc region->def_memtype->name);
62433d6423SLionel Sambuc return EINVAL;
63433d6423SLionel Sambuc }
64433d6423SLionel Sambuc
65433d6423SLionel Sambuc if(!region->param.shared.ep || !region->param.shared.vaddr) {
66433d6423SLionel Sambuc printf("shared region has not defined source region.\n");
67433d6423SLionel Sambuc util_stacktrace();
68433d6423SLionel Sambuc return EINVAL;
69433d6423SLionel Sambuc }
70433d6423SLionel Sambuc
71433d6423SLionel Sambuc if(vm_isokendpt((endpoint_t) region->param.shared.ep, &srcproc) != OK) {
72433d6423SLionel Sambuc printf("VM: shared memory with missing source process.\n");
73433d6423SLionel Sambuc util_stacktrace();
74433d6423SLionel Sambuc return EINVAL;
75433d6423SLionel Sambuc }
76433d6423SLionel Sambuc
77433d6423SLionel Sambuc *vmp = &vmproc[srcproc];
78433d6423SLionel Sambuc
79433d6423SLionel Sambuc if(!(*r=map_lookup(*vmp, region->param.shared.vaddr, NULL))) {
80433d6423SLionel Sambuc printf("VM: shared memory with missing vaddr 0x%lx.\n",
81433d6423SLionel Sambuc region->param.shared.vaddr);
82433d6423SLionel Sambuc return EINVAL;
83433d6423SLionel Sambuc }
84433d6423SLionel Sambuc
85433d6423SLionel Sambuc if((*r)->def_memtype != &mem_type_anon) {
86433d6423SLionel Sambuc printf("source region hasn't anon type but %s.\n",
87433d6423SLionel Sambuc (*r)->def_memtype->name);
88433d6423SLionel Sambuc return EINVAL;
89433d6423SLionel Sambuc }
90433d6423SLionel Sambuc
91433d6423SLionel Sambuc if(region->param.shared.id != (*r)->id) {
92433d6423SLionel Sambuc printf("source region has no matching id\n");
93433d6423SLionel Sambuc return EINVAL;
94433d6423SLionel Sambuc }
95433d6423SLionel Sambuc
96433d6423SLionel Sambuc return OK;
97433d6423SLionel Sambuc }
98433d6423SLionel Sambuc
shared_regionid(struct vir_region * vr)99433d6423SLionel Sambuc static u32_t shared_regionid(struct vir_region *vr)
100433d6423SLionel Sambuc {
101433d6423SLionel Sambuc struct vir_region *src_region;
102433d6423SLionel Sambuc struct vmproc *src_vmp;
103433d6423SLionel Sambuc
104433d6423SLionel Sambuc if(getsrc(vr, &src_vmp, &src_region) != OK)
105433d6423SLionel Sambuc return 0;
106433d6423SLionel Sambuc
107433d6423SLionel Sambuc return src_region->id;
108433d6423SLionel Sambuc }
109433d6423SLionel Sambuc
shared_delete(struct vir_region * region)110433d6423SLionel Sambuc static void shared_delete(struct vir_region *region)
111433d6423SLionel Sambuc {
112433d6423SLionel Sambuc struct vir_region *src_region;
113433d6423SLionel Sambuc struct vmproc *src_vmp;
114433d6423SLionel Sambuc
115433d6423SLionel Sambuc if(getsrc(region, &src_vmp, &src_region) != OK)
116433d6423SLionel Sambuc return;
117433d6423SLionel Sambuc
118433d6423SLionel Sambuc assert(src_region->remaps > 0);
119433d6423SLionel Sambuc src_region->remaps--;
120433d6423SLionel Sambuc }
121433d6423SLionel Sambuc
shared_pagefault(struct vmproc * vmp,struct vir_region * region,struct phys_region * ph,int write,vfs_callback_t cb,void * state,int statelen,int * io)122433d6423SLionel Sambuc static int shared_pagefault(struct vmproc *vmp, struct vir_region *region,
123433d6423SLionel Sambuc struct phys_region *ph, int write, vfs_callback_t cb,
124433d6423SLionel Sambuc void *state, int statelen, int *io)
125433d6423SLionel Sambuc {
126433d6423SLionel Sambuc struct vir_region *src_region;
127433d6423SLionel Sambuc struct vmproc *src_vmp;
128433d6423SLionel Sambuc struct phys_region *pr;
129433d6423SLionel Sambuc
130433d6423SLionel Sambuc if(getsrc(region, &src_vmp, &src_region) != OK) {
131433d6423SLionel Sambuc return EINVAL;
132433d6423SLionel Sambuc }
133433d6423SLionel Sambuc
134*4f9ef4d3SBen Gras if(ph->ph->phys != MAP_NONE) {
135*4f9ef4d3SBen Gras /* memory is there - pagefault does not need handling */
136*4f9ef4d3SBen Gras return OK;
137*4f9ef4d3SBen Gras }
138*4f9ef4d3SBen Gras
139433d6423SLionel Sambuc pb_free(ph->ph);
140433d6423SLionel Sambuc
141433d6423SLionel Sambuc if(!(pr = physblock_get(src_region, ph->offset))) {
142433d6423SLionel Sambuc int r;
143433d6423SLionel Sambuc if((r=map_pf(src_vmp, src_region, ph->offset, write,
144433d6423SLionel Sambuc NULL, NULL, 0, io)) != OK)
145433d6423SLionel Sambuc return r;
146433d6423SLionel Sambuc if(!(pr = physblock_get(src_region, ph->offset))) {
147433d6423SLionel Sambuc panic("missing region after pagefault handling");
148433d6423SLionel Sambuc }
149433d6423SLionel Sambuc }
150433d6423SLionel Sambuc
151433d6423SLionel Sambuc pb_link(ph, pr->ph, ph->offset, region);
152433d6423SLionel Sambuc
153433d6423SLionel Sambuc return OK;
154433d6423SLionel Sambuc }
155433d6423SLionel Sambuc
shared_sanitycheck(struct phys_region * pr,const char * file,int line)156433d6423SLionel Sambuc static int shared_sanitycheck(struct phys_region *pr, const char *file, int line)
157433d6423SLionel Sambuc {
158433d6423SLionel Sambuc return OK;
159433d6423SLionel Sambuc }
160433d6423SLionel Sambuc
shared_writable(struct phys_region * pr)161433d6423SLionel Sambuc static int shared_writable(struct phys_region *pr)
162433d6423SLionel Sambuc {
163433d6423SLionel Sambuc assert(pr->ph->refcount > 0);
164433d6423SLionel Sambuc return pr->ph->phys != MAP_NONE;
165433d6423SLionel Sambuc }
166433d6423SLionel Sambuc
shared_setsource(struct vir_region * vr,endpoint_t ep,struct vir_region * src_vr)167433d6423SLionel Sambuc void shared_setsource(struct vir_region *vr, endpoint_t ep,
168433d6423SLionel Sambuc struct vir_region *src_vr)
169433d6423SLionel Sambuc {
170433d6423SLionel Sambuc struct vmproc *vmp;
171433d6423SLionel Sambuc struct vir_region *srcvr;
172433d6423SLionel Sambuc int id = src_vr->id;
173433d6423SLionel Sambuc vir_bytes vaddr = src_vr->vaddr;
174433d6423SLionel Sambuc
175433d6423SLionel Sambuc assert(vr->def_memtype == &mem_type_shared);
176433d6423SLionel Sambuc
177433d6423SLionel Sambuc if(!ep || !vaddr || !id) {
178433d6423SLionel Sambuc printf("VM: shared_setsource: zero ep/vaddr/id - ignoring\n");
179433d6423SLionel Sambuc return;
180433d6423SLionel Sambuc }
181433d6423SLionel Sambuc
182433d6423SLionel Sambuc vr->param.shared.ep = ep;
183433d6423SLionel Sambuc vr->param.shared.vaddr = vaddr;
184433d6423SLionel Sambuc vr->param.shared.id = id;
185433d6423SLionel Sambuc
186433d6423SLionel Sambuc if(getsrc(vr, &vmp, &srcvr) != OK)
187433d6423SLionel Sambuc panic("initial getsrc failed");
188433d6423SLionel Sambuc
189433d6423SLionel Sambuc assert(srcvr == src_vr);
190433d6423SLionel Sambuc
191433d6423SLionel Sambuc srcvr->remaps++;
192433d6423SLionel Sambuc }
193433d6423SLionel Sambuc
shared_copy(struct vir_region * vr,struct vir_region * newvr)194433d6423SLionel Sambuc static int shared_copy(struct vir_region *vr, struct vir_region *newvr)
195433d6423SLionel Sambuc {
196433d6423SLionel Sambuc struct vmproc *vmp;
197433d6423SLionel Sambuc struct vir_region *srcvr;
198433d6423SLionel Sambuc
199433d6423SLionel Sambuc if(getsrc(vr, &vmp, &srcvr) != OK)
200433d6423SLionel Sambuc panic("copy: original getsrc failed");
201433d6423SLionel Sambuc
202433d6423SLionel Sambuc shared_setsource(newvr, vr->param.shared.ep, srcvr);
203433d6423SLionel Sambuc
204433d6423SLionel Sambuc return OK;
205433d6423SLionel Sambuc }
206433d6423SLionel Sambuc
shared_refcount(struct vir_region * vr)207433d6423SLionel Sambuc static int shared_refcount(struct vir_region *vr)
208433d6423SLionel Sambuc {
209433d6423SLionel Sambuc return 1 + vr->remaps;
210433d6423SLionel Sambuc }
211433d6423SLionel Sambuc
212