xref: /minix3/minix/servers/vm/main.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/const.h>
16433d6423SLionel Sambuc #include <minix/bitmap.h>
17433d6423SLionel Sambuc #include <minix/rs.h>
18433d6423SLionel Sambuc #include <minix/vfsif.h>
19433d6423SLionel Sambuc 
20433d6423SLionel Sambuc #include <sys/exec.h>
21433d6423SLionel Sambuc 
22433d6423SLionel Sambuc #include <libexec.h>
23433d6423SLionel Sambuc #include <ctype.h>
24433d6423SLionel Sambuc #include <errno.h>
25433d6423SLionel Sambuc #include <string.h>
26433d6423SLionel Sambuc #include <stdio.h>
27433d6423SLionel Sambuc #include <assert.h>
28433d6423SLionel Sambuc 
29433d6423SLionel Sambuc #define _MAIN 1
30433d6423SLionel Sambuc #include "glo.h"
31433d6423SLionel Sambuc #include "proto.h"
32433d6423SLionel Sambuc #include "util.h"
33433d6423SLionel Sambuc #include "vm.h"
34433d6423SLionel Sambuc #include "sanitycheck.h"
35433d6423SLionel Sambuc 
36433d6423SLionel Sambuc extern int missing_spares;
37433d6423SLionel Sambuc 
38433d6423SLionel Sambuc #include <machine/archtypes.h>
39433d6423SLionel Sambuc #include <sys/param.h>
40433d6423SLionel Sambuc #include "kernel/const.h"
41433d6423SLionel Sambuc #include "kernel/config.h"
42433d6423SLionel Sambuc #include "kernel/proc.h"
43433d6423SLionel Sambuc 
44433d6423SLionel Sambuc #include <signal.h>
45433d6423SLionel Sambuc #include <lib.h>
46433d6423SLionel Sambuc 
47433d6423SLionel Sambuc /* Table of calls and a macro to test for being in range. */
48433d6423SLionel Sambuc struct {
49433d6423SLionel Sambuc 	int (*vmc_func)(message *);	/* Call handles message. */
50433d6423SLionel Sambuc 	const char *vmc_name;			/* Human-readable string. */
51433d6423SLionel Sambuc } vm_calls[NR_VM_CALLS];
52433d6423SLionel Sambuc 
53433d6423SLionel Sambuc /* Macro to verify call range and map 'high' range to 'base' range
54433d6423SLionel Sambuc  * (starting at 0) in one. Evaluates to zero-based call number if call
55433d6423SLionel Sambuc  * number is valid, returns -1 otherwise.
56433d6423SLionel Sambuc  */
57433d6423SLionel Sambuc #define CALLNUMBER(c) (((c) >= VM_RQ_BASE && 				\
58433d6423SLionel Sambuc 			(c) < VM_RQ_BASE + ELEMENTS(vm_calls)) ?	\
59433d6423SLionel Sambuc 			((c) - VM_RQ_BASE) : -1)
60433d6423SLionel Sambuc 
61433d6423SLionel Sambuc static int map_service(struct rprocpub *rpub);
620e78c016SCristiano Giuffrida 
630e78c016SCristiano Giuffrida static struct rprocpub rprocpub[NR_SYS_PROCS];
640e78c016SCristiano Giuffrida int __vm_init_fresh;
65433d6423SLionel Sambuc 
66433d6423SLionel Sambuc /* SEF functions and variables. */
670e78c016SCristiano Giuffrida static void sef_local_startup(void);
680e78c016SCristiano Giuffrida static int sef_cb_init_lu_restart(int type, sef_init_info_t *info);
690e78c016SCristiano Giuffrida static int sef_cb_init_fresh(int type, sef_init_info_t *info);
70433d6423SLionel Sambuc static void sef_cb_signal_handler(int signo);
71433d6423SLionel Sambuc 
72433d6423SLionel Sambuc void init_vm(void);
73433d6423SLionel Sambuc 
740e78c016SCristiano Giuffrida int do_sef_init_request(message *);
750e78c016SCristiano Giuffrida 
760e78c016SCristiano Giuffrida /*===========================================================================*
770e78c016SCristiano Giuffrida  *				is_first_time				     *
780e78c016SCristiano Giuffrida  *===========================================================================*/
is_first_time(void)790e78c016SCristiano Giuffrida static int is_first_time(void)
800e78c016SCristiano Giuffrida {
810e78c016SCristiano Giuffrida 	struct proc rs_proc;
820e78c016SCristiano Giuffrida 	int r;
830e78c016SCristiano Giuffrida 
840e78c016SCristiano Giuffrida 	if ((r = sys_getproc(&rs_proc, RS_PROC_NR)) != OK)
850e78c016SCristiano Giuffrida 		panic("VM: couldn't get RS process data: %d", r);
860e78c016SCristiano Giuffrida 
870e78c016SCristiano Giuffrida 	return RTS_ISSET(&rs_proc, RTS_BOOTINHIBIT);
880e78c016SCristiano Giuffrida }
890e78c016SCristiano Giuffrida 
90433d6423SLionel Sambuc /*===========================================================================*
91433d6423SLionel Sambuc  *				main					     *
92433d6423SLionel Sambuc  *===========================================================================*/
main(void)93433d6423SLionel Sambuc int main(void)
94433d6423SLionel Sambuc {
95433d6423SLionel Sambuc   message msg;
96433d6423SLionel Sambuc   int result, who_e, rcv_sts;
97433d6423SLionel Sambuc   int caller_slot;
98433d6423SLionel Sambuc 
990e78c016SCristiano Giuffrida   /* Initialize system so that all processes are runnable the first time. */
1000e78c016SCristiano Giuffrida   if (is_first_time()) {
101433d6423SLionel Sambuc 	init_vm();
1020e78c016SCristiano Giuffrida 	__vm_init_fresh=1;
1030e78c016SCristiano Giuffrida   }
104433d6423SLionel Sambuc 
1050e78c016SCristiano Giuffrida   /* SEF local startup. */
1060e78c016SCristiano Giuffrida   sef_local_startup();
1070e78c016SCristiano Giuffrida   __vm_init_fresh=0;
108433d6423SLionel Sambuc 
109433d6423SLionel Sambuc   SANITYCHECK(SCL_TOP);
110433d6423SLionel Sambuc 
111433d6423SLionel Sambuc   /* This is VM's main loop. */
112433d6423SLionel Sambuc   while (TRUE) {
113433d6423SLionel Sambuc 	int r, c;
114433d6423SLionel Sambuc 	int type;
115433d6423SLionel Sambuc 	int transid = 0;	/* VFS transid if any */
116433d6423SLionel Sambuc 
117433d6423SLionel Sambuc 	SANITYCHECK(SCL_TOP);
118433d6423SLionel Sambuc 	if(missing_spares > 0) {
119433d6423SLionel Sambuc 		alloc_cycle();	/* mem alloc code wants to be called */
120433d6423SLionel Sambuc 	}
121433d6423SLionel Sambuc 
122433d6423SLionel Sambuc   	if ((r=sef_receive_status(ANY, &msg, &rcv_sts)) != OK)
123433d6423SLionel Sambuc 		panic("sef_receive_status() error: %d", r);
124433d6423SLionel Sambuc 
125433d6423SLionel Sambuc 	if (is_ipc_notify(rcv_sts)) {
126433d6423SLionel Sambuc 		/* Unexpected ipc_notify(). */
127433d6423SLionel Sambuc 		printf("VM: ignoring ipc_notify() from %d\n", msg.m_source);
128433d6423SLionel Sambuc 		continue;
129433d6423SLionel Sambuc 	}
130433d6423SLionel Sambuc 	who_e = msg.m_source;
131433d6423SLionel Sambuc 	if(vm_isokendpt(who_e, &caller_slot) != OK)
132433d6423SLionel Sambuc 		panic("invalid caller %d", who_e);
133433d6423SLionel Sambuc 
134433d6423SLionel Sambuc 	/* We depend on this being false for the initialized value. */
135433d6423SLionel Sambuc 	assert(!IS_VFS_FS_TRANSID(transid));
136433d6423SLionel Sambuc 
137433d6423SLionel Sambuc 	type = msg.m_type;
138433d6423SLionel Sambuc 	c = CALLNUMBER(type);
139433d6423SLionel Sambuc 	result = ENOSYS; /* Out of range or restricted calls return this. */
140433d6423SLionel Sambuc 
141433d6423SLionel Sambuc 	transid = TRNS_GET_ID(msg.m_type);
142433d6423SLionel Sambuc 
143433d6423SLionel Sambuc 	if((msg.m_source == VFS_PROC_NR) && IS_VFS_FS_TRANSID(transid)) {
144433d6423SLionel Sambuc 		/* If it's a request from VFS, it might have a transaction id. */
145433d6423SLionel Sambuc 		msg.m_type = TRNS_DEL_ID(msg.m_type);
146433d6423SLionel Sambuc 
147433d6423SLionel Sambuc 		/* Calls that use the transid */
148433d6423SLionel Sambuc 		result = do_procctl(&msg, transid);
149433d6423SLionel Sambuc 	} else if(msg.m_type == RS_INIT && msg.m_source == RS_PROC_NR) {
1500e78c016SCristiano Giuffrida 		result = do_sef_init_request(&msg);
1510e78c016SCristiano Giuffrida 		if(result != OK) panic("do_sef_init_request failed!\n");
1520e78c016SCristiano Giuffrida 		result = SUSPEND;	/* do not reply to RS */
153433d6423SLionel Sambuc 	} else if (msg.m_type == VM_PAGEFAULT) {
154433d6423SLionel Sambuc 		if (!IPC_STATUS_FLAGS_TEST(rcv_sts, IPC_FLG_MSG_FROM_KERNEL)) {
155433d6423SLionel Sambuc 			printf("VM: process %d faked VM_PAGEFAULT "
156433d6423SLionel Sambuc 					"message!\n", msg.m_source);
157433d6423SLionel Sambuc 		}
158433d6423SLionel Sambuc 		do_pagefaults(&msg);
159433d6423SLionel Sambuc 		/*
160433d6423SLionel Sambuc 		 * do not reply to this call, the caller is unblocked by
161433d6423SLionel Sambuc 		 * a sys_vmctl() call in do_pagefaults if success. VM panics
162433d6423SLionel Sambuc 		 * otherwise
163433d6423SLionel Sambuc 		 */
164433d6423SLionel Sambuc 		continue;
165433d6423SLionel Sambuc 	} else if(c < 0 || !vm_calls[c].vmc_func) {
166433d6423SLionel Sambuc 		/* out of range or missing callnr */
167433d6423SLionel Sambuc 	} else {
168433d6423SLionel Sambuc 		if (acl_check(&vmproc[caller_slot], c) != OK) {
169433d6423SLionel Sambuc 			printf("VM: unauthorized %s by %d\n",
170433d6423SLionel Sambuc 					vm_calls[c].vmc_name, who_e);
171433d6423SLionel Sambuc 		} else {
172433d6423SLionel Sambuc 			SANITYCHECK(SCL_FUNCTIONS);
173433d6423SLionel Sambuc 			result = vm_calls[c].vmc_func(&msg);
174433d6423SLionel Sambuc 			SANITYCHECK(SCL_FUNCTIONS);
175433d6423SLionel Sambuc 		}
176433d6423SLionel Sambuc 	}
177433d6423SLionel Sambuc 
178433d6423SLionel Sambuc 	/* Send reply message, unless the return code is SUSPEND,
179433d6423SLionel Sambuc 	 * which is a pseudo-result suppressing the reply message.
180433d6423SLionel Sambuc 	 */
181433d6423SLionel Sambuc 	if(result != SUSPEND) {
182433d6423SLionel Sambuc 		msg.m_type = result;
183433d6423SLionel Sambuc 
184433d6423SLionel Sambuc 		assert(!IS_VFS_FS_TRANSID(transid));
185433d6423SLionel Sambuc 
186433d6423SLionel Sambuc 		if((r=ipc_send(who_e, &msg)) != OK) {
187433d6423SLionel Sambuc 			printf("VM: couldn't send %d to %d (err %d)\n",
188433d6423SLionel Sambuc 				msg.m_type, who_e, r);
189433d6423SLionel Sambuc 			panic("ipc_send() error");
190433d6423SLionel Sambuc 		}
191433d6423SLionel Sambuc 	}
192433d6423SLionel Sambuc   }
193433d6423SLionel Sambuc   return(OK);
194433d6423SLionel Sambuc }
195433d6423SLionel Sambuc 
sef_cb_lu_state_changed(int old_state,int state)1965a4672e3SDavid van Moolenbroek static void sef_cb_lu_state_changed(int old_state, int state)
1975a4672e3SDavid van Moolenbroek {
1985a4672e3SDavid van Moolenbroek /* Called whenever the live-update state changes. We need to restore certain
1995a4672e3SDavid van Moolenbroek  * state in the old VM instance after a live update has failed, because some
2005a4672e3SDavid van Moolenbroek  * but not all memory is shared between the two VM instances.
2015a4672e3SDavid van Moolenbroek  */
2025a4672e3SDavid van Moolenbroek   struct vmproc *vmp;
2035a4672e3SDavid van Moolenbroek 
2045a4672e3SDavid van Moolenbroek   if (state == SEF_LU_STATE_NULL) {
2055a4672e3SDavid van Moolenbroek 	/* Undo some of the changes that may have been made by the new VM
2065a4672e3SDavid van Moolenbroek 	 * instance.  If the new VM instance is us, nothing happens.
2075a4672e3SDavid van Moolenbroek 	 */
2085a4672e3SDavid van Moolenbroek 	vmp = &vmproc[VM_PROC_NR];
2095a4672e3SDavid van Moolenbroek 
2105a4672e3SDavid van Moolenbroek 	/* Rebind page tables. */
2115a4672e3SDavid van Moolenbroek 	pt_bind(&vmp->vm_pt, vmp);
2125a4672e3SDavid van Moolenbroek 	pt_clearmapcache();
2135a4672e3SDavid van Moolenbroek 
2145a4672e3SDavid van Moolenbroek 	/* Readjust process references. */
2155a4672e3SDavid van Moolenbroek 	adjust_proc_refs();
2165a4672e3SDavid van Moolenbroek   }
2175a4672e3SDavid van Moolenbroek }
2185a4672e3SDavid van Moolenbroek 
sef_local_startup(void)2190e78c016SCristiano Giuffrida static void sef_local_startup(void)
2200e78c016SCristiano Giuffrida {
2210e78c016SCristiano Giuffrida 	/* Register init callbacks. */
2220e78c016SCristiano Giuffrida 	sef_setcb_init_fresh(sef_cb_init_fresh);
2230e78c016SCristiano Giuffrida 	sef_setcb_init_lu(sef_cb_init_lu_restart);
2240e78c016SCristiano Giuffrida 	sef_setcb_init_restart(sef_cb_init_lu_restart);
22537489f8aSDavid van Moolenbroek 	/* In order to avoid a deadlock at boot time, send the first RS_INIT
22637489f8aSDavid van Moolenbroek 	 * reply to RS asynchronously. After that, use sendrec as usual.
22737489f8aSDavid van Moolenbroek 	 */
22837489f8aSDavid van Moolenbroek 	if (__vm_init_fresh)
22937489f8aSDavid van Moolenbroek 		sef_setcb_init_response(sef_cb_init_response_rs_asyn_once);
2300e78c016SCristiano Giuffrida 
2315a4672e3SDavid van Moolenbroek 	/* Register live update callbacks. */
2325a4672e3SDavid van Moolenbroek 	sef_setcb_lu_state_changed(sef_cb_lu_state_changed);
2335a4672e3SDavid van Moolenbroek 
2340e78c016SCristiano Giuffrida 	/* Register signal callbacks. */
2350e78c016SCristiano Giuffrida 	sef_setcb_signal_handler(sef_cb_signal_handler);
2360e78c016SCristiano Giuffrida 
2370e78c016SCristiano Giuffrida 	/* Let SEF perform startup. */
2380e78c016SCristiano Giuffrida 	sef_startup();
2390e78c016SCristiano Giuffrida }
2400e78c016SCristiano Giuffrida 
sef_cb_init_fresh(int type,sef_init_info_t * info)2410e78c016SCristiano Giuffrida static int sef_cb_init_fresh(int type, sef_init_info_t *info)
242433d6423SLionel Sambuc {
243433d6423SLionel Sambuc 	int s, i;
244433d6423SLionel Sambuc 
245433d6423SLionel Sambuc 	/* Map all the services in the boot image. */
2460e78c016SCristiano Giuffrida 	if((s = sys_safecopyfrom(RS_PROC_NR, info->rproctab_gid, 0,
247433d6423SLionel Sambuc 		(vir_bytes) rprocpub, sizeof(rprocpub))) != OK) {
248433d6423SLionel Sambuc 		panic("vm: sys_safecopyfrom (rs) failed: %d", s);
249433d6423SLionel Sambuc 	}
250433d6423SLionel Sambuc 
251433d6423SLionel Sambuc 	for(i=0;i < NR_BOOT_PROCS;i++) {
252433d6423SLionel Sambuc 		if(rprocpub[i].in_use) {
253433d6423SLionel Sambuc 			if((s = map_service(&rprocpub[i])) != OK) {
254433d6423SLionel Sambuc 				panic("unable to map service: %d", s);
255433d6423SLionel Sambuc 			}
256433d6423SLionel Sambuc 		}
257433d6423SLionel Sambuc 	}
258433d6423SLionel Sambuc 
2590e78c016SCristiano Giuffrida 	return(OK);
260433d6423SLionel Sambuc }
261433d6423SLionel Sambuc 
init_proc(endpoint_t ep_nr)262433d6423SLionel Sambuc static struct vmproc *init_proc(endpoint_t ep_nr)
263433d6423SLionel Sambuc {
264129adfebSDavid van Moolenbroek 	struct boot_image *ip;
265433d6423SLionel Sambuc 
266433d6423SLionel Sambuc 	for (ip = &kernel_boot_info.boot_procs[0];
267433d6423SLionel Sambuc 		ip < &kernel_boot_info.boot_procs[NR_BOOT_PROCS]; ip++) {
268433d6423SLionel Sambuc 		struct vmproc *vmp;
269433d6423SLionel Sambuc 
270433d6423SLionel Sambuc 		if(ip->proc_nr != ep_nr) continue;
271433d6423SLionel Sambuc 
272433d6423SLionel Sambuc 		if(ip->proc_nr >= _NR_PROCS || ip->proc_nr < 0)
273433d6423SLionel Sambuc 			panic("proc: %d", ip->proc_nr);
274433d6423SLionel Sambuc 
275433d6423SLionel Sambuc 		vmp = &vmproc[ip->proc_nr];
276433d6423SLionel Sambuc 		assert(!(vmp->vm_flags & VMF_INUSE));	/* no double procs */
277433d6423SLionel Sambuc 		clear_proc(vmp);
278433d6423SLionel Sambuc 		vmp->vm_flags = VMF_INUSE;
279433d6423SLionel Sambuc 		vmp->vm_endpoint = ip->endpoint;
280433d6423SLionel Sambuc 		vmp->vm_boot = ip;
281433d6423SLionel Sambuc 
282433d6423SLionel Sambuc 		return vmp;
283433d6423SLionel Sambuc 	}
284433d6423SLionel Sambuc 
285433d6423SLionel Sambuc 	panic("no init_proc");
286433d6423SLionel Sambuc }
287433d6423SLionel Sambuc 
288433d6423SLionel Sambuc struct vm_exec_info {
289433d6423SLionel Sambuc 	struct exec_info execi;
290433d6423SLionel Sambuc 	struct boot_image *ip;
291433d6423SLionel Sambuc 	struct vmproc *vmp;
292433d6423SLionel Sambuc };
293433d6423SLionel Sambuc 
libexec_copy_physcopy(struct exec_info * execi,off_t off,vir_bytes vaddr,size_t len)294433d6423SLionel Sambuc static int libexec_copy_physcopy(struct exec_info *execi,
295433d6423SLionel Sambuc 	off_t off, vir_bytes vaddr, size_t len)
296433d6423SLionel Sambuc {
297433d6423SLionel Sambuc 	vir_bytes end;
298433d6423SLionel Sambuc 	struct vm_exec_info *ei = execi->opaque;
299433d6423SLionel Sambuc 	end = ei->ip->start_addr + ei->ip->len;
300433d6423SLionel Sambuc 	assert(ei->ip->start_addr + off + len <= end);
301433d6423SLionel Sambuc 	return sys_physcopy(NONE, ei->ip->start_addr + off,
302433d6423SLionel Sambuc 		execi->proc_e, vaddr, len, 0);
303433d6423SLionel Sambuc }
304433d6423SLionel Sambuc 
boot_alloc(struct exec_info * execi,off_t vaddr,size_t len,int flags)305433d6423SLionel Sambuc static void boot_alloc(struct exec_info *execi, off_t vaddr,
306433d6423SLionel Sambuc 	size_t len, int flags)
307433d6423SLionel Sambuc {
308433d6423SLionel Sambuc 	struct vmproc *vmp = ((struct vm_exec_info *) execi->opaque)->vmp;
309433d6423SLionel Sambuc 
310433d6423SLionel Sambuc 	if(!(map_page_region(vmp, vaddr, 0, len,
311433d6423SLionel Sambuc 		VR_ANON | VR_WRITABLE | VR_UNINITIALIZED, flags,
312433d6423SLionel Sambuc 		&mem_type_anon))) {
313433d6423SLionel Sambuc 		panic("VM: exec: map_page_region for boot process failed");
314433d6423SLionel Sambuc 	}
315433d6423SLionel Sambuc }
316433d6423SLionel Sambuc 
libexec_alloc_vm_prealloc(struct exec_info * execi,vir_bytes vaddr,size_t len)317433d6423SLionel Sambuc static int libexec_alloc_vm_prealloc(struct exec_info *execi,
318433d6423SLionel Sambuc 	vir_bytes vaddr, size_t len)
319433d6423SLionel Sambuc {
320433d6423SLionel Sambuc 	boot_alloc(execi, vaddr, len, MF_PREALLOC);
321433d6423SLionel Sambuc 	return OK;
322433d6423SLionel Sambuc }
323433d6423SLionel Sambuc 
libexec_alloc_vm_ondemand(struct exec_info * execi,vir_bytes vaddr,size_t len)324433d6423SLionel Sambuc static int libexec_alloc_vm_ondemand(struct exec_info *execi,
325433d6423SLionel Sambuc 	vir_bytes vaddr, size_t len)
326433d6423SLionel Sambuc {
327433d6423SLionel Sambuc 	boot_alloc(execi, vaddr, len, 0);
328433d6423SLionel Sambuc 	return OK;
329433d6423SLionel Sambuc }
330433d6423SLionel Sambuc 
exec_bootproc(struct vmproc * vmp,struct boot_image * ip)331433d6423SLionel Sambuc static void exec_bootproc(struct vmproc *vmp, struct boot_image *ip)
332433d6423SLionel Sambuc {
333433d6423SLionel Sambuc 	struct vm_exec_info vmexeci;
334433d6423SLionel Sambuc 	struct exec_info *execi = &vmexeci.execi;
3355ba2e6e6SDavid van Moolenbroek 	/* libexec need proper alignment for casting to structures */
3365ba2e6e6SDavid van Moolenbroek 	char hdr[VM_PAGE_SIZE] __aligned(8);
337433d6423SLionel Sambuc 
338433d6423SLionel Sambuc 	size_t frame_size = 0;	/* Size of the new initial stack. */
339433d6423SLionel Sambuc 	int argc = 0;		/* Argument count. */
340433d6423SLionel Sambuc 	int envc = 0;		/* Environment count */
341433d6423SLionel Sambuc 	char overflow = 0;	/* No overflow yet. */
342433d6423SLionel Sambuc 	struct ps_strings *psp;
343433d6423SLionel Sambuc 
344433d6423SLionel Sambuc 	int vsp = 0;	/* (virtual) Stack pointer in new address space. */
345433d6423SLionel Sambuc 	char *argv[] = { ip->proc_name, NULL };
346433d6423SLionel Sambuc 	char *envp[] = { NULL };
347433d6423SLionel Sambuc 	char *path = ip->proc_name;
348*65c4b82fSDavid van Moolenbroek 	char frame[VM_PAGE_SIZE] __aligned(sizeof(void *));
349433d6423SLionel Sambuc 
350433d6423SLionel Sambuc 	memset(&vmexeci, 0, sizeof(vmexeci));
351433d6423SLionel Sambuc 
352433d6423SLionel Sambuc 	if(pt_new(&vmp->vm_pt) != OK)
353433d6423SLionel Sambuc 		panic("VM: no new pagetable");
354433d6423SLionel Sambuc 
355433d6423SLionel Sambuc 	if(pt_bind(&vmp->vm_pt, vmp) != OK)
356433d6423SLionel Sambuc 		panic("VM: pt_bind failed");
357433d6423SLionel Sambuc 
358433d6423SLionel Sambuc 	if(sys_physcopy(NONE, ip->start_addr, SELF,
359433d6423SLionel Sambuc 		(vir_bytes) hdr, sizeof(hdr), 0) != OK)
360433d6423SLionel Sambuc 		panic("can't look at boot proc header");
361433d6423SLionel Sambuc 
362433d6423SLionel Sambuc 	execi->stack_high = kernel_boot_info.user_sp;
363433d6423SLionel Sambuc 	execi->stack_size = DEFAULT_STACK_LIMIT;
364433d6423SLionel Sambuc 	execi->proc_e = vmp->vm_endpoint;
365433d6423SLionel Sambuc 	execi->hdr = hdr;
366433d6423SLionel Sambuc 	execi->hdr_len = sizeof(hdr);
367433d6423SLionel Sambuc 	strlcpy(execi->progname, ip->proc_name, sizeof(execi->progname));
368433d6423SLionel Sambuc 	execi->frame_len = 0;
369433d6423SLionel Sambuc 	execi->opaque = &vmexeci;
370433d6423SLionel Sambuc 	execi->filesize = ip->len;
371433d6423SLionel Sambuc 
372433d6423SLionel Sambuc 	vmexeci.ip = ip;
373433d6423SLionel Sambuc 	vmexeci.vmp = vmp;
374433d6423SLionel Sambuc 
375433d6423SLionel Sambuc 	/* callback functions and data */
376433d6423SLionel Sambuc 	execi->copymem = libexec_copy_physcopy;
377433d6423SLionel Sambuc 	execi->clearproc = NULL;
378433d6423SLionel Sambuc 	execi->clearmem = libexec_clear_sys_memset;
379433d6423SLionel Sambuc 	execi->allocmem_prealloc_junk = libexec_alloc_vm_prealloc;
380433d6423SLionel Sambuc 	execi->allocmem_prealloc_cleared = libexec_alloc_vm_prealloc;
381433d6423SLionel Sambuc 	execi->allocmem_ondemand = libexec_alloc_vm_ondemand;
382433d6423SLionel Sambuc 
383433d6423SLionel Sambuc 	if (libexec_load_elf(execi) != OK)
384433d6423SLionel Sambuc 		panic("vm: boot process load of process %s (ep=%d) failed\n",
385433d6423SLionel Sambuc 			execi->progname, vmp->vm_endpoint);
386433d6423SLionel Sambuc 
387433d6423SLionel Sambuc 	/* Setup a minimal stack. */
388433d6423SLionel Sambuc 	minix_stack_params(path, argv, envp, &frame_size, &overflow, &argc,
389433d6423SLionel Sambuc 		&envc);
390433d6423SLionel Sambuc 
391433d6423SLionel Sambuc 	/* The party is off if there is an overflow, or it is too big for our
392433d6423SLionel Sambuc 	 * pre-allocated space. */
393433d6423SLionel Sambuc 	if(overflow || frame_size > sizeof(frame))
394433d6423SLionel Sambuc 		panic("vm: could not alloc stack for boot process %s (ep=%d)\n",
395433d6423SLionel Sambuc 			execi->progname, vmp->vm_endpoint);
396433d6423SLionel Sambuc 
397433d6423SLionel Sambuc 	minix_stack_fill(path, argc, argv, envc, envp, frame_size, frame, &vsp,
398433d6423SLionel Sambuc 		&psp);
399433d6423SLionel Sambuc 
400433d6423SLionel Sambuc 	if(handle_memory_once(vmp, vsp, frame_size, 1) != OK)
401433d6423SLionel Sambuc 		panic("vm: could not map stack for boot process %s (ep=%d)\n",
402433d6423SLionel Sambuc 			execi->progname, vmp->vm_endpoint);
403433d6423SLionel Sambuc 
404433d6423SLionel Sambuc 	if(sys_datacopy(SELF, (vir_bytes)frame, vmp->vm_endpoint, vsp, frame_size) != OK)
405433d6423SLionel Sambuc 		panic("vm: could not copy stack for boot process %s (ep=%d)\n",
406433d6423SLionel Sambuc 			execi->progname, vmp->vm_endpoint);
407433d6423SLionel Sambuc 
408433d6423SLionel Sambuc 	if(sys_exec(vmp->vm_endpoint, (vir_bytes)vsp,
409433d6423SLionel Sambuc 		   (vir_bytes)execi->progname, execi->pc,
410433d6423SLionel Sambuc 		   vsp + ((int)psp - (int)frame)) != OK)
411433d6423SLionel Sambuc 		panic("vm: boot process exec of process %s (ep=%d) failed\n",
412433d6423SLionel Sambuc 			execi->progname,vmp->vm_endpoint);
413433d6423SLionel Sambuc 
414433d6423SLionel Sambuc 	/* make it runnable */
415433d6423SLionel Sambuc 	if(sys_vmctl(vmp->vm_endpoint, VMCTL_BOOTINHIBIT_CLEAR, 0) != OK)
416433d6423SLionel Sambuc 		panic("VMCTL_BOOTINHIBIT_CLEAR failed");
417433d6423SLionel Sambuc }
418433d6423SLionel Sambuc 
do_procctl_notrans(message * msg)419433d6423SLionel Sambuc static int do_procctl_notrans(message *msg)
420433d6423SLionel Sambuc {
421433d6423SLionel Sambuc 	int transid = 0;
422433d6423SLionel Sambuc 
423433d6423SLionel Sambuc 	assert(!IS_VFS_FS_TRANSID(transid));
424433d6423SLionel Sambuc 
425433d6423SLionel Sambuc 	return do_procctl(msg, transid);
426433d6423SLionel Sambuc }
427433d6423SLionel Sambuc 
init_vm(void)428433d6423SLionel Sambuc void init_vm(void)
429433d6423SLionel Sambuc {
430433d6423SLionel Sambuc 	int s, i;
431433d6423SLionel Sambuc 	static struct memory mem_chunks[NR_MEMS];
432129adfebSDavid van Moolenbroek 	struct boot_image *ip;
433433d6423SLionel Sambuc 	extern void __minix_init(void);
434433d6423SLionel Sambuc 	multiboot_module_t *mod;
435433d6423SLionel Sambuc 	vir_bytes kern_dyn, kern_static;
436433d6423SLionel Sambuc 
437433d6423SLionel Sambuc #if SANITYCHECKS
438433d6423SLionel Sambuc 	incheck = nocheck = 0;
439433d6423SLionel Sambuc #endif
440433d6423SLionel Sambuc 
441433d6423SLionel Sambuc 	/* Retrieve various crucial boot parameters */
442433d6423SLionel Sambuc 	if(OK != (s=sys_getkinfo(&kernel_boot_info))) {
443433d6423SLionel Sambuc 		panic("couldn't get bootinfo: %d", s);
444433d6423SLionel Sambuc 	}
445433d6423SLionel Sambuc 
446433d6423SLionel Sambuc 	/* Turn file mmap on? */
447433d6423SLionel Sambuc 	enable_filemap=1;	/* yes by default */
448433d6423SLionel Sambuc 	env_parse("filemap", "d", 0, &enable_filemap, 0, 1);
449433d6423SLionel Sambuc 
450433d6423SLionel Sambuc 	/* Sanity check */
451433d6423SLionel Sambuc 	assert(kernel_boot_info.mmap_size > 0);
452433d6423SLionel Sambuc 	assert(kernel_boot_info.mods_with_kernel > 0);
453433d6423SLionel Sambuc 
454433d6423SLionel Sambuc 	/* Get chunks of available memory. */
455433d6423SLionel Sambuc 	get_mem_chunks(mem_chunks);
456433d6423SLionel Sambuc 
457433d6423SLionel Sambuc 	/* Set table to 0. This invalidates all slots (clear VMF_INUSE). */
458433d6423SLionel Sambuc 	memset(vmproc, 0, sizeof(vmproc));
459433d6423SLionel Sambuc 
460433d6423SLionel Sambuc 	for(i = 0; i < ELEMENTS(vmproc); i++) {
461433d6423SLionel Sambuc 		vmproc[i].vm_slot = i;
462433d6423SLionel Sambuc 	}
463433d6423SLionel Sambuc 
464433d6423SLionel Sambuc 	/* Initialize ACL data structures. */
465433d6423SLionel Sambuc 	acl_init();
466433d6423SLionel Sambuc 
467433d6423SLionel Sambuc 	/* region management initialization. */
468433d6423SLionel Sambuc 	map_region_init();
469433d6423SLionel Sambuc 
470433d6423SLionel Sambuc 	/* Initialize tables to all physical memory. */
471433d6423SLionel Sambuc 	mem_init(mem_chunks);
472433d6423SLionel Sambuc 
473433d6423SLionel Sambuc 	/* Architecture-dependent initialization. */
474433d6423SLionel Sambuc 	init_proc(VM_PROC_NR);
475433d6423SLionel Sambuc 	pt_init();
476433d6423SLionel Sambuc 
477433d6423SLionel Sambuc 	/* Acquire kernel ipc vectors that weren't available
478433d6423SLionel Sambuc 	 * before VM had determined kernel mappings
479433d6423SLionel Sambuc 	 */
480433d6423SLionel Sambuc 	__minix_init();
481433d6423SLionel Sambuc 
482433d6423SLionel Sambuc 	/* The kernel's freelist does not include boot-time modules; let
483433d6423SLionel Sambuc 	 * the allocator know that the total memory is bigger.
484433d6423SLionel Sambuc 	 */
485433d6423SLionel Sambuc 	for (mod = &kernel_boot_info.module_list[0];
486433d6423SLionel Sambuc 		mod < &kernel_boot_info.module_list[kernel_boot_info.mods_with_kernel-1]; mod++) {
487433d6423SLionel Sambuc 		phys_bytes len = mod->mod_end-mod->mod_start+1;
488433d6423SLionel Sambuc 		len = roundup(len, VM_PAGE_SIZE);
489433d6423SLionel Sambuc 		mem_add_total_pages(len/VM_PAGE_SIZE);
490433d6423SLionel Sambuc 	}
491433d6423SLionel Sambuc 
492433d6423SLionel Sambuc 	kern_dyn = kernel_boot_info.kernel_allocated_bytes_dynamic;
493433d6423SLionel Sambuc 	kern_static = kernel_boot_info.kernel_allocated_bytes;
494433d6423SLionel Sambuc 	kern_static = roundup(kern_static, VM_PAGE_SIZE);
495433d6423SLionel Sambuc 	mem_add_total_pages((kern_dyn + kern_static)/VM_PAGE_SIZE);
496433d6423SLionel Sambuc 
497433d6423SLionel Sambuc 	/* Give these processes their own page table. */
498433d6423SLionel Sambuc 	for (ip = &kernel_boot_info.boot_procs[0];
499433d6423SLionel Sambuc 		ip < &kernel_boot_info.boot_procs[NR_BOOT_PROCS]; ip++) {
500433d6423SLionel Sambuc 		struct vmproc *vmp;
501433d6423SLionel Sambuc 
502433d6423SLionel Sambuc 		if(ip->proc_nr < 0) continue;
503433d6423SLionel Sambuc 
504433d6423SLionel Sambuc 		assert(ip->start_addr);
505433d6423SLionel Sambuc 
506433d6423SLionel Sambuc 		/* VM has already been set up by the kernel and pt_init().
507433d6423SLionel Sambuc 		 * Any other boot process is already in memory and is set up
508433d6423SLionel Sambuc 		 * here.
509433d6423SLionel Sambuc 		 */
510433d6423SLionel Sambuc 		if(ip->proc_nr == VM_PROC_NR) continue;
511433d6423SLionel Sambuc 
512433d6423SLionel Sambuc 		vmp = init_proc(ip->proc_nr);
513433d6423SLionel Sambuc 
514433d6423SLionel Sambuc 		exec_bootproc(vmp, ip);
515433d6423SLionel Sambuc 
516433d6423SLionel Sambuc 		/* Free the file blob */
517433d6423SLionel Sambuc 		assert(!(ip->start_addr % VM_PAGE_SIZE));
518433d6423SLionel Sambuc 		ip->len = roundup(ip->len, VM_PAGE_SIZE);
519433d6423SLionel Sambuc 		free_mem(ABS2CLICK(ip->start_addr), ABS2CLICK(ip->len));
520433d6423SLionel Sambuc 	}
521433d6423SLionel Sambuc 
522433d6423SLionel Sambuc 	/* Set up table of calls. */
523433d6423SLionel Sambuc #define CALLMAP(code, func) { int _cmi;		      \
524433d6423SLionel Sambuc 	_cmi=CALLNUMBER(code);				\
525433d6423SLionel Sambuc 	assert(_cmi >= 0);					\
526433d6423SLionel Sambuc 	assert(_cmi < NR_VM_CALLS);		\
527433d6423SLionel Sambuc 	vm_calls[_cmi].vmc_func = (func); 	      \
528433d6423SLionel Sambuc 	vm_calls[_cmi].vmc_name = #code;	      \
529433d6423SLionel Sambuc }
530433d6423SLionel Sambuc 
531433d6423SLionel Sambuc 	/* Set call table to 0. This invalidates all calls (clear
532433d6423SLionel Sambuc 	 * vmc_func).
533433d6423SLionel Sambuc 	 */
534433d6423SLionel Sambuc 	memset(vm_calls, 0, sizeof(vm_calls));
535433d6423SLionel Sambuc 
536433d6423SLionel Sambuc 	/* Basic VM calls. */
537433d6423SLionel Sambuc 	CALLMAP(VM_MMAP, do_mmap);
538433d6423SLionel Sambuc 	CALLMAP(VM_MUNMAP, do_munmap);
539433d6423SLionel Sambuc 	CALLMAP(VM_MAP_PHYS, do_map_phys);
540433d6423SLionel Sambuc 	CALLMAP(VM_UNMAP_PHYS, do_munmap);
541433d6423SLionel Sambuc 
542433d6423SLionel Sambuc 	/* Calls from PM. */
543433d6423SLionel Sambuc 	CALLMAP(VM_EXIT, do_exit);
544433d6423SLionel Sambuc 	CALLMAP(VM_FORK, do_fork);
545433d6423SLionel Sambuc 	CALLMAP(VM_BRK, do_brk);
546433d6423SLionel Sambuc 	CALLMAP(VM_WILLEXIT, do_willexit);
547433d6423SLionel Sambuc 
548433d6423SLionel Sambuc 	CALLMAP(VM_PROCCTL, do_procctl_notrans);
549433d6423SLionel Sambuc 
550433d6423SLionel Sambuc 	/* Calls from VFS. */
551433d6423SLionel Sambuc 	CALLMAP(VM_VFS_REPLY, do_vfs_reply);
552433d6423SLionel Sambuc 	CALLMAP(VM_VFS_MMAP, do_vfs_mmap);
553433d6423SLionel Sambuc 
554433d6423SLionel Sambuc 	/* Calls from RS */
555433d6423SLionel Sambuc 	CALLMAP(VM_RS_SET_PRIV, do_rs_set_priv);
556abf8a7e7SDavid van Moolenbroek 	CALLMAP(VM_RS_PREPARE, do_rs_prepare);
557433d6423SLionel Sambuc 	CALLMAP(VM_RS_UPDATE, do_rs_update);
558433d6423SLionel Sambuc 	CALLMAP(VM_RS_MEMCTL, do_rs_memctl);
559433d6423SLionel Sambuc 
560433d6423SLionel Sambuc 	/* Generic calls. */
561433d6423SLionel Sambuc 	CALLMAP(VM_REMAP, do_remap);
562433d6423SLionel Sambuc 	CALLMAP(VM_REMAP_RO, do_remap);
563433d6423SLionel Sambuc 	CALLMAP(VM_GETPHYS, do_get_phys);
564433d6423SLionel Sambuc 	CALLMAP(VM_SHM_UNMAP, do_munmap);
565433d6423SLionel Sambuc 	CALLMAP(VM_GETREF, do_get_refcount);
566433d6423SLionel Sambuc 	CALLMAP(VM_INFO, do_info);
567433d6423SLionel Sambuc 
568433d6423SLionel Sambuc 	/* Cache blocks. */
569433d6423SLionel Sambuc 	CALLMAP(VM_MAPCACHEPAGE, do_mapcache);
570433d6423SLionel Sambuc 	CALLMAP(VM_SETCACHEPAGE, do_setcache);
571e94f856bSDavid van Moolenbroek 	CALLMAP(VM_FORGETCACHEPAGE, do_forgetcache);
572433d6423SLionel Sambuc 	CALLMAP(VM_CLEARCACHE, do_clearcache);
573433d6423SLionel Sambuc 
574433d6423SLionel Sambuc 	/* getrusage */
575433d6423SLionel Sambuc 	CALLMAP(VM_GETRUSAGE, do_getrusage);
576433d6423SLionel Sambuc 
57763483e02SCristiano Giuffrida 	/* Mark VM instances. */
57863483e02SCristiano Giuffrida 	num_vm_instances = 1;
57963483e02SCristiano Giuffrida 	vmproc[VM_PROC_NR].vm_flags |= VMF_VM_INSTANCE;
580162b8995SCristiano Giuffrida 
581162b8995SCristiano Giuffrida 	/* Let SEF know about VM mmapped regions. */
582162b8995SCristiano Giuffrida 	s = sef_llvm_add_special_mem_region((void*)VM_OWN_HEAPBASE,
583162b8995SCristiano Giuffrida 	    VM_OWN_MMAPTOP-VM_OWN_HEAPBASE, "%MMAP_ALL");
584162b8995SCristiano Giuffrida 	if(s < 0) {
585162b8995SCristiano Giuffrida 	    printf("VM: st_add_special_mmapped_region failed %d\n", s);
586162b8995SCristiano Giuffrida 	}
587433d6423SLionel Sambuc }
588433d6423SLionel Sambuc 
589433d6423SLionel Sambuc /*===========================================================================*
5900e78c016SCristiano Giuffrida  *			      sef_cb_init_vm_multi_lu			     *
5910e78c016SCristiano Giuffrida  *===========================================================================*/
sef_cb_init_vm_multi_lu(int type,sef_init_info_t * info)5920e78c016SCristiano Giuffrida static int sef_cb_init_vm_multi_lu(int type, sef_init_info_t *info)
5930e78c016SCristiano Giuffrida {
5940e78c016SCristiano Giuffrida 	message m;
5950e78c016SCristiano Giuffrida 	int i, r;
5960e78c016SCristiano Giuffrida 	ipc_filter_el_t ipc_filter[IPCF_MAX_ELEMENTS];
5970e78c016SCristiano Giuffrida 	int num_elements;
5980e78c016SCristiano Giuffrida 
5990e78c016SCristiano Giuffrida 	if(type != SEF_INIT_LU || !(info->flags & SEF_LU_MULTI)) {
6000e78c016SCristiano Giuffrida 	    return OK;
6010e78c016SCristiano Giuffrida 	}
6020e78c016SCristiano Giuffrida 
6030e78c016SCristiano Giuffrida 	/* If this is a multi-component update, we need to perform the update
6040e78c016SCristiano Giuffrida 	 * for services that need to be updated. In addition, make sure VM
6050e78c016SCristiano Giuffrida 	 * can only receive messages from RS, tasks, and other services being
6060e78c016SCristiano Giuffrida 	 * updated until RS specifically sends a special update cancel message.
6070e78c016SCristiano Giuffrida 	 * This is necessary to limit the number of VM state changes to support
6080e78c016SCristiano Giuffrida 	 * rollback. Allow only safe message types for safe updates.
6090e78c016SCristiano Giuffrida 	 */
6100e78c016SCristiano Giuffrida 	memset(ipc_filter, 0, sizeof(ipc_filter));
6110e78c016SCristiano Giuffrida 	num_elements = 0;
6120e78c016SCristiano Giuffrida 	ipc_filter[num_elements].flags = IPCF_MATCH_M_SOURCE;
6130e78c016SCristiano Giuffrida 	ipc_filter[num_elements++].m_source = RS_PROC_NR;
6140e78c016SCristiano Giuffrida 	if((r = sys_safecopyfrom(RS_PROC_NR, info->rproctab_gid, 0,
6150e78c016SCristiano Giuffrida 	    (vir_bytes) rprocpub, NR_SYS_PROCS*sizeof(struct rprocpub))) != OK) {
6160e78c016SCristiano Giuffrida 	    panic("sys_safecopyfrom failed: %d", r);
6170e78c016SCristiano Giuffrida 	}
6180e78c016SCristiano Giuffrida 	m.m_source = VM_PROC_NR;
6190e78c016SCristiano Giuffrida 	for(i=0;i < NR_SYS_PROCS;i++) {
6200e78c016SCristiano Giuffrida 	    if(rprocpub[i].in_use && rprocpub[i].old_endpoint != NONE) {
6212867e60aSDavid van Moolenbroek 	        if(num_elements <= IPCF_MAX_ELEMENTS-5) {
6222867e60aSDavid van Moolenbroek                     /* VM_BRK is needed for normal operation during the live
6232867e60aSDavid van Moolenbroek                      * update.  VM_INFO is needed for state transfer in the
6242867e60aSDavid van Moolenbroek                      * light of holes.  Pagefaults and handle-memory requests
6252867e60aSDavid van Moolenbroek                      * are blocked intentionally, as handling these would
6262867e60aSDavid van Moolenbroek                      * prevent VM from being able to roll back.
6272867e60aSDavid van Moolenbroek                      */
628c0df94ecSDavid van Moolenbroek 	            ipc_filter[num_elements].flags = IPCF_MATCH_M_SOURCE | IPCF_MATCH_M_TYPE;
6290e78c016SCristiano Giuffrida 	            ipc_filter[num_elements].m_source = rprocpub[i].old_endpoint;
630c0df94ecSDavid van Moolenbroek 	            ipc_filter[num_elements++].m_type = VM_BRK;
631c0df94ecSDavid van Moolenbroek 	            ipc_filter[num_elements].flags = IPCF_MATCH_M_SOURCE | IPCF_MATCH_M_TYPE;
6320e78c016SCristiano Giuffrida 	            ipc_filter[num_elements].m_source = rprocpub[i].new_endpoint;
633c0df94ecSDavid van Moolenbroek 	            ipc_filter[num_elements++].m_type = VM_BRK;
6342867e60aSDavid van Moolenbroek 	            ipc_filter[num_elements].flags = IPCF_MATCH_M_SOURCE | IPCF_MATCH_M_TYPE;
6352867e60aSDavid van Moolenbroek 	            ipc_filter[num_elements].m_source = rprocpub[i].old_endpoint;
6362867e60aSDavid van Moolenbroek 	            ipc_filter[num_elements++].m_type = VM_INFO;
6372867e60aSDavid van Moolenbroek 	            ipc_filter[num_elements].flags = IPCF_MATCH_M_SOURCE | IPCF_MATCH_M_TYPE;
6382867e60aSDavid van Moolenbroek 	            ipc_filter[num_elements].m_source = rprocpub[i].new_endpoint;
6392867e60aSDavid van Moolenbroek 	            ipc_filter[num_elements++].m_type = VM_INFO;
6400e78c016SCristiano Giuffrida 	            /* Make sure we can talk to any RS instance. */
6410e78c016SCristiano Giuffrida 	            if(rprocpub[i].old_endpoint == RS_PROC_NR) {
6420e78c016SCristiano Giuffrida 	                ipc_filter[num_elements].flags = IPCF_MATCH_M_SOURCE;
6430e78c016SCristiano Giuffrida 	                ipc_filter[num_elements++].m_source = rprocpub[i].new_endpoint;
6440e78c016SCristiano Giuffrida 	            }
6450e78c016SCristiano Giuffrida 	            else if(rprocpub[i].new_endpoint == RS_PROC_NR) {
6460e78c016SCristiano Giuffrida 	                ipc_filter[num_elements].flags = IPCF_MATCH_M_SOURCE;
6470e78c016SCristiano Giuffrida 	                ipc_filter[num_elements++].m_source = rprocpub[i].old_endpoint;
6480e78c016SCristiano Giuffrida 	            }
6490e78c016SCristiano Giuffrida 	        }
6500e78c016SCristiano Giuffrida 	        else {
6510e78c016SCristiano Giuffrida 	            printf("sef_cb_init_vm_multi_lu: skipping ipc filter elements for %d and %d\n",
6520e78c016SCristiano Giuffrida 	                rprocpub[i].old_endpoint, rprocpub[i].new_endpoint);
6530e78c016SCristiano Giuffrida 	        }
6540e78c016SCristiano Giuffrida 	        if(rprocpub[i].sys_flags & SF_VM_UPDATE) {
6550e78c016SCristiano Giuffrida 	            m.m_lsys_vm_update.src = rprocpub[i].new_endpoint;
6560e78c016SCristiano Giuffrida 	            m.m_lsys_vm_update.dst = rprocpub[i].old_endpoint;
6570e78c016SCristiano Giuffrida 	            m.m_lsys_vm_update.flags = rprocpub[i].sys_flags;
6580e78c016SCristiano Giuffrida 	            r = do_rs_update(&m);
6590e78c016SCristiano Giuffrida 	            if(r != OK && r != SUSPEND) {
6600e78c016SCristiano Giuffrida 	                printf("sef_cb_init_vm_multi_lu: do_rs_update failed: %d", r);
6610e78c016SCristiano Giuffrida 	            }
6620e78c016SCristiano Giuffrida 	        }
6630e78c016SCristiano Giuffrida 	    }
6640e78c016SCristiano Giuffrida 	}
6650e78c016SCristiano Giuffrida 
6660e78c016SCristiano Giuffrida 	r = sys_statectl(SYS_STATE_ADD_IPC_WL_FILTER, ipc_filter, num_elements*sizeof(ipc_filter_el_t));
6670e78c016SCristiano Giuffrida 	if(r != OK) {
6680e78c016SCristiano Giuffrida 	    printf("sef_cb_init_vm_multi_lu: sys_statectl failed: %d", r);
6690e78c016SCristiano Giuffrida 	}
6700e78c016SCristiano Giuffrida 
6710e78c016SCristiano Giuffrida 	return OK;
6720e78c016SCristiano Giuffrida }
6730e78c016SCristiano Giuffrida 
6740e78c016SCristiano Giuffrida /*===========================================================================*
6750e78c016SCristiano Giuffrida  *			     sef_cb_init_lu_restart			     *
6760e78c016SCristiano Giuffrida  *===========================================================================*/
sef_cb_init_lu_restart(int type,sef_init_info_t * info)6770e78c016SCristiano Giuffrida static int sef_cb_init_lu_restart(int type, sef_init_info_t *info)
6780e78c016SCristiano Giuffrida {
6790e78c016SCristiano Giuffrida /* Restart the vm server. */
6800e78c016SCristiano Giuffrida         int r;
6810e78c016SCristiano Giuffrida         endpoint_t old_e;
6820e78c016SCristiano Giuffrida         int old_p;
6830e78c016SCristiano Giuffrida         struct vmproc *old_vmp, *new_vmp;
6840e78c016SCristiano Giuffrida 
6853f82ac6aSCristiano Giuffrida         /* Perform default state transfer first. */
6860e78c016SCristiano Giuffrida         if(type == SEF_INIT_LU) {
6873f82ac6aSCristiano Giuffrida 		sef_setcb_init_restart(SEF_CB_INIT_RESTART_STATEFUL);
6880e78c016SCristiano Giuffrida 		r = SEF_CB_INIT_LU_DEFAULT(type, info);
6890e78c016SCristiano Giuffrida         }
6900e78c016SCristiano Giuffrida         else {
6913f82ac6aSCristiano Giuffrida 		r = SEF_CB_INIT_RESTART_STATEFUL(type, info);
6920e78c016SCristiano Giuffrida         }
6930e78c016SCristiano Giuffrida         if(r != OK) {
6940e78c016SCristiano Giuffrida 		return r;
6950e78c016SCristiano Giuffrida         }
6960e78c016SCristiano Giuffrida 
6970e78c016SCristiano Giuffrida 	/* Lookup slots for old process. */
6980e78c016SCristiano Giuffrida 	old_e = info->old_endpoint;
6990e78c016SCristiano Giuffrida 	if(vm_isokendpt(old_e, &old_p) != OK) {
7000e78c016SCristiano Giuffrida 		printf("sef_cb_init_lu_restart: bad old endpoint %d\n", old_e);
7010e78c016SCristiano Giuffrida 		return EINVAL;
7020e78c016SCristiano Giuffrida 	}
7030e78c016SCristiano Giuffrida 	old_vmp = &vmproc[old_p];
7040e78c016SCristiano Giuffrida 	new_vmp = &vmproc[VM_PROC_NR];
7050e78c016SCristiano Giuffrida 
7060e78c016SCristiano Giuffrida 	/* Swap proc slots and dynamic data. */
7070e78c016SCristiano Giuffrida 	if((r = swap_proc_slot(old_vmp, new_vmp)) != OK) {
7080e78c016SCristiano Giuffrida 		printf("sef_cb_init_lu_restart: swap_proc_slot failed\n");
7090e78c016SCristiano Giuffrida 		return r;
7100e78c016SCristiano Giuffrida 	}
7110e78c016SCristiano Giuffrida         if((r = swap_proc_dyn_data(old_vmp, new_vmp, 0)) != OK) {
7120e78c016SCristiano Giuffrida 		printf("sef_cb_init_lu_restart: swap_proc_dyn_data failed\n");
7130e78c016SCristiano Giuffrida 		return r;
7140e78c016SCristiano Giuffrida 	}
7150e78c016SCristiano Giuffrida 
7160e78c016SCristiano Giuffrida 	/* Rebind page tables. */
7170e78c016SCristiano Giuffrida 	pt_bind(&new_vmp->vm_pt, new_vmp);
7180e78c016SCristiano Giuffrida 	pt_bind(&old_vmp->vm_pt, old_vmp);
7190e78c016SCristiano Giuffrida 	pt_clearmapcache();
7200e78c016SCristiano Giuffrida 
7210e78c016SCristiano Giuffrida 	/* Adjust process references. */
7220e78c016SCristiano Giuffrida 	adjust_proc_refs();
7230e78c016SCristiano Giuffrida 
7240e78c016SCristiano Giuffrida 	/* Handle multi-component live update when necessary. */
7250e78c016SCristiano Giuffrida 	return sef_cb_init_vm_multi_lu(type, info);
7260e78c016SCristiano Giuffrida }
7270e78c016SCristiano Giuffrida 
7280e78c016SCristiano Giuffrida /*===========================================================================*
729433d6423SLionel Sambuc  *                         sef_cb_signal_handler                             *
730433d6423SLionel Sambuc  *===========================================================================*/
sef_cb_signal_handler(int signo)731433d6423SLionel Sambuc static void sef_cb_signal_handler(int signo)
732433d6423SLionel Sambuc {
733433d6423SLionel Sambuc 	/* Check for known kernel signals, ignore anything else. */
734433d6423SLionel Sambuc 	switch(signo) {
735433d6423SLionel Sambuc 		/* There is a pending memory request from the kernel. */
736433d6423SLionel Sambuc 		case SIGKMEM:
737433d6423SLionel Sambuc 			do_memory();
738433d6423SLionel Sambuc 		break;
739433d6423SLionel Sambuc 	}
740433d6423SLionel Sambuc 
741433d6423SLionel Sambuc 	/* It can happen that we get stuck receiving signals
742433d6423SLionel Sambuc 	 * without sef_receive() returning. We could need more memory
743433d6423SLionel Sambuc 	 * though.
744433d6423SLionel Sambuc 	 */
745433d6423SLionel Sambuc 	if(missing_spares > 0) {
746433d6423SLionel Sambuc 		alloc_cycle();	/* pagetable code wants to be called */
747433d6423SLionel Sambuc 	}
748433d6423SLionel Sambuc 
749433d6423SLionel Sambuc 	pt_clearmapcache();
750433d6423SLionel Sambuc }
751433d6423SLionel Sambuc 
752433d6423SLionel Sambuc /*===========================================================================*
753433d6423SLionel Sambuc  *                             map_service                                   *
754433d6423SLionel Sambuc  *===========================================================================*/
map_service(struct rprocpub * rpub)755433d6423SLionel Sambuc static int map_service(struct rprocpub *rpub)
756433d6423SLionel Sambuc {
757433d6423SLionel Sambuc /* Map a new service by initializing its call mask. */
758433d6423SLionel Sambuc 	int r, proc_nr;
759433d6423SLionel Sambuc 
760433d6423SLionel Sambuc 	if ((r = vm_isokendpt(rpub->endpoint, &proc_nr)) != OK) {
761433d6423SLionel Sambuc 		return r;
762433d6423SLionel Sambuc 	}
763433d6423SLionel Sambuc 
764433d6423SLionel Sambuc 	/* Copy the call mask. */
765433d6423SLionel Sambuc 	acl_set(&vmproc[proc_nr], rpub->vm_call_mask, !IS_RPUB_BOOT_USR(rpub));
766433d6423SLionel Sambuc 
767433d6423SLionel Sambuc 	return(OK);
768433d6423SLionel Sambuc }
769