From 691c295cf991fd13d18a30951b67a9fee7a575ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Sch=C3=A4r?= Date: Thu, 28 Apr 2022 11:25:04 +0200 Subject: [PATCH] Implement spawn over URPC It doesn't work yet because bootinfo is missing on core 1. --- errors/errno.fugu | 1 + hake/menu.lst.armv8_a57_qemu | 2 +- hake/menu.lst.armv8_imx8x | 2 +- include/aos/aos_urpc.h | 6 ++- include/spawn/rpc_server.h | 1 + lib/aos/aos_urpc.c | 13 ++++++ lib/grading/grading.c | 5 +++ lib/mm/mm.c | 4 +- lib/spawn/rpc_server.c | 76 ++++++++++++++++++++++++++++++++++-- usr/hello/hello.c | 19 +++++++-- usr/init/main.c | 6 +++ 11 files changed, 122 insertions(+), 13 deletions(-) diff --git a/errors/errno.fugu b/errors/errno.fugu index be26d1e..ac78baf 100755 --- a/errors/errno.fugu +++ b/errors/errno.fugu @@ -1384,6 +1384,7 @@ errors aos AOS_ERR_ { failure RPC_RET_TOO_BIG "RPC return value is too big", failure RPC_UNKNOWN_MSG_TYPE "RPC with unknown message type", failure RPC_PROCESS_UNKNOWN_PID "Requested process name for an unknown PID", + success RPC_ASYNC_REPLY "The RPC call will complete asynchronously", }; // errors NIC driver diff --git a/hake/menu.lst.armv8_a57_qemu b/hake/menu.lst.armv8_a57_qemu index 67267cd..8a733bb 100644 --- a/hake/menu.lst.armv8_a57_qemu +++ b/hake/menu.lst.armv8_a57_qemu @@ -5,7 +5,7 @@ bootdriver /armv8/sbin/boot_armv8_generic cpudriver /armv8/sbin/cpu_a57_qemu loglevel=3 serial=0x9000000 logmask=128 module /armv8/sbin/init -module /armv8/sbin/hello spawn +module /armv8/sbin/hello spawn_remote module /armv8/sbin/memeater module /armv8/sbin/mallocator module /armv8/sbin/stackoverflow diff --git a/hake/menu.lst.armv8_imx8x b/hake/menu.lst.armv8_imx8x index 72e9063..927f20b 100644 --- a/hake/menu.lst.armv8_imx8x +++ b/hake/menu.lst.armv8_imx8x @@ -5,7 +5,7 @@ bootdriver /armv8/sbin/boot_armv8_generic cpudriver /armv8/sbin/cpu_imx8x module /armv8/sbin/init -module /armv8/sbin/hello spawn +module /armv8/sbin/hello spawn_remote module /armv8/sbin/memeater module /armv8/sbin/mallocator module /armv8/sbin/stackoverflow diff --git a/include/aos/aos_urpc.h b/include/aos/aos_urpc.h index aa9779b..41ba454 100644 --- a/include/aos/aos_urpc.h +++ b/include/aos/aos_urpc.h @@ -35,12 +35,14 @@ struct aos_urpc_server { struct thread_sem sem; }; -int urpc_server(void *arg); - errval_t do_aos_urpc( struct aos_urpc *rpc, uintptr_t msg_type, struct capref arg_cap, size_t arg_size, uintptr_t arg0, uintptr_t arg1, struct capref *ret_cap, size_t *ret_size, uintptr_t *ret0, uintptr_t *ret1 ); +int urpc_client_loop(void *arg); + +int urpc_server(void *arg); + #endif // _LIB_BARRELFISH_AOS_URPC_H diff --git a/include/spawn/rpc_server.h b/include/spawn/rpc_server.h index c62d16a..bdea91d 100644 --- a/include/spawn/rpc_server.h +++ b/include/spawn/rpc_server.h @@ -5,6 +5,7 @@ struct generic_rpc_server { void *shared_mem; + void (*async_reply)(struct generic_rpc_server *rpc, errval_t ret_err); }; struct aos_rpc_server { diff --git a/lib/aos/aos_urpc.c b/lib/aos/aos_urpc.c index 8c35325..64e0d61 100644 --- a/lib/aos/aos_urpc.c +++ b/lib/aos/aos_urpc.c @@ -71,6 +71,19 @@ errval_t do_aos_urpc( return rpc->meta->a0; } +// URPC calls on the BSP core should only be done on this thread. +int urpc_client_loop(void *arg) { + errval_t err; + struct waitset *ws = arg; + while (true) { + err = event_dispatch(ws); + if (err_is_fail(err)) { + DEBUG_ERR(err, "in event_dispatch"); + abort(); + } + } +} + static void urpc_server_handler(void *arg) { struct aos_urpc_server *urpc = arg; diff --git a/lib/grading/grading.c b/lib/grading/grading.c index 4ef6419..3f31cf8 100644 --- a/lib/grading/grading.c +++ b/lib/grading/grading.c @@ -16,6 +16,8 @@ #include #include +extern coreid_t my_core_id; + void grading_setup_bsp_init(int argc, char **argv) { } @@ -46,4 +48,7 @@ grading_test_early(void) { void grading_test_late(void) { + if (my_core_id == 0) { + do_test_spawn(); + } } diff --git a/lib/mm/mm.c b/lib/mm/mm.c index bf033bf..bc7b2df 100644 --- a/lib/mm/mm.c +++ b/lib/mm/mm.c @@ -207,8 +207,8 @@ errval_t mm_alloc_aligned(struct mm *mm, size_t size, size_t alignment, struct c // Create a capability for the allocated memory err = cap_retype(*retcap, current->cap, alloc_offset, mm->objtype, size, 1); if (err_is_fail(err)) { - err = slot_free(*retcap); - assert(!err_is_fail(err)); + errval_t err2 = slot_free(*retcap); + assert(!err_is_fail(err2)); return err_push(err, LIB_ERR_CAP_RETYPE); } diff --git a/lib/spawn/rpc_server.c b/lib/spawn/rpc_server.c index b5b7822..6d8cbb1 100644 --- a/lib/spawn/rpc_server.c +++ b/lib/spawn/rpc_server.c @@ -1,5 +1,7 @@ #include #include +#include +#include #include #include #include @@ -7,12 +9,17 @@ extern coreid_t my_core_id; rpc_handler_t rpc_handlers[RPC_MTYPE_COUNT]; +extern struct aos_urpc urpc_to_app; +extern struct waitset urpc_to_app_ws; + static void rpc_server_handle_recv(void *arg); static void rpc_server_send_reply(void *arg); +static void rpc_server_async_reply(struct generic_rpc_server *g_rpc, errval_t ret_err); void rpc_server_init(struct aos_rpc_server *rpc, struct lmp_chan *chan, void *shared_mem) { rpc->chan = chan; rpc->g.shared_mem = shared_mem; + rpc->g.async_reply = rpc_server_async_reply; } void rpc_server_register_recv(struct aos_rpc_server *rpc) { @@ -52,6 +59,8 @@ static void rpc_server_handle_recv(void *arg) { ); } } + + if (err == AOS_ERR_RPC_ASYNC_REPLY) return; rpc->ret_err = err; rpc_server_send_reply(rpc); @@ -82,6 +91,12 @@ static void rpc_server_send_reply(void *arg) { rpc_server_register_recv(rpc); } +static void rpc_server_async_reply(struct generic_rpc_server *g_rpc, errval_t ret_err) { + struct aos_rpc_server *rpc = (struct aos_rpc_server *)g_rpc; + rpc->ret_err = ret_err; + rpc_server_send_reply(rpc); +} + // RPC handlers static errval_t handle_rpc_send_number( @@ -183,6 +198,43 @@ static errval_t handle_rpc_serial_read( return SYS_ERR_OK; } +struct rpc_to_urpc_arg { + struct waitset_chanstate chan; + struct generic_rpc_server *rpc; + uintptr_t msg_type; + size_t arg_size; + uintptr_t arg0; + uintptr_t arg1; + size_t *ret_size; + uintptr_t *ret0; + uintptr_t *ret1; +}; + +// forward an RPC call over URPC, asynchronously (meaning without blocking the default waitset) +static void rpc_to_urpc(void *arg) { + errval_t err; + struct rpc_to_urpc_arg *urpc_arg = arg; + + if (urpc_arg->arg_size > 0) { + assert(urpc_arg->arg_size <= RPC_SHARED_SIZE); + memcpy(urpc_to_app.shared_mem, urpc_arg->rpc->shared_mem, urpc_arg->arg_size); + } + + err = do_aos_urpc( + &urpc_to_app, urpc_arg->msg_type, + NULL_CAP, urpc_arg->arg_size, urpc_arg->arg0, urpc_arg->arg1, + NULL, urpc_arg->ret_size, urpc_arg->ret0, urpc_arg->ret1 + ); + + if (*urpc_arg->ret_size > 0) { + assert(*urpc_arg->ret_size <= RPC_SHARED_SIZE); + memcpy(urpc_arg->rpc->shared_mem, urpc_to_app.shared_mem, *urpc_arg->ret_size); + } + + urpc_arg->rpc->async_reply(urpc_arg->rpc, err); + free(urpc_arg); +} + static errval_t handle_rpc_process_spawn( struct generic_rpc_server *rpc, struct capref arg_cap, size_t arg_size, uintptr_t arg0, uintptr_t arg1, @@ -196,7 +248,7 @@ static errval_t handle_rpc_process_spawn( grading_rpc_handler_process_spawn(cmdline, core); - if (core != my_core_id) { + if (core == my_core_id) { struct spawninfo *si = malloc(sizeof(struct spawninfo)); char *argv[MAX_CMDLINE_ARGS]; @@ -205,8 +257,26 @@ static errval_t handle_rpc_process_spawn( return spawn_load_argv(argc, argv, si, (domainid_t *)ret0); } - assert(core == 0); // Spawning from core 1 on core 0 is not supported. - abort(); // TODO + + assert(my_core_id == 0); // Spawning from core 1 on core 0 is not supported. + assert(rpc->async_reply != NULL); + + struct rpc_to_urpc_arg *urpc_arg = malloc(sizeof(struct rpc_to_urpc_arg)); + if (urpc_arg == NULL) return LIB_ERR_MALLOC_FAIL; + waitset_chanstate_init(&urpc_arg->chan, CHANTYPE_OTHER); + urpc_arg->msg_type = RPC_MTYPE_PROCESS_SPAWN; + urpc_arg->rpc = rpc; + urpc_arg->arg_size = arg_size; + urpc_arg->arg0 = arg0; + urpc_arg->arg1 = arg1; + urpc_arg->ret_size = ret_size; + urpc_arg->ret0 = ret0; + urpc_arg->ret1 = ret1; + + waitset_chan_trigger_closure(&urpc_to_app_ws, &urpc_arg->chan, + MKCLOSURE(rpc_to_urpc, urpc_arg)); + + return AOS_ERR_RPC_ASYNC_REPLY; } static errval_t handle_rpc_process_get_name( diff --git a/usr/hello/hello.c b/usr/hello/hello.c index 8aa834a..5c16eb0 100644 --- a/usr/hello/hello.c +++ b/usr/hello/hello.c @@ -23,9 +23,11 @@ #define HELLO_CATCH_COMMAND "catch" #define HELLO_SPAWN_COMMAND "spawn" +#define HELLO_SPAWN_COMMAND_REMOTE "spawn_remote" #define HELLO_CMDLINE_READ_LEN 100 +__attribute__((__used__)) static int null_dereference(void *ignored) { debug_printf("[null_dereference] Oh no! :O\n"); // cause a page fault (slight offset from null simulates NULL struct field access) @@ -37,10 +39,10 @@ int main(int argc, char *argv[]) { errval_t err; printf("Hello, world!\n"); - + // test page fault handling by doing a null dereference on a different thread - thread_create(null_dereference, NULL); - barrelfish_usleep(10000000); + // thread_create(null_dereference, NULL); + // barrelfish_usleep(10000000); printf("argv:\n"); for(int i = 0; i < argc; ++i) { @@ -91,7 +93,7 @@ int main(int argc, char *argv[]) err = aos_rpc_process_spawn(rpc, cmdline, 0, &pid); if (err_is_fail(err)) USER_PANIC_ERR(err, "Failed to spawn process"); printf("Started a new process!\n"); - + // get process name char *name; err = aos_rpc_process_get_name(rpc, pid, &name); @@ -120,5 +122,14 @@ int main(int argc, char *argv[]) } } + if (argc > 1 && !strncmp(argv[1], HELLO_SPAWN_COMMAND_REMOTE, sizeof(HELLO_SPAWN_COMMAND_REMOTE))) { + printf("Spawning process on core 1...\n"); + domainid_t pid; + rpc = aos_rpc_get_process_channel(); + err = aos_rpc_process_spawn(rpc, "hello world", 1, &pid); + if (err_is_fail(err)) USER_PANIC_ERR(err, "Failed to spawn process"); + printf("Spawn succeeded, pid=%"PRIuDOMAINID"\n", pid); + } + return EXIT_SUCCESS; } diff --git a/usr/init/main.c b/usr/init/main.c index 7d46ed9..a7dbf53 100644 --- a/usr/init/main.c +++ b/usr/init/main.c @@ -44,6 +44,7 @@ static struct aos_urpc_server urpc_to_app_server; // only valid on bsp core struct aos_urpc urpc_to_app; +struct waitset urpc_to_app_ws; static errval_t ram_alloc_remote_core(struct capref *ret, size_t size, size_t alignment) @@ -133,12 +134,16 @@ bsp_main(int argc, char *argv[]) { struct aos_urpc_server *urpc_to_bsp_server = malloc(sizeof(struct aos_urpc_server)); urpc_to_bsp_server->g.shared_mem = &urpc->shared_mem_to_bsp; + urpc_to_bsp_server->g.async_reply = NULL; urpc_to_bsp_server->meta = &urpc->meta_to_bsp; thread_create(urpc_server, urpc_to_bsp_server); urpc_to_app.shared_mem = &urpc->shared_mem_to_app; urpc_to_app.meta = &urpc->meta_to_app; + waitset_init(&urpc_to_app_ws); + thread_create(urpc_client_loop, &urpc_to_app_ws); + // Grading grading_test_late(); @@ -188,6 +193,7 @@ app_main(int argc, char *argv[]) { urpc_to_bsp.meta = &urpc->meta_to_bsp; urpc_to_app_server.g.shared_mem = &urpc->shared_mem_to_app; + urpc_to_app_server.g.async_reply = NULL; urpc_to_app_server.meta = &urpc->meta_to_app; ram_alloc_set(ram_alloc_remote_core);