/*===========================================================================* * kenv_dmp * *===========================================================================*/ PUBLIC void kenv_dmp() { struct kinfo kinfo; struct machine machine; int r; if ((r = sys_getkinfo(&kinfo)) != OK) { printf("IS: warning: couldn't get copy of kernel info struct: %d\n", r); return; } if ((r = sys_getmachine(&machine)) != OK) { printf("IS: warning: couldn't get copy of kernel machine struct: %d\n", r); return; } printf("Dump of kinfo structure.\n\n"); printf("Kernel info structure:\n"); printf("- code_base: %5lu\n", kinfo.code_base); printf("- code_size: %5lu\n", kinfo.code_size); printf("- data_base: %5lu\n", kinfo.data_base); printf("- data_size: %5lu\n", kinfo.data_size); printf("- proc_addr: %5lu\n", kinfo.proc_addr); printf("- bootdev_base: %5lu\n", kinfo.bootdev_base); printf("- bootdev_size: %5lu\n", kinfo.bootdev_size); printf("- ramdev_base: %5lu\n", kinfo.ramdev_base); printf("- ramdev_size: %5lu\n", kinfo.ramdev_size); printf("- nr_procs: %3u\n", kinfo.nr_procs); printf("- nr_tasks: %3u\n", kinfo.nr_tasks); printf("- release: %.6s\n", kinfo.release); printf("- version: %.6s\n", kinfo.version); printf("\n"); }
/* * Print general kernel information. */ static void root_kinfo(void) { struct kinfo kinfo; if (sys_getkinfo(&kinfo) != OK) return; buf_printf("%u %u\n", kinfo.nr_procs, kinfo.nr_tasks); }
/*===========================================================================* * root_kinfo * *===========================================================================*/ static void root_kinfo(void) { /* Print general kernel information. */ struct kinfo kinfo; if (sys_getkinfo(&kinfo) != OK) return; buf_printf("%u %u\n", kinfo.nr_procs, kinfo.nr_tasks); }
/*===========================================================================* * kenv_dmp * *===========================================================================*/ PUBLIC void kenv_dmp() { struct kinfo kinfo; struct machine machine; int r; if ((r = sys_getkinfo(&kinfo)) != OK) { report("IS","warning: couldn't get copy of kernel info struct", r); return; } if ((r = sys_getmachine(&machine)) != OK) { report("IS","warning: couldn't get copy of kernel machine struct", r); return; } printf("Dump of kinfo and machine structures.\n\n"); printf("Machine structure:\n"); printf("- pc_at: %3d\n", machine.pc_at); printf("- ps_mca: %3d\n", machine.ps_mca); printf("- processor: %3d\n", machine.processor); printf("- protected: %3d\n", machine.prot); printf("- vdu_ega: %3d\n", machine.vdu_ega); printf("- vdu_vga: %3d\n\n", machine.vdu_vga); printf("Kernel info structure:\n"); printf("- code_base: %5u\n", kinfo.code_base); printf("- code_size: %5u\n", kinfo.code_size); printf("- data_base: %5u\n", kinfo.data_base); printf("- data_size: %5u\n", kinfo.data_size); printf("- proc_addr: %5u\n", kinfo.proc_addr); printf("- kmem_base: %5u\n", kinfo.kmem_base); printf("- kmem_size: %5u\n", kinfo.kmem_size); printf("- bootdev_base: %5u\n", kinfo.bootdev_base); printf("- bootdev_size: %5u\n", kinfo.bootdev_size); printf("- ramdev_base: %5u\n", kinfo.ramdev_base); printf("- ramdev_size: %5u\n", kinfo.ramdev_size); printf("- params_base: %5u\n", kinfo.params_base); printf("- params_size: %5u\n", kinfo.params_size); printf("- nr_procs: %3u\n", kinfo.nr_procs); printf("- nr_tasks: %3u\n", kinfo.nr_tasks); printf("- release: %.6s\n", kinfo.release); printf("- version: %.6s\n", kinfo.version); #if DEBUG_LOCK_CHECK printf("- relocking: %d\n", kinfo.relocking); #endif printf("\n"); }
/*===========================================================================* * sched_dmp * *===========================================================================*/ PUBLIC void sched_dmp() { struct proc *rdy_head[NR_SCHED_QUEUES]; struct kinfo kinfo; register struct proc *rp; vir_bytes ptr_diff; int r; /* First obtain a scheduling information. */ if ((r = sys_getschedinfo(proc, rdy_head)) != OK) { report("IS","warning: couldn't get copy of process table", r); return; } /* Then obtain kernel addresses to correct pointer information. */ if ((r = sys_getkinfo(&kinfo)) != OK) { report("IS","warning: couldn't get kernel addresses", r); return; } /* Update all pointers. Nasty pointer algorithmic ... */ ptr_diff = (vir_bytes) proc - (vir_bytes) kinfo.proc_addr; for (r=0;r<NR_SCHED_QUEUES; r++) if (rdy_head[r] != NIL_PROC) rdy_head[r] = (struct proc *)((vir_bytes) rdy_head[r] + ptr_diff); for (rp=BEG_PROC_ADDR; rp < END_PROC_ADDR; rp++) if (rp->p_nextready != NIL_PROC) rp->p_nextready = (struct proc *)((vir_bytes) rp->p_nextready + ptr_diff); /* Now show scheduling queues. */ printf("Dumping scheduling queues.\n"); for (r=0;r<NR_SCHED_QUEUES; r++) { rp = rdy_head[r]; if (!rp) continue; printf("%2d: ", r); while (rp != NIL_PROC) { printf("%3d ", rp->p_nr); rp = rp->p_nextready; } printf("\n"); } printf("\n"); }
/*===========================================================================* * sef_cb_init_fresh * *===========================================================================*/ static int sef_cb_init_fresh(int UNUSED(type), sef_init_info_t *UNUSED(info)) { /* Initialize the memory driver. */ int i; #if 0 struct kinfo kinfo; /* kernel information */ int s; if (OK != (s=sys_getkinfo(&kinfo))) { panic("Couldn't get kernel information: %d", s); } /* Map in kernel memory for /dev/kmem. */ m_geom[KMEM_DEV].dv_base = cvul64(kinfo.kmem_base); m_geom[KMEM_DEV].dv_size = cvul64(kinfo.kmem_size); if((m_vaddrs[KMEM_DEV] = vm_map_phys(SELF, (void *) kinfo.kmem_base, kinfo.kmem_size)) == MAP_FAILED) { printf("MEM: Couldn't map in /dev/kmem."); } #endif /* Ramdisk image built into the memory driver */ m_geom[IMGRD_DEV].dv_base= cvul64(0); m_geom[IMGRD_DEV].dv_size= cvul64(imgrd_size); m_vaddrs[IMGRD_DEV] = (vir_bytes) imgrd; /* Initialize /dev/zero. Simply write zeros into the buffer. */ for (i=0; i<ZERO_BUF_SIZE; i++) { dev_zero[i] = '\0'; } for(i = 0; i < NR_DEVS; i++) openct[i] = 0; /* Set up memory range for /dev/mem. */ m_geom[MEM_DEV].dv_base = cvul64(0); m_geom[MEM_DEV].dv_size = cvul64(0xffffffff); m_vaddrs[MEM_DEV] = (vir_bytes) MAP_FAILED; /* we are not mapping this in. */ return(OK); }
/*===========================================================================* * kenv_dmp * *===========================================================================*/ void kenv_dmp() { struct kinfo kinfo; struct machine machine; int r; if ((r = sys_getkinfo(&kinfo)) != OK) { printf("IS: warning: couldn't get copy of kernel info struct: %d\n", r); return; } if ((r = sys_getmachine(&machine)) != OK) { printf("IS: warning: couldn't get copy of kernel machine struct: %d\n", r); return; } printf("Dump of kinfo structure.\n\n"); printf("Kernel info structure:\n"); printf("- nr_procs: %3u\n", kinfo.nr_procs); printf("- nr_tasks: %3u\n", kinfo.nr_tasks); printf("- release: %.6s\n", kinfo.release); printf("- version: %.6s\n", kinfo.version); printf("\n"); }
/*===========================================================================* * sef_cb_init_fresh * *===========================================================================*/ static int sef_cb_init_fresh(int UNUSED(type), sef_init_info_t *UNUSED(info)) { /* Initialize the process manager. * Memory use info is collected from the boot monitor, the kernel, and * all processes compiled into the system image. Initially this information * is put into an array mem_chunks. Elements of mem_chunks are struct memory, * and hold base, size pairs in units of clicks. This array is small, there * should be no more than 8 chunks. After the array of chunks has been built * the contents are used to initialize the hole list. Space for the hole list * is reserved as an array with twice as many elements as the maximum number * of processes allowed. It is managed as a linked list, and elements of the * array are struct hole, which, in addition to storage for a base and size in * click units also contain space for a link, a pointer to another element. */ int s; static struct boot_image image[NR_BOOT_PROCS]; register struct boot_image *ip; static char core_sigs[] = { SIGQUIT, SIGILL, SIGTRAP, SIGABRT, SIGEMT, SIGFPE, SIGBUS, SIGSEGV }; static char ign_sigs[] = { SIGCHLD, SIGWINCH, SIGCONT }; static char noign_sigs[] = { SIGILL, SIGTRAP, SIGEMT, SIGFPE, SIGBUS, SIGSEGV }; register struct mproc *rmp; register char *sig_ptr; message mess; /* Initialize process table, including timers. */ for (rmp=&mproc[0]; rmp<&mproc[NR_PROCS]; rmp++) { init_timer(&rmp->mp_timer); rmp->mp_magic = MP_MAGIC; } /* Build the set of signals which cause core dumps, and the set of signals * that are by default ignored. */ sigemptyset(&core_sset); for (sig_ptr = core_sigs; sig_ptr < core_sigs+sizeof(core_sigs); sig_ptr++) sigaddset(&core_sset, *sig_ptr); sigemptyset(&ign_sset); for (sig_ptr = ign_sigs; sig_ptr < ign_sigs+sizeof(ign_sigs); sig_ptr++) sigaddset(&ign_sset, *sig_ptr); sigemptyset(&noign_sset); for (sig_ptr = noign_sigs; sig_ptr < noign_sigs+sizeof(noign_sigs); sig_ptr++) sigaddset(&noign_sset, *sig_ptr); /* Obtain a copy of the boot monitor parameters and the kernel info struct. * Parse the list of free memory chunks. This list is what the boot monitor * reported, but it must be corrected for the kernel and system processes. */ if ((s=sys_getmonparams(monitor_params, sizeof(monitor_params))) != OK) panic("get monitor params failed: %d", s); if ((s=sys_getkinfo(&kinfo)) != OK) panic("get kernel info failed: %d", s); /* Initialize PM's process table. Request a copy of the system image table * that is defined at the kernel level to see which slots to fill in. */ if (OK != (s=sys_getimage(image))) panic("couldn't get image table: %d", s); procs_in_use = 0; /* start populating table */ for (ip = &image[0]; ip < &image[NR_BOOT_PROCS]; ip++) { if (ip->proc_nr >= 0) { /* task have negative nrs */ procs_in_use += 1; /* found user process */ /* Set process details found in the image table. */ rmp = &mproc[ip->proc_nr]; strlcpy(rmp->mp_name, ip->proc_name, PROC_NAME_LEN); (void) sigemptyset(&rmp->mp_ignore); (void) sigemptyset(&rmp->mp_sigmask); (void) sigemptyset(&rmp->mp_catch); if (ip->proc_nr == INIT_PROC_NR) { /* user process */ /* INIT is root, we make it father of itself. This is * not really OK, INIT should have no father, i.e. * a father with pid NO_PID. But PM currently assumes * that mp_parent always points to a valid slot number. */ rmp->mp_parent = INIT_PROC_NR; rmp->mp_procgrp = rmp->mp_pid = INIT_PID; rmp->mp_flags |= IN_USE; /* Set scheduling info */ rmp->mp_scheduler = KERNEL; rmp->mp_nice = get_nice_value(USR_Q); } else { /* system process */ if(ip->proc_nr == RS_PROC_NR) { rmp->mp_parent = INIT_PROC_NR; } else { rmp->mp_parent = RS_PROC_NR; } rmp->mp_pid = get_free_pid(); rmp->mp_flags |= IN_USE | PRIV_PROC; /* RS schedules this process */ rmp->mp_scheduler = NONE; rmp->mp_nice = get_nice_value(SRV_Q); } /* Get kernel endpoint identifier. */ rmp->mp_endpoint = ip->endpoint; /* Tell VFS about this system process. */ mess.m_type = PM_INIT; mess.PM_SLOT = ip->proc_nr; mess.PM_PID = rmp->mp_pid; mess.PM_PROC = rmp->mp_endpoint; if (OK != (s=send(VFS_PROC_NR, &mess))) panic("can't sync up with VFS: %d", s); } } /* Tell VFS that no more system processes follow and synchronize. */ mess.PR_ENDPT = NONE; if (sendrec(VFS_PROC_NR, &mess) != OK || mess.m_type != OK) panic("can't sync up with VFS"); #if defined(__i386__) uts_val.machine[0] = 'i'; strcpy(uts_val.machine + 1, itoa(getprocessor())); #elif defined(__arm__) strcpy(uts_val.machine, "arm"); #endif system_hz = sys_hz(); /* Initialize user-space scheduling. */ sched_init(); return(OK); }
/*===========================================================================* * main * *===========================================================================*/ int main(void) { /* This is the main routine of this service. The main loop consists of * three major activities: getting new work, processing the work, and * sending the reply. The loop never terminates, unless a panic occurs. */ message m; /* request message */ int ipc_status; /* status code */ int call_nr, who_e,who_p; /* call number and caller */ int result; /* result to return */ int s; /* SEF local startup. */ sef_local_startup(); if (OK != (s=sys_getmachine(&machine))) panic("couldn't get machine info: %d", s); if (OK != (s=sys_getkinfo(&kinfo))) panic("couldn't get kernel kinfo: %d", s); /* Main loop - get work and do it, forever. */ while (TRUE) { /* Wait for request message. */ get_work(&m, &ipc_status); who_e = m.m_source; if(rs_isokendpt(who_e, &who_p) != OK) { panic("message from bogus source: %d", who_e); } call_nr = m.m_type; //if(who_e == 11)printf("Message for SEM recieved in RS\n"); /* Now determine what to do. Four types of requests are expected: * - Heartbeat messages (notifications from registered system services) * - System notifications (synchronous alarm) * - User requests (control messages to manage system services) * - Ready messages (reply messages from registered services) */ /* Notification messages are control messages and do not need a reply. * These include heartbeat messages and system notifications. */ if (is_ipc_notify(ipc_status)) { switch (who_p) { case CLOCK: do_period(&m); /* check services status */ continue; default: /* heartbeat notification */ if (rproc_ptr[who_p] != NULL) { /* mark heartbeat time */ rproc_ptr[who_p]->r_alive_tm = m.NOTIFY_TIMESTAMP; } else { printf("RS: warning: got unexpected notify message from %d\n", m.m_source); } } } /* If we get this far, this is a normal request. * Handle the request and send a reply to the caller. */ else { if (call_nr != COMMON_GETSYSINFO && (call_nr < RS_RQ_BASE || call_nr >= RS_RQ_BASE+0x100)) { /* Ignore invalid requests. Do not try to reply. */ printf("RS: warning: got invalid request %d from endpoint %d\n", call_nr, m.m_source); continue; } /* Handler functions are responsible for permission checking. */ switch(call_nr) { /* User requests. */ case RS_UP: result = do_up(&m); break; case RS_DOWN: result = do_down(&m); break; case RS_REFRESH: result = do_refresh(&m); break; case RS_RESTART: result = do_restart(&m); break; case RS_SHUTDOWN: result = do_shutdown(&m); break; case RS_UPDATE: result = do_update(&m); break; case RS_CLONE: result = do_clone(&m); break; case RS_EDIT: result = do_edit(&m); break; case COMMON_GETSYSINFO: result = do_getsysinfo(&m); break; case RS_LOOKUP: result = do_lookup(&m); break; /* Ready messages. */ case RS_INIT: result = do_init_ready(&m); break; case RS_LU_PREPARE: result = do_upd_ready(&m); break; default: printf("RS: warning: got unexpected request %d from %d\n", m.m_type, m.m_source); result = EINVAL; } /* Finally send reply message, unless disabled. */ if (result != EDONTREPLY) { m.m_type = result; reply(who_e, NULL, &m); } } } }
void init_vm(void) { int s, i; static struct memory mem_chunks[NR_MEMS]; static struct boot_image *ip; extern void __minix_init(void); multiboot_module_t *mod; vir_bytes kern_dyn, kern_static; #if SANITYCHECKS incheck = nocheck = 0; #endif /* Retrieve various crucial boot parameters */ if(OK != (s=sys_getkinfo(&kernel_boot_info))) { panic("couldn't get bootinfo: %d", s); } /* Turn file mmap on? */ env_parse("filemap", "d", 0, &enable_filemap, 0, 1); /* Sanity check */ assert(kernel_boot_info.mmap_size > 0); assert(kernel_boot_info.mods_with_kernel > 0); /* Get chunks of available memory. */ get_mem_chunks(mem_chunks); /* Set table to 0. This invalidates all slots (clear VMF_INUSE). */ memset(vmproc, 0, sizeof(vmproc)); for(i = 0; i < ELEMENTS(vmproc); i++) { vmproc[i].vm_slot = i; } /* Initialize ACL data structures. */ acl_init(); /* region management initialization. */ map_region_init(); /* Initialize tables to all physical memory. */ mem_init(mem_chunks); /* Architecture-dependent initialization. */ init_proc(VM_PROC_NR); pt_init(); /* The kernel's freelist does not include boot-time modules; let * the allocator know that the total memory is bigger. */ for (mod = &kernel_boot_info.module_list[0]; mod < &kernel_boot_info.module_list[kernel_boot_info.mods_with_kernel-1]; mod++) { phys_bytes len = mod->mod_end-mod->mod_start+1; len = roundup(len, VM_PAGE_SIZE); mem_add_total_pages(len/VM_PAGE_SIZE); } kern_dyn = kernel_boot_info.kernel_allocated_bytes_dynamic; kern_static = kernel_boot_info.kernel_allocated_bytes; kern_static = roundup(kern_static, VM_PAGE_SIZE); mem_add_total_pages((kern_dyn + kern_static)/VM_PAGE_SIZE); /* Give these processes their own page table. */ for (ip = &kernel_boot_info.boot_procs[0]; ip < &kernel_boot_info.boot_procs[NR_BOOT_PROCS]; ip++) { struct vmproc *vmp; if(ip->proc_nr < 0) continue; assert(ip->start_addr); /* VM has already been set up by the kernel and pt_init(). * Any other boot process is already in memory and is set up * here. */ if(ip->proc_nr == VM_PROC_NR) continue; vmp = init_proc(ip->proc_nr); exec_bootproc(vmp, ip); /* Free the file blob */ assert(!(ip->start_addr % VM_PAGE_SIZE)); ip->len = roundup(ip->len, VM_PAGE_SIZE); free_mem(ABS2CLICK(ip->start_addr), ABS2CLICK(ip->len)); } /* Set up table of calls. */ #define CALLMAP(code, func) { int i; \ i=CALLNUMBER(code); \ assert(i >= 0); \ assert(i < NR_VM_CALLS); \ vm_calls[i].vmc_func = (func); \ vm_calls[i].vmc_name = #code; \ } /* Set call table to 0. This invalidates all calls (clear * vmc_func). */ memset(vm_calls, 0, sizeof(vm_calls)); /* Basic VM calls. */ CALLMAP(VM_MMAP, do_mmap); CALLMAP(VM_MUNMAP, do_munmap); CALLMAP(VM_MAP_PHYS, do_map_phys); CALLMAP(VM_UNMAP_PHYS, do_munmap); /* Calls from PM. */ CALLMAP(VM_EXIT, do_exit); CALLMAP(VM_FORK, do_fork); CALLMAP(VM_BRK, do_brk); CALLMAP(VM_WILLEXIT, do_willexit); CALLMAP(VM_NOTIFY_SIG, do_notify_sig); /* Calls from VFS. */ CALLMAP(VM_VFS_REPLY, do_vfs_reply); CALLMAP(VM_VFS_MMAP, do_vfs_mmap); /* Calls from RS */ CALLMAP(VM_RS_SET_PRIV, do_rs_set_priv); CALLMAP(VM_RS_UPDATE, do_rs_update); CALLMAP(VM_RS_MEMCTL, do_rs_memctl); /* Calls from RS/VFS */ CALLMAP(VM_PROCCTL, do_procctl); /* Generic calls. */ CALLMAP(VM_REMAP, do_remap); CALLMAP(VM_REMAP_RO, do_remap); CALLMAP(VM_GETPHYS, do_get_phys); CALLMAP(VM_SHM_UNMAP, do_munmap); CALLMAP(VM_GETREF, do_get_refcount); CALLMAP(VM_INFO, do_info); CALLMAP(VM_QUERY_EXIT, do_query_exit); CALLMAP(VM_WATCH_EXIT, do_watch_exit); /* Cache blocks. */ CALLMAP(VM_MAPCACHEPAGE, do_mapcache); CALLMAP(VM_SETCACHEPAGE, do_setcache); /* getrusage */ CALLMAP(VM_GETRUSAGE, do_getrusage); /* Initialize the structures for queryexit */ init_query_exit(); /* Acquire kernel ipc vectors that weren't available * before VM had determined kernel mappings */ __minix_init(); }
/*===========================================================================* * main * *===========================================================================*/ int main(void) { /* This is the main program of the file system. The main loop consists of * three major activities: getting new work, processing the work, and sending * the reply. This loop never terminates as long as the file system runs. */ int transid; struct job *job; /* SEF local startup. */ sef_local_startup(); printf("Started VFS: %d worker thread(s)\n", NR_WTHREADS); if (OK != (sys_getkinfo(&kinfo))) panic("couldn't get kernel kinfo"); /* This is the main loop that gets work, processes it, and sends replies. */ while (TRUE) { yield_all(); /* let other threads run */ self = NULL; job = NULL; send_work(); get_work(); transid = TRNS_GET_ID(m_in.m_type); if (IS_VFS_FS_TRANSID(transid)) { job = worker_getjob( (thread_t) transid - VFS_TRANSID); if (job == NULL) { printf("VFS: spurious message %d from endpoint %d\n", m_in.m_type, m_in.m_source); continue; } m_in.m_type = TRNS_DEL_ID(m_in.m_type); } if (job != NULL) { do_fs_reply(job); continue; } else if (who_e == PM_PROC_NR) { /* Calls from PM */ /* Special control messages from PM */ sys_worker_start(do_pm); continue; } else if (is_notify(call_nr)) { /* A task notify()ed us */ if (who_e == DS_PROC_NR) handle_work(ds_event); else if (fp != NULL && (fp->fp_flags & FP_SRV_PROC)) handle_work(do_dev_event); else sys_worker_start(do_control_msgs); continue; } else if (who_p < 0) { /* i.e., message comes from a task */ /* We're going to ignore this message. Tasks should * send notify()s only. */ printf("VFS: ignoring message from %d (%d)\n", who_e, call_nr); continue; } /* At this point we either have results from an asynchronous device * or a new system call. In both cases a new worker thread has to be * started and there might not be one available from the pool. This is * not a problem (requests/replies are simply queued), except when * they're from an FS endpoint, because these can cause a deadlock. * handle_work() takes care of the details. */ if (IS_DRV_REPLY(call_nr)) { /* We've got results for a device request */ struct dmap *dp; dp = get_dmap(who_e); if (dp != NULL) { if (dev_style_asyn(dp->dmap_style)) { handle_work(do_async_dev_result); } else { if (dp->dmap_servicing == NONE) { printf("Got spurious dev reply from %d", who_e); } else { dev_reply(dp); } } continue; } printf("VFS: ignoring dev reply from unknown driver %d\n", who_e); } else { /* Normal syscall. */ handle_work(do_work); } } return(OK); /* shouldn't come here */ }
void init_vm(void) { int s, i; static struct memory mem_chunks[NR_MEMS]; static struct boot_image *ip; extern void __minix_init(void); #if SANITYCHECKS incheck = nocheck = 0; #endif /* Retrieve various crucial boot parameters */ if(OK != (s=sys_getkinfo(&kernel_boot_info))) { panic("couldn't get bootinfo: %d", s); } /* Sanity check */ assert(kernel_boot_info.mmap_size > 0); assert(kernel_boot_info.mods_with_kernel > 0); #if SANITYCHECKS env_parse("vm_sanitychecklevel", "d", 0, &vm_sanitychecklevel, 0, SCL_MAX); #endif /* Get chunks of available memory. */ get_mem_chunks(mem_chunks); /* Set table to 0. This invalidates all slots (clear VMF_INUSE). */ memset(vmproc, 0, sizeof(vmproc)); for(i = 0; i < ELEMENTS(vmproc); i++) { vmproc[i].vm_slot = i; } /* region management initialization. */ map_region_init(); /* Initialize tables to all physical memory. */ mem_init(mem_chunks); /* Architecture-dependent initialization. */ init_proc(VM_PROC_NR); pt_init(); /* Give these processes their own page table. */ for (ip = &kernel_boot_info.boot_procs[0]; ip < &kernel_boot_info.boot_procs[NR_BOOT_PROCS]; ip++) { struct vmproc *vmp; if(ip->proc_nr < 0) continue; assert(ip->start_addr); /* VM has already been set up by the kernel and pt_init(). * Any other boot process is already in memory and is set up * here. */ if(ip->proc_nr == VM_PROC_NR) continue; vmp = init_proc(ip->proc_nr); exec_bootproc(vmp, ip); /* Free the file blob */ assert(!(ip->start_addr % VM_PAGE_SIZE)); ip->len = roundup(ip->len, VM_PAGE_SIZE); free_mem(ABS2CLICK(ip->start_addr), ABS2CLICK(ip->len)); } /* Set up table of calls. */ #define CALLMAP(code, func) { int i; \ i=CALLNUMBER(code); \ assert(i >= 0); \ assert(i < NR_VM_CALLS); \ vm_calls[i].vmc_func = (func); \ vm_calls[i].vmc_name = #code; \ } /* Set call table to 0. This invalidates all calls (clear * vmc_func). */ memset(vm_calls, 0, sizeof(vm_calls)); /* Basic VM calls. */ CALLMAP(VM_MMAP, do_mmap); CALLMAP(VM_MUNMAP, do_munmap); CALLMAP(VM_MAP_PHYS, do_map_phys); CALLMAP(VM_UNMAP_PHYS, do_munmap); /* Calls from PM. */ CALLMAP(VM_EXIT, do_exit); CALLMAP(VM_FORK, do_fork); CALLMAP(VM_BRK, do_brk); CALLMAP(VM_WILLEXIT, do_willexit); CALLMAP(VM_NOTIFY_SIG, do_notify_sig); /* Calls from RS */ CALLMAP(VM_RS_SET_PRIV, do_rs_set_priv); CALLMAP(VM_RS_UPDATE, do_rs_update); CALLMAP(VM_RS_MEMCTL, do_rs_memctl); /* Calls from RS/VFS */ CALLMAP(VM_PROCCTL, do_procctl); /* Generic calls. */ CALLMAP(VM_REMAP, do_remap); CALLMAP(VM_REMAP_RO, do_remap); CALLMAP(VM_GETPHYS, do_get_phys); CALLMAP(VM_SHM_UNMAP, do_munmap); CALLMAP(VM_GETREF, do_get_refcount); CALLMAP(VM_INFO, do_info); CALLMAP(VM_QUERY_EXIT, do_query_exit); CALLMAP(VM_WATCH_EXIT, do_watch_exit); CALLMAP(VM_FORGETBLOCKS, do_forgetblocks); CALLMAP(VM_FORGETBLOCK, do_forgetblock); CALLMAP(VM_YIELDBLOCKGETBLOCK, do_yieldblockgetblock); /* Initialize the structures for queryexit */ init_query_exit(); /* Acquire kernel ipc vectors that weren't available * before VM had determined kernel mappings */ __minix_init(); }