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 <env.h> 27433d6423SLionel Sambuc #include <stdio.h> 28433d6423SLionel Sambuc #include <assert.h> 29433d6423SLionel Sambuc 30433d6423SLionel Sambuc #define _MAIN 1 31433d6423SLionel Sambuc #include "glo.h" 32433d6423SLionel Sambuc #include "proto.h" 33433d6423SLionel Sambuc #include "util.h" 34433d6423SLionel Sambuc #include "vm.h" 35433d6423SLionel Sambuc #include "sanitycheck.h" 36433d6423SLionel Sambuc 37433d6423SLionel Sambuc extern int missing_spares; 38433d6423SLionel Sambuc 39433d6423SLionel Sambuc #include <machine/archtypes.h> 40433d6423SLionel Sambuc #include <sys/param.h> 41433d6423SLionel Sambuc #include "kernel/const.h" 42433d6423SLionel Sambuc #include "kernel/config.h" 43433d6423SLionel Sambuc #include "kernel/proc.h" 44433d6423SLionel Sambuc 45433d6423SLionel Sambuc #include <signal.h> 46433d6423SLionel Sambuc #include <lib.h> 47433d6423SLionel Sambuc 48433d6423SLionel Sambuc /* Table of calls and a macro to test for being in range. */ 49433d6423SLionel Sambuc struct { 50433d6423SLionel Sambuc int (*vmc_func)(message *); /* Call handles message. */ 51433d6423SLionel Sambuc const char *vmc_name; /* Human-readable string. */ 52433d6423SLionel Sambuc } vm_calls[NR_VM_CALLS]; 53433d6423SLionel Sambuc 54433d6423SLionel Sambuc /* Macro to verify call range and map 'high' range to 'base' range 55433d6423SLionel Sambuc * (starting at 0) in one. Evaluates to zero-based call number if call 56433d6423SLionel Sambuc * number is valid, returns -1 otherwise. 57433d6423SLionel Sambuc */ 58433d6423SLionel Sambuc #define CALLNUMBER(c) (((c) >= VM_RQ_BASE && \ 59433d6423SLionel Sambuc (c) < VM_RQ_BASE + ELEMENTS(vm_calls)) ? \ 60433d6423SLionel Sambuc ((c) - VM_RQ_BASE) : -1) 61433d6423SLionel Sambuc 62433d6423SLionel Sambuc static int map_service(struct rprocpub *rpub); 63433d6423SLionel Sambuc static int do_rs_init(message *m); 64433d6423SLionel Sambuc 65433d6423SLionel Sambuc /* SEF functions and variables. */ 66433d6423SLionel Sambuc static void sef_cb_signal_handler(int signo); 67433d6423SLionel Sambuc 68433d6423SLionel Sambuc void init_vm(void); 69433d6423SLionel Sambuc 70433d6423SLionel Sambuc /*===========================================================================* 71433d6423SLionel Sambuc * main * 72433d6423SLionel Sambuc *===========================================================================*/ 73433d6423SLionel Sambuc int main(void) 74433d6423SLionel Sambuc { 75433d6423SLionel Sambuc message msg; 76433d6423SLionel Sambuc int result, who_e, rcv_sts; 77433d6423SLionel Sambuc int caller_slot; 78433d6423SLionel Sambuc 79433d6423SLionel Sambuc /* Initialize system so that all processes are runnable */ 80433d6423SLionel Sambuc init_vm(); 81433d6423SLionel Sambuc 82433d6423SLionel Sambuc /* Register init callbacks. */ 83433d6423SLionel Sambuc sef_setcb_init_restart(sef_cb_init_fail); 84433d6423SLionel Sambuc sef_setcb_signal_handler(sef_cb_signal_handler); 85433d6423SLionel Sambuc 86433d6423SLionel Sambuc /* Let SEF perform startup. */ 87433d6423SLionel Sambuc sef_startup(); 88433d6423SLionel Sambuc 89433d6423SLionel Sambuc SANITYCHECK(SCL_TOP); 90433d6423SLionel Sambuc 91433d6423SLionel Sambuc /* This is VM's main loop. */ 92433d6423SLionel Sambuc while (TRUE) { 93433d6423SLionel Sambuc int r, c; 94433d6423SLionel Sambuc int type; 95433d6423SLionel Sambuc int transid = 0; /* VFS transid if any */ 96433d6423SLionel Sambuc 97433d6423SLionel Sambuc SANITYCHECK(SCL_TOP); 98433d6423SLionel Sambuc if(missing_spares > 0) { 99433d6423SLionel Sambuc alloc_cycle(); /* mem alloc code wants to be called */ 100433d6423SLionel Sambuc } 101433d6423SLionel Sambuc 102433d6423SLionel Sambuc if ((r=sef_receive_status(ANY, &msg, &rcv_sts)) != OK) 103433d6423SLionel Sambuc panic("sef_receive_status() error: %d", r); 104433d6423SLionel Sambuc 105433d6423SLionel Sambuc if (is_ipc_notify(rcv_sts)) { 106433d6423SLionel Sambuc /* Unexpected ipc_notify(). */ 107433d6423SLionel Sambuc printf("VM: ignoring ipc_notify() from %d\n", msg.m_source); 108433d6423SLionel Sambuc continue; 109433d6423SLionel Sambuc } 110433d6423SLionel Sambuc who_e = msg.m_source; 111433d6423SLionel Sambuc if(vm_isokendpt(who_e, &caller_slot) != OK) 112433d6423SLionel Sambuc panic("invalid caller %d", who_e); 113433d6423SLionel Sambuc 114433d6423SLionel Sambuc /* We depend on this being false for the initialized value. */ 115433d6423SLionel Sambuc assert(!IS_VFS_FS_TRANSID(transid)); 116433d6423SLionel Sambuc 117433d6423SLionel Sambuc type = msg.m_type; 118433d6423SLionel Sambuc c = CALLNUMBER(type); 119433d6423SLionel Sambuc result = ENOSYS; /* Out of range or restricted calls return this. */ 120433d6423SLionel Sambuc 121433d6423SLionel Sambuc transid = TRNS_GET_ID(msg.m_type); 122433d6423SLionel Sambuc 123433d6423SLionel Sambuc if((msg.m_source == VFS_PROC_NR) && IS_VFS_FS_TRANSID(transid)) { 124433d6423SLionel Sambuc /* If it's a request from VFS, it might have a transaction id. */ 125433d6423SLionel Sambuc msg.m_type = TRNS_DEL_ID(msg.m_type); 126433d6423SLionel Sambuc 127433d6423SLionel Sambuc /* Calls that use the transid */ 128433d6423SLionel Sambuc result = do_procctl(&msg, transid); 129433d6423SLionel Sambuc } else if(msg.m_type == RS_INIT && msg.m_source == RS_PROC_NR) { 130433d6423SLionel Sambuc result = do_rs_init(&msg); 131433d6423SLionel Sambuc } else if (msg.m_type == VM_PAGEFAULT) { 132433d6423SLionel Sambuc if (!IPC_STATUS_FLAGS_TEST(rcv_sts, IPC_FLG_MSG_FROM_KERNEL)) { 133433d6423SLionel Sambuc printf("VM: process %d faked VM_PAGEFAULT " 134433d6423SLionel Sambuc "message!\n", msg.m_source); 135433d6423SLionel Sambuc } 136433d6423SLionel Sambuc do_pagefaults(&msg); 137433d6423SLionel Sambuc /* 138433d6423SLionel Sambuc * do not reply to this call, the caller is unblocked by 139433d6423SLionel Sambuc * a sys_vmctl() call in do_pagefaults if success. VM panics 140433d6423SLionel Sambuc * otherwise 141433d6423SLionel Sambuc */ 142433d6423SLionel Sambuc continue; 143433d6423SLionel Sambuc } else if(c < 0 || !vm_calls[c].vmc_func) { 144433d6423SLionel Sambuc /* out of range or missing callnr */ 145433d6423SLionel Sambuc } else { 146433d6423SLionel Sambuc if (acl_check(&vmproc[caller_slot], c) != OK) { 147433d6423SLionel Sambuc printf("VM: unauthorized %s by %d\n", 148433d6423SLionel Sambuc vm_calls[c].vmc_name, who_e); 149433d6423SLionel Sambuc } else { 150433d6423SLionel Sambuc SANITYCHECK(SCL_FUNCTIONS); 151433d6423SLionel Sambuc result = vm_calls[c].vmc_func(&msg); 152433d6423SLionel Sambuc SANITYCHECK(SCL_FUNCTIONS); 153433d6423SLionel Sambuc } 154433d6423SLionel Sambuc } 155433d6423SLionel Sambuc 156433d6423SLionel Sambuc /* Send reply message, unless the return code is SUSPEND, 157433d6423SLionel Sambuc * which is a pseudo-result suppressing the reply message. 158433d6423SLionel Sambuc */ 159433d6423SLionel Sambuc if(result != SUSPEND) { 160433d6423SLionel Sambuc msg.m_type = result; 161433d6423SLionel Sambuc 162433d6423SLionel Sambuc assert(!IS_VFS_FS_TRANSID(transid)); 163433d6423SLionel Sambuc 164433d6423SLionel Sambuc if((r=ipc_send(who_e, &msg)) != OK) { 165433d6423SLionel Sambuc printf("VM: couldn't send %d to %d (err %d)\n", 166433d6423SLionel Sambuc msg.m_type, who_e, r); 167433d6423SLionel Sambuc panic("ipc_send() error"); 168433d6423SLionel Sambuc } 169433d6423SLionel Sambuc } 170433d6423SLionel Sambuc } 171433d6423SLionel Sambuc return(OK); 172433d6423SLionel Sambuc } 173433d6423SLionel Sambuc 174433d6423SLionel Sambuc static int do_rs_init(message *m) 175433d6423SLionel Sambuc { 176433d6423SLionel Sambuc int s, i; 177433d6423SLionel Sambuc static struct rprocpub rprocpub[NR_BOOT_PROCS]; 178433d6423SLionel Sambuc 179433d6423SLionel Sambuc /* Map all the services in the boot image. */ 180433d6423SLionel Sambuc if((s = sys_safecopyfrom(RS_PROC_NR, m->m_rs_init.rproctab_gid, 0, 181433d6423SLionel Sambuc (vir_bytes) rprocpub, sizeof(rprocpub))) != OK) { 182433d6423SLionel Sambuc panic("vm: sys_safecopyfrom (rs) failed: %d", s); 183433d6423SLionel Sambuc } 184433d6423SLionel Sambuc 185433d6423SLionel Sambuc for(i=0;i < NR_BOOT_PROCS;i++) { 186433d6423SLionel Sambuc if(rprocpub[i].in_use) { 187433d6423SLionel Sambuc if((s = map_service(&rprocpub[i])) != OK) { 188433d6423SLionel Sambuc panic("unable to map service: %d", s); 189433d6423SLionel Sambuc } 190433d6423SLionel Sambuc } 191433d6423SLionel Sambuc } 192433d6423SLionel Sambuc 193433d6423SLionel Sambuc /* RS expects this response that it then again wants to reply to: */ 194433d6423SLionel Sambuc m->m_rs_init.result = OK; 195433d6423SLionel Sambuc ipc_sendrec(RS_PROC_NR, m); 196433d6423SLionel Sambuc 197433d6423SLionel Sambuc return(SUSPEND); 198433d6423SLionel Sambuc } 199433d6423SLionel Sambuc 200433d6423SLionel Sambuc static struct vmproc *init_proc(endpoint_t ep_nr) 201433d6423SLionel Sambuc { 202433d6423SLionel Sambuc static struct boot_image *ip; 203433d6423SLionel Sambuc 204433d6423SLionel Sambuc for (ip = &kernel_boot_info.boot_procs[0]; 205433d6423SLionel Sambuc ip < &kernel_boot_info.boot_procs[NR_BOOT_PROCS]; ip++) { 206433d6423SLionel Sambuc struct vmproc *vmp; 207433d6423SLionel Sambuc 208433d6423SLionel Sambuc if(ip->proc_nr != ep_nr) continue; 209433d6423SLionel Sambuc 210433d6423SLionel Sambuc if(ip->proc_nr >= _NR_PROCS || ip->proc_nr < 0) 211433d6423SLionel Sambuc panic("proc: %d", ip->proc_nr); 212433d6423SLionel Sambuc 213433d6423SLionel Sambuc vmp = &vmproc[ip->proc_nr]; 214433d6423SLionel Sambuc assert(!(vmp->vm_flags & VMF_INUSE)); /* no double procs */ 215433d6423SLionel Sambuc clear_proc(vmp); 216433d6423SLionel Sambuc vmp->vm_flags = VMF_INUSE; 217433d6423SLionel Sambuc vmp->vm_endpoint = ip->endpoint; 218433d6423SLionel Sambuc vmp->vm_boot = ip; 219433d6423SLionel Sambuc 220433d6423SLionel Sambuc return vmp; 221433d6423SLionel Sambuc } 222433d6423SLionel Sambuc 223433d6423SLionel Sambuc panic("no init_proc"); 224433d6423SLionel Sambuc } 225433d6423SLionel Sambuc 226433d6423SLionel Sambuc struct vm_exec_info { 227433d6423SLionel Sambuc struct exec_info execi; 228433d6423SLionel Sambuc struct boot_image *ip; 229433d6423SLionel Sambuc struct vmproc *vmp; 230433d6423SLionel Sambuc }; 231433d6423SLionel Sambuc 232433d6423SLionel Sambuc static int libexec_copy_physcopy(struct exec_info *execi, 233433d6423SLionel Sambuc off_t off, vir_bytes vaddr, size_t len) 234433d6423SLionel Sambuc { 235433d6423SLionel Sambuc vir_bytes end; 236433d6423SLionel Sambuc struct vm_exec_info *ei = execi->opaque; 237433d6423SLionel Sambuc end = ei->ip->start_addr + ei->ip->len; 238433d6423SLionel Sambuc assert(ei->ip->start_addr + off + len <= end); 239433d6423SLionel Sambuc return sys_physcopy(NONE, ei->ip->start_addr + off, 240433d6423SLionel Sambuc execi->proc_e, vaddr, len, 0); 241433d6423SLionel Sambuc } 242433d6423SLionel Sambuc 243433d6423SLionel Sambuc static void boot_alloc(struct exec_info *execi, off_t vaddr, 244433d6423SLionel Sambuc size_t len, int flags) 245433d6423SLionel Sambuc { 246433d6423SLionel Sambuc struct vmproc *vmp = ((struct vm_exec_info *) execi->opaque)->vmp; 247433d6423SLionel Sambuc 248433d6423SLionel Sambuc if(!(map_page_region(vmp, vaddr, 0, len, 249433d6423SLionel Sambuc VR_ANON | VR_WRITABLE | VR_UNINITIALIZED, flags, 250433d6423SLionel Sambuc &mem_type_anon))) { 251433d6423SLionel Sambuc panic("VM: exec: map_page_region for boot process failed"); 252433d6423SLionel Sambuc } 253433d6423SLionel Sambuc } 254433d6423SLionel Sambuc 255433d6423SLionel Sambuc static int libexec_alloc_vm_prealloc(struct exec_info *execi, 256433d6423SLionel Sambuc vir_bytes vaddr, size_t len) 257433d6423SLionel Sambuc { 258433d6423SLionel Sambuc boot_alloc(execi, vaddr, len, MF_PREALLOC); 259433d6423SLionel Sambuc return OK; 260433d6423SLionel Sambuc } 261433d6423SLionel Sambuc 262433d6423SLionel Sambuc static int libexec_alloc_vm_ondemand(struct exec_info *execi, 263433d6423SLionel Sambuc vir_bytes vaddr, size_t len) 264433d6423SLionel Sambuc { 265433d6423SLionel Sambuc boot_alloc(execi, vaddr, len, 0); 266433d6423SLionel Sambuc return OK; 267433d6423SLionel Sambuc } 268433d6423SLionel Sambuc 269433d6423SLionel Sambuc static void exec_bootproc(struct vmproc *vmp, struct boot_image *ip) 270433d6423SLionel Sambuc { 271433d6423SLionel Sambuc struct vm_exec_info vmexeci; 272433d6423SLionel Sambuc struct exec_info *execi = &vmexeci.execi; 273433d6423SLionel Sambuc char hdr[VM_PAGE_SIZE]; 274433d6423SLionel Sambuc 275433d6423SLionel Sambuc size_t frame_size = 0; /* Size of the new initial stack. */ 276433d6423SLionel Sambuc int argc = 0; /* Argument count. */ 277433d6423SLionel Sambuc int envc = 0; /* Environment count */ 278433d6423SLionel Sambuc char overflow = 0; /* No overflow yet. */ 279433d6423SLionel Sambuc struct ps_strings *psp; 280433d6423SLionel Sambuc 281433d6423SLionel Sambuc int vsp = 0; /* (virtual) Stack pointer in new address space. */ 282433d6423SLionel Sambuc char *argv[] = { ip->proc_name, NULL }; 283433d6423SLionel Sambuc char *envp[] = { NULL }; 284433d6423SLionel Sambuc char *path = ip->proc_name; 285433d6423SLionel Sambuc char frame[VM_PAGE_SIZE]; 286433d6423SLionel Sambuc 287433d6423SLionel Sambuc memset(&vmexeci, 0, sizeof(vmexeci)); 288433d6423SLionel Sambuc 289433d6423SLionel Sambuc if(pt_new(&vmp->vm_pt) != OK) 290433d6423SLionel Sambuc panic("VM: no new pagetable"); 291433d6423SLionel Sambuc 292433d6423SLionel Sambuc if(pt_bind(&vmp->vm_pt, vmp) != OK) 293433d6423SLionel Sambuc panic("VM: pt_bind failed"); 294433d6423SLionel Sambuc 295433d6423SLionel Sambuc if(sys_physcopy(NONE, ip->start_addr, SELF, 296433d6423SLionel Sambuc (vir_bytes) hdr, sizeof(hdr), 0) != OK) 297433d6423SLionel Sambuc panic("can't look at boot proc header"); 298433d6423SLionel Sambuc 299433d6423SLionel Sambuc execi->stack_high = kernel_boot_info.user_sp; 300433d6423SLionel Sambuc execi->stack_size = DEFAULT_STACK_LIMIT; 301433d6423SLionel Sambuc execi->proc_e = vmp->vm_endpoint; 302433d6423SLionel Sambuc execi->hdr = hdr; 303433d6423SLionel Sambuc execi->hdr_len = sizeof(hdr); 304433d6423SLionel Sambuc strlcpy(execi->progname, ip->proc_name, sizeof(execi->progname)); 305433d6423SLionel Sambuc execi->frame_len = 0; 306433d6423SLionel Sambuc execi->opaque = &vmexeci; 307433d6423SLionel Sambuc execi->filesize = ip->len; 308433d6423SLionel Sambuc 309433d6423SLionel Sambuc vmexeci.ip = ip; 310433d6423SLionel Sambuc vmexeci.vmp = vmp; 311433d6423SLionel Sambuc 312433d6423SLionel Sambuc /* callback functions and data */ 313433d6423SLionel Sambuc execi->copymem = libexec_copy_physcopy; 314433d6423SLionel Sambuc execi->clearproc = NULL; 315433d6423SLionel Sambuc execi->clearmem = libexec_clear_sys_memset; 316433d6423SLionel Sambuc execi->allocmem_prealloc_junk = libexec_alloc_vm_prealloc; 317433d6423SLionel Sambuc execi->allocmem_prealloc_cleared = libexec_alloc_vm_prealloc; 318433d6423SLionel Sambuc execi->allocmem_ondemand = libexec_alloc_vm_ondemand; 319433d6423SLionel Sambuc 320433d6423SLionel Sambuc if (libexec_load_elf(execi) != OK) 321433d6423SLionel Sambuc panic("vm: boot process load of process %s (ep=%d) failed\n", 322433d6423SLionel Sambuc execi->progname, vmp->vm_endpoint); 323433d6423SLionel Sambuc 324433d6423SLionel Sambuc /* Setup a minimal stack. */ 325433d6423SLionel Sambuc minix_stack_params(path, argv, envp, &frame_size, &overflow, &argc, 326433d6423SLionel Sambuc &envc); 327433d6423SLionel Sambuc 328433d6423SLionel Sambuc /* The party is off if there is an overflow, or it is too big for our 329433d6423SLionel Sambuc * pre-allocated space. */ 330433d6423SLionel Sambuc if(overflow || frame_size > sizeof(frame)) 331433d6423SLionel Sambuc panic("vm: could not alloc stack for boot process %s (ep=%d)\n", 332433d6423SLionel Sambuc execi->progname, vmp->vm_endpoint); 333433d6423SLionel Sambuc 334433d6423SLionel Sambuc minix_stack_fill(path, argc, argv, envc, envp, frame_size, frame, &vsp, 335433d6423SLionel Sambuc &psp); 336433d6423SLionel Sambuc 337433d6423SLionel Sambuc if(handle_memory_once(vmp, vsp, frame_size, 1) != OK) 338433d6423SLionel Sambuc panic("vm: could not map stack for boot process %s (ep=%d)\n", 339433d6423SLionel Sambuc execi->progname, vmp->vm_endpoint); 340433d6423SLionel Sambuc 341433d6423SLionel Sambuc if(sys_datacopy(SELF, (vir_bytes)frame, vmp->vm_endpoint, vsp, frame_size) != OK) 342433d6423SLionel Sambuc panic("vm: could not copy stack for boot process %s (ep=%d)\n", 343433d6423SLionel Sambuc execi->progname, vmp->vm_endpoint); 344433d6423SLionel Sambuc 345433d6423SLionel Sambuc if(sys_exec(vmp->vm_endpoint, (vir_bytes)vsp, 346433d6423SLionel Sambuc (vir_bytes)execi->progname, execi->pc, 347433d6423SLionel Sambuc vsp + ((int)psp - (int)frame)) != OK) 348433d6423SLionel Sambuc panic("vm: boot process exec of process %s (ep=%d) failed\n", 349433d6423SLionel Sambuc execi->progname,vmp->vm_endpoint); 350433d6423SLionel Sambuc 351433d6423SLionel Sambuc /* make it runnable */ 352433d6423SLionel Sambuc if(sys_vmctl(vmp->vm_endpoint, VMCTL_BOOTINHIBIT_CLEAR, 0) != OK) 353433d6423SLionel Sambuc panic("VMCTL_BOOTINHIBIT_CLEAR failed"); 354433d6423SLionel Sambuc } 355433d6423SLionel Sambuc 356433d6423SLionel Sambuc static int do_procctl_notrans(message *msg) 357433d6423SLionel Sambuc { 358433d6423SLionel Sambuc int transid = 0; 359433d6423SLionel Sambuc 360433d6423SLionel Sambuc assert(!IS_VFS_FS_TRANSID(transid)); 361433d6423SLionel Sambuc 362433d6423SLionel Sambuc return do_procctl(msg, transid); 363433d6423SLionel Sambuc } 364433d6423SLionel Sambuc 365433d6423SLionel Sambuc void init_vm(void) 366433d6423SLionel Sambuc { 367433d6423SLionel Sambuc int s, i; 368433d6423SLionel Sambuc static struct memory mem_chunks[NR_MEMS]; 369433d6423SLionel Sambuc static struct boot_image *ip; 370433d6423SLionel Sambuc extern void __minix_init(void); 371433d6423SLionel Sambuc multiboot_module_t *mod; 372433d6423SLionel Sambuc vir_bytes kern_dyn, kern_static; 373433d6423SLionel Sambuc 374433d6423SLionel Sambuc #if SANITYCHECKS 375433d6423SLionel Sambuc incheck = nocheck = 0; 376433d6423SLionel Sambuc #endif 377433d6423SLionel Sambuc 378433d6423SLionel Sambuc /* Retrieve various crucial boot parameters */ 379433d6423SLionel Sambuc if(OK != (s=sys_getkinfo(&kernel_boot_info))) { 380433d6423SLionel Sambuc panic("couldn't get bootinfo: %d", s); 381433d6423SLionel Sambuc } 382433d6423SLionel Sambuc 383433d6423SLionel Sambuc /* Turn file mmap on? */ 384433d6423SLionel Sambuc enable_filemap=1; /* yes by default */ 385433d6423SLionel Sambuc env_parse("filemap", "d", 0, &enable_filemap, 0, 1); 386433d6423SLionel Sambuc 387433d6423SLionel Sambuc /* Sanity check */ 388433d6423SLionel Sambuc assert(kernel_boot_info.mmap_size > 0); 389433d6423SLionel Sambuc assert(kernel_boot_info.mods_with_kernel > 0); 390433d6423SLionel Sambuc 391433d6423SLionel Sambuc /* Get chunks of available memory. */ 392433d6423SLionel Sambuc get_mem_chunks(mem_chunks); 393433d6423SLionel Sambuc 394433d6423SLionel Sambuc /* Set table to 0. This invalidates all slots (clear VMF_INUSE). */ 395433d6423SLionel Sambuc memset(vmproc, 0, sizeof(vmproc)); 396433d6423SLionel Sambuc 397433d6423SLionel Sambuc for(i = 0; i < ELEMENTS(vmproc); i++) { 398433d6423SLionel Sambuc vmproc[i].vm_slot = i; 399433d6423SLionel Sambuc } 400433d6423SLionel Sambuc 401433d6423SLionel Sambuc /* Initialize ACL data structures. */ 402433d6423SLionel Sambuc acl_init(); 403433d6423SLionel Sambuc 404433d6423SLionel Sambuc /* region management initialization. */ 405433d6423SLionel Sambuc map_region_init(); 406433d6423SLionel Sambuc 407433d6423SLionel Sambuc /* Initialize tables to all physical memory. */ 408433d6423SLionel Sambuc mem_init(mem_chunks); 409433d6423SLionel Sambuc 410433d6423SLionel Sambuc /* Architecture-dependent initialization. */ 411433d6423SLionel Sambuc init_proc(VM_PROC_NR); 412433d6423SLionel Sambuc pt_init(); 413433d6423SLionel Sambuc 414433d6423SLionel Sambuc /* Acquire kernel ipc vectors that weren't available 415433d6423SLionel Sambuc * before VM had determined kernel mappings 416433d6423SLionel Sambuc */ 417433d6423SLionel Sambuc __minix_init(); 418433d6423SLionel Sambuc 419433d6423SLionel Sambuc /* The kernel's freelist does not include boot-time modules; let 420433d6423SLionel Sambuc * the allocator know that the total memory is bigger. 421433d6423SLionel Sambuc */ 422433d6423SLionel Sambuc for (mod = &kernel_boot_info.module_list[0]; 423433d6423SLionel Sambuc mod < &kernel_boot_info.module_list[kernel_boot_info.mods_with_kernel-1]; mod++) { 424433d6423SLionel Sambuc phys_bytes len = mod->mod_end-mod->mod_start+1; 425433d6423SLionel Sambuc len = roundup(len, VM_PAGE_SIZE); 426433d6423SLionel Sambuc mem_add_total_pages(len/VM_PAGE_SIZE); 427433d6423SLionel Sambuc } 428433d6423SLionel Sambuc 429433d6423SLionel Sambuc kern_dyn = kernel_boot_info.kernel_allocated_bytes_dynamic; 430433d6423SLionel Sambuc kern_static = kernel_boot_info.kernel_allocated_bytes; 431433d6423SLionel Sambuc kern_static = roundup(kern_static, VM_PAGE_SIZE); 432433d6423SLionel Sambuc mem_add_total_pages((kern_dyn + kern_static)/VM_PAGE_SIZE); 433433d6423SLionel Sambuc 434433d6423SLionel Sambuc /* Give these processes their own page table. */ 435433d6423SLionel Sambuc for (ip = &kernel_boot_info.boot_procs[0]; 436433d6423SLionel Sambuc ip < &kernel_boot_info.boot_procs[NR_BOOT_PROCS]; ip++) { 437433d6423SLionel Sambuc struct vmproc *vmp; 438433d6423SLionel Sambuc 439433d6423SLionel Sambuc if(ip->proc_nr < 0) continue; 440433d6423SLionel Sambuc 441433d6423SLionel Sambuc assert(ip->start_addr); 442433d6423SLionel Sambuc 443433d6423SLionel Sambuc /* VM has already been set up by the kernel and pt_init(). 444433d6423SLionel Sambuc * Any other boot process is already in memory and is set up 445433d6423SLionel Sambuc * here. 446433d6423SLionel Sambuc */ 447433d6423SLionel Sambuc if(ip->proc_nr == VM_PROC_NR) continue; 448433d6423SLionel Sambuc 449433d6423SLionel Sambuc vmp = init_proc(ip->proc_nr); 450433d6423SLionel Sambuc 451433d6423SLionel Sambuc exec_bootproc(vmp, ip); 452433d6423SLionel Sambuc 453433d6423SLionel Sambuc /* Free the file blob */ 454433d6423SLionel Sambuc assert(!(ip->start_addr % VM_PAGE_SIZE)); 455433d6423SLionel Sambuc ip->len = roundup(ip->len, VM_PAGE_SIZE); 456433d6423SLionel Sambuc free_mem(ABS2CLICK(ip->start_addr), ABS2CLICK(ip->len)); 457433d6423SLionel Sambuc } 458433d6423SLionel Sambuc 459433d6423SLionel Sambuc /* Set up table of calls. */ 460433d6423SLionel Sambuc #define CALLMAP(code, func) { int _cmi; \ 461433d6423SLionel Sambuc _cmi=CALLNUMBER(code); \ 462433d6423SLionel Sambuc assert(_cmi >= 0); \ 463433d6423SLionel Sambuc assert(_cmi < NR_VM_CALLS); \ 464433d6423SLionel Sambuc vm_calls[_cmi].vmc_func = (func); \ 465433d6423SLionel Sambuc vm_calls[_cmi].vmc_name = #code; \ 466433d6423SLionel Sambuc } 467433d6423SLionel Sambuc 468433d6423SLionel Sambuc /* Set call table to 0. This invalidates all calls (clear 469433d6423SLionel Sambuc * vmc_func). 470433d6423SLionel Sambuc */ 471433d6423SLionel Sambuc memset(vm_calls, 0, sizeof(vm_calls)); 472433d6423SLionel Sambuc 473433d6423SLionel Sambuc /* Basic VM calls. */ 474433d6423SLionel Sambuc CALLMAP(VM_MMAP, do_mmap); 475433d6423SLionel Sambuc CALLMAP(VM_MUNMAP, do_munmap); 476433d6423SLionel Sambuc CALLMAP(VM_MAP_PHYS, do_map_phys); 477433d6423SLionel Sambuc CALLMAP(VM_UNMAP_PHYS, do_munmap); 478433d6423SLionel Sambuc 479433d6423SLionel Sambuc /* Calls from PM. */ 480433d6423SLionel Sambuc CALLMAP(VM_EXIT, do_exit); 481433d6423SLionel Sambuc CALLMAP(VM_FORK, do_fork); 482433d6423SLionel Sambuc CALLMAP(VM_BRK, do_brk); 483433d6423SLionel Sambuc CALLMAP(VM_WILLEXIT, do_willexit); 484433d6423SLionel Sambuc CALLMAP(VM_NOTIFY_SIG, do_notify_sig); 485433d6423SLionel Sambuc 486433d6423SLionel Sambuc CALLMAP(VM_PROCCTL, do_procctl_notrans); 487433d6423SLionel Sambuc 488433d6423SLionel Sambuc /* Calls from VFS. */ 489433d6423SLionel Sambuc CALLMAP(VM_VFS_REPLY, do_vfs_reply); 490433d6423SLionel Sambuc CALLMAP(VM_VFS_MMAP, do_vfs_mmap); 491433d6423SLionel Sambuc 492433d6423SLionel Sambuc /* Calls from RS */ 493433d6423SLionel Sambuc CALLMAP(VM_RS_SET_PRIV, do_rs_set_priv); 494433d6423SLionel Sambuc CALLMAP(VM_RS_UPDATE, do_rs_update); 495433d6423SLionel Sambuc CALLMAP(VM_RS_MEMCTL, do_rs_memctl); 496433d6423SLionel Sambuc 497433d6423SLionel Sambuc /* Generic calls. */ 498433d6423SLionel Sambuc CALLMAP(VM_REMAP, do_remap); 499433d6423SLionel Sambuc CALLMAP(VM_REMAP_RO, do_remap); 500433d6423SLionel Sambuc CALLMAP(VM_GETPHYS, do_get_phys); 501433d6423SLionel Sambuc CALLMAP(VM_SHM_UNMAP, do_munmap); 502433d6423SLionel Sambuc CALLMAP(VM_GETREF, do_get_refcount); 503433d6423SLionel Sambuc CALLMAP(VM_INFO, do_info); 504433d6423SLionel Sambuc CALLMAP(VM_QUERY_EXIT, do_query_exit); 505433d6423SLionel Sambuc CALLMAP(VM_WATCH_EXIT, do_watch_exit); 506433d6423SLionel Sambuc 507433d6423SLionel Sambuc /* Cache blocks. */ 508433d6423SLionel Sambuc CALLMAP(VM_MAPCACHEPAGE, do_mapcache); 509433d6423SLionel Sambuc CALLMAP(VM_SETCACHEPAGE, do_setcache); 510*e94f856bSDavid van Moolenbroek CALLMAP(VM_FORGETCACHEPAGE, do_forgetcache); 511433d6423SLionel Sambuc CALLMAP(VM_CLEARCACHE, do_clearcache); 512433d6423SLionel Sambuc 513433d6423SLionel Sambuc /* getrusage */ 514433d6423SLionel Sambuc CALLMAP(VM_GETRUSAGE, do_getrusage); 515433d6423SLionel Sambuc 516433d6423SLionel Sambuc /* Initialize the structures for queryexit */ 517433d6423SLionel Sambuc init_query_exit(); 518433d6423SLionel Sambuc } 519433d6423SLionel Sambuc 520433d6423SLionel Sambuc /*===========================================================================* 521433d6423SLionel Sambuc * sef_cb_signal_handler * 522433d6423SLionel Sambuc *===========================================================================*/ 523433d6423SLionel Sambuc static void sef_cb_signal_handler(int signo) 524433d6423SLionel Sambuc { 525433d6423SLionel Sambuc /* Check for known kernel signals, ignore anything else. */ 526433d6423SLionel Sambuc switch(signo) { 527433d6423SLionel Sambuc /* There is a pending memory request from the kernel. */ 528433d6423SLionel Sambuc case SIGKMEM: 529433d6423SLionel Sambuc do_memory(); 530433d6423SLionel Sambuc break; 531433d6423SLionel Sambuc } 532433d6423SLionel Sambuc 533433d6423SLionel Sambuc /* It can happen that we get stuck receiving signals 534433d6423SLionel Sambuc * without sef_receive() returning. We could need more memory 535433d6423SLionel Sambuc * though. 536433d6423SLionel Sambuc */ 537433d6423SLionel Sambuc if(missing_spares > 0) { 538433d6423SLionel Sambuc alloc_cycle(); /* pagetable code wants to be called */ 539433d6423SLionel Sambuc } 540433d6423SLionel Sambuc 541433d6423SLionel Sambuc pt_clearmapcache(); 542433d6423SLionel Sambuc } 543433d6423SLionel Sambuc 544433d6423SLionel Sambuc /*===========================================================================* 545433d6423SLionel Sambuc * map_service * 546433d6423SLionel Sambuc *===========================================================================*/ 547433d6423SLionel Sambuc static int map_service(struct rprocpub *rpub) 548433d6423SLionel Sambuc { 549433d6423SLionel Sambuc /* Map a new service by initializing its call mask. */ 550433d6423SLionel Sambuc int r, proc_nr; 551433d6423SLionel Sambuc 552433d6423SLionel Sambuc if ((r = vm_isokendpt(rpub->endpoint, &proc_nr)) != OK) { 553433d6423SLionel Sambuc return r; 554433d6423SLionel Sambuc } 555433d6423SLionel Sambuc 556433d6423SLionel Sambuc /* Copy the call mask. */ 557433d6423SLionel Sambuc acl_set(&vmproc[proc_nr], rpub->vm_call_mask, !IS_RPUB_BOOT_USR(rpub)); 558433d6423SLionel Sambuc 559433d6423SLionel Sambuc return(OK); 560433d6423SLionel Sambuc } 561