Beispiel #1
0
/*===========================================================================*
 *		            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);
}
Beispiel #2
0
/*
**  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;
}
Beispiel #3
0
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;
}
Beispiel #5
0
/*===========================================================================*
 *		            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);
}
Beispiel #6
0
/*===========================================================================*
 *				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;
		}
	}
}
Beispiel #7
0
/*===========================================================================*
 *				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);
		}
	}
}
Beispiel #8
0
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;
}
Beispiel #9
0
/*=========================================================================*
 *				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 */
}
Beispiel #10
0
/*
**  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;
}
Beispiel #11
0
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;
}
Beispiel #12
0
/*===========================================================================*
 *		            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);
}
Beispiel #13
0
/*===========================================================================*
 *		            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);
}
Beispiel #14
0
/*===========================================================================*
 *		            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;
}
Beispiel #15
0
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);
}
Beispiel #16
0
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);
}
Beispiel #17
0
/*
 * 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]));
}
Beispiel #18
0
/*===========================================================================*
 *		            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);
}
Beispiel #19
0
/*===========================================================================*
 *		            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;
}
Beispiel #20
0
/*
 * 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;
}
Beispiel #21
0
/*===========================================================================*
 *		            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);
}
Beispiel #22
0
/*===========================================================================*
 *				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);
		}
	}
}
Beispiel #23
0
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();
}
Beispiel #24
0
/*===========================================================================*
 *				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;
}
Beispiel #25
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);
}
Beispiel #26
0
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();
}
Beispiel #27
0
/*===========================================================================*
 *		            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);
}
Beispiel #28
0
/*===========================================================================*
 *				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);
}