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; }
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; }
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); }
/* 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); }
/* 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; }
/* 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; }
/* 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); } }
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; }
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 */ }
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); }
/* 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); }
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; }
/* 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; }
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; }
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 }
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; } }
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; }
/* 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); }
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; }
/* 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); }
/* 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; }
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); } } }
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; }
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); }
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); }
/** * 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, ®)==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, ®)==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, ®)==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, ®)==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; }
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); }