Index: netd_gatesrv.cc =================================================================== --- netd_gatesrv.cc (revision 7456) +++ netd_gatesrv.cc (working copy) @@ -10,6 +10,7 @@ #include #include #include +#include #include #include @@ -24,6 +25,16 @@ #include #include +struct fast_args { + struct cobj_ref stackobj; + void *stackbase; + struct cobj_ref ipc_seg; + struct netd_ipc_segment *ipc; + uint64_t bytes; + struct cobj_ref temp_as; + netd_handler h; +}; + static uint64_t netd_server_enabled; static struct cobj_ref declassify_gate; static struct cobj_ref netd_asref; @@ -67,65 +78,31 @@ rg->ret(0, 0, 0); } -static void -netd_ipc_setup(uint64_t taint_ct, struct cobj_ref ipc_seg, uint64_t flags, - void **va, uint64_t *bytes, struct cobj_ref *temp_as) +void __attribute__((noreturn)) +netd_fast_cleanup(struct fast_args *args) { - uint64_t netd_ct = start_env->proc_container; - - error_check(sys_self_addref(netd_ct)); - scope_guard unref(sys_obj_unref, COBJ(netd_ct, thread_id())); - - // Create private container backed by user resources + AS clone - { - label private_label; - thread_cur_label(&private_label); - private_label.transform(label::star_to, private_label.get_default()); - private_label.set(start_env->process_grant, 0); - private_label.set(start_env->process_taint, 3); - - int64_t private_ct; - error_check(private_ct = - sys_container_alloc(taint_ct, private_label.to_ulabel(), - "netd_fast private", 0, CT_QUOTA_INF)); - - int64_t asid; - error_check(asid = sys_as_copy(netd_asref, private_ct, - 0, "netd_ipc temp AS")); - *temp_as = COBJ(private_ct, asid); - } - - error_check(sys_self_set_as(*temp_as)); - segment_as_switched(); - error_check(segment_map(ipc_seg, 0, flags, va, bytes, 0)); + struct cobj_ref o = args->stackobj; + segment_unmap(args->stackbase); + sys_obj_unref(o); + thread_halt(); } static void __attribute__((noreturn)) -netd_fast_gate_entry(uint64_t a, struct gate_call_data *gcd, gatesrv_return *rg) +netd_fast_server(struct fast_args *args) { - netd_handler h = (netd_handler) (uintptr_t) a; + struct netd_ipc_segment *ipc = args->ipc; uint64_t netd_ct = start_env->proc_container; - struct cobj_ref temp_as; - struct netd_ipc_segment *ipc = 0; - uint64_t map_bytes = 0; - error_check(sys_segment_resize(COBJ(0, kobject_id_thread_sg), 2 * PGSIZE)); - - while (!netd_server_enabled) - sys_sync_wait(&netd_server_enabled, 0, UINT64(~0)); - - netd_ipc_setup(gcd->taint_container, gcd->param_obj, - SEGMAP_READ | SEGMAP_WRITE, - (void **) &ipc, &map_bytes, &temp_as); - struct jos_jmp_buf pgfault; - if (jos_setjmp(&pgfault) != 0) - thread_halt(); + if (jos_setjmp(&pgfault) != 0) { + stack_switch((uint64_t)(uintptr_t)args, 0, 0, 0, + (char *)tls_stack_top - 8, (void *) &netd_fast_cleanup); + } tls_data->tls_pgfault = &pgfault; - if (map_bytes != sizeof(*ipc)) + if (args->bytes != sizeof(*ipc)) throw basic_exception("wrong size IPC segment: %"PRIu64" should be %"PRIu64"\n", - map_bytes, (uint64_t) sizeof(*ipc)); + args->bytes, (uint64_t) sizeof(*ipc)); for (;;) { while (ipc->sync == NETD_IPC_SYNC_REPLY) @@ -140,10 +117,10 @@ // Map shared memory segment & execute operation { struct netd_ipc_segment *ipc_shared = 0; - error_check(segment_map(gcd->param_obj, 0, + error_check(segment_map(args->ipc_seg, 0, SEGMAP_READ | SEGMAP_WRITE | SEGMAP_VECTOR_PF, - (void **) &ipc_shared, &map_bytes, 0)); + (void **) &ipc_shared, &args->bytes, 0)); scope_guard unmap(segment_unmap, ipc_shared); struct netd_ipc_segment *ipc_copy; @@ -162,7 +139,7 @@ while (ipc_shared->sync == NETD_IPC_SYNC_REQUEST) { memcpy(&ipc_copy->args, &ipc_shared->args, ipc_shared->args.size); - h(&ipc_copy->args); + args->h(&ipc_copy->args); memcpy(&ipc_shared->args, &ipc_copy->args, ipc_copy->args.size); @@ -180,10 +157,82 @@ } unref.force(); - error_check(sys_self_set_as(temp_as)); + error_check(sys_self_set_as(args->temp_as)); } + + stack_switch((uint64_t)(uintptr_t)args, 0, 0, 0, + (char *)tls_stack_top - 8, (void *) &netd_fast_cleanup); +} - thread_halt(); +static void __attribute__((noreturn)) +netd_fast_gate_entry(uint64_t a, struct gate_call_data *gcd, gatesrv_return *rg) +{ + netd_handler h = (netd_handler) (uintptr_t) a; + struct netd_ipc_segment *ipc = 0; + + error_check(sys_segment_resize(COBJ(0, kobject_id_thread_sg), 2 * PGSIZE)); + + while (!netd_server_enabled) + sys_sync_wait(&netd_server_enabled, 0, UINT64(~0)); + + uint64_t netd_ct = start_env->proc_container; + + error_check(sys_self_addref(netd_ct)); + scope_guard unref(sys_obj_unref, COBJ(netd_ct, thread_id())); + + struct cobj_ref stackobj; + void *stackbase = 0; + char *stacktop; + + struct cobj_ref temp_as; + + // Create private container backed by user resources + AS clone + { + label private_label; + thread_cur_label(&private_label); + private_label.transform(label::star_to, private_label.get_default()); + private_label.set(start_env->process_grant, 0); + private_label.set(start_env->process_taint, 3); + + int64_t private_ct; + error_check(private_ct = + sys_container_alloc(gcd->taint_container, private_label.to_ulabel(), + "netd_fast private", 0, CT_QUOTA_INF)); + + error_check(segment_alloc(netd_ct, PGSIZE, &stackobj, + 0, 0, "netd_fast stack")); + scope_guard s(sys_obj_unref, stackobj); + + uint64_t stackbytes = thread_stack_pages * PGSIZE; + error_check(segment_map(stackobj, 0, SEGMAP_READ | SEGMAP_WRITE | + SEGMAP_STACK | SEGMAP_REVERSE_PAGES, + &stackbase, &stackbytes, 0)); + stacktop = ((char *) stackbase) + stackbytes; + s.dismiss(); + + int64_t asid; + error_check(asid = sys_as_copy(netd_asref, private_ct, + 0, "netd_ipc temp AS")); + temp_as = COBJ(private_ct, asid); + } + + struct fast_args *args; + stacktop -= sizeof(*args); + args = (struct fast_args *)stacktop; + + error_check(sys_self_set_as(temp_as)); + segment_as_switched(); + error_check(segment_map(gcd->param_obj, 0, SEGMAP_READ | SEGMAP_WRITE, (void **)&ipc, &args->bytes, 0)); + + args->stackobj = stackobj; + args->stackbase = stackbase; + args->ipc = ipc; + args->ipc_seg = gcd->param_obj; + args->temp_as = temp_as; + args->h = h; + + stack_switch((uint64_t)(uintptr_t)args, 0, 0, 0, + stacktop, (void *) &netd_fast_server); } static void Index: netd_lwipinit.c =================================================================== --- netd_lwipinit.c (revision 7456) +++ netd_lwipinit.c (working copy) @@ -43,18 +43,6 @@ lwip_init(struct netif *nif, void *if_state, uint32_t init_addr, uint32_t init_mask, uint32_t init_gw) { - lwipext_init(1); - // lwIP initialization sequence, as suggested by lwip/doc/rawapi.txt - stats_init(); - sys_init(); - mem_init(); - memp_init(); - pbuf_init(); - etharp_init(); - ip_init(); - udp_init(); - tcp_init(); - struct ip_addr ipaddr, netmask, gateway; ipaddr.addr = init_addr; netmask.addr = init_mask; @@ -118,8 +106,9 @@ static void tcpip_init_done(void *arg) { - sys_sem_t *sem = (sys_sem_t *) arg; - sys_sem_signal(*sem); + uint64_t *done = arg; + *done = 1; + sys_sync_wakeup(done); } static const char * @@ -150,6 +139,14 @@ if (r < 0) panic("cannot alloc netif: %s\n", e2s(r)); + lwipext_init(1); + + uint64_t done = 0; + tcpip_init(&tcpip_init_done, &done); + lwip_core_unlock(); + sys_sync_wait(&done, 0, UINT64(~0)); + lwip_core_lock(); + lwip_init(nif, if_state, ipaddr, netmask, gw); if (ipaddr == 0) @@ -174,11 +171,6 @@ start_timer(&t_dhcpc, &dhcp_coarse_tmr, "dhcp c timer", DHCP_COARSE_TIMER_SECS * 1000); } - sys_sem_t tcpip_init_sem = sys_sem_new(0); - tcpip_init(&tcpip_init_done, &tcpip_init_sem); - sys_sem_wait(tcpip_init_sem); - sys_sem_free(tcpip_init_sem); - cb(cbarg); int dhcp_state = 0;