1 2 #define _SYSTEM 1 3 4 #include <minix/callnr.h> 5 #include <minix/com.h> 6 #include <minix/config.h> 7 #include <minix/const.h> 8 #include <minix/ds.h> 9 #include <minix/endpoint.h> 10 #include <minix/minlib.h> 11 #include <minix/type.h> 12 #include <minix/ipc.h> 13 #include <minix/sysutil.h> 14 #include <minix/syslib.h> 15 #include <minix/const.h> 16 #include <minix/bitmap.h> 17 #include <minix/rs.h> 18 #include <minix/vfsif.h> 19 20 #include <sys/exec.h> 21 22 #include <libexec.h> 23 #include <ctype.h> 24 #include <errno.h> 25 #include <string.h> 26 #include <env.h> 27 #include <stdio.h> 28 #include <assert.h> 29 30 #define _MAIN 1 31 #include "glo.h" 32 #include "proto.h" 33 #include "util.h" 34 #include "vm.h" 35 #include "sanitycheck.h" 36 37 extern int missing_spares; 38 39 #include <machine/archtypes.h> 40 #include <sys/param.h> 41 #include "kernel/const.h" 42 #include "kernel/config.h" 43 #include "kernel/proc.h" 44 45 #include <signal.h> 46 #include <lib.h> 47 48 /* Table of calls and a macro to test for being in range. */ 49 struct { 50 int (*vmc_func)(message *); /* Call handles message. */ 51 const char *vmc_name; /* Human-readable string. */ 52 } vm_calls[NR_VM_CALLS]; 53 54 /* Macro to verify call range and map 'high' range to 'base' range 55 * (starting at 0) in one. Evaluates to zero-based call number if call 56 * number is valid, returns -1 otherwise. 57 */ 58 #define CALLNUMBER(c) (((c) >= VM_RQ_BASE && \ 59 (c) < VM_RQ_BASE + ELEMENTS(vm_calls)) ? \ 60 ((c) - VM_RQ_BASE) : -1) 61 62 static int map_service(struct rprocpub *rpub); 63 64 static struct rprocpub rprocpub[NR_SYS_PROCS]; 65 int __vm_init_fresh; 66 67 /* SEF functions and variables. */ 68 static void sef_local_startup(void); 69 static int sef_cb_init_lu_restart(int type, sef_init_info_t *info); 70 static int sef_cb_init_fresh(int type, sef_init_info_t *info); 71 static void sef_cb_signal_handler(int signo); 72 73 void init_vm(void); 74 75 int do_sef_init_request(message *); 76 77 /*===========================================================================* 78 * is_first_time * 79 *===========================================================================*/ 80 static int is_first_time(void) 81 { 82 struct proc rs_proc; 83 int r; 84 85 if ((r = sys_getproc(&rs_proc, RS_PROC_NR)) != OK) 86 panic("VM: couldn't get RS process data: %d", r); 87 88 return RTS_ISSET(&rs_proc, RTS_BOOTINHIBIT); 89 } 90 91 /*===========================================================================* 92 * main * 93 *===========================================================================*/ 94 int main(void) 95 { 96 message msg; 97 int result, who_e, rcv_sts; 98 int caller_slot; 99 100 /* Initialize system so that all processes are runnable the first time. */ 101 if (is_first_time()) { 102 init_vm(); 103 __vm_init_fresh=1; 104 } 105 106 /* SEF local startup. */ 107 sef_local_startup(); 108 __vm_init_fresh=0; 109 110 SANITYCHECK(SCL_TOP); 111 112 /* This is VM's main loop. */ 113 while (TRUE) { 114 int r, c; 115 int type; 116 int transid = 0; /* VFS transid if any */ 117 118 SANITYCHECK(SCL_TOP); 119 if(missing_spares > 0) { 120 alloc_cycle(); /* mem alloc code wants to be called */ 121 } 122 123 if ((r=sef_receive_status(ANY, &msg, &rcv_sts)) != OK) 124 panic("sef_receive_status() error: %d", r); 125 126 if (is_ipc_notify(rcv_sts)) { 127 /* Unexpected ipc_notify(). */ 128 printf("VM: ignoring ipc_notify() from %d\n", msg.m_source); 129 continue; 130 } 131 who_e = msg.m_source; 132 if(vm_isokendpt(who_e, &caller_slot) != OK) 133 panic("invalid caller %d", who_e); 134 135 /* We depend on this being false for the initialized value. */ 136 assert(!IS_VFS_FS_TRANSID(transid)); 137 138 type = msg.m_type; 139 c = CALLNUMBER(type); 140 result = ENOSYS; /* Out of range or restricted calls return this. */ 141 142 transid = TRNS_GET_ID(msg.m_type); 143 144 if((msg.m_source == VFS_PROC_NR) && IS_VFS_FS_TRANSID(transid)) { 145 /* If it's a request from VFS, it might have a transaction id. */ 146 msg.m_type = TRNS_DEL_ID(msg.m_type); 147 148 /* Calls that use the transid */ 149 result = do_procctl(&msg, transid); 150 } else if(msg.m_type == RS_INIT && msg.m_source == RS_PROC_NR) { 151 result = do_sef_init_request(&msg); 152 if(result != OK) panic("do_sef_init_request failed!\n"); 153 result = SUSPEND; /* do not reply to RS */ 154 } else if (msg.m_type == VM_PAGEFAULT) { 155 if (!IPC_STATUS_FLAGS_TEST(rcv_sts, IPC_FLG_MSG_FROM_KERNEL)) { 156 printf("VM: process %d faked VM_PAGEFAULT " 157 "message!\n", msg.m_source); 158 } 159 do_pagefaults(&msg); 160 /* 161 * do not reply to this call, the caller is unblocked by 162 * a sys_vmctl() call in do_pagefaults if success. VM panics 163 * otherwise 164 */ 165 continue; 166 } else if(c < 0 || !vm_calls[c].vmc_func) { 167 /* out of range or missing callnr */ 168 } else { 169 if (acl_check(&vmproc[caller_slot], c) != OK) { 170 printf("VM: unauthorized %s by %d\n", 171 vm_calls[c].vmc_name, who_e); 172 } else { 173 SANITYCHECK(SCL_FUNCTIONS); 174 result = vm_calls[c].vmc_func(&msg); 175 SANITYCHECK(SCL_FUNCTIONS); 176 } 177 } 178 179 /* Send reply message, unless the return code is SUSPEND, 180 * which is a pseudo-result suppressing the reply message. 181 */ 182 if(result != SUSPEND) { 183 msg.m_type = result; 184 185 assert(!IS_VFS_FS_TRANSID(transid)); 186 187 if((r=ipc_send(who_e, &msg)) != OK) { 188 printf("VM: couldn't send %d to %d (err %d)\n", 189 msg.m_type, who_e, r); 190 panic("ipc_send() error"); 191 } 192 } 193 } 194 return(OK); 195 } 196 197 static void sef_local_startup(void) 198 { 199 /* Register init callbacks. */ 200 sef_setcb_init_fresh(sef_cb_init_fresh); 201 sef_setcb_init_lu(sef_cb_init_lu_restart); 202 sef_setcb_init_restart(sef_cb_init_lu_restart); 203 /* In order to avoid a deadlock at boot time, send the first RS_INIT 204 * reply to RS asynchronously. After that, use sendrec as usual. 205 */ 206 if (__vm_init_fresh) 207 sef_setcb_init_response(sef_cb_init_response_rs_asyn_once); 208 209 /* Register signal callbacks. */ 210 sef_setcb_signal_handler(sef_cb_signal_handler); 211 212 /* Let SEF perform startup. */ 213 sef_startup(); 214 } 215 216 static int sef_cb_init_fresh(int type, sef_init_info_t *info) 217 { 218 int s, i; 219 220 /* Map all the services in the boot image. */ 221 if((s = sys_safecopyfrom(RS_PROC_NR, info->rproctab_gid, 0, 222 (vir_bytes) rprocpub, sizeof(rprocpub))) != OK) { 223 panic("vm: sys_safecopyfrom (rs) failed: %d", s); 224 } 225 226 for(i=0;i < NR_BOOT_PROCS;i++) { 227 if(rprocpub[i].in_use) { 228 if((s = map_service(&rprocpub[i])) != OK) { 229 panic("unable to map service: %d", s); 230 } 231 } 232 } 233 234 return(OK); 235 } 236 237 static struct vmproc *init_proc(endpoint_t ep_nr) 238 { 239 static struct boot_image *ip; 240 241 for (ip = &kernel_boot_info.boot_procs[0]; 242 ip < &kernel_boot_info.boot_procs[NR_BOOT_PROCS]; ip++) { 243 struct vmproc *vmp; 244 245 if(ip->proc_nr != ep_nr) continue; 246 247 if(ip->proc_nr >= _NR_PROCS || ip->proc_nr < 0) 248 panic("proc: %d", ip->proc_nr); 249 250 vmp = &vmproc[ip->proc_nr]; 251 assert(!(vmp->vm_flags & VMF_INUSE)); /* no double procs */ 252 clear_proc(vmp); 253 vmp->vm_flags = VMF_INUSE; 254 vmp->vm_endpoint = ip->endpoint; 255 vmp->vm_boot = ip; 256 257 return vmp; 258 } 259 260 panic("no init_proc"); 261 } 262 263 struct vm_exec_info { 264 struct exec_info execi; 265 struct boot_image *ip; 266 struct vmproc *vmp; 267 }; 268 269 static int libexec_copy_physcopy(struct exec_info *execi, 270 off_t off, vir_bytes vaddr, size_t len) 271 { 272 vir_bytes end; 273 struct vm_exec_info *ei = execi->opaque; 274 end = ei->ip->start_addr + ei->ip->len; 275 assert(ei->ip->start_addr + off + len <= end); 276 return sys_physcopy(NONE, ei->ip->start_addr + off, 277 execi->proc_e, vaddr, len, 0); 278 } 279 280 static void boot_alloc(struct exec_info *execi, off_t vaddr, 281 size_t len, int flags) 282 { 283 struct vmproc *vmp = ((struct vm_exec_info *) execi->opaque)->vmp; 284 285 if(!(map_page_region(vmp, vaddr, 0, len, 286 VR_ANON | VR_WRITABLE | VR_UNINITIALIZED, flags, 287 &mem_type_anon))) { 288 panic("VM: exec: map_page_region for boot process failed"); 289 } 290 } 291 292 static int libexec_alloc_vm_prealloc(struct exec_info *execi, 293 vir_bytes vaddr, size_t len) 294 { 295 boot_alloc(execi, vaddr, len, MF_PREALLOC); 296 return OK; 297 } 298 299 static int libexec_alloc_vm_ondemand(struct exec_info *execi, 300 vir_bytes vaddr, size_t len) 301 { 302 boot_alloc(execi, vaddr, len, 0); 303 return OK; 304 } 305 306 static void exec_bootproc(struct vmproc *vmp, struct boot_image *ip) 307 { 308 struct vm_exec_info vmexeci; 309 struct exec_info *execi = &vmexeci.execi; 310 char hdr[VM_PAGE_SIZE]; 311 312 size_t frame_size = 0; /* Size of the new initial stack. */ 313 int argc = 0; /* Argument count. */ 314 int envc = 0; /* Environment count */ 315 char overflow = 0; /* No overflow yet. */ 316 struct ps_strings *psp; 317 318 int vsp = 0; /* (virtual) Stack pointer in new address space. */ 319 char *argv[] = { ip->proc_name, NULL }; 320 char *envp[] = { NULL }; 321 char *path = ip->proc_name; 322 char frame[VM_PAGE_SIZE]; 323 324 memset(&vmexeci, 0, sizeof(vmexeci)); 325 326 if(pt_new(&vmp->vm_pt) != OK) 327 panic("VM: no new pagetable"); 328 329 if(pt_bind(&vmp->vm_pt, vmp) != OK) 330 panic("VM: pt_bind failed"); 331 332 if(sys_physcopy(NONE, ip->start_addr, SELF, 333 (vir_bytes) hdr, sizeof(hdr), 0) != OK) 334 panic("can't look at boot proc header"); 335 336 execi->stack_high = kernel_boot_info.user_sp; 337 execi->stack_size = DEFAULT_STACK_LIMIT; 338 execi->proc_e = vmp->vm_endpoint; 339 execi->hdr = hdr; 340 execi->hdr_len = sizeof(hdr); 341 strlcpy(execi->progname, ip->proc_name, sizeof(execi->progname)); 342 execi->frame_len = 0; 343 execi->opaque = &vmexeci; 344 execi->filesize = ip->len; 345 346 vmexeci.ip = ip; 347 vmexeci.vmp = vmp; 348 349 /* callback functions and data */ 350 execi->copymem = libexec_copy_physcopy; 351 execi->clearproc = NULL; 352 execi->clearmem = libexec_clear_sys_memset; 353 execi->allocmem_prealloc_junk = libexec_alloc_vm_prealloc; 354 execi->allocmem_prealloc_cleared = libexec_alloc_vm_prealloc; 355 execi->allocmem_ondemand = libexec_alloc_vm_ondemand; 356 357 if (libexec_load_elf(execi) != OK) 358 panic("vm: boot process load of process %s (ep=%d) failed\n", 359 execi->progname, vmp->vm_endpoint); 360 361 /* Setup a minimal stack. */ 362 minix_stack_params(path, argv, envp, &frame_size, &overflow, &argc, 363 &envc); 364 365 /* The party is off if there is an overflow, or it is too big for our 366 * pre-allocated space. */ 367 if(overflow || frame_size > sizeof(frame)) 368 panic("vm: could not alloc stack for boot process %s (ep=%d)\n", 369 execi->progname, vmp->vm_endpoint); 370 371 minix_stack_fill(path, argc, argv, envc, envp, frame_size, frame, &vsp, 372 &psp); 373 374 if(handle_memory_once(vmp, vsp, frame_size, 1) != OK) 375 panic("vm: could not map stack for boot process %s (ep=%d)\n", 376 execi->progname, vmp->vm_endpoint); 377 378 if(sys_datacopy(SELF, (vir_bytes)frame, vmp->vm_endpoint, vsp, frame_size) != OK) 379 panic("vm: could not copy stack for boot process %s (ep=%d)\n", 380 execi->progname, vmp->vm_endpoint); 381 382 if(sys_exec(vmp->vm_endpoint, (vir_bytes)vsp, 383 (vir_bytes)execi->progname, execi->pc, 384 vsp + ((int)psp - (int)frame)) != OK) 385 panic("vm: boot process exec of process %s (ep=%d) failed\n", 386 execi->progname,vmp->vm_endpoint); 387 388 /* make it runnable */ 389 if(sys_vmctl(vmp->vm_endpoint, VMCTL_BOOTINHIBIT_CLEAR, 0) != OK) 390 panic("VMCTL_BOOTINHIBIT_CLEAR failed"); 391 } 392 393 static int do_procctl_notrans(message *msg) 394 { 395 int transid = 0; 396 397 assert(!IS_VFS_FS_TRANSID(transid)); 398 399 return do_procctl(msg, transid); 400 } 401 402 void init_vm(void) 403 { 404 int s, i; 405 static struct memory mem_chunks[NR_MEMS]; 406 static struct boot_image *ip; 407 extern void __minix_init(void); 408 multiboot_module_t *mod; 409 vir_bytes kern_dyn, kern_static; 410 411 #if SANITYCHECKS 412 incheck = nocheck = 0; 413 #endif 414 415 /* Retrieve various crucial boot parameters */ 416 if(OK != (s=sys_getkinfo(&kernel_boot_info))) { 417 panic("couldn't get bootinfo: %d", s); 418 } 419 420 /* Turn file mmap on? */ 421 enable_filemap=1; /* yes by default */ 422 env_parse("filemap", "d", 0, &enable_filemap, 0, 1); 423 424 /* Sanity check */ 425 assert(kernel_boot_info.mmap_size > 0); 426 assert(kernel_boot_info.mods_with_kernel > 0); 427 428 /* Get chunks of available memory. */ 429 get_mem_chunks(mem_chunks); 430 431 /* Set table to 0. This invalidates all slots (clear VMF_INUSE). */ 432 memset(vmproc, 0, sizeof(vmproc)); 433 434 for(i = 0; i < ELEMENTS(vmproc); i++) { 435 vmproc[i].vm_slot = i; 436 } 437 438 /* Initialize ACL data structures. */ 439 acl_init(); 440 441 /* region management initialization. */ 442 map_region_init(); 443 444 /* Initialize tables to all physical memory. */ 445 mem_init(mem_chunks); 446 447 /* Architecture-dependent initialization. */ 448 init_proc(VM_PROC_NR); 449 pt_init(); 450 451 /* Acquire kernel ipc vectors that weren't available 452 * before VM had determined kernel mappings 453 */ 454 __minix_init(); 455 456 /* The kernel's freelist does not include boot-time modules; let 457 * the allocator know that the total memory is bigger. 458 */ 459 for (mod = &kernel_boot_info.module_list[0]; 460 mod < &kernel_boot_info.module_list[kernel_boot_info.mods_with_kernel-1]; mod++) { 461 phys_bytes len = mod->mod_end-mod->mod_start+1; 462 len = roundup(len, VM_PAGE_SIZE); 463 mem_add_total_pages(len/VM_PAGE_SIZE); 464 } 465 466 kern_dyn = kernel_boot_info.kernel_allocated_bytes_dynamic; 467 kern_static = kernel_boot_info.kernel_allocated_bytes; 468 kern_static = roundup(kern_static, VM_PAGE_SIZE); 469 mem_add_total_pages((kern_dyn + kern_static)/VM_PAGE_SIZE); 470 471 /* Give these processes their own page table. */ 472 for (ip = &kernel_boot_info.boot_procs[0]; 473 ip < &kernel_boot_info.boot_procs[NR_BOOT_PROCS]; ip++) { 474 struct vmproc *vmp; 475 476 if(ip->proc_nr < 0) continue; 477 478 assert(ip->start_addr); 479 480 /* VM has already been set up by the kernel and pt_init(). 481 * Any other boot process is already in memory and is set up 482 * here. 483 */ 484 if(ip->proc_nr == VM_PROC_NR) continue; 485 486 vmp = init_proc(ip->proc_nr); 487 488 exec_bootproc(vmp, ip); 489 490 /* Free the file blob */ 491 assert(!(ip->start_addr % VM_PAGE_SIZE)); 492 ip->len = roundup(ip->len, VM_PAGE_SIZE); 493 free_mem(ABS2CLICK(ip->start_addr), ABS2CLICK(ip->len)); 494 } 495 496 /* Set up table of calls. */ 497 #define CALLMAP(code, func) { int _cmi; \ 498 _cmi=CALLNUMBER(code); \ 499 assert(_cmi >= 0); \ 500 assert(_cmi < NR_VM_CALLS); \ 501 vm_calls[_cmi].vmc_func = (func); \ 502 vm_calls[_cmi].vmc_name = #code; \ 503 } 504 505 /* Set call table to 0. This invalidates all calls (clear 506 * vmc_func). 507 */ 508 memset(vm_calls, 0, sizeof(vm_calls)); 509 510 /* Basic VM calls. */ 511 CALLMAP(VM_MMAP, do_mmap); 512 CALLMAP(VM_MUNMAP, do_munmap); 513 CALLMAP(VM_MAP_PHYS, do_map_phys); 514 CALLMAP(VM_UNMAP_PHYS, do_munmap); 515 516 /* Calls from PM. */ 517 CALLMAP(VM_EXIT, do_exit); 518 CALLMAP(VM_FORK, do_fork); 519 CALLMAP(VM_BRK, do_brk); 520 CALLMAP(VM_WILLEXIT, do_willexit); 521 CALLMAP(VM_NOTIFY_SIG, do_notify_sig); 522 523 CALLMAP(VM_PROCCTL, do_procctl_notrans); 524 525 /* Calls from VFS. */ 526 CALLMAP(VM_VFS_REPLY, do_vfs_reply); 527 CALLMAP(VM_VFS_MMAP, do_vfs_mmap); 528 529 /* Calls from RS */ 530 CALLMAP(VM_RS_SET_PRIV, do_rs_set_priv); 531 CALLMAP(VM_RS_UPDATE, do_rs_update); 532 CALLMAP(VM_RS_MEMCTL, do_rs_memctl); 533 534 /* Generic calls. */ 535 CALLMAP(VM_REMAP, do_remap); 536 CALLMAP(VM_REMAP_RO, do_remap); 537 CALLMAP(VM_GETPHYS, do_get_phys); 538 CALLMAP(VM_SHM_UNMAP, do_munmap); 539 CALLMAP(VM_GETREF, do_get_refcount); 540 CALLMAP(VM_INFO, do_info); 541 CALLMAP(VM_QUERY_EXIT, do_query_exit); 542 CALLMAP(VM_WATCH_EXIT, do_watch_exit); 543 544 /* Cache blocks. */ 545 CALLMAP(VM_MAPCACHEPAGE, do_mapcache); 546 CALLMAP(VM_SETCACHEPAGE, do_setcache); 547 CALLMAP(VM_FORGETCACHEPAGE, do_forgetcache); 548 CALLMAP(VM_CLEARCACHE, do_clearcache); 549 550 /* getrusage */ 551 CALLMAP(VM_GETRUSAGE, do_getrusage); 552 553 /* Initialize the structures for queryexit */ 554 init_query_exit(); 555 556 /* Mark VM instances. */ 557 num_vm_instances = 1; 558 vmproc[VM_PROC_NR].vm_flags |= VMF_VM_INSTANCE; 559 560 /* Let SEF know about VM mmapped regions. */ 561 s = sef_llvm_add_special_mem_region((void*)VM_OWN_HEAPBASE, 562 VM_OWN_MMAPTOP-VM_OWN_HEAPBASE, "%MMAP_ALL"); 563 if(s < 0) { 564 printf("VM: st_add_special_mmapped_region failed %d\n", s); 565 } 566 } 567 568 /*===========================================================================* 569 * sef_cb_init_vm_multi_lu * 570 *===========================================================================*/ 571 static int sef_cb_init_vm_multi_lu(int type, sef_init_info_t *info) 572 { 573 message m; 574 int i, r; 575 ipc_filter_el_t ipc_filter[IPCF_MAX_ELEMENTS]; 576 int num_elements; 577 578 if(type != SEF_INIT_LU || !(info->flags & SEF_LU_MULTI)) { 579 return OK; 580 } 581 582 /* If this is a multi-component update, we need to perform the update 583 * for services that need to be updated. In addition, make sure VM 584 * can only receive messages from RS, tasks, and other services being 585 * updated until RS specifically sends a special update cancel message. 586 * This is necessary to limit the number of VM state changes to support 587 * rollback. Allow only safe message types for safe updates. 588 */ 589 memset(ipc_filter, 0, sizeof(ipc_filter)); 590 num_elements = 0; 591 ipc_filter[num_elements].flags = IPCF_MATCH_M_SOURCE; 592 ipc_filter[num_elements++].m_source = RS_PROC_NR; 593 if(info->flags & SEF_LU_UNSAFE) { 594 ipc_filter[num_elements].flags = IPCF_MATCH_M_SOURCE; 595 ipc_filter[num_elements++].m_source = ANY_TSK; 596 } 597 if((r = sys_safecopyfrom(RS_PROC_NR, info->rproctab_gid, 0, 598 (vir_bytes) rprocpub, NR_SYS_PROCS*sizeof(struct rprocpub))) != OK) { 599 panic("sys_safecopyfrom failed: %d", r); 600 } 601 m.m_source = VM_PROC_NR; 602 for(i=0;i < NR_SYS_PROCS;i++) { 603 if(rprocpub[i].in_use && rprocpub[i].old_endpoint != NONE) { 604 if(num_elements <= IPCF_MAX_ELEMENTS-5) { 605 /* VM_BRK is needed for normal operation during the live 606 * update. VM_INFO is needed for state transfer in the 607 * light of holes. Pagefaults and handle-memory requests 608 * are blocked intentionally, as handling these would 609 * prevent VM from being able to roll back. 610 */ 611 ipc_filter[num_elements].flags = IPCF_MATCH_M_SOURCE; 612 ipc_filter[num_elements].m_source = rprocpub[i].old_endpoint; 613 if(!(info->flags & SEF_LU_UNSAFE)) { 614 ipc_filter[num_elements].flags |= IPCF_MATCH_M_TYPE; 615 ipc_filter[num_elements].m_type = VM_BRK; 616 } 617 num_elements++; 618 ipc_filter[num_elements].flags = IPCF_MATCH_M_SOURCE; 619 ipc_filter[num_elements].m_source = rprocpub[i].new_endpoint; 620 if(!(info->flags & SEF_LU_UNSAFE)) { 621 ipc_filter[num_elements].flags |= IPCF_MATCH_M_TYPE; 622 ipc_filter[num_elements].m_type = VM_BRK; 623 } 624 num_elements++; 625 if(!(info->flags & SEF_LU_UNSAFE)) { 626 ipc_filter[num_elements].flags = IPCF_MATCH_M_SOURCE | IPCF_MATCH_M_TYPE; 627 ipc_filter[num_elements].m_source = rprocpub[i].old_endpoint; 628 ipc_filter[num_elements++].m_type = VM_INFO; 629 ipc_filter[num_elements].flags = IPCF_MATCH_M_SOURCE | IPCF_MATCH_M_TYPE; 630 ipc_filter[num_elements].m_source = rprocpub[i].new_endpoint; 631 ipc_filter[num_elements++].m_type = VM_INFO; 632 } 633 /* Make sure we can talk to any RS instance. */ 634 if(rprocpub[i].old_endpoint == RS_PROC_NR) { 635 ipc_filter[num_elements].flags = IPCF_MATCH_M_SOURCE; 636 ipc_filter[num_elements++].m_source = rprocpub[i].new_endpoint; 637 } 638 else if(rprocpub[i].new_endpoint == RS_PROC_NR) { 639 ipc_filter[num_elements].flags = IPCF_MATCH_M_SOURCE; 640 ipc_filter[num_elements++].m_source = rprocpub[i].old_endpoint; 641 } 642 } 643 else { 644 printf("sef_cb_init_vm_multi_lu: skipping ipc filter elements for %d and %d\n", 645 rprocpub[i].old_endpoint, rprocpub[i].new_endpoint); 646 } 647 if(rprocpub[i].sys_flags & SF_VM_UPDATE) { 648 m.m_lsys_vm_update.src = rprocpub[i].new_endpoint; 649 m.m_lsys_vm_update.dst = rprocpub[i].old_endpoint; 650 m.m_lsys_vm_update.flags = rprocpub[i].sys_flags; 651 r = do_rs_update(&m); 652 if(r != OK && r != SUSPEND) { 653 printf("sef_cb_init_vm_multi_lu: do_rs_update failed: %d", r); 654 } 655 } 656 } 657 } 658 659 r = sys_statectl(SYS_STATE_ADD_IPC_WL_FILTER, ipc_filter, num_elements*sizeof(ipc_filter_el_t)); 660 if(r != OK) { 661 printf("sef_cb_init_vm_multi_lu: sys_statectl failed: %d", r); 662 } 663 664 return OK; 665 } 666 667 /*===========================================================================* 668 * sef_cb_init_lu_restart * 669 *===========================================================================*/ 670 static int sef_cb_init_lu_restart(int type, sef_init_info_t *info) 671 { 672 /* Restart the vm server. */ 673 int r; 674 endpoint_t old_e; 675 int old_p; 676 struct vmproc *old_vmp, *new_vmp; 677 678 /* Perform default state transfer first. */ 679 if(type == SEF_INIT_LU) { 680 sef_setcb_init_restart(SEF_CB_INIT_RESTART_STATEFUL); 681 r = SEF_CB_INIT_LU_DEFAULT(type, info); 682 } 683 else { 684 r = SEF_CB_INIT_RESTART_STATEFUL(type, info); 685 } 686 if(r != OK) { 687 return r; 688 } 689 690 /* Lookup slots for old process. */ 691 old_e = info->old_endpoint; 692 if(vm_isokendpt(old_e, &old_p) != OK) { 693 printf("sef_cb_init_lu_restart: bad old endpoint %d\n", old_e); 694 return EINVAL; 695 } 696 old_vmp = &vmproc[old_p]; 697 new_vmp = &vmproc[VM_PROC_NR]; 698 699 /* Swap proc slots and dynamic data. */ 700 if((r = swap_proc_slot(old_vmp, new_vmp)) != OK) { 701 printf("sef_cb_init_lu_restart: swap_proc_slot failed\n"); 702 return r; 703 } 704 if((r = swap_proc_dyn_data(old_vmp, new_vmp, 0)) != OK) { 705 printf("sef_cb_init_lu_restart: swap_proc_dyn_data failed\n"); 706 return r; 707 } 708 709 /* Rebind page tables. */ 710 pt_bind(&new_vmp->vm_pt, new_vmp); 711 pt_bind(&old_vmp->vm_pt, old_vmp); 712 pt_clearmapcache(); 713 714 /* Adjust process references. */ 715 adjust_proc_refs(); 716 717 /* Handle multi-component live update when necessary. */ 718 return sef_cb_init_vm_multi_lu(type, info); 719 } 720 721 /*===========================================================================* 722 * sef_cb_signal_handler * 723 *===========================================================================*/ 724 static void sef_cb_signal_handler(int signo) 725 { 726 /* Check for known kernel signals, ignore anything else. */ 727 switch(signo) { 728 /* There is a pending memory request from the kernel. */ 729 case SIGKMEM: 730 do_memory(); 731 break; 732 } 733 734 /* It can happen that we get stuck receiving signals 735 * without sef_receive() returning. We could need more memory 736 * though. 737 */ 738 if(missing_spares > 0) { 739 alloc_cycle(); /* pagetable code wants to be called */ 740 } 741 742 pt_clearmapcache(); 743 } 744 745 /*===========================================================================* 746 * map_service * 747 *===========================================================================*/ 748 static int map_service(struct rprocpub *rpub) 749 { 750 /* Map a new service by initializing its call mask. */ 751 int r, proc_nr; 752 753 if ((r = vm_isokendpt(rpub->endpoint, &proc_nr)) != OK) { 754 return r; 755 } 756 757 /* Copy the call mask. */ 758 acl_set(&vmproc[proc_nr], rpub->vm_call_mask, !IS_RPUB_BOOT_USR(rpub)); 759 760 return(OK); 761 } 762