/*===========================================================================* * sef_cb_init_fresh * *===========================================================================*/ static int sef_cb_init_fresh(int UNUSED(type), sef_init_info_t *UNUSED(info)) { /* Initialize the ti1225 driver. */ int r, devind; long v; if((r=tsc_calibrate()) != OK) panic("tsc_calibrate failed: %d", r); v = 0; (void) env_parse("instance", "d", 0, &v, 0, 255); instance = (int) v; v = 0; (void) env_parse("debug", "d", 0, &v, 0, 1); debug = (int) v; devind = hw_probe(instance); if (devind < 0) return(ENODEV); hw_init(&port, devind); return(OK); }
/* ** Name: void update_conf(dpeth_t *dep, dp_conf_t *dcp) ** Function: Gets the default settings from 'dp_conf' table and ** modifies them from the environment. */ static void update_conf(dpeth_t * dep, const dp_conf_t * dcp) { static char dpc_fmt[] = "x:d:x"; char ec_key[16]; long val; strcpy(ec_key, "DPETH0"); ec_key[5] += de_instance; dep->de_mode = DEM_SINK; val = dcp->dpc_port; /* Get I/O port address */ switch (env_parse(ec_key, dpc_fmt, 0, &val, 0x000L, 0x3FFL)) { case EP_OFF: dep->de_mode = DEM_DISABLED; break; case EP_ON: case EP_SET: dep->de_mode = DEM_ENABLED; break; } dep->de_base_port = val; val = dcp->dpc_irq | DEI_DEFAULT; /* Get Interrupt line (IRQ) */ env_parse(ec_key, dpc_fmt, 1, &val, 0L, (long) NR_IRQ_VECTORS - 1); dep->de_irq = val; val = dcp->dpc_mem; /* Get shared memory address */ env_parse(ec_key, dpc_fmt, 2, &val, 0L, LONG_MAX); dep->de_linmem = val; return; }
static int tda19988_env_parse() { int r; long int cec_busl; long int cec_addressl; long int hdmi_busl; long int hdmi_addressl; r = env_parse("cec_bus", "d", 0, &cec_busl, 1, 3); if (r != EP_SET) { return -1; } cec_bus = (uint32_t) cec_busl; r = env_parse("cec_address", "x", 0, &cec_addressl, 0x34, 0x37); if (r != EP_SET) { return -1; } cec_address = (i2c_addr_t) cec_addressl; r = env_parse("hdmi_bus", "d", 0, &hdmi_busl, 1, 3); if (r != EP_SET) { return -1; } hdmi_bus = (uint32_t) hdmi_busl; r = env_parse("hdmi_address", "x", 0, &hdmi_addressl, 0x70, 0x73); if (r != EP_SET) { return -1; } hdmi_address = (i2c_addr_t) hdmi_addressl; return OK; }
/*============================================================================* * lan8710a_init_addr * *============================================================================*/ static void lan8710a_init_addr(netdriver_addr_t * addr, unsigned int instance) { static char eakey[]= LAN8710A_ENVVAR "#_EA"; static char eafmt[]= "x:x:x:x:x:x"; int i; long v; /* * Do we have a user defined ethernet address? */ eakey[sizeof(LAN8710A_ENVVAR)-1] = '0' + instance; for (i= 0; i < 6; i++) { if (env_parse(eakey, eafmt, i, &v, 0x00L, 0xFFL) != EP_SET) break; else addr->na_addr[i] = v; } if (i == 6) return; /* * No; get the address from the chip itself. */ addr->na_addr[0] = lan8710a_reg_read(CTRL_MAC_ID0_HI) & 0xFF; addr->na_addr[1] = (lan8710a_reg_read(CTRL_MAC_ID0_HI) >> 8) & 0xFF; addr->na_addr[2] = (lan8710a_reg_read(CTRL_MAC_ID0_HI) >> 16) & 0xFF; addr->na_addr[3] = (lan8710a_reg_read(CTRL_MAC_ID0_HI) >> 24) & 0xFF; addr->na_addr[4] = lan8710a_reg_read(CTRL_MAC_ID0_LO) & 0xFF; addr->na_addr[5] = (lan8710a_reg_read(CTRL_MAC_ID0_LO) >> 8) & 0xFF; }
/*===========================================================================* * sef_cb_init_fresh * *===========================================================================*/ static int sef_cb_init_fresh(int type, sef_init_info_t *UNUSED(info)) { /* Initialize the dp8390 driver. */ dpeth_t *dep; long v; system_hz = sys_hz(); if (env_argc < 1) { panic("A head which at this time has no name"); } v = 0; (void) env_parse("instance", "d", 0, &v, 0, 255); de_instance = (int) v; dep = &de_state; strcpy(dep->de_name, "dp8390#0"); dep->de_name[7] += de_instance; /* Announce we are up! */ netdriver_announce(); return(OK); }
/*===========================================================================* * pci_conf * *===========================================================================*/ static void pci_conf() { int i, h; char *envvar, *p; struct dpeth *dep; static char envfmt[] = "*:d.d.d"; long v; static int first_time= 1; if (!first_time) return; first_time= 0; for (i= 0, dep= de_table; i<DE_PORT_NR; i++, dep++) { envvar= dp_conf[i].dpc_envvar; if (!(dep->de_pci= env_prefix(envvar, "pci"))) continue; /* no PCI config */ v= 0; (void) env_parse(envvar, envfmt, 1, &v, 0, 255); dep->de_pcibus= v; v= 0; (void) env_parse(envvar, envfmt, 2, &v, 0, 255); dep->de_pcidev= v; v= 0; (void) env_parse(envvar, envfmt, 3, &v, 0, 255); dep->de_pcifunc= v; } for (h= TRUE; h >= FALSE; h--) { for (i= 0, dep= de_table; i<DE_PORT_NR; i++, dep++) { if (!dep->de_pci) continue; if (((dep->de_pcibus | dep->de_pcidev | dep->de_pcifunc) != 0) != h) { continue; } if (!rtl_probe(dep)) dep->de_pci= -1; } } }
/*===========================================================================* * dpeth_task * *===========================================================================*/ void dp8390_task() { message m; int i, irq, r; dpeth_t *dep; long v; dpeth_tasknr= proc_number(proc_ptr); for (i= 0, dep= de_table; i<DE_PORT_NR; i++, dep++) { strcpy(dep->de_name, "dp8390#0"); dep->de_name[7] += i; } v= 0; (void) env_parse("ETH_IGN_PROTO", "x", 0, &v, 0x0000L, 0xFFFFL); eth_ign_proto= htons((u16_t) v); while (TRUE) { if ((r= receive(ANY, &m)) != OK) panic("dp8390: receive failed", r); switch (m.m_type) { case DL_WRITE: do_vwrite(&m, FALSE, FALSE); break; case DL_WRITEV: do_vwrite(&m, FALSE, TRUE); break; case DL_READ: do_vread(&m, FALSE); break; case DL_READV: do_vread(&m, TRUE); break; case DL_INIT: do_init(&m); break; case DL_GETSTAT: do_getstat(&m); break; case DL_STOP: do_stop(&m); break; case HARD_INT: for (i= 0, dep= &de_table[0]; i<DE_PORT_NR; i++, dep++) { if (dep->de_mode != DEM_ENABLED) continue; assert(dep->de_flags & DEF_ENABLED); irq= dep->de_irq; assert(irq >= 0 && irq < NR_IRQ_VECTORS); if (dep->de_int_pending) { dep->de_int_pending= 0; dp_check_ints(dep); do_int(dep); enable_irq(&dep->de_hook); } } break; default: panic("dp8390: illegal message", m.m_type); } } }
static int apply_env() { long v; /* apply the env setting passed to this driver parameters accepted * log_level=[0-4] (NONE,WARN,INFO,DEBUG,TRACE) instance=[0-3] * instance/bus number to use for this driver Passing these arguments * is done when starting the driver using the service command in the * following way service up /sbin/mmc -args "log_level=2 instance=1 * driver=dummy" -dev /dev/c2d0 */ char driver[16]; memset(driver, '\0', 16); (void) env_get_param("driver", driver, 16); if (strlen(driver) == 0 || strncmp(driver, "mmchs", strlen("mmchs") + 1) == 0) { /* early init of host mmc host controller. This code should * depend on knowing the hardware that is running bellow. */ #ifdef __arm__ host_initialize_host_structure_mmchs(&host); #endif } else if (strncmp(driver, "dummy", strlen("dummy") + 1) == 0) { host_initialize_host_structure_dummy(&host); } else { mmc_log_warn(&log, "Unknown driver %s\n", driver); } /* Initialize the verbosity level. */ v = 0; if (env_parse("log_level", "d", 0, &v, LEVEL_NONE, LEVEL_TRACE) == EP_SET) { set_log_level(v); } /* Find out which driver instance we are. */ v = 0; env_parse("instance", "d", 0, &v, 0, 3); if (host.host_set_instance(&host, v)) { mmc_log_warn(&log, "Failed to set mmc instance to %d\n", v); return -1; /* NOT OK */ } return OK; }
/*=========================================================================* * mcd_task * *=========================================================================*/ PUBLIC void mcd_task() { long v; static char var[] = "MCD"; static char fmt[] = "x:d"; #if __minix_vmd mcd_tasknr = proc_number(proc_ptr); #endif /* Configure I/O base and IRQ. */ v = MCD_IO_BASE_ADDRESS; (void) env_parse(var, fmt, 0, &v, 0x000L, 0x3FFL); mcd_io_base = v; v = MCD_IRQ; (void) env_parse(var, fmt, 0, &v, 0L, (long) NR_IRQ_VECTORS - 1); mcd_irq = v; driver_task(&mcd_dtab); /* Start driver task for cdrom */ }
/* ** Name: void dp_confaddr(dpeth_t *dep) ** Function: Checks environment for a User defined ethernet address. */ static void dp_confaddr(dpeth_t * dep) { static char ea_fmt[] = "x:x:x:x:x:x"; char ea_key[16]; int ix; long val; strcpy(ea_key, "DPETH0_EA"); ea_key[5] += de_instance; for (ix = 0; ix < SA_ADDR_LEN; ix++) { val = dep->de_address.ea_addr[ix]; if (env_parse(ea_key, ea_fmt, ix, &val, 0x00L, 0xFFL) != EP_SET) break; dep->de_address.ea_addr[ix] = val; } if (ix != 0 && ix != SA_ADDR_LEN) /* It's all or nothing, force a panic */ env_parse(ea_key, "?", 0, &val, 0L, 0L); return; }
static void de_update_conf(dpeth_t * dep) { static char dpc_fmt[] = "x:d:x"; char ec_key[16]; long val; strlcpy(ec_key, "DEETH0", sizeof(ec_key)); ec_key[5] += de_instance; dep->de_mode = DEM_ENABLED; switch (env_parse(ec_key, dpc_fmt, 0, &val, 0x000L, 0x3FFL)) { case EP_OFF: dep->de_mode = DEM_DISABLED; break; case EP_ON: dep->de_mode = DEM_SINK; break; } dep->de_base_port = 0; return; }
/*===========================================================================* * sef_cb_init_fresh * *===========================================================================*/ static int sef_cb_init_fresh(int type, sef_init_info_t *UNUSED(info)) { /* Initialize the rtl8169 driver. */ long v; system_hz = sys_hz(); v = 0; (void) env_parse("instance", "d", 0, &v, 0, 255); re_instance = (int) v; /* Claim buffer memory now. */ rl_init_buf(&re_state); /* Announce we are up! */ netdriver_announce(); return(OK); }
/*===========================================================================* * sef_cb_init_fresh * *===========================================================================*/ PRIVATE int sef_cb_init_fresh(int type, sef_init_info_t *UNUSED(info)) { /* Initialize the dpeth driver. */ int fkeys, sfkeys; long v; /* Request function key for debug dumps */ fkeys = sfkeys = 0; bit_set(sfkeys, 8); if ((fkey_map(&fkeys, &sfkeys)) != OK) printf("%s: couldn't program Shift+F8 key (%d)\n", DevName, errno); v = 0; (void) env_parse("instance", "d", 0, &v, 0, 255); de_instance = (int) v; /* Announce we are up! */ netdriver_announce(); return(OK); }
/*===========================================================================* * sef_cb_init_fresh * *===========================================================================*/ static int sef_cb_init_fresh(int type, sef_init_info_t *UNUSED(info)) { /* Initialize the DEC 21140A driver. */ int fkeys, sfkeys; long v; v = 0; (void) env_parse("instance", "d", 0, &v, 0, 255); de_instance = (int) v; /* Request function key for debug dumps */ fkeys = sfkeys = 0; bit_set(sfkeys, DE_FKEY); if ((fkey_map(&fkeys, &sfkeys)) != OK) printf("%s: error using Shift+F%d key(%d)\n", str_DevName, DE_FKEY, errno); /* Announce we are up! */ netdriver_announce(); return OK; }
static int sef_cb_init_fresh(int type, sef_init_info_t *info) { long instance = 0; env_parse("instance", "d", 0, &instance, 0, 255); if (virtio_net_probe((int)instance) != OK) panic("%s: No device found", name); if (virtio_net_config() != OK) panic("%s: No device found", name); if (virtio_net_alloc_bufs() != OK) panic("%s: Buffer allocation failed", name); virtio_net_init_queues(); netdriver_announce(); return(OK); }
static int sef_cb_init_fresh(int type, sef_init_info_t *info) { long instance = 0; int r; env_parse("instance", "d", 0, &instance, 0, 255); if ((r = virtio_blk_probe((int)instance)) == OK) { blockdriver_announce(type); return OK; } /* Error path */ if (r == ENXIO) panic("%s: No device found", name); if (r == ENOMEM) panic("%s: Not enough memory", name); panic("%s: Unexpected failure (%d)", name, r); }
/* * Initialize and return the card's ethernet address. */ static void e1000_init_addr(e1000_t * e, ether_addr_t * addr) { static char eakey[] = E1000_ENVVAR "#_EA"; static char eafmt[] = "x:x:x:x:x:x"; u16_t word; int i; long v; /* Do we have a user defined ethernet address? */ eakey[sizeof(E1000_ENVVAR)-1] = '0' + e1000_instance; for (i = 0; i < 6; i++) { if (env_parse(eakey, eafmt, i, &v, 0x00L, 0xFFL) != EP_SET) break; else addr->ea_addr[i] = v; } /* If that fails, read Ethernet Address from EEPROM. */ if (i != 6) { for (i = 0; i < 3; i++) { word = e->eeprom_read(e, i); addr->ea_addr[i * 2] = (word & 0x00ff); addr->ea_addr[i * 2 + 1] = (word & 0xff00) >> 8; } } /* Set Receive Address. */ e1000_reg_write(e, E1000_REG_RAL, *(u32_t *)(&addr->ea_addr[0])); e1000_reg_write(e, E1000_REG_RAH, *(u16_t *)(&addr->ea_addr[4])); e1000_reg_set(e, E1000_REG_RAH, E1000_REG_RAH_AV); e1000_reg_set(e, E1000_REG_RCTL, E1000_REG_RCTL_MPE); E1000_DEBUG(3, ("%s: Ethernet Address %x:%x:%x:%x:%x:%x\n", e->name, addr->ea_addr[0], addr->ea_addr[1], addr->ea_addr[2], addr->ea_addr[3], addr->ea_addr[4], addr->ea_addr[5])); }
/*===========================================================================* * sef_cb_init_fresh * *===========================================================================*/ static int sef_cb_init_fresh(int UNUSED(type), sef_init_info_t *UNUSED(info)) { /* Initialize the atl2 driver. */ int r, devind; long v; #if ATL2_FKEY int fkeys, sfkeys; #endif /* How many matching devices should we skip? */ v = 0; (void) env_parse("instance", "d", 0, &v, 0, 255); instance = (int) v; /* Try to find a recognized device. */ devind = atl2_probe(instance); if (devind < 0) panic("no matching device found"); /* Initialize the device. */ atl2_init(devind); /* Announce we are up! */ netdriver_announce(); #if ATL2_FKEY /* Register debug dump function key. */ fkeys = sfkeys = 0; bit_set(sfkeys, 11); if ((r = fkey_map(&fkeys, &sfkeys)) != OK) printf("ATL2: warning, could not map Shift+F11 key (%d)\n", r); #endif return(OK); }
/*===========================================================================* * sef_cb_init_fresh * *===========================================================================*/ static int sef_cb_init_fresh(int type, sef_init_info_t *UNUSED(info)) { /* Initialize the lance driver. */ long v; #if LANCE_FKEY int r, fkeys, sfkeys; #endif #if LANCE_FKEY fkeys = sfkeys = 0; bit_set( sfkeys, 7 ); if ( (r = fkey_map(&fkeys, &sfkeys)) != OK ) printf("Warning: lance couldn't observe Shift+F7 key: %d\n",r); #endif v = 0; (void) env_parse("instance", "d", 0, &v, 0, 255); ec_instance = (int) v; /* Announce we are up! */ netdriver_announce(); return OK; }
/* * Initialize the device. */ static int vnd_init(int UNUSED(type), sef_init_info_t *UNUSED(info)) { long v; /* * No support for crash recovery. The driver would have no way to * reacquire the file descriptor for the target file. */ /* * The instance number is used for two purposes: reporting errors, and * returning the proper unit number to userland in VNDIOCGET calls. */ v = 0; (void) env_parse("instance", "d", 0, &v, 0, 255); instance = (unsigned int) v; state.openct = 0; state.exiting = FALSE; state.fd = -1; return OK; }
/*===========================================================================* * sef_cb_init_fresh * *===========================================================================*/ PRIVATE int sef_cb_init_fresh(int UNUSED(type), sef_init_info_t *UNUSED(info)) { /* Initialize the e1000 driver. */ long v; int r; v = 0; (void) env_parse("instance", "d", 0, &v, 0, 255); e1000_instance = (int) v; /* Clear state. */ memset(&e1000_state, 0, sizeof(e1000_state)); /* Perform calibration. */ if((r = tsc_calibrate()) != OK) { panic("tsc_calibrate failed: %d", r); } /* Announce we are up! */ netdriver_announce(); return(OK); }
/*===========================================================================* * dpeth_task * *===========================================================================*/ int main(int argc, char *argv[]) { message m; int i, irq, r; dpeth_t *dep; long v; env_setargs(argc, argv); for (i= 0, dep= de_table; i<DE_PORT_NR; i++, dep++) { strcpy(dep->de_name, "dp8390#0"); dep->de_name[7] += i; } v= 0; (void) env_parse("ETH_IGN_PROTO", "x", 0, &v, 0x0000L, 0xFFFFL); eth_ign_proto= htons((u16_t) v); while (TRUE) { if ((r= receive(ANY, &m)) != OK) panic("", "dp8390: receive failed", r); switch (m.m_type) { case DL_WRITE: do_vwrite(&m, FALSE, FALSE); break; case DL_WRITEV: do_vwrite(&m, FALSE, TRUE); break; case DL_READ: do_vread(&m, FALSE); break; case DL_READV: do_vread(&m, TRUE); break; case DL_INIT: do_init(&m); break; case DL_GETSTAT: do_getstat(&m); break; case DL_STOP: do_stop(&m); break; case HARD_INT: for (i= 0, dep= &de_table[0]; i<DE_PORT_NR; i++, dep++) { if (dep->de_mode != DEM_ENABLED) continue; assert(dep->de_flags & DEF_ENABLED); irq= dep->de_irq; assert(irq >= 0 && irq < NR_IRQ_VECTORS); if (dep->de_int_pending || 1) { dep->de_int_pending= 0; dp_check_ints(dep); do_int(dep); r= sys_irqenable(&dep->de_hook); if (r != OK) { panic("DP8390", "unable enable interrupts", r); } } } break; case SYS_SIG: { sigset_t sigset = m.NOTIFY_ARG; if (sigismember(&sigset, SIGKSTOP)) dp8390_stop(); break; } case SYN_ALARM: printf("dp8390: strange, got SYN_ALARM\n"); break; default: panic("", "dp8390: illegal message", m.m_type); } } }
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(); }
/*===========================================================================* * main * *===========================================================================*/ int main(void) { kipc_msg_t msg; int result, who_e; #if SANITYCHECKS incheck = nocheck = 0; FIXME("VM SANITYCHECKS are on"); #endif vm_paged = 1; env_parse("vm_paged", "d", 0, &vm_paged, 0, 1); #if SANITYCHECKS env_parse("vm_sanitychecklevel", "d", 0, &vm_sanitychecklevel, 0, SCL_MAX); #endif vm_init(); /* This is VM's main loop. */ while (TRUE) { int r, c; SANITYCHECK(SCL_TOP); if(missing_spares > 0) { pt_cycle(); /* pagetable code wants to be called */ } SANITYCHECK(SCL_DETAIL); if ((r=kipc_module_call(KIPC_RECEIVE, 0, ENDPT_ANY, &msg)) != 0) vm_panic("receive() error", r); SANITYCHECK(SCL_DETAIL); if(msg.m_type & NOTIFY_MESSAGE) { switch(msg.m_source) { case SYSTEM: /* Kernel wants to have memory ranges * verified, and/or pagefaults handled. */ do_memory(); break; case HARDWARE: do_pagefaults(); break; case PM_PROC_NR: /* PM sends a notify() on shutdown, which * is OK and we ignore. */ break; default: /* No-one else should send us notifies. */ printk("VM: ignoring notify() from %d\n", msg.m_source); break; } continue; } who_e = msg.m_source; c = CALLNUMBER(msg.m_type); result = -ENOSYS; /* Out of range or restricted calls return this. */ if(c < 0 || !vm_calls[c].vmc_func) { printk("VM: out of range or missing callnr %d from %d\n", msg.m_type, who_e); } else if (vm_acl_ok(who_e, c) != 0) { printk("VM: unauthorized %s by %d\n", vm_calls[c].vmc_name, who_e); } else { SANITYCHECK(SCL_FUNCTIONS); result = vm_calls[c].vmc_func(&msg); SANITYCHECK(SCL_FUNCTIONS); } /* Send reply message, unless the return code is SUSPEND, * which is a pseudo-result suppressing the reply message. */ if(result != SUSPEND) { SANITYCHECK(SCL_DETAIL); msg.m_type = result; if((r=kipc_module_call(KIPC_SEND, 0, who_e, &msg)) != 0) { printk("VM: couldn't send %d to %d (err %d)\n", msg.m_type, who_e, r); vm_panic("send() error", NO_NUM); } SANITYCHECK(SCL_DETAIL); } SANITYCHECK(SCL_DETAIL); } return 0; }
/*===========================================================================* * sef_cb_init_fresh * *===========================================================================*/ PRIVATE int sef_cb_init_fresh(int type, sef_init_info_t *info) { /* Initialize the reincarnation server. */ struct sigaction sa; struct boot_image *ip; int s,i,j; int nr_image_srvs, nr_image_priv_srvs, nr_uncaught_init_srvs; struct rproc *rp; struct rprocpub *rpub; struct boot_image image[NR_BOOT_PROCS]; struct mproc mproc[NR_PROCS]; struct exec header; struct boot_image_priv *boot_image_priv; struct boot_image_sys *boot_image_sys; struct boot_image_dev *boot_image_dev; /* See if we run in verbose mode. */ env_parse("rs_verbose", "d", 0, &rs_verbose, 0, 1); /* Initialize the global init descriptor. */ rinit.rproctab_gid = cpf_grant_direct(ANY, (vir_bytes) rprocpub, sizeof(rprocpub), CPF_READ); if(!GRANT_VALID(rinit.rproctab_gid)) { panic("RS", "unable to create rprocpub table grant", rinit.rproctab_gid); } /* Initialize the global update descriptor. */ rupdate.flags = 0; /* Get a copy of the boot image table. */ if ((s = sys_getimage(image)) != OK) { panic("RS", "unable to get copy of boot image table", s); } /* Determine the number of system services in the boot image table and * compute the size required for the boot image buffer. */ nr_image_srvs = 0; boot_image_buffer_size = 0; for(i=0;i<NR_BOOT_PROCS;i++) { ip = &image[i]; /* System services only. */ if(iskerneln(_ENDPOINT_P(ip->endpoint))) { continue; } nr_image_srvs++; /* Lookup the corresponding entry in the boot image sys table. */ boot_image_info_lookup(ip->endpoint, image, NULL, NULL, &boot_image_sys, NULL); /* If we must keep a copy of this system service, read the header * and increase the size of the boot image buffer. */ if(boot_image_sys->flags & SF_USE_COPY) { if((s = sys_getaoutheader(&header, i)) != OK) { panic("RS", "unable to get copy of a.out header", s); } boot_image_buffer_size += header.a_hdrlen + header.a_text + header.a_data; } } /* Determine the number of entries in the boot image priv table and make sure * it matches the number of system services in the boot image table. */ nr_image_priv_srvs = 0; for (i=0; boot_image_priv_table[i].endpoint != NULL_BOOT_NR; i++) { boot_image_priv = &boot_image_priv_table[i]; /* System services only. */ if(iskerneln(_ENDPOINT_P(boot_image_priv->endpoint))) { continue; } nr_image_priv_srvs++; } if(nr_image_srvs != nr_image_priv_srvs) { panic("RS", "boot image table and boot image priv table mismatch", NO_NUM); } /* Allocate boot image buffer. */ if(boot_image_buffer_size > 0) { boot_image_buffer = rs_startup_sbrk(boot_image_buffer_size); if(boot_image_buffer == (char *) -1) { panic("RS", "unable to allocate boot image buffer", NO_NUM); } } /* Reset the system process table. */ for (rp=BEG_RPROC_ADDR; rp<END_RPROC_ADDR; rp++) { rp->r_flags = 0; rp->r_pub = &rprocpub[rp - rproc]; rp->r_pub->in_use = FALSE; } /* Initialize the system process table in 4 steps, each of them following * the appearance of system services in the boot image priv table. * - Step 1: get a copy of the executable image of every system service that * requires it while it is not yet running. * In addition, set priviliges, sys properties, and dev properties (if any) * for every system service. */ for (i=0; boot_image_priv_table[i].endpoint != NULL_BOOT_NR; i++) { boot_image_priv = &boot_image_priv_table[i]; /* System services only. */ if(iskerneln(_ENDPOINT_P(boot_image_priv->endpoint))) { continue; } /* Lookup the corresponding entries in other tables. */ boot_image_info_lookup(boot_image_priv->endpoint, image, &ip, NULL, &boot_image_sys, &boot_image_dev); rp = &rproc[boot_image_priv - boot_image_priv_table]; rpub = rp->r_pub; /* * Get a copy of the executable image if required. */ rp->r_exec_len = 0; rp->r_exec = NULL; if(boot_image_sys->flags & SF_USE_COPY) { exec_image_copy(ip - image, ip, rp); } /* * Set privileges. */ /* Get label. */ strcpy(rpub->label, boot_image_priv->label); if(boot_image_priv->endpoint != RS_PROC_NR) { /* Force a static priv id for system services in the boot image. */ rp->r_priv.s_id = static_priv_id( _ENDPOINT_P(boot_image_priv->endpoint)); /* Initialize privilege bitmaps. */ rp->r_priv.s_flags = boot_image_priv->flags; /* priv flags */ rp->r_priv.s_trap_mask = boot_image_priv->trap_mask; /* traps */ memcpy(&rp->r_priv.s_ipc_to, &boot_image_priv->ipc_to, sizeof(rp->r_priv.s_ipc_to)); /* targets */ /* Initialize kernel call mask bitmap from unordered set. */ fill_call_mask(boot_image_priv->k_calls, NR_SYS_CALLS, rp->r_priv.s_k_call_mask, KERNEL_CALL, TRUE); /* Set the privilege structure. */ if ((s = sys_privctl(ip->endpoint, SYS_PRIV_SET_SYS, &(rp->r_priv))) != OK) { panic("RS", "unable to set privilege structure", s); } } /* Synch the privilege structure with the kernel. */ if ((s = sys_getpriv(&(rp->r_priv), ip->endpoint)) != OK) { panic("RS", "unable to synch privilege structure", s); } /* * Set sys properties. */ rpub->sys_flags = boot_image_sys->flags; /* sys flags */ /* * Set dev properties. */ rpub->dev_nr = boot_image_dev->dev_nr; /* major device number */ rpub->dev_style = boot_image_dev->dev_style; /* device style */ rpub->period = boot_image_dev->period; /* heartbeat period */ /* Get process name. */ strcpy(rpub->proc_name, ip->proc_name); /* Get command settings. */ rp->r_cmd[0]= '\0'; rp->r_argv[0] = rp->r_cmd; rp->r_argv[1] = NULL; rp->r_argc = 1; rp->r_script[0]= '\0'; /* Initialize vm call mask bitmap from unordered set. */ fill_call_mask(boot_image_priv->vm_calls, NR_VM_CALLS, rpub->vm_call_mask, VM_RQ_BASE, TRUE); /* Get some settings from the boot image table. */ rp->r_nice = ip->priority; rpub->endpoint = ip->endpoint; /* Set some defaults. */ rp->r_uid = 0; /* root */ rp->r_check_tm = 0; /* not checked yet */ getuptime(&rp->r_alive_tm); /* currently alive */ rp->r_stop_tm = 0; /* not exiting yet */ rp->r_restarts = 0; /* no restarts so far */ rp->r_set_resources = 0; /* don't set resources */ /* Mark as in use. */ rp->r_flags = RS_IN_USE; rproc_ptr[_ENDPOINT_P(rpub->endpoint)]= rp; rpub->in_use = TRUE; } /* - Step 2: allow every system service in the boot image to run. */ nr_uncaught_init_srvs = 0; for (i=0; boot_image_priv_table[i].endpoint != NULL_BOOT_NR; i++) { boot_image_priv = &boot_image_priv_table[i]; /* System services only. */ if(iskerneln(_ENDPOINT_P(boot_image_priv->endpoint))) { continue; } /* Ignore RS. */ if(boot_image_priv->endpoint == RS_PROC_NR) { continue; } /* Lookup the corresponding slot in the system process table. */ rp = &rproc[boot_image_priv - boot_image_priv_table]; rpub = rp->r_pub; /* Allow the service to run. */ if ((s = sys_privctl(rpub->endpoint, SYS_PRIV_ALLOW, NULL)) != OK) { panic("RS", "unable to initialize privileges", s); } /* Initialize service. We assume every service will always get * back to us here at boot time. */ if(boot_image_priv->flags & SYS_PROC) { if ((s = init_service(rp, SEF_INIT_FRESH)) != OK) { panic("RS", "unable to initialize service", s); } if(rpub->sys_flags & SF_SYNCH_BOOT) { /* Catch init ready message now to synchronize. */ catch_boot_init_ready(rpub->endpoint); } else { /* Catch init ready message later. */ nr_uncaught_init_srvs++; } } } /* - Step 3: let every system service complete initialization by * catching all the init ready messages left. */ while(nr_uncaught_init_srvs) { catch_boot_init_ready(ANY); nr_uncaught_init_srvs--; } /* - Step 4: all the system services in the boot image are now running. * Complete the initialization of the system process table in collaboration * with other system processes. */ if ((s = getsysinfo(PM_PROC_NR, SI_PROC_TAB, mproc)) != OK) { panic("RS", "unable to get copy of PM process table", s); } for (i=0; boot_image_priv_table[i].endpoint != NULL_BOOT_NR; i++) { boot_image_priv = &boot_image_priv_table[i]; /* System services only. */ if(iskerneln(_ENDPOINT_P(boot_image_priv->endpoint))) { continue; } /* Lookup the corresponding slot in the system process table. */ rp = &rproc[boot_image_priv - boot_image_priv_table]; rpub = rp->r_pub; /* Get pid from PM process table. */ rp->r_pid = NO_PID; for (j = 0; j < NR_PROCS; j++) { if (mproc[j].mp_endpoint == rpub->endpoint) { rp->r_pid = mproc[j].mp_pid; break; } } if(j == NR_PROCS) { panic("RS", "unable to get pid", NO_NUM); } } /* * Now complete RS initialization process in collaboration with other * system services. */ /* Let the rest of the system know about our dynamically allocated buffer. */ if(boot_image_buffer_size > 0) { boot_image_buffer = rs_startup_sbrk_synch(boot_image_buffer_size); if(boot_image_buffer == (char *) -1) { panic("RS", "unable to synch boot image buffer", NO_NUM); } } /* Set alarm to periodically check service status. */ if (OK != (s=sys_setalarm(RS_DELTA_T, 0))) panic("RS", "couldn't set alarm", s); /* Install signal handlers. Ask PM to transform signal into message. */ sa.sa_handler = SIG_MESS; sigemptyset(&sa.sa_mask); sa.sa_flags = 0; if (sigaction(SIGCHLD,&sa,NULL)<0) panic("RS","sigaction failed", errno); if (sigaction(SIGTERM,&sa,NULL)<0) panic("RS","sigaction failed", errno); /* Initialize the exec pipe. */ if (pipe(exec_pipe) == -1) panic("RS", "pipe failed", errno); if (fcntl(exec_pipe[0], F_SETFD, fcntl(exec_pipe[0], F_GETFD) | FD_CLOEXEC) == -1) { panic("RS", "fcntl set FD_CLOEXEC on pipe input failed", errno); } if (fcntl(exec_pipe[1], F_SETFD, fcntl(exec_pipe[1], F_GETFD) | FD_CLOEXEC) == -1) { panic("RS", "fcntl set FD_CLOEXEC on pipe output failed", errno); } if (fcntl(exec_pipe[0], F_SETFL, fcntl(exec_pipe[0], F_GETFL) | O_NONBLOCK) == -1) { panic("RS", "fcntl set O_NONBLOCK on pipe input failed", errno); } /* Map out our own text and data. This is normally done in crtso.o * but RS is an exception - we don't get to talk to VM so early on. * That's why we override munmap() and munmap_text() in utility.c. * * _minix_unmapzero() is the same code in crtso.o that normally does * it on startup. It's best that it's there as crtso.o knows exactly * what the ranges are of the filler data. */ unmap_ok = 1; _minix_unmapzero(); return(OK); }
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(); }
/*===========================================================================* * sef_cb_init_fresh * *===========================================================================*/ PRIVATE int sef_cb_init_fresh(int type, sef_init_info_t *info) { /* Initialize the reincarnation server. */ struct boot_image *ip; int s,i; int nr_image_srvs, nr_image_priv_srvs, nr_uncaught_init_srvs; struct rproc *rp; struct rproc *replica_rp; struct rprocpub *rpub; struct boot_image image[NR_BOOT_PROCS]; struct boot_image_priv *boot_image_priv; struct boot_image_sys *boot_image_sys; struct boot_image_dev *boot_image_dev; int pid, replica_pid; endpoint_t replica_endpoint; int ipc_to; int *calls; int all_c[] = { ALL_C, NULL_C }; int no_c[] = { NULL_C }; /* See if we run in verbose mode. */ env_parse("rs_verbose", "d", 0, &rs_verbose, 0, 1); if ((s = sys_getinfo(GET_HZ, &system_hz, sizeof(system_hz), 0, 0)) != OK) panic("Cannot get system timer frequency\n"); /* Initialize the global init descriptor. */ rinit.rproctab_gid = cpf_grant_direct(ANY, (vir_bytes) rprocpub, sizeof(rprocpub), CPF_READ); if(!GRANT_VALID(rinit.rproctab_gid)) { panic("unable to create rprocpub table grant: %d", rinit.rproctab_gid); } /* Initialize some global variables. */ rupdate.flags = 0; shutting_down = FALSE; /* Get a copy of the boot image table. */ if ((s = sys_getimage(image)) != OK) { panic("unable to get copy of boot image table: %d", s); } /* Determine the number of system services in the boot image table. */ nr_image_srvs = 0; for(i=0;i<NR_BOOT_PROCS;i++) { ip = &image[i]; /* System services only. */ if(iskerneln(_ENDPOINT_P(ip->endpoint))) { continue; } nr_image_srvs++; } /* Determine the number of entries in the boot image priv table and make sure * it matches the number of system services in the boot image table. */ nr_image_priv_srvs = 0; for (i=0; boot_image_priv_table[i].endpoint != NULL_BOOT_NR; i++) { boot_image_priv = &boot_image_priv_table[i]; /* System services only. */ if(iskerneln(_ENDPOINT_P(boot_image_priv->endpoint))) { continue; } nr_image_priv_srvs++; } if(nr_image_srvs != nr_image_priv_srvs) { panic("boot image table and boot image priv table mismatch"); } /* Reset the system process table. */ for (rp=BEG_RPROC_ADDR; rp<END_RPROC_ADDR; rp++) { rp->r_flags = 0; rp->r_pub = &rprocpub[rp - rproc]; rp->r_pub->in_use = FALSE; } /* Initialize the system process table in 4 steps, each of them following * the appearance of system services in the boot image priv table. * - Step 1: set priviliges, sys properties, and dev properties (if any) * for every system service. */ for (i=0; boot_image_priv_table[i].endpoint != NULL_BOOT_NR; i++) { boot_image_priv = &boot_image_priv_table[i]; /* System services only. */ if(iskerneln(_ENDPOINT_P(boot_image_priv->endpoint))) { continue; } /* Lookup the corresponding entries in other tables. */ boot_image_info_lookup(boot_image_priv->endpoint, image, &ip, NULL, &boot_image_sys, &boot_image_dev); rp = &rproc[boot_image_priv - boot_image_priv_table]; rpub = rp->r_pub; /* * Set privileges. */ /* Get label. */ strcpy(rpub->label, boot_image_priv->label); /* Force a static priv id for system services in the boot image. */ rp->r_priv.s_id = static_priv_id( _ENDPOINT_P(boot_image_priv->endpoint)); /* Initialize privilege bitmaps and signal manager. */ rp->r_priv.s_flags = boot_image_priv->flags; /* priv flags */ rp->r_priv.s_trap_mask= SRV_OR_USR(rp, SRV_T, USR_T); /* traps */ ipc_to = SRV_OR_USR(rp, SRV_M, USR_M); /* targets */ fill_send_mask(&rp->r_priv.s_ipc_to, ipc_to == ALL_M); rp->r_priv.s_sig_mgr= SRV_OR_USR(rp, SRV_SM, USR_SM); /* sig mgr */ rp->r_priv.s_bak_sig_mgr = NONE; /* backup sig mgr */ /* Initialize kernel call mask bitmap. */ calls = SRV_OR_USR(rp, SRV_KC, USR_KC) == ALL_C ? all_c : no_c; fill_call_mask(calls, NR_SYS_CALLS, rp->r_priv.s_k_call_mask, KERNEL_CALL, TRUE); /* Set the privilege structure. */ if(boot_image_priv->endpoint != RS_PROC_NR) { if ((s = sys_privctl(ip->endpoint, SYS_PRIV_SET_SYS, &(rp->r_priv))) != OK) { panic("unable to set privilege structure: %d", s); } } /* Synch the privilege structure with the kernel. */ if ((s = sys_getpriv(&(rp->r_priv), ip->endpoint)) != OK) { panic("unable to synch privilege structure: %d", s); } /* * Set sys properties. */ rpub->sys_flags = boot_image_sys->flags; /* sys flags */ /* * Set dev properties. */ rpub->dev_flags = boot_image_dev->flags; /* device flags */ rpub->dev_nr = boot_image_dev->dev_nr; /* major device number */ rpub->dev_style = boot_image_dev->dev_style; /* device style */ rpub->dev_style2 = boot_image_dev->dev_style2; /* device style 2 */ /* Get process name. */ strcpy(rpub->proc_name, ip->proc_name); /* Build command settings. */ rp->r_cmd[0]= '\0'; rp->r_script[0]= '\0'; build_cmd_dep(rp); /* Initialize vm call mask bitmap. */ calls = SRV_OR_USR(rp, SRV_VC, USR_VC) == ALL_C ? all_c : no_c; fill_call_mask(calls, NR_VM_CALLS, rpub->vm_call_mask, VM_RQ_BASE, TRUE); /* Scheduling parameters. */ rp->r_scheduler = SRV_OR_USR(rp, SRV_SCH, USR_SCH); rp->r_priority = SRV_OR_USR(rp, SRV_Q, USR_Q); rp->r_quantum = SRV_OR_USR(rp, SRV_QT, USR_QT); /* Get some settings from the boot image table. */ rpub->endpoint = ip->endpoint; /* Set some defaults. */ rp->r_old_rp = NULL; /* no old version yet */ rp->r_new_rp = NULL; /* no new version yet */ rp->r_prev_rp = NULL; /* no prev replica yet */ rp->r_next_rp = NULL; /* no next replica yet */ rp->r_uid = 0; /* root */ rp->r_check_tm = 0; /* not checked yet */ getuptime(&rp->r_alive_tm); /* currently alive */ rp->r_stop_tm = 0; /* not exiting yet */ rp->r_restarts = 0; /* no restarts so far */ rp->r_period = 0; /* no period yet */ rp->r_exec = NULL; /* no in-memory copy yet */ rp->r_exec_len = 0; /* Mark as in use and active. */ rp->r_flags = RS_IN_USE | RS_ACTIVE; rproc_ptr[_ENDPOINT_P(rpub->endpoint)]= rp; rpub->in_use = TRUE; } /* - Step 2: allow every system service in the boot image to run. */ nr_uncaught_init_srvs = 0; for (i=0; boot_image_priv_table[i].endpoint != NULL_BOOT_NR; i++) { boot_image_priv = &boot_image_priv_table[i]; /* System services only. */ if(iskerneln(_ENDPOINT_P(boot_image_priv->endpoint))) { continue; } /* Lookup the corresponding slot in the system process table. */ rp = &rproc[boot_image_priv - boot_image_priv_table]; rpub = rp->r_pub; /* RS is already running as we speak. */ if(boot_image_priv->endpoint == RS_PROC_NR) { if ((s = init_service(rp, SEF_INIT_FRESH)) != OK) { panic("unable to initialize RS: %d", s); } continue; } /* Allow the service to run. */ if ((s = sched_init_proc(rp)) != OK) { panic("unable to initialize scheduling: %d", s); } if ((s = sys_privctl(rpub->endpoint, SYS_PRIV_ALLOW, NULL)) != OK) { panic("unable to initialize privileges: %d", s); } /* Initialize service. We assume every service will always get * back to us here at boot time. */ if(boot_image_priv->flags & SYS_PROC) { if ((s = init_service(rp, SEF_INIT_FRESH)) != OK) { panic("unable to initialize service: %d", s); } if(rpub->sys_flags & SF_SYNCH_BOOT) { /* Catch init ready message now to synchronize. */ catch_boot_init_ready(rpub->endpoint); } else { /* Catch init ready message later. */ nr_uncaught_init_srvs++; } } } /* - Step 3: let every system service complete initialization by * catching all the init ready messages left. */ while(nr_uncaught_init_srvs) { catch_boot_init_ready(ANY); nr_uncaught_init_srvs--; } /* - Step 4: all the system services in the boot image are now running. * Complete the initialization of the system process table in collaboration * with other system services. */ for (i=0; boot_image_priv_table[i].endpoint != NULL_BOOT_NR; i++) { boot_image_priv = &boot_image_priv_table[i]; /* System services only. */ if(iskerneln(_ENDPOINT_P(boot_image_priv->endpoint))) { continue; } /* Lookup the corresponding slot in the system process table. */ rp = &rproc[boot_image_priv - boot_image_priv_table]; rpub = rp->r_pub; /* Get pid from PM. */ rp->r_pid = getnpid(rpub->endpoint); if(rp->r_pid == -1) { panic("unable to get pid"); } } /* Set alarm to periodically check service status. */ if (OK != (s=sys_setalarm(RS_DELTA_T, 0))) panic("couldn't set alarm: %d", s); /* Now create a new RS instance with a private page table and let the current * instance live update into the replica. Clone RS' own slot first. */ rp = rproc_ptr[_ENDPOINT_P(RS_PROC_NR)]; if((s = clone_slot(rp, &replica_rp)) != OK) { panic("unable to clone current RS instance: %d", s); } /* Fork a new RS instance. */ pid = srv_fork(); if(pid == -1) { panic("unable to fork a new RS instance"); } replica_pid = pid ? pid : getpid(); replica_endpoint = getnprocnr(replica_pid); replica_rp->r_pid = replica_pid; replica_rp->r_pub->endpoint = replica_endpoint; if(pid == 0) { /* New RS instance running. */ /* Live update the old instance into the new one. */ s = update_service(&rp, &replica_rp, RS_SWAP); if(s != OK) { panic("unable to live update RS: %d", s); } cpf_reload(); /* Clean up the old RS instance, the new instance will take over. */ cleanup_service(rp); /* Map out our own text and data. */ unmap_ok = 1; _minix_unmapzero(); /* Ask VM to pin memory for the new RS instance. */ if((s = vm_memctl(RS_PROC_NR, VM_RS_MEM_PIN)) != OK) { panic("unable to pin memory for the new RS instance: %d", s); } } else { /* Old RS instance running. */ /* Set up privileges for the new instance and let it run. */ s = sys_privctl(replica_endpoint, SYS_PRIV_SET_SYS, &(replica_rp->r_priv)); if(s != OK) { panic("unable to set privileges for the new RS instance: %d", s); } if ((s = sched_init_proc(replica_rp)) != OK) { panic("unable to initialize RS replica scheduling: %d", s); } s = sys_privctl(replica_endpoint, SYS_PRIV_YIELD, NULL); if(s != OK) { panic("unable to yield control to the new RS instance: %d", s); } NOT_REACHABLE; } return(OK); }
/*===========================================================================* * sef_cb_init_fresh * *===========================================================================*/ PRIVATE int sef_cb_init_fresh(int type, sef_init_info_t *info) { /* Initialize the vm server. */ int s, i; int click, clicksforgotten = 0; struct memory mem_chunks[NR_MEMS]; struct boot_image image[NR_BOOT_PROCS]; struct boot_image *ip; struct rprocpub rprocpub[NR_BOOT_PROCS]; phys_bytes limit = 0; #if SANITYCHECKS incheck = nocheck = 0; FIXME("VM SANITYCHECKS are on"); #endif vm_paged = 1; env_parse("vm_paged", "d", 0, &vm_paged, 0, 1); #if SANITYCHECKS env_parse("vm_sanitychecklevel", "d", 0, &vm_sanitychecklevel, 0, SCL_MAX); #endif /* Get chunks of available memory. */ get_mem_chunks(mem_chunks); /* Initialize VM'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))) vm_panic("couldn't get image table: %d\n", s); /* 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; } /* Walk through boot-time system processes that are alive * now and make valid slot entries for them. */ for (ip = &image[0]; ip < &image[NR_BOOT_PROCS]; ip++) { phys_bytes proclimit; struct vmproc *vmp; if(ip->proc_nr >= _NR_PROCS) { vm_panic("proc", ip->proc_nr); } if(ip->proc_nr < 0 && ip->proc_nr != SYSTEM) continue; #define GETVMP(v, nr) \ if(nr >= 0) { \ vmp = &vmproc[ip->proc_nr]; \ } else if(nr == SYSTEM) { \ vmp = &vmproc[VMP_SYSTEM]; \ } else { \ vm_panic("init: crazy proc_nr", nr); \ } /* Initialize normal process table slot or special SYSTEM * table slot. Kernel memory is already reserved. */ GETVMP(vmp, ip->proc_nr); /* reset fields as if exited */ clear_proc(vmp); /* Get memory map for this process from the kernel. */ if ((s=get_mem_map(ip->proc_nr, vmp->vm_arch.vm_seg)) != OK) vm_panic("couldn't get process mem_map",s); /* Remove this memory from the free list. */ reserve_proc_mem(mem_chunks, vmp->vm_arch.vm_seg); /* Set memory limit. */ proclimit = CLICK2ABS(vmp->vm_arch.vm_seg[S].mem_phys + vmp->vm_arch.vm_seg[S].mem_len) - 1; if(proclimit > limit) limit = proclimit; vmp->vm_flags = VMF_INUSE; vmp->vm_endpoint = ip->endpoint; vmp->vm_stacktop = CLICK2ABS(vmp->vm_arch.vm_seg[S].mem_vir + vmp->vm_arch.vm_seg[S].mem_len); if (vmp->vm_arch.vm_seg[T].mem_len != 0) vmp->vm_flags |= VMF_SEPARATE; } /* Architecture-dependent initialization. */ pt_init(limit); /* Initialize tables to all physical memory. */ mem_init(mem_chunks); meminit_done = 1; /* Give these processes their own page table. */ for (ip = &image[0]; ip < &image[NR_BOOT_PROCS]; ip++) { int s; struct vmproc *vmp; vir_bytes old_stacktop, old_stack; if(ip->proc_nr < 0) continue; GETVMP(vmp, ip->proc_nr); if(!(ip->flags & PROC_FULLVM)) continue; old_stack = vmp->vm_arch.vm_seg[S].mem_vir + vmp->vm_arch.vm_seg[S].mem_len - vmp->vm_arch.vm_seg[D].mem_len; if(pt_new(&vmp->vm_pt) != OK) vm_panic("VM: no new pagetable", NO_NUM); #define BASICSTACK VM_PAGE_SIZE old_stacktop = CLICK2ABS(vmp->vm_arch.vm_seg[S].mem_vir + vmp->vm_arch.vm_seg[S].mem_len); if(sys_vmctl(vmp->vm_endpoint, VMCTL_INCSP, VM_STACKTOP - old_stacktop) != OK) { vm_panic("VM: vmctl for new stack failed", NO_NUM); } FREE_MEM(vmp->vm_arch.vm_seg[D].mem_phys + vmp->vm_arch.vm_seg[D].mem_len, old_stack); if(proc_new(vmp, VM_PROCSTART, CLICK2ABS(vmp->vm_arch.vm_seg[T].mem_len), CLICK2ABS(vmp->vm_arch.vm_seg[D].mem_len), BASICSTACK, CLICK2ABS(vmp->vm_arch.vm_seg[S].mem_vir + vmp->vm_arch.vm_seg[S].mem_len - vmp->vm_arch.vm_seg[D].mem_len) - BASICSTACK, CLICK2ABS(vmp->vm_arch.vm_seg[T].mem_phys), CLICK2ABS(vmp->vm_arch.vm_seg[D].mem_phys), VM_STACKTOP) != OK) { vm_panic("failed proc_new for boot process", NO_NUM); } } /* Set up table of calls. */ #define CALLMAP(code, func) { int i; \ if((i=CALLNUMBER(code)) < 0) { vm_panic(#code " invalid", (code)); } \ if(i >= NR_VM_CALLS) { vm_panic(#code " invalid", (code)); } \ 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_MUNMAP_TEXT, do_munmap); CALLMAP(VM_MAP_PHYS, do_map_phys); CALLMAP(VM_UNMAP_PHYS, do_unmap_phys); /* Calls from PM. */ CALLMAP(VM_EXIT, do_exit); CALLMAP(VM_FORK, do_fork); CALLMAP(VM_BRK, do_brk); CALLMAP(VM_EXEC_NEWMEM, do_exec_newmem); CALLMAP(VM_PUSH_SIG, do_push_sig); CALLMAP(VM_WILLEXIT, do_willexit); CALLMAP(VM_ADDDMA, do_adddma); CALLMAP(VM_DELDMA, do_deldma); CALLMAP(VM_GETDMA, do_getdma); CALLMAP(VM_NOTIFY_SIG, do_notify_sig); /* Calls from RS */ CALLMAP(VM_RS_SET_PRIV, do_rs_set_priv); /* Generic calls. */ CALLMAP(VM_REMAP, do_remap); CALLMAP(VM_GETPHYS, do_get_phys); CALLMAP(VM_SHM_UNMAP, do_shared_unmap); CALLMAP(VM_GETREF, do_get_refcount); CALLMAP(VM_INFO, do_info); CALLMAP(VM_QUERY_EXIT, do_query_exit); /* Sanity checks */ if(find_kernel_top() >= VM_PROCSTART) vm_panic("kernel loaded too high", NO_NUM); /* Initialize the structures for queryexit */ init_query_exit(); /* Unmap our own low pages. */ unmap_ok = 1; _minix_unmapzero(); /* Map all the services in the boot image. */ if((s = sys_safecopyfrom(RS_PROC_NR, info->rproctab_gid, 0, (vir_bytes) rprocpub, sizeof(rprocpub), S)) != OK) { panic("VM", "sys_safecopyfrom failed", s); } for(i=0;i < NR_BOOT_PROCS;i++) { if(rprocpub[i].in_use) { if((s = map_service(&rprocpub[i])) != OK) { vm_panic("unable to map service", s); } } } return(OK); }