Implement RPC

This commit is contained in:
Jan Schär 2022-03-30 20:12:19 +02:00
parent f2fb4d5d01
commit 14063e60be
15 changed files with 459 additions and 112 deletions

View File

@ -1323,7 +1323,7 @@ errors sfn NIC_ERR_{
failure IO "Error during card IO",
failure INTR "Interrupted system call",
failure NOSYS "Not implemented",
failure UNKNOWN "Uknown error",
failure UNKNOWN "Unknown error",
failure TX_PKT "Error sending packet",
failure RX_PKT "Error receiving packet",
failure RX_DISCARD "Error, packet needs to be discared",
@ -1376,6 +1376,10 @@ errors vas VAS_ERR_ {
errors aos AOS_ERR_ {
failure LMP_SEND_FAILURE "Failure while sending AOS LMP message",
failure LMP_MSGTYPE_UNKNOWN "Unknown message type for AOS LMP implementation",
failure RPC_UNEXPECTED_MSGTYPE "Received RPC message of unexpected type",
failure RPC_ARG_TOO_BIG "RPC argument is too big",
failure RPC_RET_TOO_BIG "RPC return value is too big",
failure RPC_UNKNOWN_MSG_TYPE "RPC with unknown message type",
};
// 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 catch Aurel Jan Sandro
module /armv8/sbin/hello Aurel Jan Sandro
module /armv8/sbin/memeater
# End of file, this needs to have a certain length...

View File

@ -5,5 +5,5 @@
bootdriver /armv8/sbin/boot_armv8_generic
cpudriver /armv8/sbin/cpu_imx8x
module /armv8/sbin/init
module /armv8/sbin/hello catch Aurel Jan Sandro
module /armv8/sbin/hello Aurel Jan Sandro
module /armv8/sbin/memeater

View File

@ -17,23 +17,34 @@
#include <aos/aos.h>
#define RPC_SHARED_SIZE PAGE_SIZE
// define some message types
#define RPC_MTYPE_CHILD_ENDPOINT 1UL
#define RPC_MTYPE_CHILD_ENDPOINT_OK 2UL
#define RPC_MTYPE_GET_RAM_CAP 3UL
#define RPC_MTYPE_GET_RAM_CAP_OK 4UL
enum rpc_mtype {
RPC_MTYPE_CHILD_ENDPOINT,
RPC_MTYPE_SEND_NUMBER,
RPC_MTYPE_SEND_STRING,
RPC_MTYPE_GET_RAM_CAP,
RPC_MTYPE_SERIAL_GETCHAR,
RPC_MTYPE_SERIAL_PUTCHAR,
RPC_MTYPE_PROCESS_SPAWN,
RPC_MTYPE_PROCESS_GET_NAME,
RPC_MTYPE_PROCESS_GET_ALL_PIDS,
RPC_MTYPE_COUNT // How many message types exist
};
/* An RPC binding, which may be transported over LMP or UMP. */
struct aos_rpc {
// TODO(M3): Add state
struct lmp_chan *chan;
struct waitset ws;
void *shared_mem;
};
/**
* \brief Initialize an aos_rpc struct.
*/
errval_t aos_rpc_init(struct aos_rpc *rpc);
errval_t aos_rpc_init(struct aos_rpc *rpc, struct lmp_chan *chan, void *shared_mem);
/**

View File

@ -25,6 +25,7 @@ struct spawn_domain_params {
char *envp[MAX_ENVIRON_VARS + 1]; ///< Environment strings; +1 for NULL terminator
void *vspace_buf; ///< Serialised vspace data
size_t vspace_buf_len; ///< Length of serialised vspace data
void *rpc_shared_memory;
void *tls_init_base; ///< Address of initialised TLS data block
size_t tls_init_len; ///< Length of initialised TLS data block
size_t tls_total_len; ///< Total (initialised + BSS) TLS data length

View File

@ -0,0 +1,28 @@
#ifndef _RPC_SERVER_H_
#define _RPC_SERVER_H_
#include <aos/aos.h>
struct aos_rpc_server {
struct lmp_chan *chan;
struct waitset ws;
void *shared_mem;
struct capref ret_cap;
errval_t ret_err;
size_t ret_size;
uintptr_t ret0;
uintptr_t ret1;
};
/**
* Initialize an aos_rpc_server struct.
*/
void rpc_server_init(struct aos_rpc_server *rpc, struct lmp_chan *chan, void *shared_mem);
/**
* Start listening for RPCs.
*/
void rpc_server_register_recv(struct aos_rpc_server *rpc);
#endif /* _RPC_SERVER_H_ */

View File

@ -17,6 +17,7 @@
#include "aos/slot_alloc.h"
#include "aos/paging.h"
#include <spawn/rpc_server.h>
@ -58,6 +59,8 @@ struct spawninfo {
struct capref vspace_cap_l0_pagetable;
struct lmp_chan init_chan;
struct capref rpc_shared_frame;
struct aos_rpc_server rpc_server;
};
// Start a child process using the multiboot command line. Fills in si.

View File

@ -17,74 +17,171 @@
static void noop_callback(void *arg) {
}
static errval_t do_aos_rpc(
struct aos_rpc *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
) {
errval_t err;
// Send call
while (true) {
err = lmp_chan_send4(rpc->chan, LMP_FLAG_YIELD | LMP_FLAG_SYNC, arg_cap, msg_type, arg_size, arg0, arg1);
if (!err_is_fail(err)) break;
if (!lmp_err_is_transient(err)) {
return err_push(err, AOS_ERR_LMP_SEND_FAILURE);
}
err = lmp_chan_register_send(rpc->chan, &rpc->ws, MKCLOSURE(noop_callback, NULL));
if (err_is_fail(err)) return err;
err = event_dispatch(&rpc->ws);
if (err_is_fail(err)) return err;
}
// Receive return value
struct lmp_recv_msg recv = LMP_RECV_MSG_INIT;
while (!lmp_endpoint_can_recv(rpc->chan->endpoint)) {
err = lmp_chan_register_recv(rpc->chan, &rpc->ws, MKCLOSURE(noop_callback, NULL));
if (err_is_fail(err)) return err;
err = event_dispatch(&rpc->ws);
if (err_is_fail(err)) return err;
}
err = lmp_chan_recv(rpc->chan, &recv, ret_cap);
assert(err_is_ok(err));
if (ret_size != NULL) *ret_size = recv.words[1];
if (ret0 != NULL) *ret0 = recv.words[2];
if (ret1 != NULL) *ret1 = recv.words[3];
return recv.words[0];
}
errval_t
aos_rpc_send_number(struct aos_rpc *rpc, uintptr_t num) {
// TODO: implement functionality to send a number over the channel
// Implement functionality to send a number over the channel
// given channel and wait until the ack gets returned.
return SYS_ERR_OK;
return do_aos_rpc(
rpc, RPC_MTYPE_SEND_NUMBER,
NULL_CAP, 0, num, 0,
NULL, NULL, NULL, NULL);
}
errval_t
aos_rpc_send_string(struct aos_rpc *rpc, const char *string) {
// TODO: implement functionality to send a string over the given channel
// Implement functionality to send a string over the given channel
// and wait for a response.
return SYS_ERR_OK;
size_t string_size = strlen(string) + 1;
if (string_size > RPC_SHARED_SIZE) return AOS_ERR_RPC_ARG_TOO_BIG;
memcpy(rpc->shared_mem, string, string_size);
return do_aos_rpc(
rpc, RPC_MTYPE_SEND_STRING,
NULL_CAP, string_size, 0, 0,
NULL, NULL, NULL, NULL
);
}
errval_t
aos_rpc_get_ram_cap(struct aos_rpc *rpc, size_t bytes, size_t alignment,
struct capref *ret_cap, size_t *ret_bytes) {
// TODO: implement functionality to request a RAM capability over the
// Implement functionality to request a RAM capability over the
// given channel and wait until it is delivered.
return SYS_ERR_OK;
return do_aos_rpc(
rpc, RPC_MTYPE_GET_RAM_CAP,
NULL_CAP, 0, bytes, alignment,
ret_cap, NULL, ret_bytes, NULL
);
}
errval_t
aos_rpc_serial_getchar(struct aos_rpc *rpc, char *retc) {
// TODO implement functionality to request a character from
// Implement functionality to request a character from
// the serial driver.
return SYS_ERR_OK;
uintptr_t retval;
errval_t err = do_aos_rpc(
rpc, RPC_MTYPE_SERIAL_GETCHAR,
NULL_CAP, 0, 0, 0,
NULL, NULL, &retval, NULL);
*retc = retval;
return err;
}
errval_t
aos_rpc_serial_putchar(struct aos_rpc *rpc, char c) {
// TODO implement functionality to send a character to the
// Implement functionality to send a character to the
// serial port.
return SYS_ERR_OK;
return do_aos_rpc(
rpc, RPC_MTYPE_SERIAL_PUTCHAR,
NULL_CAP, 0, c, 0,
NULL, NULL, NULL, NULL
);
}
errval_t
aos_rpc_process_spawn(struct aos_rpc *rpc, char *cmdline,
coreid_t core, domainid_t *newpid) {
// TODO (M5): implement spawn new process rpc
return SYS_ERR_OK;
// (M5): implement spawn new process rpc
size_t cmdline_size = strlen(cmdline) + 1;
if (cmdline_size > RPC_SHARED_SIZE) return AOS_ERR_RPC_ARG_TOO_BIG;
memcpy(rpc->shared_mem, cmdline, cmdline_size);
uintptr_t retval;
errval_t err = do_aos_rpc(
rpc, RPC_MTYPE_PROCESS_SPAWN,
NULL_CAP, cmdline_size, core, 0,
NULL, NULL, &retval, NULL
);
*newpid = retval;
return err;
}
errval_t
aos_rpc_process_get_name(struct aos_rpc *rpc, domainid_t pid, char **name) {
// TODO (M5): implement name lookup for process given a process id
return SYS_ERR_OK;
// (M5): implement name lookup for process given a process id
size_t name_len;
errval_t err = do_aos_rpc(
rpc, RPC_MTYPE_PROCESS_GET_NAME,
NULL_CAP, 0, pid, 0,
NULL, &name_len, NULL, NULL
);
if (err_is_fail(err)) return err;
*name = malloc(name_len);
if (*name == NULL) return LIB_ERR_MALLOC_FAIL;
memcpy(name, rpc->shared_mem, name_len);
return err;
}
errval_t
aos_rpc_process_get_all_pids(struct aos_rpc *rpc, domainid_t **pids,
size_t *pid_count) {
// TODO (M5): implement process id discovery
return SYS_ERR_OK;
// (M5): implement process id discovery
size_t ret_len;
errval_t err = do_aos_rpc(
rpc, RPC_MTYPE_PROCESS_GET_NAME,
NULL_CAP, 0, 0, 0,
NULL, &ret_len, NULL, NULL
);
if (err_is_fail(err)) return err;
*pid_count = ret_len / sizeof(**pids);
*pids = malloc(ret_len);
if (*pids == NULL) return LIB_ERR_MALLOC_FAIL;
memcpy(pids, rpc->shared_mem, ret_len);
return err;
}
// We are allowed to change the signature for this one
errval_t aos_rpc_init(struct aos_rpc *rpc)
errval_t aos_rpc_init(struct aos_rpc *rpc, struct lmp_chan *chan, void *shared_mem)
{
// TODO!
rpc->chan = chan;
rpc->shared_mem = shared_mem;
waitset_init(&rpc->ws);
return SYS_ERR_OK;
}
@ -93,9 +190,8 @@ errval_t aos_rpc_init(struct aos_rpc *rpc)
*/
struct aos_rpc *aos_rpc_get_init_channel(void)
{
//TODO: Return channel to talk to init process
debug_printf("aos_rpc_get_init_channel NYI\n");
return NULL;
// Return channel to talk to init process
return get_init_rpc();
}
/**
@ -103,10 +199,9 @@ struct aos_rpc *aos_rpc_get_init_channel(void)
*/
struct aos_rpc *aos_rpc_get_memory_channel(void)
{
//TODO: Return channel to talk to memory server process (or whoever
//implements memory server functionality)
debug_printf("aos_rpc_get_memory_channel NYI\n");
return NULL;
// Return channel to talk to memory server process (or whoever
// implements memory server functionality)
return get_init_rpc();
}
/**
@ -114,10 +209,9 @@ struct aos_rpc *aos_rpc_get_memory_channel(void)
*/
struct aos_rpc *aos_rpc_get_process_channel(void)
{
//TODO: Return channel to talk to process server process (or whoever
//implements process server functionality)
debug_printf("aos_rpc_get_process_channel NYI\n");
return NULL;
// Return channel to talk to process server process (or whoever
// implements process server functionality)
return get_init_rpc();
}
/**
@ -125,9 +219,7 @@ struct aos_rpc *aos_rpc_get_process_channel(void)
*/
struct aos_rpc *aos_rpc_get_serial_channel(void)
{
//TODO: Return channel to talk to serial driver/terminal process (whoever
//implements print/read functionality)
debug_printf("aos_rpc_get_serial_channel NYI\n");
return NULL;
// Return channel to talk to serial driver/terminal process (whoever
// implements print/read functionality)
return get_init_rpc();
}

View File

@ -83,7 +83,6 @@ 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;
@ -95,8 +94,6 @@ static int event_init_dispatch_thread(void *arg)
}
}
// TODO rueegges: putting it here for now. Not sure how to do rcp abstraction yet
// receive messages sent by the init
static void handle_init_recv(void *arg)
{
errval_t err;
@ -106,31 +103,13 @@ static void handle_init_recv(void *arg)
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;
}
assert(err_is_ok(err));
switch(msg.words[0]){
case RPC_MTYPE_CHILD_ENDPOINT_OK:
if (msg.words[0] == SYS_ERR_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, "[handle_init_recv]: Could not register endpoint after receiving message");
} else {
USER_PANIC("Child LMP initialization failed.");
}
}
@ -207,6 +186,7 @@ errval_t barrelfish_init_onthread(struct spawn_domain_params *params)
// TODO MILESTONE 3: register ourselves with init
/* allocate lmp channel structure */
struct lmp_chan *init_chan = malloc(sizeof(struct lmp_chan));
lmp_chan_init(init_chan);
/* create local endpoint */
err = endpoint_create(DEFAULT_LMP_BUF_WORDS, &init_chan->local_cap, &init_chan->endpoint);
if (err_is_fail(err)) {
@ -232,7 +212,7 @@ errval_t barrelfish_init_onthread(struct spawn_domain_params *params)
}
/* initialize init RPC client with lmp channel */
struct aos_rpc *init_rpc = malloc(sizeof(struct aos_rpc));
err = aos_rpc_init(init_rpc);
err = aos_rpc_init(init_rpc, init_chan, params->rpc_shared_memory);
if (err_is_fail(err)){
return err_push(err, ERR_NOTIMP);
}
@ -261,7 +241,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);
}

