Implement spawn over URPC

It doesn't work yet because bootinfo is missing on core 1.
This commit is contained in:
Jan Schär 2022-04-28 11:25:04 +02:00
parent 0148df04a0
commit 691c295cf9
11 changed files with 122 additions and 13 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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 {

View File

@ -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;

View File

@ -16,6 +16,8 @@
#include <test_threads.h>
#include <test_stackoverflow.h>
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();
}
}

View File

@ -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);
}

View File

@ -1,5 +1,7 @@
#include <aos/aos.h>
#include <aos/aos_rpc.h>
#include <aos/aos_urpc.h>
#include <aos/waitset_chan.h>
#include <spawn/rpc_server.h>
#include <grading.h>
#include <spawn/spawn.h>
@ -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(

View File

@ -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;
}

View File

@ -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);