xref: /minix3/minix/servers/vm/rs.c (revision 5f6c420586374d552d4a81aa129ada5aa46b797d)
1433d6423SLionel Sambuc 
2433d6423SLionel Sambuc #define _SYSTEM 1
3433d6423SLionel Sambuc 
4433d6423SLionel Sambuc #include <minix/callnr.h>
5433d6423SLionel Sambuc #include <minix/com.h>
6433d6423SLionel Sambuc #include <minix/config.h>
7433d6423SLionel Sambuc #include <minix/const.h>
8433d6423SLionel Sambuc #include <minix/ds.h>
9433d6423SLionel Sambuc #include <minix/endpoint.h>
10433d6423SLionel Sambuc #include <minix/minlib.h>
11433d6423SLionel Sambuc #include <minix/type.h>
12433d6423SLionel Sambuc #include <minix/ipc.h>
13433d6423SLionel Sambuc #include <minix/sysutil.h>
14433d6423SLionel Sambuc #include <minix/syslib.h>
15433d6423SLionel Sambuc #include <minix/safecopies.h>
16433d6423SLionel Sambuc #include <minix/bitmap.h>
17a1760b57SCristiano Giuffrida #include <minix/rs.h>
18433d6423SLionel Sambuc 
1963483e02SCristiano Giuffrida #include <sys/mman.h>
2063483e02SCristiano Giuffrida 
21433d6423SLionel Sambuc #include <errno.h>
22433d6423SLionel Sambuc #include <string.h>
23433d6423SLionel Sambuc #include <stdio.h>
24433d6423SLionel Sambuc #include <assert.h>
25433d6423SLionel Sambuc 
26433d6423SLionel Sambuc #include "glo.h"
27433d6423SLionel Sambuc #include "proto.h"
28433d6423SLionel Sambuc #include "util.h"
29433d6423SLionel Sambuc #include "region.h"
30433d6423SLionel Sambuc 
31433d6423SLionel Sambuc /*===========================================================================*
32433d6423SLionel Sambuc  *				do_rs_set_priv				     *
33433d6423SLionel Sambuc  *===========================================================================*/
do_rs_set_priv(message * m)34433d6423SLionel Sambuc int do_rs_set_priv(message *m)
35433d6423SLionel Sambuc {
36433d6423SLionel Sambuc 	int r, n, nr;
37433d6423SLionel Sambuc 	struct vmproc *vmp;
38433d6423SLionel Sambuc 	bitchunk_t call_mask[VM_CALL_MASK_SIZE], *call_mask_p;
39433d6423SLionel Sambuc 
40433d6423SLionel Sambuc 	nr = m->VM_RS_NR;
41433d6423SLionel Sambuc 
42433d6423SLionel Sambuc 	if ((r = vm_isokendpt(nr, &n)) != OK) {
43433d6423SLionel Sambuc 		printf("do_rs_set_priv: bad endpoint %d\n", nr);
44433d6423SLionel Sambuc 		return EINVAL;
45433d6423SLionel Sambuc 	}
46433d6423SLionel Sambuc 
47433d6423SLionel Sambuc 	vmp = &vmproc[n];
48433d6423SLionel Sambuc 
49433d6423SLionel Sambuc 	if (m->VM_RS_BUF) {
50433d6423SLionel Sambuc 		r = sys_datacopy(m->m_source, (vir_bytes) m->VM_RS_BUF, SELF,
51433d6423SLionel Sambuc 			(vir_bytes) call_mask, sizeof(call_mask));
52433d6423SLionel Sambuc 		if (r != OK)
53433d6423SLionel Sambuc 			return r;
54433d6423SLionel Sambuc 		call_mask_p = call_mask;
55433d6423SLionel Sambuc 	} else {
56433d6423SLionel Sambuc 		if (m->VM_RS_SYS) {
57433d6423SLionel Sambuc 			printf("VM: do_rs_set_priv: sys procs don't share!\n");
58433d6423SLionel Sambuc 			return EINVAL;
59433d6423SLionel Sambuc 		}
60433d6423SLionel Sambuc 		call_mask_p = NULL;
61433d6423SLionel Sambuc 	}
62433d6423SLionel Sambuc 
63433d6423SLionel Sambuc 	acl_set(vmp, call_mask_p, m->VM_RS_SYS);
64433d6423SLionel Sambuc 
65433d6423SLionel Sambuc 	return OK;
66433d6423SLionel Sambuc }
67433d6423SLionel Sambuc 
68433d6423SLionel Sambuc /*===========================================================================*
69*abf8a7e7SDavid van Moolenbroek  *				do_rs_prepare	     			     *
70*abf8a7e7SDavid van Moolenbroek  *===========================================================================*/
do_rs_prepare(message * m_ptr)71*abf8a7e7SDavid van Moolenbroek int do_rs_prepare(message *m_ptr)
72*abf8a7e7SDavid van Moolenbroek {
73*abf8a7e7SDavid van Moolenbroek 	/* Prepare a new instance of a service for an upcoming live-update
74*abf8a7e7SDavid van Moolenbroek 	 * switch, based on the old instance of this service.  This call is
75*abf8a7e7SDavid van Moolenbroek 	 * used only by RS and only for a multicomponent live update which
76*abf8a7e7SDavid van Moolenbroek 	 * includes VM.  In this case, all processes need to be prepared such
77*abf8a7e7SDavid van Moolenbroek 	 * that they don't require the new VM instance to perform actions
78*abf8a7e7SDavid van Moolenbroek 	 * during live update that cannot be undone in the case of a rollback.
79*abf8a7e7SDavid van Moolenbroek 	 */
80*abf8a7e7SDavid van Moolenbroek 	endpoint_t src_e, dst_e;
81*abf8a7e7SDavid van Moolenbroek 	int src_p, dst_p;
82*abf8a7e7SDavid van Moolenbroek 	struct vmproc *src_vmp, *dst_vmp;
83*abf8a7e7SDavid van Moolenbroek 	struct vir_region *src_data_vr, *dst_data_vr;
84*abf8a7e7SDavid van Moolenbroek 	vir_bytes src_addr, dst_addr;
85*abf8a7e7SDavid van Moolenbroek 	int sys_upd_flags;
86*abf8a7e7SDavid van Moolenbroek 
87*abf8a7e7SDavid van Moolenbroek 	src_e = m_ptr->m_lsys_vm_update.src;
88*abf8a7e7SDavid van Moolenbroek 	dst_e = m_ptr->m_lsys_vm_update.dst;
89*abf8a7e7SDavid van Moolenbroek         sys_upd_flags = m_ptr->m_lsys_vm_update.flags;
90*abf8a7e7SDavid van Moolenbroek 
91*abf8a7e7SDavid van Moolenbroek 	/* Lookup slots for source and destination process. */
92*abf8a7e7SDavid van Moolenbroek 	if(vm_isokendpt(src_e, &src_p) != OK) {
93*abf8a7e7SDavid van Moolenbroek 		printf("VM: do_rs_prepare: bad src endpoint %d\n", src_e);
94*abf8a7e7SDavid van Moolenbroek 		return EINVAL;
95*abf8a7e7SDavid van Moolenbroek 	}
96*abf8a7e7SDavid van Moolenbroek 	src_vmp = &vmproc[src_p];
97*abf8a7e7SDavid van Moolenbroek 	if(vm_isokendpt(dst_e, &dst_p) != OK) {
98*abf8a7e7SDavid van Moolenbroek 		printf("VM: do_rs_prepare: bad dst endpoint %d\n", dst_e);
99*abf8a7e7SDavid van Moolenbroek 		return EINVAL;
100*abf8a7e7SDavid van Moolenbroek 	}
101*abf8a7e7SDavid van Moolenbroek 	dst_vmp = &vmproc[dst_p];
102*abf8a7e7SDavid van Moolenbroek 
103*abf8a7e7SDavid van Moolenbroek 	/* Pin memory for the source process. */
104*abf8a7e7SDavid van Moolenbroek 	map_pin_memory(src_vmp);
105*abf8a7e7SDavid van Moolenbroek 
106*abf8a7e7SDavid van Moolenbroek 	/* See if the source process has a larger heap than the destination
107*abf8a7e7SDavid van Moolenbroek 	 * process.  If so, extend the heap of the destination process to
108*abf8a7e7SDavid van Moolenbroek 	 * match the source's.  While this may end up wasting quite some
109*abf8a7e7SDavid van Moolenbroek 	 * memory, it is absolutely essential that the destination process
110*abf8a7e7SDavid van Moolenbroek 	 * does not run out of heap memory during the live update window,
111*abf8a7e7SDavid van Moolenbroek 	 * and since most processes will be doing an identity transfer, they
112*abf8a7e7SDavid van Moolenbroek 	 * are likely to require as much heap as their previous instances.
113*abf8a7e7SDavid van Moolenbroek 	 * Better safe than sorry.  TODO: prevent wasting memory somehow;
114*abf8a7e7SDavid van Moolenbroek 	 * this seems particularly relevant for RS.
115*abf8a7e7SDavid van Moolenbroek 	 */
116*abf8a7e7SDavid van Moolenbroek 	src_data_vr = region_search(&src_vmp->vm_regions_avl, VM_MMAPBASE,
117*abf8a7e7SDavid van Moolenbroek 	    AVL_LESS);
118*abf8a7e7SDavid van Moolenbroek 	assert(src_data_vr);
119*abf8a7e7SDavid van Moolenbroek 	dst_data_vr = region_search(&dst_vmp->vm_regions_avl, VM_MMAPBASE,
120*abf8a7e7SDavid van Moolenbroek 	    AVL_LESS);
121*abf8a7e7SDavid van Moolenbroek 	assert(dst_data_vr);
122*abf8a7e7SDavid van Moolenbroek 
123*abf8a7e7SDavid van Moolenbroek 	src_addr = src_data_vr->vaddr + src_data_vr->length;
124*abf8a7e7SDavid van Moolenbroek 	dst_addr = dst_data_vr->vaddr + dst_data_vr->length;
125*abf8a7e7SDavid van Moolenbroek 	if (src_addr > dst_addr)
126*abf8a7e7SDavid van Moolenbroek 		real_brk(dst_vmp, src_addr);
127*abf8a7e7SDavid van Moolenbroek 
128*abf8a7e7SDavid van Moolenbroek 	/* Now also pin memory for the destination process. */
129*abf8a7e7SDavid van Moolenbroek 	map_pin_memory(dst_vmp);
130*abf8a7e7SDavid van Moolenbroek 
131*abf8a7e7SDavid van Moolenbroek 	/* Finally, map the source process's memory-mapped regions into the
132*abf8a7e7SDavid van Moolenbroek 	 * destination process.  This needs to happen now, because VM may not
133*abf8a7e7SDavid van Moolenbroek 	 * allocate any objects during the live update window, since this
134*abf8a7e7SDavid van Moolenbroek 	 * would prevent successful rollback of VM afterwards.  The
135*abf8a7e7SDavid van Moolenbroek 	 * destination may not actually touch these regions during the live
136*abf8a7e7SDavid van Moolenbroek 	 * update window either, because they are mapped copy-on-write and a
137*abf8a7e7SDavid van Moolenbroek 	 * pagefault would also cause object allocation.  Objects are pages,
138*abf8a7e7SDavid van Moolenbroek 	 * slab objects, anything in the new VM instance to which changes are
139*abf8a7e7SDavid van Moolenbroek 	 * visible in the old VM basically.
140*abf8a7e7SDavid van Moolenbroek 	 */
141*abf8a7e7SDavid van Moolenbroek 	if (!(sys_upd_flags & SF_VM_NOMMAP))
142*abf8a7e7SDavid van Moolenbroek 		map_proc_dyn_data(src_vmp, dst_vmp);
143*abf8a7e7SDavid van Moolenbroek 
144*abf8a7e7SDavid van Moolenbroek 	return OK;
145*abf8a7e7SDavid van Moolenbroek }
146*abf8a7e7SDavid van Moolenbroek 
147*abf8a7e7SDavid van Moolenbroek /*===========================================================================*
148433d6423SLionel Sambuc  *				do_rs_update	     			     *
149433d6423SLionel Sambuc  *===========================================================================*/
do_rs_update(message * m_ptr)150433d6423SLionel Sambuc int do_rs_update(message *m_ptr)
151433d6423SLionel Sambuc {
152433d6423SLionel Sambuc 	endpoint_t src_e, dst_e, reply_e;
153433d6423SLionel Sambuc 	int src_p, dst_p;
154433d6423SLionel Sambuc 	struct vmproc *src_vmp, *dst_vmp;
155a1760b57SCristiano Giuffrida 	int r, sys_upd_flags;
156433d6423SLionel Sambuc 
157433d6423SLionel Sambuc 	src_e = m_ptr->m_lsys_vm_update.src;
158433d6423SLionel Sambuc 	dst_e = m_ptr->m_lsys_vm_update.dst;
159a1760b57SCristiano Giuffrida         sys_upd_flags = m_ptr->m_lsys_vm_update.flags;
16063483e02SCristiano Giuffrida         reply_e = m_ptr->m_source;
161433d6423SLionel Sambuc 
162433d6423SLionel Sambuc 	/* Lookup slots for source and destination process. */
163433d6423SLionel Sambuc 	if(vm_isokendpt(src_e, &src_p) != OK) {
164433d6423SLionel Sambuc 		printf("do_rs_update: bad src endpoint %d\n", src_e);
165433d6423SLionel Sambuc 		return EINVAL;
166433d6423SLionel Sambuc 	}
167433d6423SLionel Sambuc 	src_vmp = &vmproc[src_p];
168433d6423SLionel Sambuc 	if(vm_isokendpt(dst_e, &dst_p) != OK) {
169433d6423SLionel Sambuc 		printf("do_rs_update: bad dst endpoint %d\n", dst_e);
170433d6423SLionel Sambuc 		return EINVAL;
171433d6423SLionel Sambuc 	}
172433d6423SLionel Sambuc 	dst_vmp = &vmproc[dst_p];
173433d6423SLionel Sambuc 
17463483e02SCristiano Giuffrida 	/* Check flags. */
17563483e02SCristiano Giuffrida 	if((sys_upd_flags & (SF_VM_ROLLBACK|SF_VM_NOMMAP)) == 0) {
17663483e02SCristiano Giuffrida 	        /* Can't preallocate when transfering mmapped regions. */
17763483e02SCristiano Giuffrida 	        if(map_region_lookup_type(dst_vmp, VR_PREALLOC_MAP)) {
17863483e02SCristiano Giuffrida 			return ENOSYS;
17963483e02SCristiano Giuffrida 	        }
18063483e02SCristiano Giuffrida 	}
18163483e02SCristiano Giuffrida 
182433d6423SLionel Sambuc 	/* Let the kernel do the update first. */
183a1760b57SCristiano Giuffrida 	r = sys_update(src_e, dst_e,
184a1760b57SCristiano Giuffrida 	    sys_upd_flags & SF_VM_ROLLBACK ? SYS_UPD_ROLLBACK : 0);
185433d6423SLionel Sambuc 	if(r != OK) {
186433d6423SLionel Sambuc 		return r;
187433d6423SLionel Sambuc 	}
188433d6423SLionel Sambuc 
189433d6423SLionel Sambuc 	/* Do the update in VM now. */
190433d6423SLionel Sambuc 	r = swap_proc_slot(src_vmp, dst_vmp);
191433d6423SLionel Sambuc 	if(r != OK) {
192433d6423SLionel Sambuc 		return r;
193433d6423SLionel Sambuc 	}
19463483e02SCristiano Giuffrida 	r = swap_proc_dyn_data(src_vmp, dst_vmp, sys_upd_flags);
195433d6423SLionel Sambuc 	if(r != OK) {
196433d6423SLionel Sambuc 		return r;
197433d6423SLionel Sambuc 	}
198433d6423SLionel Sambuc 	pt_bind(&src_vmp->vm_pt, src_vmp);
199433d6423SLionel Sambuc 	pt_bind(&dst_vmp->vm_pt, dst_vmp);
200433d6423SLionel Sambuc 
20163483e02SCristiano Giuffrida 	/* Reply in case of external request, update-aware. */
20263483e02SCristiano Giuffrida 	if(reply_e != VM_PROC_NR) {
203433d6423SLionel Sambuc             if(reply_e == src_e) reply_e = dst_e;
204433d6423SLionel Sambuc             else if(reply_e == dst_e) reply_e = src_e;
205433d6423SLionel Sambuc             m_ptr->m_type = OK;
206433d6423SLionel Sambuc             r = ipc_send(reply_e, m_ptr);
207433d6423SLionel Sambuc             if(r != OK) {
208433d6423SLionel Sambuc                     panic("ipc_send() error");
209433d6423SLionel Sambuc             }
21063483e02SCristiano Giuffrida 	}
211433d6423SLionel Sambuc 
212433d6423SLionel Sambuc 	return SUSPEND;
213433d6423SLionel Sambuc }
214433d6423SLionel Sambuc 
215433d6423SLionel Sambuc /*===========================================================================*
216433d6423SLionel Sambuc  *		           rs_memctl_make_vm_instance			     *
217433d6423SLionel Sambuc  *===========================================================================*/
rs_memctl_make_vm_instance(struct vmproc * new_vm_vmp)218433d6423SLionel Sambuc static int rs_memctl_make_vm_instance(struct vmproc *new_vm_vmp)
219433d6423SLionel Sambuc {
220433d6423SLionel Sambuc 	int r;
221433d6423SLionel Sambuc 	u32_t flags;
222433d6423SLionel Sambuc 	int verify;
223433d6423SLionel Sambuc 	struct vmproc *this_vm_vmp;
224433d6423SLionel Sambuc 
225433d6423SLionel Sambuc 	this_vm_vmp = &vmproc[VM_PROC_NR];
226433d6423SLionel Sambuc 
22710e6ba68SBen Gras 	pt_assert(&this_vm_vmp->vm_pt);
22810e6ba68SBen Gras 
22963483e02SCristiano Giuffrida 	/* Check if the operation is allowed. */
23063483e02SCristiano Giuffrida 	assert(num_vm_instances == 1 || num_vm_instances == 2);
23163483e02SCristiano Giuffrida 	if(num_vm_instances == 2) {
23263483e02SCristiano Giuffrida 		printf("VM can currently support no more than 2 VM instances at the time.");
23363483e02SCristiano Giuffrida 		return EPERM;
23463483e02SCristiano Giuffrida 	}
23563483e02SCristiano Giuffrida 
23663483e02SCristiano Giuffrida 	/* Copy settings from current VM. */
23763483e02SCristiano Giuffrida 	new_vm_vmp->vm_flags |= VMF_VM_INSTANCE;
23863483e02SCristiano Giuffrida 	num_vm_instances++;
23963483e02SCristiano Giuffrida 
240433d6423SLionel Sambuc 	/* Pin memory for the new VM instance. */
241433d6423SLionel Sambuc 	r = map_pin_memory(new_vm_vmp);
242433d6423SLionel Sambuc 	if(r != OK) {
243433d6423SLionel Sambuc 		return r;
244433d6423SLionel Sambuc 	}
245433d6423SLionel Sambuc 
246433d6423SLionel Sambuc 	/* Preallocate page tables for the entire address space for both
247433d6423SLionel Sambuc 	 * VM and the new VM instance.
248433d6423SLionel Sambuc 	 */
249433d6423SLionel Sambuc 	flags = 0;
250433d6423SLionel Sambuc 	verify = FALSE;
2510be08400SCristiano Giuffrida 	r = pt_ptalloc_in_range(&this_vm_vmp->vm_pt,
25210e6ba68SBen Gras 		VM_OWN_HEAPBASE, VM_DATATOP, flags, verify);
253433d6423SLionel Sambuc 	if(r != OK) {
254433d6423SLionel Sambuc 		return r;
255433d6423SLionel Sambuc 	}
2560be08400SCristiano Giuffrida 	r = pt_ptalloc_in_range(&new_vm_vmp->vm_pt,
25710e6ba68SBen Gras 		VM_OWN_HEAPBASE, VM_DATATOP, flags, verify);
258433d6423SLionel Sambuc 	if(r != OK) {
259433d6423SLionel Sambuc 		return r;
260433d6423SLionel Sambuc 	}
261433d6423SLionel Sambuc 
262433d6423SLionel Sambuc 	/* Let the new VM instance map VM's page tables and its own. */
263433d6423SLionel Sambuc 	r = pt_ptmap(this_vm_vmp, new_vm_vmp);
264433d6423SLionel Sambuc 	if(r != OK) {
265433d6423SLionel Sambuc 		return r;
266433d6423SLionel Sambuc 	}
267433d6423SLionel Sambuc 	r = pt_ptmap(new_vm_vmp, new_vm_vmp);
268433d6423SLionel Sambuc 	if(r != OK) {
269433d6423SLionel Sambuc 		return r;
270433d6423SLionel Sambuc 	}
271433d6423SLionel Sambuc 
27210e6ba68SBen Gras 	pt_assert(&this_vm_vmp->vm_pt);
27310e6ba68SBen Gras 	pt_assert(&new_vm_vmp->vm_pt);
27410e6ba68SBen Gras 
275433d6423SLionel Sambuc 	return OK;
276433d6423SLionel Sambuc }
277433d6423SLionel Sambuc 
278433d6423SLionel Sambuc /*===========================================================================*
27948f446ecSCristiano Giuffrida  *		           rs_memctl_heap_prealloc			     *
28048f446ecSCristiano Giuffrida  *===========================================================================*/
rs_memctl_heap_prealloc(struct vmproc * vmp,vir_bytes * addr,size_t * len)28148f446ecSCristiano Giuffrida static int rs_memctl_heap_prealloc(struct vmproc *vmp,
28248f446ecSCristiano Giuffrida 	vir_bytes *addr, size_t *len)
28348f446ecSCristiano Giuffrida {
284eacaa829SCristiano Giuffrida 	struct vir_region *data_vr;
285eacaa829SCristiano Giuffrida 	vir_bytes bytes;
28648f446ecSCristiano Giuffrida 
287eacaa829SCristiano Giuffrida 	if(*len <= 0) {
288eacaa829SCristiano Giuffrida 		return EINVAL;
289eacaa829SCristiano Giuffrida 	}
290eacaa829SCristiano Giuffrida 	data_vr = region_search(&vmp->vm_regions_avl, VM_MMAPBASE, AVL_LESS);
291eacaa829SCristiano Giuffrida 	*addr = data_vr->vaddr + data_vr->length;
292eacaa829SCristiano Giuffrida 	bytes = *addr + *len;
29348f446ecSCristiano Giuffrida 
294eacaa829SCristiano Giuffrida 	return real_brk(vmp, bytes);
29548f446ecSCristiano Giuffrida }
29648f446ecSCristiano Giuffrida 
29748f446ecSCristiano Giuffrida /*===========================================================================*
29848f446ecSCristiano Giuffrida  *		           rs_memctl_map_prealloc			     *
29948f446ecSCristiano Giuffrida  *===========================================================================*/
rs_memctl_map_prealloc(struct vmproc * vmp,vir_bytes * addr,size_t * len)30048f446ecSCristiano Giuffrida static int rs_memctl_map_prealloc(struct vmproc *vmp,
30148f446ecSCristiano Giuffrida 	vir_bytes *addr, size_t *len)
30248f446ecSCristiano Giuffrida {
30348f446ecSCristiano Giuffrida 	struct vir_region *vr;
30463483e02SCristiano Giuffrida 	vir_bytes base, top;
30563483e02SCristiano Giuffrida 	int is_vm;
30663483e02SCristiano Giuffrida 
30748f446ecSCristiano Giuffrida 	if(*len <= 0) {
30848f446ecSCristiano Giuffrida 		return EINVAL;
30948f446ecSCristiano Giuffrida 	}
31048f446ecSCristiano Giuffrida 	*len = CLICK_CEIL(*len);
31148f446ecSCristiano Giuffrida 
31263483e02SCristiano Giuffrida 	is_vm = (vmp->vm_endpoint == VM_PROC_NR);
31363483e02SCristiano Giuffrida 	base = is_vm ? VM_OWN_MMAPBASE : VM_MMAPBASE;
31463483e02SCristiano Giuffrida 	top = is_vm ? VM_OWN_MMAPTOP : VM_MMAPTOP;
31563483e02SCristiano Giuffrida 
31663483e02SCristiano Giuffrida 	if (!(vr = map_page_region(vmp, base, top, *len,
31763483e02SCristiano Giuffrida 	    VR_ANON|VR_WRITABLE|VR_UNINITIALIZED, MF_PREALLOC,
31863483e02SCristiano Giuffrida 	    &mem_type_anon))) {
31948f446ecSCristiano Giuffrida 		return ENOMEM;
32048f446ecSCristiano Giuffrida 	}
32163483e02SCristiano Giuffrida 	vr->flags |= VR_PREALLOC_MAP;
32263483e02SCristiano Giuffrida 	*addr = vr->vaddr;
32348f446ecSCristiano Giuffrida 	return OK;
32448f446ecSCristiano Giuffrida }
32548f446ecSCristiano Giuffrida 
32648f446ecSCristiano Giuffrida /*===========================================================================*
32748f446ecSCristiano Giuffrida  *		         rs_memctl_get_prealloc_map			     *
32848f446ecSCristiano Giuffrida  *===========================================================================*/
rs_memctl_get_prealloc_map(struct vmproc * vmp,vir_bytes * addr,size_t * len)32948f446ecSCristiano Giuffrida static int rs_memctl_get_prealloc_map(struct vmproc *vmp,
33048f446ecSCristiano Giuffrida 	vir_bytes *addr, size_t *len)
33148f446ecSCristiano Giuffrida {
33248f446ecSCristiano Giuffrida 	struct vir_region *vr;
33348f446ecSCristiano Giuffrida 
33463483e02SCristiano Giuffrida 	vr = map_region_lookup_type(vmp, VR_PREALLOC_MAP);
33548f446ecSCristiano Giuffrida 	if(!vr) {
33648f446ecSCristiano Giuffrida 		*addr = 0;
33748f446ecSCristiano Giuffrida 		*len = 0;
33848f446ecSCristiano Giuffrida 	}
33948f446ecSCristiano Giuffrida 	else {
34063483e02SCristiano Giuffrida 		*addr = vr->vaddr;
34148f446ecSCristiano Giuffrida 		*len = vr->length;
34248f446ecSCristiano Giuffrida 	}
34348f446ecSCristiano Giuffrida 	return OK;
34448f446ecSCristiano Giuffrida }
34548f446ecSCristiano Giuffrida 
34648f446ecSCristiano Giuffrida /*===========================================================================*
347433d6423SLionel Sambuc  *				do_rs_memctl	     			     *
348433d6423SLionel Sambuc  *===========================================================================*/
do_rs_memctl(message * m_ptr)349433d6423SLionel Sambuc int do_rs_memctl(message *m_ptr)
350433d6423SLionel Sambuc {
351433d6423SLionel Sambuc 	endpoint_t ep;
352433d6423SLionel Sambuc 	int req, r, proc_nr;
353433d6423SLionel Sambuc 	struct vmproc *vmp;
354433d6423SLionel Sambuc 
355433d6423SLionel Sambuc 	ep = m_ptr->VM_RS_CTL_ENDPT;
356433d6423SLionel Sambuc 	req = m_ptr->VM_RS_CTL_REQ;
357433d6423SLionel Sambuc 
358433d6423SLionel Sambuc 	/* Lookup endpoint. */
359433d6423SLionel Sambuc 	if ((r = vm_isokendpt(ep, &proc_nr)) != OK) {
360433d6423SLionel Sambuc 		printf("do_rs_memctl: bad endpoint %d\n", ep);
361433d6423SLionel Sambuc 		return EINVAL;
362433d6423SLionel Sambuc 	}
363433d6423SLionel Sambuc 	vmp = &vmproc[proc_nr];
364433d6423SLionel Sambuc 
365433d6423SLionel Sambuc 	/* Process request. */
366433d6423SLionel Sambuc 	switch(req)
367433d6423SLionel Sambuc 	{
368433d6423SLionel Sambuc 	case VM_RS_MEM_PIN:
369fb6bd596SCristiano Giuffrida 		/* Only actually pin RS memory if VM can recover from crashes (saves memory). */
370fb6bd596SCristiano Giuffrida 		if (num_vm_instances <= 1)
371fb6bd596SCristiano Giuffrida 			return OK;
372433d6423SLionel Sambuc 		r = map_pin_memory(vmp);
373433d6423SLionel Sambuc 		return r;
374433d6423SLionel Sambuc 	case VM_RS_MEM_MAKE_VM:
375433d6423SLionel Sambuc 		r = rs_memctl_make_vm_instance(vmp);
376433d6423SLionel Sambuc 		return r;
37748f446ecSCristiano Giuffrida 	case VM_RS_MEM_HEAP_PREALLOC:
37848f446ecSCristiano Giuffrida 		r = rs_memctl_heap_prealloc(vmp, (vir_bytes*) &m_ptr->VM_RS_CTL_ADDR, (size_t*) &m_ptr->VM_RS_CTL_LEN);
37948f446ecSCristiano Giuffrida 		return r;
38048f446ecSCristiano Giuffrida 	case VM_RS_MEM_MAP_PREALLOC:
38148f446ecSCristiano Giuffrida 		r = rs_memctl_map_prealloc(vmp, (vir_bytes*) &m_ptr->VM_RS_CTL_ADDR, (size_t*) &m_ptr->VM_RS_CTL_LEN);
38248f446ecSCristiano Giuffrida 		return r;
38348f446ecSCristiano Giuffrida 	case VM_RS_MEM_GET_PREALLOC_MAP:
38448f446ecSCristiano Giuffrida 		r = rs_memctl_get_prealloc_map(vmp, (vir_bytes*) &m_ptr->VM_RS_CTL_ADDR, (size_t*) &m_ptr->VM_RS_CTL_LEN);
38548f446ecSCristiano Giuffrida 		return r;
386433d6423SLionel Sambuc 	default:
387433d6423SLionel Sambuc 		printf("do_rs_memctl: bad request %d\n", req);
388433d6423SLionel Sambuc 		return EINVAL;
389433d6423SLionel Sambuc 	}
390433d6423SLionel Sambuc }
391433d6423SLionel Sambuc 
392