View File

@ -8,32 +8,40 @@
void grading_rpc_handle_number(uintptr_t val)
{
debug_printf("grading_rpc_handle_number(%"PRIuPTR")\n", val);
}
void grading_rpc_handler_string(const char* string)
{
debug_printf("grading_rpc_handler_string(\"%s\")\n", string);
}
void grading_rpc_handler_serial_getchar(void)
{
debug_printf("grading_rpc_handler_serial_getchar()\n");
}
void grading_rpc_handler_serial_putchar(char c)
{
debug_printf("grading_rpc_handler_serial_putchar(0x%"PRIx8")\n", c);
}
void grading_rpc_handler_ram_cap(size_t bytes, size_t alignment)
{
debug_printf("grading_rpc_handler_ram_cap(0x%"PRIxPTR", 0x%"PRIxPTR")\n", bytes, alignment);
}
void grading_rpc_handler_process_spawn(char* cmdline, coreid_t core)
{
debug_printf("grading_rpc_handler_process_spawn(\"%s\", %"PRIuCOREID")\n", cmdline, core);
}
void grading_rpc_handler_process_get_name(domainid_t pid)
{
debug_printf("grading_rpc_handler_process_get_name(%"PRIuDOMAINID")\n", pid);
}
void grading_rpc_handler_process_get_all_pids(void)
{
debug_printf("grading_rpc_handler_process_get_all_pids()\n");
}

