Beispiel #1
0
kern_return_t
S_exec_init (struct trivfs_protid *protid,
	     auth_t auth, process_t proc)
{
  mach_port_t host_priv, startup;
  error_t err;

  if (! protid || ! protid->isroot)
    return EPERM;

  _hurd_port_set (&_hurd_ports[INIT_PORT_PROC], proc); /* Consume.  */
  _hurd_port_set (&_hurd_ports[INIT_PORT_AUTH], auth); /* Consume.  */

  /* Do initial setup with the proc server.  */
  _hurd_proc_init (save_argv, NULL, 0);

  procserver = getproc ();

  /* Have the proc server notify us when the canonical ints and ports
     change.  This will generate an immediate callback giving us the
     initial boot-time canonical sets.  */
  {
    struct iouser *user;
    struct trivfs_protid *cred;
    mach_port_t right;

    err = iohelp_create_empty_iouser (&user);
    assert_perror (err);
    err = trivfs_open (fsys, user, 0, MACH_PORT_NULL, &cred);
    assert_perror (err);

    right = ports_get_send_right (cred);
    proc_execdata_notify (procserver, right, MACH_MSG_TYPE_COPY_SEND);
    mach_port_deallocate (mach_task_self (), right);
  }

  err = get_privileged_ports (&host_priv, NULL);
  assert_perror (err);

  proc_register_version (procserver, host_priv, "exec", "", HURD_VERSION);

  err = proc_getmsgport (procserver, 1, &startup);
  assert_perror (err);
  mach_port_deallocate (mach_task_self (), procserver);

  /* Call startup_essential task last; init assumes we are ready to
     run once we call it. */
  err = startup_essential_task (startup, mach_task_self (), MACH_PORT_NULL,
				"exec", host_priv);
  assert_perror (err);
  mach_port_deallocate (mach_task_self (), startup);

  mach_port_deallocate (mach_task_self (), host_priv);

  return 0;
}
Beispiel #2
0
static void buf_enqueue(int rank, void *buf, int len) {
    assert_perror( recv_buf[rank].buf
      = (struct buf_queue *)realloc( recv_buf[rank].buf,
				     recv_buf[rank].end + len ) );
    assert_perror( memcpy( recv_buf[rank].buf + recv_buf[rank].end,
                           buf, len ) );
    if ( rank != MPINU_myrank ) {
      /* We read from network and enqueue only after we have searched buf */
      assert( recv_buf[rank].end == recv_buf[rank].curs );
      recv_buf[rank].end += len;
      recv_buf[rank].curs = recv_buf[rank].end;
    } else /* If message from self, it did not arrive via network. */
      recv_buf[rank].end += len;
}
Beispiel #3
0
int
main (int argc, char **argv)
{
  error_t err;
  mach_port_t bootstrap;

  argp_parse (&argp, argc, argv, 0, 0, 0);

  if (MACH_PORT_VALID (opt_device_master))
    {
      err = open_console (opt_device_master);
      assert_perror (err);
      mach_port_deallocate (mach_task_self (), opt_device_master);
    }

  save_argv = argv;

  task_get_bootstrap_port (mach_task_self (), &bootstrap);
  if (bootstrap == MACH_PORT_NULL)
    error (2, 0, "Must be started as a translator");

  /* Fetch our proc server port for easy use.  If we are booting, it is not
     set yet and `getproc' returns MACH_PORT_NULL; we reset PROCSERVER in
     S_exec_init (below).  */
  procserver = getproc ();

  err = trivfs_add_port_bucket (&port_bucket);
  if (err)
    error (1, 0, "error creating port bucket");

  err = trivfs_add_control_port_class (&trivfs_control_class);
  if (err)
    error (1, 0, "error creating control port class");

  err = trivfs_add_protid_port_class (&trivfs_protid_class);
  if (err)
    error (1, 0, "error creating protid port class");

  execboot_portclass = ports_create_class (deadboot, NULL);

  /* Reply to our parent.  */
  err = trivfs_startup (bootstrap, 0,
                        trivfs_control_class, port_bucket,
                        trivfs_protid_class, port_bucket, &fsys);

  /* Reply to our parent.  */
  err = trivfs_startup (bootstrap, 0,
			trivfs_control_class, port_bucket,
			trivfs_protid_class, port_bucket,
			&fsys);
  mach_port_deallocate (mach_task_self (), bootstrap);
  if (err)
    error (3, err, "Contacting parent");

  /* Launch.  */
  ports_manage_port_operations_multithread (port_bucket, exec_demuxer,
					    2 * 60 * 1000, 0, 0);

  return 0;
}
static void
fault_handler (int sig, long int sigcode, struct sigcontext *scp)
{
  jmp_buf *env = cthread_data (cthread_self ());
  error_t err;

#ifndef NDEBUG
  if (!env)
    {
      error (0, 0,
	     "BUG: unexpected fault on disk image (%d, %#lx) in [%#lx,%#lx)"
	     " eip %#zx err %#x",
	     sig, sigcode,
	     preemptor.first, preemptor.last,
	     scp->sc_pc, scp->sc_error);
      assert (scp->sc_error == EKERN_MEMORY_ERROR);
      err = pager_get_error (diskfs_disk_pager, sigcode);
      assert (err);
      assert_perror (err);
    }
#endif

  /* Clear the record, since the faulting thread will not.  */
  cthread_set_data (cthread_self (), 0);

  /* Fetch the error code from the pager.  */
  assert (scp->sc_error == EKERN_MEMORY_ERROR);
  err = pager_get_error (diskfs_disk_pager, sigcode);
  assert (err);

  /* Make `diskfault_catch' return the error code.  */
  longjmp (*env, err);
}
Beispiel #5
0
/* Deliver a signal.  SS is not locked.  */
void
_hurd_internal_post_signal (struct hurd_sigstate *ss,
			    int signo, struct hurd_signal_detail *detail,
			    mach_port_t reply_port,
			    mach_msg_type_name_t reply_port_type,
			    int untraced)
{
  error_t err;
  struct machine_thread_all_state thread_state;
  enum { stop, ignore, core, term, handle } act;
  sighandler_t handler;
  sigset_t pending;
  int ss_suspended;

  /* Reply to this sig_post message.  */
  __typeof (__msg_sig_post_reply) *reply_rpc
    = (untraced ? __msg_sig_post_untraced_reply : __msg_sig_post_reply);
  void reply (void)
    {
      error_t err;
      if (reply_port == MACH_PORT_NULL)
	return;
      err = (*reply_rpc) (reply_port, reply_port_type, 0);
      reply_port = MACH_PORT_NULL;
      if (err != MACH_SEND_INVALID_DEST) /* Ignore dead reply port.  */
	assert_perror (err);
    }
Beispiel #6
0
/* Send the Mach message indicated by msg_spec.   call cthread_exit
   when it has been delivered. */
static any_t
blocking_message_send (any_t arg)
{
  struct msg_sig_post_request *const req = arg;
  error_t err;

  err = mach_msg (&req->head, MACH_SEND_MSG, sizeof *req, 0,
		  MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);

  switch (err)
    {
      /* These are the codes that mean a pseudo-receive modified
	 the message buffer and we might need to clean up the send rights.
	 None of them should be possible in our usage.  */
    case MACH_SEND_TIMED_OUT:
    case MACH_SEND_INTERRUPTED:
    case MACH_SEND_INVALID_NOTIFY:
    case MACH_SEND_NO_NOTIFY:
    case MACH_SEND_NOTIFY_IN_PROGRESS:
      assert_perror (err);
      break;

    default:			/* Other errors are safe to ignore.  */
      break;
    }


  return 0;
}
Beispiel #7
0
/* Transmit an ethernet frame */
int
ethernet_xmit (struct sk_buff *skb, struct device *dev)
{
  error_t err;
  struct ether_device *edev = (struct ether_device *) dev->priv;
  u_int count;
  u_int tried = 0;

  do
    {
      tried++;
      err = device_write (edev->ether_port, D_NOWAIT, 0, skb->data, skb->len, &count);
      if (err == EMACH_SEND_INVALID_DEST || err == EMIG_SERVER_DIED)
	{
	  /* Device probably just died, try to reopen it.  */

	  if (tried == 2)
	    /* Too many tries, abort */
	    break;

	  ethernet_close (dev);
	  ethernet_open (dev);
	}
      else
	{
	  assert_perror (err);
	  assert (count == skb->len);
	}
    }
  while (err);

  dev_kfree_skb (skb);
  return 0;
}
mach_port_t
ports_claim_right (void *portstruct)
{
  error_t err;
  struct port_info *pi = portstruct;
  mach_port_t ret = pi->port_right;

  if (ret == MACH_PORT_NULL)
    return ret;

  mutex_lock (&_ports_lock);
  hurd_ihash_locp_remove (&pi->bucket->htable, pi->hentry);
  err = mach_port_move_member (mach_task_self (), ret, MACH_PORT_NULL);
  assert_perror (err);
  pi->port_right = MACH_PORT_NULL;
  if (pi->flags & PORT_HAS_SENDRIGHTS)
    {
      pi->flags &= ~PORT_HAS_SENDRIGHTS;
      mutex_unlock (&_ports_lock);
      ports_port_deref (pi);
    }
  else
    mutex_unlock (&_ports_lock);

  return ret;
}
Beispiel #9
0
/* In the childs, unlock the interlock, and start a profiling thread up
   if necessary. */
static void
fork_profil_child (void)
{
    u_short *sb;
    size_t n, o, ss;
    error_t err;

    __spin_unlock (&lock);

    if (profile_thread != MACH_PORT_NULL)
    {
        __mach_port_deallocate (__mach_task_self (), profile_thread);
        profile_thread = MACH_PORT_NULL;
    }

    sb = samples;
    samples = NULL;
    n = maxsamples;
    maxsamples = 0;
    o = pc_offset;
    pc_offset = 0;
    ss = sample_scale;
    sample_scale = 0;

    if (ss != 0)
    {
        err = update_waiter (sb, n * sizeof *sb, o, ss);
        assert_perror (err);
    }
}
Beispiel #10
0
int
ethernet_open (struct device *dev)
{
  error_t err;
  device_t master_device;
  struct ether_device *edev = (struct ether_device *) dev->priv;

  assert (edev->ether_port == MACH_PORT_NULL);

  err = ports_create_port (etherreadclass, etherport_bucket,
			   sizeof (struct port_info), &edev->readpt);
  assert_perror (err);
  edev->readptname = ports_get_right (edev->readpt);
  mach_port_insert_right (mach_task_self (), edev->readptname, edev->readptname,
			  MACH_MSG_TYPE_MAKE_SEND);

  mach_port_set_qlimit (mach_task_self (), edev->readptname, MACH_PORT_QLIMIT_MAX);

  master_device = file_name_lookup (dev->name, O_READ | O_WRITE, 0);
  if (master_device != MACH_PORT_NULL)
    {
      /* The device name here is the path of a device file.  */
      err = device_open (master_device, D_WRITE | D_READ, "eth", &edev->ether_port);
      mach_port_deallocate (mach_task_self (), master_device);
      if (err)
	error (2, err, "device_open on %s", dev->name);

      err = device_set_filter (edev->ether_port, ports_get_right (edev->readpt),
			       MACH_MSG_TYPE_MAKE_SEND, 0,
			       bpf_ether_filter, bpf_ether_filter_len);
      if (err)
	error (2, err, "device_set_filter on %s", dev->name);
    }
  else
    {
      /* No, perhaps a Mach device?  */
      int file_errno = errno;
      err = get_privileged_ports (0, &master_device);
      if (err)
	{
	  error (0, file_errno, "file_name_lookup %s", dev->name);
	  error (2, err, "and cannot get device master port");
	}
      err = device_open (master_device, D_WRITE | D_READ, dev->name, &edev->ether_port);
      mach_port_deallocate (mach_task_self (), master_device);
      if (err)
	{
	  error (0, file_errno, "file_name_lookup %s", dev->name);
	  error (2, err, "device_open(%s)", dev->name);
	}

      err = device_set_filter (edev->ether_port, ports_get_right (edev->readpt),
			       MACH_MSG_TYPE_MAKE_SEND, 0,
			       ether_filter, ether_filter_len);
      if (err)
	error (2, err, "device_set_filter on %s", dev->name);
    }

  return 0;
}
Beispiel #11
0
int
main (int argc, char *argv[])
{
  const size_t size = 10;
  const int default_prot = PROT_READ | PROT_WRITE;
  char *private_anon, *shared_anon;
  char *dont_dump;
  int i;

  private_anon = do_mmap (NULL, size, default_prot,
			  MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
  memset (private_anon, 0x11, size);

  shared_anon = do_mmap (NULL, size, default_prot,
			 MAP_SHARED | MAP_ANONYMOUS, -1, 0);
  memset (shared_anon, 0x22, size);

  dont_dump = do_mmap (NULL, size, default_prot,
		       MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
  memset (dont_dump, 0x55, size);
  i = madvise (dont_dump, size, MADV_DONTDUMP);
  assert_perror (errno);
  assert (i == 0);

  return 0; /* break-here */
}
Beispiel #12
0
void
setup_dummy_device (char *name, struct device **device)
{
  error_t err;
  struct dummy_device *ddev;
  struct device *dev;

  ddev = calloc (1, sizeof (struct dummy_device));
  if (!ddev)
    error (2, ENOMEM, "%s", name);
  ddev->next = dummy_dev;
  dummy_dev = ddev;

  *device = dev = &ddev->dev;

  dev->name = strdup (name);

  dev->priv = ddev;
  dev->get_stats = dummy_get_stats;

  dev->open = dummy_open;
  dev->stop = dummy_stop;
  dev->hard_start_xmit = dummy_xmit;
  dev->set_multicast_list = dummy_set_multi;

  /* These are the ones set by drivers/net/net_init.c::ether_setup.  */
  dev->hard_header = eth_header;
  dev->rebuild_header = eth_rebuild_header;
  dev->hard_header_cache = eth_header_cache;
  dev->header_cache_update = eth_header_cache_update;
  dev->hard_header_parse = eth_header_parse;
  /* We can't do these two (and we never try anyway).  */
  /* dev->change_mtu = eth_change_mtu; */
  /* dev->set_mac_address = eth_mac_addr; */

  /* Some more fields */
  dev->type = ARPHRD_ETHER;
  dev->hard_header_len = ETH_HLEN;
  dev->addr_len = ETH_ALEN;
  memset (dev->broadcast, 0xff, ETH_ALEN);
  dev->flags = IFF_BROADCAST | IFF_MULTICAST;
  dev_init_buffers (dev);

  dev->mtu = 1500;
  dev->tx_queue_len = 0;
  dev->flags |= IFF_NOARP;
  dev->flags &= ~IFF_MULTICAST;

  /* That should be enough.  */

  /* This call adds the device to the `dev_base' chain,
     initializes its `ifindex' member (which matters!),
     and tells the protocol stacks about the device.  */
  err = - register_netdevice (dev);
  assert_perror (err);
}
Beispiel #13
0
/* Block THREAD.  */
void
__pthread_block (struct __pthread *thread)
{
  mach_msg_header_t msg;
  error_t err;

  err = __mach_msg (&msg, MACH_RCV_MSG, 0, sizeof msg,
		    thread->wakeupmsg.msgh_remote_port,
		    MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
  assert_perror (err);
}
Beispiel #14
0
int
main()
{
    LNSTools::Process p([] () {
            return 0;
        });
    p.set_signal(0);
    assert(p.signal() == 0);
    int pid = p.run();
    assert_perror(pid <= 0 ? errno : 0);
    return 0;
}
Beispiel #15
0
/* Allocate a reference for the memory object backing the pager
   USER_PAGER with protection PROT and return it.  */
mach_port_t
user_pager_get_filemap (struct user_pager *user_pager, vm_prot_t prot)
{
  error_t err;

  /* Add a reference for each call, the caller will deallocate it.  */
  err = mach_port_mod_refs (mach_task_self (), user_pager->memobj,
                            MACH_PORT_RIGHT_SEND, +1);
  assert_perror (err);

  return user_pager->memobj;
}
Beispiel #16
0
int
main (int argc, char *argv[])
{
  error_t err;
  pid_t child;

  child = fork ();
  switch (child)
    {
    case -1:
      error (1, errno, "fork");
      break;

    case 0:
      {
	pthread_attr_t attr;
	pthread_t tid;
	void *ret;

	err = pthread_attr_init (&attr);
	assert_perror (err);

	err = pthread_attr_getstacksize (&attr, &stacksize);
	assert_perror (err);

	err = pthread_attr_setguardsize (&attr, stacksize / 2);
	if (err == ENOTSUP)
	  {
	    printf ("Stack guard attribute not supported.\n");
	    return 1;
	  }
	assert_perror (err);

	err = pthread_create (&tid, &attr, thr, 0);
	assert_perror (err);

	err = pthread_attr_destroy (&attr);
	assert_perror (err);

	err = pthread_join (tid, &ret);
	/* Should never be successful.  */
	printf ("Thread did not segfault!?!\n");
	assert_perror (err);
	return 0;
      }

    default:
      {
	pid_t pid;
	int status;

	pid = waitpid (child, &status, 0);
	printf ("pid = %d; child = %d; status = %d\n", pid, child, status);
	assert (pid == child);
	assert (status != 0);
      }
    }

  return 0;
}
Beispiel #17
0
void
memory_grab (void)
{
  bool first = true;

  void add (l4_word_t addr, l4_word_t length)
    {
      if (first || addr < first_frame)
	first_frame = addr;
      if (first || addr + length - PAGESIZE > last_frame)
	last_frame = addr + length - PAGESIZE;
      if (first)
	first = false;

      memory_add (addr, addr + length - 1);
    }

#ifdef _L4_TEST_ENVIRONMENT
#define SIZE 8 * 1024 * 1024
  void *m = mmap (NULL, SIZE, PROT_READ | PROT_WRITE,
		  MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
  if (m == MAP_FAILED)
    panic ("No memory: %m");
  assert_perror (errno);
  add ((l4_word_t) m, SIZE);

#else
  l4_word_t s;
  l4_fpage_t fpage;

#if 0
  /* We need the dirty bits at a page granularity due to our own
     references.  This unfortunately means no large pages.  */

  /* Try with the largest fpage possible.  */
  for (s = L4_WORDSIZE - 1; s >= l4_min_page_size_log2 (); s --)
    ...;
#endif

  s = l4_min_page_size_log2 ();
  /* Keep getting pages of size 2^S.  */
  while (! l4_is_nil_fpage (fpage = sigma0_get_any (s)))
    /* FPAGE is an fpage of size 2^S.  Add each non-reserved base
       frame to the free list.  */
    add (l4_address (fpage), l4_size (fpage));
#endif

#ifndef NDEBUG
  do_debug (3)
    zalloc_dump_zones (__func__);
#endif
}
Beispiel #18
0
static void buf_init () {
    int i;
    if (recv_buf != NULL)
      return;
    assert_perror( recv_buf
      = (struct buf_queue *)malloc((MPINU_num_slaves+1)
				   * sizeof(struct buf_queue)) );
    for ( i = 0; i <= MPINU_num_slaves; i++ ) {
      recv_buf[i].buf = NULL;
      recv_buf[i].end = 0;
      recv_buf[i].curs = 0;
    }
}
Beispiel #19
0
static inline int get_msg(msg_t& msg,int id){
	int ret;
	std::string str;
	Json::Reader reader;

	msg.clear();
	assert_perror(id < 0);
	if(!get_str_from_fd(id,str))
		return 0;
	reader.parse(str,msg,false);

	return 1;
}
Beispiel #20
0
/* SS->thread is suspended.  Abort the thread and get its basic state.  */
static void
abort_thread (struct hurd_sigstate *ss, struct machine_thread_all_state *state,
	      void (*reply) (void))
{
  if (!(state->set & THREAD_ABORTED))
    {
      error_t err = __thread_abort (ss->thread);
      assert_perror (err);
      /* Clear all thread state flavor set bits, because thread_abort may
	 have changed the state.  */
      state->set = THREAD_ABORTED;
    }

  if (reply)
    (*reply) ();

  machine_get_basic_state (ss->thread, state);
}
Beispiel #21
0
int main(int argc, const char *argv[])
{
	init_function *fun;
	int id;
	//init
	signal(SIGPIPE,SIG_IGN);
	callback_tab["list"] = list;
	callback_tab["close"] = close;
	msg_t config = get_config_from_file("config.json");
	sock::init(config);
	for(fun = &__initlist_start;fun < &__initlist_end;fun++)
		assert_perror((*fun)(config) < 0);

	//main message loop
	while(get_msg_source(id)){
		process_msg(id);
	}

	return 0;
}
Beispiel #22
0
/* Wake up any sigsuspend call that is blocking SS->thread.  SS must be
   locked.  */
static void
wake_sigsuspend (struct hurd_sigstate *ss)
{
  error_t err;
  mach_msg_header_t msg;

  if (ss->suspended == MACH_PORT_NULL)
    return;

  /* There is a sigsuspend waiting.  Tell it to wake up.  */
  msg.msgh_bits = MACH_MSGH_BITS (MACH_MSG_TYPE_MAKE_SEND, 0);
  msg.msgh_remote_port = ss->suspended;
  msg.msgh_local_port = MACH_PORT_NULL;
  /* These values do not matter.  */
  msg.msgh_id = 8675309; /* Jenny, Jenny.  */
  ss->suspended = MACH_PORT_NULL;
  err = __mach_msg (&msg, MACH_SEND_MSG, sizeof msg, 0,
      MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE,
      MACH_PORT_NULL);
  assert_perror (err);
}
Beispiel #23
0
/* Block THREAD.  */
error_t
__pthread_timedblock (struct __pthread *thread,
		      const struct timespec *abstime,
		      clockid_t clock_id)
{
  error_t err;
  mach_msg_header_t msg;
  mach_msg_timeout_t timeout;
  struct timeval now;

  /* We have an absolute time and now we have to convert it to a
     relative time.  Arg.  */

  err = gettimeofday(&now, NULL);
  assert (! err);

  if (now.tv_sec > abstime->tv_sec
      || (now.tv_sec == abstime->tv_sec
	  && now.tv_usec > ((abstime->tv_nsec + 999) / 1000)))
    return ETIMEDOUT;

  timeout = (abstime->tv_sec - now.tv_sec) * 1000;

  if (((abstime->tv_nsec + 999) / 1000) >= now.tv_usec)
    timeout += (((abstime->tv_nsec + 999) / 1000) - now.tv_usec + 999) / 1000;
  else
    /* Need to do a carry.  */
    timeout -= (now.tv_usec + 999) / 1000 -
      ((abstime->tv_nsec + 999999) / 1000000);

  err = __mach_msg (&msg, MACH_RCV_MSG | MACH_RCV_TIMEOUT, 0,
		    sizeof msg, thread->wakeupmsg.msgh_remote_port,
		    timeout, MACH_PORT_NULL);
  if (err == EMACH_RCV_TIMED_OUT)
    return ETIMEDOUT;

  assert_perror (err);
  return 0;
}
Beispiel #24
0
static void
abort_all_rpcs (int signo, struct machine_thread_all_state *state, int live)
{
  /* We can just loop over the sigstates.  Any thread doing something
     interruptible must have one.  We needn't bother locking because all
     other threads are stopped.  */

  struct hurd_sigstate *ss;
  size_t nthreads;
  mach_port_t *reply_ports;

  /* First loop over the sigstates to count them.
     We need to know how big a vector we will need for REPLY_PORTS.  */
  nthreads = 0;
  for (ss = _hurd_sigstates; ss != NULL; ss = ss->next)
    ++nthreads;

  reply_ports = alloca (nthreads * sizeof *reply_ports);

  nthreads = 0;
  for (ss = _hurd_sigstates; ss != NULL; ss = ss->next, ++nthreads)
    if (ss->thread == _hurd_msgport_thread)
      reply_ports[nthreads] = MACH_PORT_NULL;
    else
      {
	int state_changed;
	state->set = 0;		/* Reset scratch area.  */

	/* Abort any operation in progress with interrupt_operation.
	   Record the reply port the thread is waiting on.
	   We will wait for all the replies below.  */
	reply_ports[nthreads] = _hurdsig_abort_rpcs (ss, signo, 1,
						     state, &state_changed,
						     NULL);
	if (live)
	  {
	    if (reply_ports[nthreads] != MACH_PORT_NULL)
	      {
		/* We will wait for the reply to this RPC below, so the
		   thread must issue a new RPC rather than waiting for the
		   reply to the one it sent.  */
		state->basic.SYSRETURN = EINTR;
		state_changed = 1;
	      }
	    if (state_changed)
	      /* Aborting the RPC needed to change this thread's state,
		 and it might ever run again.  So write back its state.  */
	      __thread_set_state (ss->thread, MACHINE_THREAD_STATE_FLAVOR,
				  (natural_t *) &state->basic,
				  MACHINE_THREAD_STATE_COUNT);
	  }
      }

  /* Wait for replies from all the successfully interrupted RPCs.  */
  while (nthreads-- > 0)
    if (reply_ports[nthreads] != MACH_PORT_NULL)
      {
	error_t err;
	mach_msg_header_t head;
	err = __mach_msg (&head, MACH_RCV_MSG|MACH_RCV_TIMEOUT, 0, sizeof head,
			  reply_ports[nthreads],
			  _hurd_interrupted_rpc_timeout, MACH_PORT_NULL);
	switch (err)
	  {
	  case MACH_RCV_TIMED_OUT:
	  case MACH_RCV_TOO_LARGE:
	    break;

	  default:
	    assert_perror (err);
	  }
      }
}
Beispiel #25
0
int
main (int argc, char **argv)
{
  int i;
  int standalone = 0;
  struct sigaction act;

  if (argc == 2 && strcmp (argv[1], "-s") == 0)
    standalone = 1;
  else
    assert (argc == 1);

  setbuf (stdout, NULL);

  timed_mutex_lock (&thread1_tid_mutex);
  timed_mutex_lock (&thread2_tid_mutex);

  timed_mutex_lock (&terminate_mutex);

  errno = 0;
  memset (&act, 0, sizeof (act));
  act.sa_sigaction = handler;
  act.sa_flags = SA_RESTART | SA_SIGINFO;
  i = sigemptyset (&act.sa_mask);
  assert_perror (errno);
  assert (i == 0);
  i = sigaction (SIGUSR1, &act, NULL);
  assert_perror (errno);
  assert (i == 0);
  i = sigaction (SIGUSR2, &act, NULL);
  assert_perror (errno);
  assert (i == 0);

  pthread_barrier_init (&threads_started_barrier, NULL, 3);

  i = pthread_create (&thread1, NULL, thread1_func, NULL);
  assert (i == 0);

  i = pthread_create (&thread2, NULL, thread2_func, NULL);
  assert (i == 0);

  if (!standalone)
    {
      tracer = proc_ulong ("/proc/self/status", "TracerPid:\t");
      if (tracer == 0)
	{
	  fprintf (stderr, "The testcase must be run by GDB!\n");
	  exit (EXIT_FAILURE);
	}
      if (tracer != getppid ())
	{
	  fprintf (stderr, "The testcase parent must be our GDB tracer!\n");
	  exit (EXIT_FAILURE);
	}
    }

  /* SIGCONT our debugger in the case of our crash as we would deadlock
     otherwise.  */

  atexit (cleanup);

  /* Wait until all threads are seen running.  On Linux (at least),
     new threads start stopped, and the debugger must resume them.
     Need to wait for that before stopping GDB.  */
  pthread_barrier_wait (&threads_started_barrier);

  printf ("Stopping GDB PID %lu.\n", (unsigned long) tracer);

  if (tracer)
    {
      i = kill (tracer, SIGSTOP);
      assert (i == 0);
      state_wait (tracer, "T (stopped)");
    }

  /* Threads are now waiting at timed_mutex_lock (thread1_tid_mutex)
     and so they could not trigger the signals before GDB is unstopped
     later.  Threads get resumed by the pthread_cond_wait below.  Use
     `while' loops for protection against spurious pthread_cond_wait
     wakeups.  */

  printf ("Waiting till the threads initialize their TIDs.\n");

  while (thread1_tid == 0)
    {
      i = pthread_cond_wait (&thread1_tid_cond, &thread1_tid_mutex);
      assert (i == 0);
    }

  while (thread2_tid == 0)
    {
      i = pthread_cond_wait (&thread2_tid_cond, &thread2_tid_mutex);
      assert (i == 0);
    }

  printf ("Thread 1 TID = %lu, thread 2 TID = %lu, PID = %lu.\n",
	  (unsigned long) thread1_tid, (unsigned long) thread2_tid,
	  (unsigned long) getpid ());

  errno = 0;
  i = tgkill (getpid (), thread1_tid, SIGUSR1);
  assert_perror (errno);
  assert (i == 0);
  i = tgkill (getpid (), thread1_tid, SIGUSR2);
  assert_perror (errno);
  assert (i == 0);
  i = tgkill (getpid (), thread2_tid, SIGUSR1);
  assert_perror (errno);
  assert (i == 0);
  i = tgkill (getpid (), thread2_tid, SIGUSR2);
  assert_perror (errno);
  assert (i == 0);

  printf ("Waiting till the threads are trapped by the signals.\n");

  if (tracer)
    {
      /* s390x-unknown-linux-gnu will fail with "R (running)".  */

      state_wait (thread1_tid, "t (tracing stop)");

      state_wait (thread2_tid, "t (tracing stop)");
    }

  cleanup ();

  printf ("Joining the threads.\n");

  i = pthread_mutex_unlock (&terminate_mutex);
  assert (i == 0);

  i = pthread_join (thread1, NULL);
  assert (i == 0);

  i = pthread_join (thread2, NULL);
  assert (i == 0);

  printf ("Exiting.\n");	/* break-at-exit */

  return EXIT_SUCCESS;
}
Beispiel #26
0
void
setup_ethernet_device (char *name, struct device **device)
{
  struct net_status netstat;
  size_t count;
  int net_address[2];
  error_t err;
  struct ether_device *edev;
  struct device *dev;

  edev = calloc (1, sizeof (struct ether_device));
  if (!edev)
    error (2, ENOMEM, "%s", name);
  edev->next = ether_dev;
  ether_dev = edev;

  *device = dev = &edev->dev;

  dev->name = strdup (name);
  /* Functions.  These ones are the true "hardware layer" in Linux.  */
  dev->open = 0;		/* We set up before calling dev_open.  */
  dev->stop = ethernet_stop;
  dev->hard_start_xmit = ethernet_xmit;
  dev->get_stats = ethernet_get_stats;
  dev->set_multicast_list = ethernet_set_multi;

  /* These are the ones set by drivers/net/net_init.c::ether_setup.  */
  dev->hard_header = eth_header;
  dev->rebuild_header = eth_rebuild_header;
  dev->hard_header_cache = eth_header_cache;
  dev->header_cache_update = eth_header_cache_update;
  dev->hard_header_parse = eth_header_parse;
  /* We can't do these two (and we never try anyway).  */
  /* dev->change_mtu = eth_change_mtu; */
  /* dev->set_mac_address = eth_mac_addr; */

  /* Some more fields */
  dev->priv = edev;         /* For reverse lookup.  */
  dev->type = ARPHRD_ETHER;
  dev->hard_header_len = ETH_HLEN;
  dev->addr_len = ETH_ALEN;
  memset (dev->broadcast, 0xff, ETH_ALEN);
  dev->flags = IFF_BROADCAST | IFF_MULTICAST;

  /* FIXME: Receive all multicast to fix IPv6, until we implement
     ethernet_set_multi.  */
  dev->flags |= IFF_ALLMULTI;

  dev->change_flags = ethernet_change_flags;

  dev_init_buffers (dev);

  ethernet_open (dev);

  /* Fetch hardware information */
  count = NET_STATUS_COUNT;
  err = device_get_status (edev->ether_port, NET_STATUS,
			   (dev_status_t) &netstat, &count);
  if (err)
    error (2, err, "%s: Cannot get device status", name);
  dev->mtu = netstat.max_packet_size - dev->hard_header_len;
  assert (netstat.header_format == HDR_ETHERNET);
  assert (netstat.header_size == ETH_HLEN);
  assert (netstat.address_size == ETH_ALEN);

  count = 2;
  assert (count * sizeof (int) >= ETH_ALEN);
  err = device_get_status (edev->ether_port, NET_ADDRESS, net_address, &count);
  if (err)
    error (2, err, "%s: Cannot get hardware Ethernet address", name);
  net_address[0] = ntohl (net_address[0]);
  net_address[1] = ntohl (net_address[1]);
  memcpy (dev->dev_addr, net_address, ETH_ALEN);

  /* That should be enough.  */

  /* This call adds the device to the `dev_base' chain,
     initializes its `ifindex' member (which matters!),
     and tells the protocol stacks about the device.  */
  err = - register_netdevice (dev);
  assert_perror (err);
}
Beispiel #27
0
void
_hurdsig_fault_init (void)
{
  error_t err;
  struct machine_thread_state state;
  mach_port_t sigexc;

  /* Allocate a port to receive signal thread exceptions.
     We will move this receive right to the proc server.  */
  err = __mach_port_allocate (__mach_task_self (),
			      MACH_PORT_RIGHT_RECEIVE, &sigexc);
  assert_perror (err);
  err = __mach_port_allocate (__mach_task_self (),
			      MACH_PORT_RIGHT_RECEIVE, &forward_sigexc);
  assert_perror (err);

  /* Allocate a port to receive the exception msgs forwarded
     from the proc server.  */
  err = __mach_port_insert_right (__mach_task_self (), sigexc,
				  sigexc, MACH_MSG_TYPE_MAKE_SEND);
  assert_perror (err);

  /* Set the queue limit for this port to just one.  The proc server will
     notice if we ever get a second exception while one remains queued and
     unreceived, and decide we are hopelessly buggy.  */
#ifdef MACH_PORT_RECEIVE_STATUS_COUNT
  {
    const mach_port_limits_t lim = { mpl_qlimit: 1 };
    assert (MACH_PORT_RECEIVE_STATUS_COUNT == sizeof lim / sizeof (natural_t));
    err = __mach_port_set_attributes (__mach_task_self (), forward_sigexc,
				      MACH_PORT_RECEIVE_STATUS,
				      (mach_port_info_t) &lim,
				      MACH_PORT_RECEIVE_STATUS_COUNT);
  }
#else
  err = __mach_port_set_qlimit (__mach_task_self (), forward_sigexc, 1);
#endif
  assert_perror (err);

  /* This state will be restored when we fault.
     It runs the function above.  */
  memset (&state, 0, sizeof state);
  MACHINE_THREAD_STATE_SET_PC (&state, faulted);
  MACHINE_THREAD_STATE_SET_SP (&state, faultstack, sizeof faultstack);

  err = __USEPORT
    (PROC,
     __proc_handle_exceptions (port,
			       sigexc,
			       forward_sigexc, MACH_MSG_TYPE_MAKE_SEND,
			       MACHINE_THREAD_STATE_FLAVOR,
			       (natural_t *) &state,
			       MACHINE_THREAD_STATE_COUNT));
  assert_perror (err);

  /* Direct signal thread exceptions to the proc server.  */
#ifdef THREAD_EXCEPTION_PORT
  err = __thread_set_special_port (_hurd_msgport_thread,
				   THREAD_EXCEPTION_PORT, sigexc);
#elif defined (EXC_MASK_ALL)
  __thread_set_exception_ports (_hurd_msgport_thread,
				EXC_MASK_ALL & ~(EXC_MASK_SYSCALL
						 | EXC_MASK_MACH_SYSCALL
						 | EXC_MASK_RPC_ALERT),
				sigexc,
				EXCEPTION_STATE_IDENTITY,
				MACHINE_THREAD_STATE);
#else
# error thread_set_exception_ports?
#endif
  __mach_port_deallocate (__mach_task_self (), sigexc);
  assert_perror (err);
}
Beispiel #28
0
/**
 * adds a new mmio_group to a the container
 */
int add_group_to_container(int groupid)
{
    int group = 0;
    char grouppath[50];
    struct vfio_group_status group_status = { .argsz = sizeof(group_status) };
    struct vfio_iommu_type1_info iommu_info = { .argsz = sizeof(iommu_info) };

    int container = open_container();
    assert(container >= 0);

    /* Open the group */
    sprintf(grouppath, "/dev/vfio/%d", groupid);
    assert((group = open(grouppath, O_RDWR))>=0);

    /* Test the group is viable and available */
    assert_perror(ioctl(group, VFIO_GROUP_GET_STATUS, &group_status));
    assert(group_status.flags & VFIO_GROUP_FLAGS_VIABLE);

    /* Add the group to the container */
    assert_perror(ioctl(group, VFIO_GROUP_SET_CONTAINER, &container));

    /* Enable the IOMMU model we want, only once */
    if (!_set_iommu_type) {
        assert_perror(ioctl(container, VFIO_SET_IOMMU, VFIO_TYPE1_IOMMU));
        _set_iommu_type = 1;
    }

    return group;
}

/**
 * opens a device using an open group descriptor
 */
int open_device_from_vfio_group (int groupfd, const char* devicename)
{
    return ioctl(groupfd, VFIO_GROUP_GET_DEVICE_FD, devicename);
}

/**
 * maps a chunk of memory to a given IOVA on the container's IO space
 */
uint64_t mmap_memory(void *buffer, uint64_t size, uint64_t iova, uint8_t read, uint8_t write)
{
    if (!_container)
        return 0;

    struct vfio_iommu_type1_dma_map dma_map = { .argsz = sizeof(dma_map) };

    dma_map.vaddr = (uint64_t)buffer;
    dma_map.size = size;
    dma_map.iova = iova;
    dma_map.flags = 0 |
        (read ? VFIO_DMA_MAP_FLAG_READ : 0) |
        (write ? VFIO_DMA_MAP_FLAG_WRITE : 0);

    if (ioctl(_container, VFIO_IOMMU_MAP_DMA, &dma_map)) {
        return 0;
    }
    return dma_map.iova;
}



void show_device_info (int device)
{
    int i;
    struct vfio_device_info device_info = { .argsz = sizeof(device_info) };
    /* Test and setup the device */
    assert(ioctl(device, VFIO_DEVICE_GET_INFO, &device_info)==0);
    if (device_info.flags & VFIO_DEVICE_FLAGS_RESET) {
        printf ("device supports RESET\n");
    }
    if (device_info.flags & VFIO_DEVICE_FLAGS_PCI) {
        printf ("it's a PCI device");
    }

    printf ("found %ud regions\n", device_info.num_regions);
    for (i = 0; i < device_info.num_regions; i++) {
        struct vfio_region_info reg = { .argsz = sizeof(reg) };

        reg.index = i;
        assert(ioctl(device, VFIO_DEVICE_GET_REGION_INFO, &reg)==0);
        printf ("region %d (%d) [%llX-%llX]:\n", i, reg.index, reg.offset, reg.size);
        if (reg.flags & VFIO_REGION_INFO_FLAG_READ) {
            printf (" supports read.");
        }
        if (reg.flags & VFIO_REGION_INFO_FLAG_WRITE) {
            printf (" supports write.");
        }
        if (reg.flags & VFIO_REGION_INFO_FLAG_MMAP) {
            printf (" supports mmap.");
        }
        printf ("\n");
    }

    printf ("found %ud interrupts\n", device_info.num_irqs);
    for (i = 0; i < device_info.num_irqs; i++) {
        struct vfio_irq_info irq = { .argsz = sizeof(irq) };

        irq.index = i;
        assert(ioctl(device, VFIO_DEVICE_GET_IRQ_INFO, &irq)==0);
        printf ("irq %d (%d) count:%d", i, irq.index, irq.count);
        if (irq.flags & VFIO_IRQ_INFO_EVENTFD) {
            printf (" eventfd");
        }
        if (irq.flags & VFIO_IRQ_INFO_MASKABLE) {
            printf (" maskable");
        }
        if (irq.flags & VFIO_IRQ_INFO_AUTOMASKED) {
            printf (" automasked");
        }
        if (irq.flags & VFIO_IRQ_INFO_NORESIZE) {
            printf (" noresize");
        }
        printf ("\n");
    }
}


/**
 * maps IO registers of the given region onto virtual memory
 */
uint32_t volatile *mmap_region (int device, int n)
{
    struct vfio_device_info device_info = { .argsz = sizeof(device_info) };
    struct vfio_region_info reg = { .argsz = sizeof(reg) };
    void *ptr = NULL;

    // check if it's a valid region
    assert(ioctl(device, VFIO_DEVICE_GET_INFO, &device_info)==0);
    if (n >= device_info.num_regions) return NULL;

    reg.index = n;
    assert(ioctl(device, VFIO_DEVICE_GET_REGION_INFO, &reg)==0);
    // is this region mmap()able?
    if (! (reg.flags & VFIO_REGION_INFO_FLAG_MMAP)) return NULL;

    ptr = mmap(NULL, reg.size, PROT_READ | PROT_WRITE, MAP_SHARED, device, reg.offset);
    if (ptr == MAP_FAILED) {
        return NULL;
    } else {
        return (uint32_t volatile *)ptr;
    }
}


size_t pread_config (int device, void* buf, size_t count, int64_t offset)
{
    struct vfio_region_info reg = { .argsz = sizeof(reg) };

    reg.index = VFIO_PCI_CONFIG_REGION_INDEX;
    assert(ioctl(device, VFIO_DEVICE_GET_REGION_INFO, &reg)==0);
    return pread(device, buf, count, reg.offset+offset);
}

size_t pwrite_config (int device, void* buf, size_t count, int64_t offset)
{
    struct vfio_region_info reg = { .argsz = sizeof(reg) };

    reg.index = VFIO_PCI_CONFIG_REGION_INDEX;
    assert(ioctl(device, VFIO_DEVICE_GET_REGION_INFO, &reg)==0);
    return pread(device, buf, count, reg.offset+offset);
}
error_t
ports_transfer_right (void *tostruct, 
		      void *fromstruct)
{
  struct port_info *topi = tostruct;
  struct port_info *frompi = fromstruct;
  mach_port_t port;
  int dereffrompi = 0;
  int dereftopi = 0;
  int hassendrights = 0;
  error_t err;

  mutex_lock (&_ports_lock);

  /* Fetch the port in FROMPI and clear its use */
  port = frompi->port_right;
  if (port != MACH_PORT_NULL)
    {
      hurd_ihash_locp_remove (&frompi->bucket->htable, frompi->hentry);
      frompi->port_right = MACH_PORT_NULL;
      if (frompi->flags & PORT_HAS_SENDRIGHTS)
	{
	  frompi->flags &= ~PORT_HAS_SENDRIGHTS;
	  hassendrights = 1;
	  dereffrompi = 1;
	}
    }
  
  /* Destroy the existing right in TOPI. */
  if (topi->port_right != MACH_PORT_NULL)
    {
      hurd_ihash_locp_remove (&topi->bucket->htable, topi->hentry);
      err = mach_port_mod_refs (mach_task_self (), topi->port_right,
				MACH_PORT_RIGHT_RECEIVE, -1);
      assert_perror (err);
      if ((topi->flags & PORT_HAS_SENDRIGHTS) && !hassendrights)
	{
	  dereftopi = 1;
	  topi->flags &= ~PORT_HAS_SENDRIGHTS;
	}
      else if (((topi->flags & PORT_HAS_SENDRIGHTS) == 0) && hassendrights)
	{
	  topi->flags |= PORT_HAS_SENDRIGHTS;
	  topi->refcnt++;
	}
    }
  
  /* Install the new right in TOPI. */
  topi->port_right = port;
  topi->cancel_threshold = frompi->cancel_threshold;
  topi->mscount = frompi->mscount;
  
  if (port)
    {
      hurd_ihash_add (&topi->bucket->htable, port, topi);
      if (topi->bucket != frompi->bucket)
        {
	  err = mach_port_move_member (mach_task_self (), port,
				       topi->bucket->portset);
	  assert_perror (err);
	}
    }
  
  mutex_unlock (&_ports_lock);
  
  /* Take care of any lowered reference counts. */
  if (dereffrompi)
    ports_port_deref (frompi);
  if (dereftopi)
    ports_port_deref (topi);
  return 0;
}
Beispiel #30
0
int
main (int argc, char **argv, char **envp)
{
  mach_port_t boot;
  error_t err;
  void *genport;
  process_t startup_port;
  mach_port_t startup;
  struct argp argp = { 0, 0, 0, "Hurd process server" };

  argp_parse (&argp, argc, argv, 0, 0, 0);

  initialize_version_info ();

  err = task_get_bootstrap_port (mach_task_self (), &boot);
  assert_perror (err);
  if (boot == MACH_PORT_NULL)
    error (2, 0, "proc server can only be run by init during boot");

  proc_bucket = ports_create_bucket ();
  proc_class = ports_create_class (0, 0);
  generic_port_class = ports_create_class (0, 0);
  exc_class = ports_create_class (exc_clean, 0);
  ports_create_port (generic_port_class, proc_bucket,
		     sizeof (struct port_info), &genport);
  generic_port = ports_get_right (genport);

  /* Create the initial proc object for init (PID 1).  */
  init_proc = create_init_proc ();

  /* Create the startup proc object for /hurd/init (PID 2).  */
  startup_proc = allocate_proc (MACH_PORT_NULL);
  startup_proc->p_deadmsg = 1;
  complete_proc (startup_proc, HURD_PID_STARTUP);

  /* Create our own proc object.  */
  self_proc = allocate_proc (mach_task_self ());
  assert (self_proc);

  complete_proc (self_proc, HURD_PID_PROC);

  startup_port = ports_get_send_right (startup_proc);
  err = startup_procinit (boot, startup_port, &startup_proc->p_task,
			  &authserver, &_hurd_host_priv, &_hurd_device_master);
  assert_perror (err);
  mach_port_deallocate (mach_task_self (), startup_port);

  mach_port_mod_refs (mach_task_self (), authserver, MACH_PORT_RIGHT_SEND, 1);
  _hurd_port_set (&_hurd_ports[INIT_PORT_AUTH], authserver);
  mach_port_deallocate (mach_task_self (), boot);

  proc_death_notify (startup_proc);
  add_proc_to_hash (startup_proc); /* Now that we have the task port.  */

  /* Set our own argv and envp locations.  */
  self_proc->p_argv = (vm_address_t) argv;
  self_proc->p_envp = (vm_address_t) envp;

  /* Give ourselves good scheduling performance, because we are so
     important. */
  err = increase_priority ();
  if (err)
    error (0, err, "Increasing priority failed");

#if 0
  err = register_new_task_notification (_hurd_host_priv,
					generic_port,
					MACH_MSG_TYPE_MAKE_SEND);
  if (err)
    error (0, err, "Registering task notifications failed");
#endif

  {
    /* Get our stderr set up to print on the console, in case we have
       to panic or something.  */
    mach_port_t cons;
    error_t err;
    err = device_open (_hurd_device_master, D_READ|D_WRITE, "console", &cons);
    assert_perror (err);
    stdin = mach_open_devstream (cons, "r");
    stdout = stderr = mach_open_devstream (cons, "w");
    mach_port_deallocate (mach_task_self (), cons);
  }

  startup = file_name_lookup (_SERVERS_STARTUP, 0, 0);
  if (MACH_PORT_VALID (startup))
    {
      err = startup_essential_task (startup, mach_task_self (),
				    MACH_PORT_NULL, "proc", _hurd_host_priv);
      if (err)
	/* Due to the single-threaded nature of /hurd/startup, it can
	   only handle requests once the core server bootstrap has
	   completed.  Therefore, it does not bind itself to
	   /servers/startup until it is ready.	*/
	/* Fall back to abusing the message port lookup.  */
	startup_fallback = 1;

      err = mach_port_deallocate (mach_task_self (), startup);
      assert_perror (err);
    }
  else
    /* Fall back to abusing the message port lookup.	*/
    startup_fallback = 1;

  while (1)
    ports_manage_port_operations_multithread (proc_bucket,
					      message_demuxer,
					      0, 0, 0);
}