Working Init Channel

This commit is contained in:
Sparchatus 2022-03-28 15:33:53 +00:00
parent 24c9fa55a9
commit 50c75ed361
12 changed files with 179 additions and 46 deletions

View File

@ -17,10 +17,15 @@
#include <aos/aos.h>
// 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;
};
/**

View File

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

View File

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

View File

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

View File

@ -28,9 +28,11 @@
#include "threads_priv.h"
#include "init.h"
#include <aos/aos_rpc.h>
/// 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);
}

View File

@ -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 &current
// 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(&current);
// debug_printf("Received initial paging state:\n");
// pt_print_state(&current);
}
set_current_paging_state(&current);

View File

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

View File

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

View File

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

View File

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

View File

@ -16,9 +16,9 @@
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <aos/aos.h>
#include <aos/deferred.h>
#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;
}
}

View File

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