diff --git a/include/aos/aos_rpc.h b/include/aos/aos_rpc.h index 15c6db4..f2166d1 100644 --- a/include/aos/aos_rpc.h +++ b/include/aos/aos_rpc.h @@ -17,10 +17,15 @@ #include +// define some message types +#define RPC_MTYPE_CHILD_ENDPOINT 0UL +#define RPC_MTYPE_CHILD_ENDPOINT_OK 1UL + /* An RPC binding, which may be transported over LMP or UMP. */ struct aos_rpc { // TODO(M3): Add state + struct lmp_chan *chan; }; /** diff --git a/include/spawn/spawn.h b/include/spawn/spawn.h index 91c0476..0488733 100644 --- a/include/spawn/spawn.h +++ b/include/spawn/spawn.h @@ -56,6 +56,8 @@ struct spawninfo { struct capref cspace_cap_vspace; // < The frame capability used to store the serialized vspace struct capref vspace_cap_l0_pagetable; + + struct lmp_chan init_chan; }; // Start a child process using the multiboot command line. Fills in si. diff --git a/include/time.h b/include/time.h index 1e6456a..17a41d3 100644 --- a/include/time.h +++ b/include/time.h @@ -152,7 +152,6 @@ time_t mktime(struct tm *); size_t strftime(char * __restrict, size_t, const char * __restrict, const struct tm * __restrict); time_t time(time_t *); -void time_wait_ms(unsigned long); long time_to_ms(struct timespec tt); #if __POSIX_VISIBLE >= 200112 struct sigevent; diff --git a/lib/aos/aos_rpc.c b/lib/aos/aos_rpc.c index 0667e0d..8656eb8 100644 --- a/lib/aos/aos_rpc.c +++ b/lib/aos/aos_rpc.c @@ -81,7 +81,12 @@ aos_rpc_process_get_all_pids(struct aos_rpc *rpc, domainid_t **pids, return SYS_ERR_OK; } - +// We are allowed to change the signature for this one +errval_t aos_rpc_init(struct aos_rpc *rpc) +{ + // TODO! + return SYS_ERR_OK; +} /** * \brief Returns the RPC channel to init. diff --git a/lib/aos/init.c b/lib/aos/init.c index 4672199..129ff76 100644 --- a/lib/aos/init.c +++ b/lib/aos/init.c @@ -28,9 +28,11 @@ #include "threads_priv.h" #include "init.h" +#include /// Are we the init domain (and thus need to take some special paths)? static bool init_domain; +static bool init_chan_initialized; extern size_t (*_libc_terminal_read_func)(char *, size_t); extern size_t (*_libc_terminal_write_func)(const char *, size_t); @@ -81,6 +83,56 @@ static size_t dummy_terminal_read(char *buf, size_t len) return 0; } +// TODO rueegges: putting it here for now. Not sure how to do rcp abstraction yet +static int event_init_dispatch_thread(void *arg) +{ + errval_t err; + while(true) { + err = event_dispatch(get_default_waitset()); + if (err_is_fail(err)) { + USER_PANIC_ERR(err_push(err, LIB_ERR_EVENT_DISPATCH), "Failed to dispatch events"); + } + } +} + +// TODO rueegges: putting it here for now. Not sure how to do rcp abstraction yet +static void handle_init_recv(void *arg) +{ + errval_t err; + struct lmp_chan *init_chan = (struct lmp_chan *)arg; + + struct lmp_recv_msg msg = LMP_RECV_MSG_INIT; + struct capref cap; + + err = lmp_chan_recv(init_chan, &msg, &cap); + if (err_is_fail(err)) { + if (lmp_err_is_transient(err)) { + err = lmp_endpoint_register(init_chan->endpoint, get_default_waitset(), MKCLOSURE(handle_init_recv, init_chan)); + if (err_is_fail(err)) { + USER_PANIC_ERR(err, "Could not reregister after failed init_chan cap receive"); + } + } else { + USER_PANIC_ERR(err, "Failure in child channel"); + } + return; + } + + switch(msg.words[0]){ + case RPC_MTYPE_CHILD_ENDPOINT_OK: + debug_printf("Received child init OK\n"); + init_chan_initialized = true; + break; + default: + USER_PANIC("Unknown rpc message type."); + break; + } + + err = lmp_endpoint_register(init_chan->endpoint, get_default_waitset(), MKCLOSURE(handle_init_recv, init_chan)); + if (err_is_fail(err)) { + USER_PANIC_ERR(err, "Could not reregister after failed init_chan cap receive"); + } +} + /* Set libc function pointers */ void barrelfish_libc_glue_init(void) { @@ -146,16 +198,48 @@ errval_t barrelfish_init_onthread(struct spawn_domain_params *params) lmp_endpoint_init(); // HINT: Use init_domain to check if we are the init domain. + // early exit for the init process + if(init_domain) { + return SYS_ERR_OK; + } // TODO MILESTONE 3: register ourselves with init /* allocate lmp channel structure */ + struct lmp_chan *init_chan = malloc(sizeof(struct lmp_chan)); /* create local endpoint */ + err = endpoint_create(DEFAULT_LMP_BUF_WORDS, &init_chan->local_cap, &init_chan->endpoint); + if (err_is_fail(err)) { + return err_push(err, LIB_ERR_ENDPOINT_CREATE); + } /* set remote endpoint to init's endpoint */ + init_chan->remote_cap = cap_initep; /* set receive handler */ + init_chan_initialized = false; + err = lmp_chan_register_recv(init_chan, get_default_waitset(), MKCLOSURE(handle_init_recv, init_chan)); /* send local ep to init */ + err = lmp_chan_send0(init_chan, LMP_FLAG_YIELD | LMP_FLAG_SYNC, init_chan->local_cap); + if (err_is_fail(err)) { + // should never fail since init listens before invoking the dispatcher + return err_push(err, LIB_ERR_LMP_CHAN_SEND); + } /* wait for init to acknowledge receiving the endpoint */ + while(!init_chan_initialized) { + err = event_dispatch(get_default_waitset()); + if (err_is_fail(err)) { + return err_push(err, LIB_ERR_EVENT_DISPATCH); + } + } /* initialize init RPC client with lmp channel */ + struct aos_rpc *init_rpc = malloc(sizeof(struct aos_rpc)); + err = aos_rpc_init(init_rpc); + if (err_is_fail(err)){ + return err_push(err, ERR_NOTIMP); + } /* set init RPC client in our program state */ + set_init_rpc(init_rpc); + + // create thread to dispatch events + thread_create(event_init_dispatch_thread, NULL); /* TODO MILESTONE 3: now we should have a channel with init set up and can * use it for the ram allocator */ @@ -176,7 +260,7 @@ errval_t barrelfish_init_onthread(struct spawn_domain_params *params) void barrelfish_init_disabled(dispatcher_handle_t handle, bool init_dom_arg); void barrelfish_init_disabled(dispatcher_handle_t handle, bool init_dom_arg) { - init_domain = init_dom_arg; + ; init_domain = init_dom_arg; disp_init_disabled(handle); thread_init_disabled(handle, init_dom_arg); } diff --git a/lib/aos/paging.c b/lib/aos/paging.c index 30eb179..dd8837e 100644 --- a/lib/aos/paging.c +++ b/lib/aos/paging.c @@ -330,7 +330,7 @@ errval_t paging_init_state_foreign(struct paging_state *st, lvaddr_t start_vaddr errval_t paging_init_params(struct spawn_domain_params *params) { errval_t err; - debug_printf("paging_init\n"); + // debug_printf("paging_init\n"); // (M2): Call paging_init_state for ¤t // TODO (M4): initialize self-paging handler // TIP: use thread_set_exception_handler() to setup a page fault handler @@ -351,8 +351,8 @@ errval_t paging_init_params(struct spawn_domain_params *params) if(params != NULL && params->vspace_buf != NULL) { current.l0_pt = **(struct pt_t **)params->vspace_buf; current.vaddr_head = **(struct pt_vaddr_reg_t **)(params->vspace_buf + sizeof(struct pt_t *)); - debug_printf("Received initial paging state:\n"); - pt_print_state(¤t); + // debug_printf("Received initial paging state:\n"); + // pt_print_state(¤t); } set_current_paging_state(¤t); diff --git a/lib/grading/test_spawn.c b/lib/grading/test_spawn.c index 62a8059..e0eb407 100644 --- a/lib/grading/test_spawn.c +++ b/lib/grading/test_spawn.c @@ -8,15 +8,24 @@ void do_test_spawn(void) { // spawn multiple processes - struct spawninfo si[PROCESS_COUNT]; - domainid_t pid[PROCESS_COUNT]; + struct spawninfo *si = malloc(PROCESS_COUNT * sizeof(struct spawninfo)); + domainid_t *pid = malloc(PROCESS_COUNT * sizeof(domainid_t)); for(uint i = 0; i < PROCESS_COUNT; ++i) { debug_printf("TEST_SPAWN: spawn %u\n", i); CHECK_ERR(spawn_load_by_name("hello", &(si[i]), &(pid[i]))); } - // wait for 10 seconds before continuing - time_wait_ms(10000); + // wait for 10 seconds but handle events in the mean time + struct waitset *default_ws = get_default_waitset(); + struct timespec tt; + clock_gettime(CLOCK_REALTIME, &tt); + long start = time_to_ms(tt); + do { + if(err_is_ok(check_for_event(default_ws))){ + CHECK_ERR(event_dispatch(default_ws)); + } + clock_gettime(CLOCK_REALTIME, &tt); + } while(time_to_ms(tt) - start < 10000); for(uint i = 0; i < PROCESS_COUNT; ++i) { debug_printf("TEST_SPAWN: Killing %u\n", i); diff --git a/lib/libc/gen/time.c b/lib/libc/gen/time.c index a480ac9..dabf5b7 100644 --- a/lib/libc/gen/time.c +++ b/lib/libc/gen/time.c @@ -55,24 +55,3 @@ long time_to_ms(struct timespec tt) { return tt.tv_sec * 1000 + tt.tv_nsec / 1000 / 1000; } - -/** - * \brief Wait for ms milliseconds before returning. - * - * \param ms Duration to wait - * - * Very ugly and approximate but useful - * - */ -void -time_wait_ms(unsigned long ms) { - struct timespec tt; - - clock_gettime(CLOCK_REALTIME, &tt); - long start = time_to_ms(tt); - long now; - do { - clock_gettime(CLOCK_REALTIME, &tt); - now = time_to_ms(tt); - } while(start + ms > now); -} \ No newline at end of file diff --git a/lib/spawn/multiboot.c b/lib/spawn/multiboot.c index 412a150..063657d 100644 --- a/lib/spawn/multiboot.c +++ b/lib/spawn/multiboot.c @@ -140,7 +140,7 @@ struct mem_region *multiboot_find_module(struct bootinfo *bi, const char *name) snprintf(pathname, len, "/armv8/sbin/%s", name); name = pathname; } - DEBUG_PRINTF("name is: %s\n", name); + // DEBUG_PRINTF("name is: %s\n", name); for(size_t i = 0; i < bi->regions_length; i++) { struct mem_region *region = &bi->regions[i]; const char *modname = multiboot_module_name(region); diff --git a/lib/spawn/spawn.c b/lib/spawn/spawn.c index 7b450e8..3914133 100644 --- a/lib/spawn/spawn.c +++ b/lib/spawn/spawn.c @@ -47,9 +47,45 @@ static void armv8_set_registers(void *arch_load_info, disabled_area->regs[REG_OFFSET(PIC_REGISTER)] = got_base; } +static void handle_child_recv(void *arg) { + errval_t err; + struct lmp_chan *init_chan = (struct lmp_chan *)arg; + struct lmp_recv_msg msg = LMP_RECV_MSG_INIT; + struct capref cap; + err = lmp_chan_recv(init_chan, &msg, &cap); + if (err_is_fail(err)) { + if (lmp_err_is_transient(err)) { + err = lmp_endpoint_register(init_chan->endpoint, get_default_waitset(), MKCLOSURE(handle_child_recv, init_chan)); + if (err_is_fail(err)) { + USER_PANIC_ERR(err, "Could not reregister after failed init_chan cap receive"); + } + } else { + USER_PANIC_ERR(err, "Failure in child channel"); + } + return; + } + switch(msg.words[0]){ + case RPC_MTYPE_CHILD_ENDPOINT: + debug_printf("SPAWN: Received child init_chan endpoint\n"); + init_chan->remote_cap = cap; + err = lmp_chan_send1(init_chan, LMP_FLAG_YIELD | LMP_FLAG_SYNC, NULL_CAP, RPC_MTYPE_CHILD_ENDPOINT_OK); + if (err_is_fail(err)) { + USER_PANIC_ERR(err, "Failed to send RPC_MTYPE_CHILD_ENDPOINT_OK"); + } + break; + default: + USER_PANIC("Unknown rpc message type."); + break; + } + + err = lmp_endpoint_register(init_chan->endpoint, get_default_waitset(), MKCLOSURE(handle_child_recv, init_chan)); + if (err_is_fail(err)) { + USER_PANIC_ERR(err, "Could not reregister after failed init_chan cap receive"); + } +} struct temp_mapping { struct temp_mapping *next; @@ -276,7 +312,7 @@ static errval_t spawn_serialize_vspace(struct spawninfo *si, struct paging_state assert(curr_offset <= total_space); - debug_printf("SPAWN: Passing vspace info at 0x%lx\n", vspace_buf_child); + // debug_printf("SPAWN: Passing vspace info at 0x%lx\n", vspace_buf_child); domain_params->vspace_buf = vspace_buf_child; domain_params->vspace_buf_len = total_space; @@ -315,11 +351,11 @@ errval_t spawn_load_argv(int argc, char *argv[], struct spawninfo *si, // - Get the module from the multiboot image // and map it (take a look at multiboot.c) - debug_printf("[spawn_load_argv]: argc: %d, argv: ", argc); - for (int i = 0; i < argc; ++i) { - printf("\"%s\", ", argv[i]); - } - printf("\n"); + // debug_printf("[spawn_load_argv]: argc: %d, argv: ", argc); + // for (int i = 0; i < argc; ++i) { + // printf("\"%s\", ", argv[i]); + // } + // printf("\n"); assert(argc > 0); assert(argc < MAX_CMDLINE_ARGS); @@ -405,9 +441,15 @@ errval_t spawn_load_argv(int argc, char *argv[], struct spawninfo *si, if (err_is_fail(err)) return err_push(err, LIB_ERR_CAP_COPY_FAIL); err = cap_retype(si->cspace_cap_selfep, si->cspace_cap_dispatcher, 0, ObjType_EndPointLMP, 0, 1); - if (err_is_fail(err)) return err; - err = cap_copy(si->cspace_cap_initep, cap_selfep); + if (err_is_fail(err)) return err_push(err, SPAWN_ERR_CREATE_SELFEP); + + // give the child an endpoint to talk to init + lmp_chan_init(&si->init_chan); + err = endpoint_create(DEFAULT_LMP_BUF_WORDS, &si->init_chan.local_cap, &si->init_chan.endpoint); + if (err_is_fail(err)) return err_push(err, LIB_ERR_ENDPOINT_CREATE); + err = cap_copy(si->cspace_cap_initep, si->init_chan.local_cap); if (err_is_fail(err)) return err_push(err, LIB_ERR_CAP_COPY_FAIL); + si->init_chan.remote_cap = NULL_CAP; // - Setup the child's vspace // afeer: create level 0 page table @@ -441,8 +483,8 @@ errval_t spawn_load_argv(int argc, char *argv[], struct spawninfo *si, got_addr = got_shdr->sh_addr; } - debug_printf("SPAWN: self paging state after loading:\n"); - pt_print_state(get_current_paging_state()); + // debug_printf("SPAWN: self paging state after loading:\n"); + // pt_print_state(get_current_paging_state()); err = paging_unmap(get_current_paging_state(), elf_base); if (err_is_fail(err)) return err_push(err, LIB_ERR_PMAP_UNMAP); @@ -454,8 +496,8 @@ errval_t spawn_load_argv(int argc, char *argv[], struct spawninfo *si, free(tm); } - debug_printf("SPAWN: self paging state after unmapping:\n"); - pt_print_state(get_current_paging_state()); + // debug_printf("SPAWN: self paging state after unmapping:\n"); + // pt_print_state(get_current_paging_state()); // - Setup the dispatcher err = frame_create(si->cspace_cap_dispframe, DISPATCHER_FRAME_SIZE, NULL); @@ -569,6 +611,11 @@ errval_t spawn_load_argv(int argc, char *argv[], struct spawninfo *si, err = paging_unmap(get_current_paging_state(), arguments_page_in_self); if (err_is_fail(err)) return err_push(err, LIB_ERR_PMAP_UNMAP); + // Receive the child's endpoint for the init channel + lmp_chan_alloc_recv_slot(&si->init_chan); + err = lmp_endpoint_register(si->init_chan.endpoint, get_default_waitset(), MKCLOSURE(handle_child_recv, &si->init_chan)); + if (err_is_fail(err)) return err; + // - Make the new dispatcher runnable err = invoke_dispatcher( si->dispatcher, cap_dispatcher, diff --git a/usr/hello/hello.c b/usr/hello/hello.c index 9fc3a75..bc1975a 100644 --- a/usr/hello/hello.c +++ b/usr/hello/hello.c @@ -16,9 +16,9 @@ #include #include -#include #include +#include #define HELLO_CATCH_COMMAND "catch" @@ -37,7 +37,7 @@ int main(int argc, char *argv[]) while(1) { printf("Catch me if you can! %d\n", iter); // wait for 1 second - time_wait_ms(1000); + barrelfish_usleep(1000000); ++iter; } } diff --git a/usr/init/main.c b/usr/init/main.c index 286bbc3..9d2068c 100644 --- a/usr/init/main.c +++ b/usr/init/main.c @@ -53,6 +53,9 @@ bsp_main(int argc, char *argv[]) { // TODO: initialize mem allocator, vspace management here + err = cap_retype(cap_selfep, cap_dispatcher, 0, ObjType_EndPointLMP, 0, 1); + if (err_is_fail(err)) return err; + // Grading grading_test_early();