View File

@ -3,7 +3,7 @@
#include <spawn/spawn.h>
#include <time.h>
#define PROCESS_COUNT 5
#define PROCESS_COUNT 1
void do_test_spawn(void) {
// spawn multiple processes

View File

@ -13,7 +13,7 @@
[
build library {
target = "spawn",
cFiles = [ "spawn.c" ],
cFiles = [ "spawn.c", "rpc_server.c" ],
addLibraries = [ "elf", "argv", "multiboot" ]
},
build library {

219
lib/spawn/rpc_server.c Normal file
View File

@ -0,0 +1,219 @@
#include <aos/aos.h>
#include <aos/aos_rpc.h>
#include <spawn/rpc_server.h>
#include <grading.h>
typedef errval_t (*rpc_handler_t)(
struct aos_rpc_server *rpc,
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
);
static rpc_handler_t rpc_handlers[RPC_MTYPE_COUNT];
static void rpc_server_handle_recv(void *arg);
static void rpc_server_send_reply(void *arg);
void rpc_server_init(struct aos_rpc_server *rpc, struct lmp_chan *chan, void *shared_mem) {
rpc->chan = chan;
rpc->shared_mem = shared_mem;
}
void rpc_server_register_recv(struct aos_rpc_server *rpc) {
errval_t err = lmp_chan_register_recv(rpc->chan, get_default_waitset(), MKCLOSURE(rpc_server_handle_recv, rpc));
if (err_is_fail(err)) {
DEBUG_ERR(err, "Could not register receive handler");
}
}
static void rpc_server_handle_recv(void *arg) {
errval_t err;
struct aos_rpc_server *rpc = (struct aos_rpc_server *)arg;
struct lmp_recv_msg msg = LMP_RECV_MSG_INIT;
struct capref arg_cap;
err = lmp_chan_recv(rpc->chan, &msg, &arg_cap);
assert(err_is_ok(err));
rpc->ret_cap = NULL_CAP;
rpc->ret_size = 0;
rpc->ret0 = 0;
rpc->ret1 = 0;
if (msg.words[0] >= RPC_MTYPE_COUNT) {
err = AOS_ERR_RPC_UNKNOWN_MSG_TYPE;
} else if (msg.words[1] > RPC_SHARED_SIZE) {
err = AOS_ERR_RPC_ARG_TOO_BIG;
} else {
rpc_handler_t handler = rpc_handlers[msg.words[0]];
if (handler == NULL) {
err = AOS_ERR_RPC_UNKNOWN_MSG_TYPE;
} else {
err = handler(
rpc,
arg_cap, msg.words[1], msg.words[2], msg.words[3],
&rpc->ret_cap, &rpc->ret_size, &rpc->ret0, &rpc->ret1
);
}
}
rpc->ret_err = err;
rpc_server_send_reply(rpc);
}
static void rpc_server_send_reply(void *arg) {
struct aos_rpc_server *rpc = (struct aos_rpc_server *)arg;
errval_t err;
err = lmp_chan_send4(
rpc->chan, LMP_FLAG_YIELD | LMP_FLAG_SYNC,
rpc->ret_cap, rpc->ret_err, rpc->ret_size, rpc->ret0, rpc->ret1
);
if (err_is_fail(err)) {
if (!lmp_err_is_transient(err)) {
DEBUG_ERR(err, "Could not send RPC reply");
return;
}
// Cannot send right now, try again later
err = lmp_chan_register_send(rpc->chan, &rpc->ws, MKCLOSURE(rpc_server_send_reply, arg));
if (err_is_fail(err)) {
DEBUG_ERR(err, "Could not register send handler");
return;
}
}
// Sent reply, wait for next RPC call
rpc_server_register_recv(rpc);
}
// RPC handlers
static errval_t handle_rpc_send_number(
struct aos_rpc_server *rpc,
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
) {
uintptr_t num = arg0;
grading_rpc_handle_number(num);
return SYS_ERR_OK;
}
static errval_t handle_rpc_send_string(
struct aos_rpc_server *rpc,
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
) {
const char* string = rpc->shared_mem;
if (arg_size == 0 || string[arg_size - 1] != '\0') {
return ERR_INVALID_ARGS;
}
grading_rpc_handler_string(string);
return SYS_ERR_OK;
}
static errval_t handle_rpc_get_ram_cap(
struct aos_rpc_server *rpc,
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
) {
size_t bytes = arg0;
size_t alignment = arg1;
grading_rpc_handler_ram_cap(bytes, alignment);
// TODO
*ret0 = bytes;
return LIB_ERR_NOT_IMPLEMENTED;
}
static errval_t handle_rpc_serial_getchar(
struct aos_rpc_server *rpc,
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
) {
grading_rpc_handler_serial_getchar();
// TODO
*ret0 = 'A';
return LIB_ERR_NOT_IMPLEMENTED;
}
static errval_t handle_rpc_serial_putchar(
struct aos_rpc_server *rpc,
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
) {
char c = arg0;
grading_rpc_handler_serial_putchar(c);
// TODO
return LIB_ERR_NOT_IMPLEMENTED;
}
static errval_t handle_rpc_process_spawn(
struct aos_rpc_server *rpc,
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
) {
char *cmdline = rpc->shared_mem;
coreid_t core = arg0;
if (arg_size == 0 || cmdline[arg_size - 1] != '\0') {
return ERR_INVALID_ARGS;
}
grading_rpc_handler_process_spawn(cmdline, core);
// TODO
*ret0 = 0;
return LIB_ERR_NOT_IMPLEMENTED;
}
static errval_t handle_rpc_process_get_name(
struct aos_rpc_server *rpc,
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
) {
domainid_t pid = arg0;
grading_rpc_handler_process_get_name(pid);
// TODO
memcpy(rpc->shared_mem, "name", 5);
*ret_size = 5;
return LIB_ERR_NOT_IMPLEMENTED;
}
static errval_t handle_rpc_process_get_all_pids(
struct aos_rpc_server *rpc,
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
) {
grading_rpc_handler_process_get_all_pids();
// TODO
return LIB_ERR_NOT_IMPLEMENTED;
}
static rpc_handler_t rpc_handlers[RPC_MTYPE_COUNT] = {
[RPC_MTYPE_SEND_NUMBER] = handle_rpc_send_number,
[RPC_MTYPE_SEND_STRING] = handle_rpc_send_string,
[RPC_MTYPE_GET_RAM_CAP] = handle_rpc_get_ram_cap,
[RPC_MTYPE_SERIAL_GETCHAR] = handle_rpc_serial_getchar,
[RPC_MTYPE_SERIAL_PUTCHAR] = handle_rpc_serial_putchar,
[RPC_MTYPE_PROCESS_SPAWN] = handle_rpc_process_spawn,
[RPC_MTYPE_PROCESS_GET_NAME] = handle_rpc_process_get_name,
[RPC_MTYPE_PROCESS_GET_ALL_PIDS] = handle_rpc_process_get_all_pids,
};

View File

@ -47,46 +47,23 @@ static void armv8_set_registers(void *arch_load_info,
disabled_area->regs[REG_OFFSET(PIC_REGISTER)] = got_base;
}
// receive messages sent by the child
static void handle_child_recv(void *arg) {
errval_t err;
struct lmp_chan *init_chan = (struct lmp_chan *)arg;
struct spawninfo *si = (struct spawninfo *)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;
}
err = lmp_chan_recv(&si->init_chan, &msg, &cap);
assert(err_is_ok(err));
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);
si->init_chan.remote_cap = cap;
err = lmp_chan_send1(&si->init_chan, LMP_FLAG_YIELD | LMP_FLAG_SYNC, NULL_CAP, SYS_ERR_OK);
if (err_is_fail(err)) {
USER_PANIC_ERR(err, "Failed to send RPC_MTYPE_CHILD_ENDPOINT_OK");
}
break;
case RPC_MTYPE_GET_RAM_CAP:
debug_printf("[handle_init_recv]: RPC_MTYPE_GET_RAM_CAP\n");
size_t requested_size = msg.words[1];
struct capref new_ram_cap;
frame_alloc(&new_ram_cap, requested_size, NULL);
err = lmp_chan_send1(init_chan, LMP_FLAG_YIELD | LMP_FLAG_SYNC, NULL_CAP, RPC_MTYPE_GET_RAM_CAP_OK);
if (err_is_fail(err)) {
USER_PANIC_ERR(err, "Failed to send RPC_MTYPE_GET_RAM_CAP_OK");
USER_PANIC_ERR(err, "Failed to send reply");
}
break;
default:
@ -94,10 +71,7 @@ static void handle_child_recv(void *arg) {
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");
}
rpc_server_register_recv(&si->rpc_server);
}
struct temp_mapping {
@ -594,6 +568,22 @@ errval_t spawn_load_argv(int argc, char *argv[], struct spawninfo *si,
return err_push(err, SPAWN_ERR_SERIALISE_VSPACE);
}
// Create shared memory for RPC
err = frame_alloc(&si->rpc_shared_frame, RPC_SHARED_SIZE, NULL);
if (err_is_fail(err)) return err_push(err, LIB_ERR_FRAME_ALLOC);
void *rpc_shared_memory;
err = paging_map_frame_attr(
get_current_paging_state(), &rpc_shared_memory,
RPC_SHARED_SIZE, si->rpc_shared_frame, VREGION_FLAGS_READ_WRITE);
if (err_is_fail(err)) return err;
err = paging_map_frame_attr(
&child_paging_state, &domain_params->rpc_shared_memory,
RPC_SHARED_SIZE, si->rpc_shared_frame, VREGION_FLAGS_READ_WRITE);
if (err_is_fail(err)) return err;
// afeer: TODO: what do i put here? do we need to set these fields to some value?
// domain_params->tls_init_base = NULL;
// domain_params->tls_init_len = 0;
@ -624,9 +614,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);
rpc_server_init(&si->rpc_server, &si->init_chan, rpc_shared_memory);
// 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));
err = lmp_chan_register_recv(&si->init_chan, get_default_waitset(), MKCLOSURE(handle_child_recv, si));
if (err_is_fail(err)) return err;
// - Make the new dispatcher runnable

View File

@ -18,12 +18,14 @@
#include <string.h>
#include <aos/aos.h>
#include <aos/aos_rpc.h>
#include <aos/deferred.h>
#define HELLO_CATCH_COMMAND "catch"
int main(int argc, char *argv[])
{
errval_t err;
printf("Hello, world!\n");
printf("argv:\n");
@ -31,6 +33,13 @@ int main(int argc, char *argv[])
printf(" %d -> %s\n", i, argv[i]);
}
struct aos_rpc *rpc = aos_rpc_get_init_channel();
err = aos_rpc_send_number(rpc, 1234);
if (err_is_fail(err)) USER_PANIC_ERR(err, "Failed to send RPC");
err = aos_rpc_send_string(rpc, "Hello World via RPC!");
if (err_is_fail(err)) USER_PANIC_ERR(err, "Failed to send RPC");
// if we receive the catch command, RUN!
if (argc > 1 && !strncmp(argv[1], HELLO_CATCH_COMMAND, sizeof(HELLO_CATCH_COMMAND))) {
int iter = 0;