module /x86_64/sbin/kaluga boot
module /x86_64/sbin/acpi boot
module /x86_64/sbin/spawnd boot
+module /x86_64/sbin/proc_mgmt boot
#bootapic-x86_64=1-15
module /x86_64/sbin/startd boot
module /x86_64/sbin/routing_setup boot
"pci",
"ping_pong",
"pixels",
+ "proc_mgmt",
"rcce",
"replay",
"routing",
--- /dev/null
+/*
+ * Copyright (c) 2017, ETH Zurich.
+ * All rights reserved.
+ *
+ * This file is distributed under the terms in the attached LICENSE file.
+ * If you do not find this file, copies can be found by writing to:
+ * ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
+ */
+
+interface proc_mgmt "Process management service" {
+
+ // Allocate a new endpoint for a future connecting client.
+ rpc alloc_ep(out errval err, out cap ep);
+
+ // Spawn a new domain, returning its domainid cap.
+ rpc spawn(in coreid core,
+ in String path[2048],
+ in char argvbuf[argvbytes, 2048],
+ in char envbuf[envbytes, 2048],
+ in uint8 flags,
+ out errval err,
+ out cap domainid_cap);
+
+ // Span the caller to a new core.
+ rpc span(in cap domainid_cap,
+ in coreid core,
+ in cap vroot,
+ in cap disp_mem,
+ out errval err);
+
+ // Kill a domain for which the caller has a domainid cap.
+ rpc kill(in cap domainid_cap, out errval err);
+
+ // TODO(razvan): exit, wait, status, some other calls from spawn.if?
+};
--- /dev/null
+/**
+ * \file
+ * \brief Client for interacting with the process management server.
+ */
+
+/*
+ * Copyright (c) 2017, ETH Zurich.
+ * All rights reserved.
+ *
+ * This file is distributed under the terms in the attached LICENSE file.
+ * If you do not find this file, copies can be found by writing to:
+ * ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
+ */
+
+#ifndef BARRELFISH_PROC_MGMT_CLIENT_H
+#define BARRELFISH_PROC_MGMT_CLIENT_H
+
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+
+struct proc_mgmt_lmp_binding;
+
+errval_t proc_mgmt_client_lmp_accept(struct proc_mgmt_lmp_binding *lmpb,
+ struct waitset *ws, size_t lmp_buflen_words);
+
+__END_DECLS
+
+#endif // BARRELFISH_PROC_MGMT_CLIENT_H
let common_srcs = [ "capabilities.c", "init.c", "dispatch.c", "threads.c",
"thread_once.c", "thread_sync.c", "slab.c", "domain.c", "idc.c",
"waitset.c", "event_queue.c", "event_mutex.c",
- "idc_export.c", "nameservice_client.c", "msgbuf.c",
+ "idc_export.c", "nameservice_client.c", "msgbuf.c", "proc_mgmt_client.c",
"monitor_client.c", "flounder_support.c", "flounder_glue_binding.c",
"flounder_txqueue.c","morecore.c", "debug.c", "heap.c",
"ram_alloc.c", "terminal.c", "spawn_client.c", "vspace/vspace.c",
--- /dev/null
+/**
+ * \file
+ * \brief Client for interacting with the process management server.
+ */
+
+/*
+ * Copyright (c) 2017, ETH Zurich.
+ * All rights reserved.
+ *
+ * This file is distributed under the terms in the attached LICENSE file.
+ * If you do not find this file, copies can be found by writing to:
+ * ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
+ */
+
+#include <barrelfish/barrelfish.h>
+#include <barrelfish/proc_mgmt_client.h>
+#include <if/proc_mgmt_defs.h>
+
+static void error_handler(struct proc_mgmt_binding *b, errval_t err)
+{
+#if defined(__x86_64__) || defined(__i386__)
+ debug_printf("%p %p %p %p\n", __builtin_return_address(0), __builtin_return_address(1),__builtin_return_address(2),__builtin_return_address(3));
+#endif
+ debug_err(__FILE__, __func__, __LINE__, err,
+ "error in proc_mgmt binding");
+ abort();
+}
+
+static void proc_mgmt_accept_recv_handler(void *arg)
+{
+ struct proc_mgmt_lmp_binding *b = arg;
+ struct lmp_recv_msg msg = LMP_RECV_MSG_INIT;
+ struct capref cap;
+ errval_t err;
+
+ // try to retrieve a message from the channel
+ err = lmp_chan_recv(&b->chan, &msg, &cap);
+ if (err_is_fail(err)) {
+ if (err_no(err) == LIB_ERR_NO_LMP_MSG) {
+ // nothing there, re-register
+ struct event_closure recv_handler = {
+ .handler = proc_mgmt_accept_recv_handler,
+ .arg = b,
+ };
+ err = lmp_chan_register_recv(&b->chan, b->b.waitset, recv_handler);
+ b->b.error_handler(&b->b,
+ err_push(err, LIB_ERR_CHAN_REGISTER_RECV));
+ } else {
+ // real error, report to user
+ b->b.error_handler(&b->b, err_push(err, LIB_ERR_LMP_CHAN_RECV));
+ }
+ return;
+ }
+
+ // if we're the monitor, we might be waiting for the other side's cap
+ // TODO(razvan): Or the process manager, which for uses LMP_MONITOR_ACCEPT
+ // as well.
+ assert(b->chan.connstate == LMP_MONITOR_ACCEPT);
+ assert(!capref_is_null(cap));
+ b->chan.remote_cap = cap;
+ b->chan.connstate = LMP_CONNECTED;
+
+ // Allocate a new receive slot.
+ // TODO(razvan): Whom is the receive slot for? Is it one of the spawnds?
+ // Or is it some arbitrary non-spawnd client domain? Need a way to tell.
+ err = lmp_chan_alloc_recv_slot(&b->chan);
+ if (err_is_fail(err)) {
+ // XXX: report the error, but continue
+ b->b.error_handler(&b->b, err_push(err, LIB_ERR_LMP_ALLOC_RECV_SLOT));
+ }
+
+ // Run the RX handler; has a side-effect of registering for receive events.
+ proc_mgmt_lmp_rx_handler(b);
+}
+
+static errval_t init_lmp_binding(struct proc_mgmt_lmp_binding *lmpb,
+ struct waitset *ws, size_t buflen_words)
+{
+ errval_t err;
+
+ proc_mgmt_lmp_init(lmpb, ws);
+
+ /* allocate a cap slot for the new endpoint cap */
+ err = slot_alloc(&lmpb->chan.local_cap);
+ if (err_is_fail(err)) {
+ return err_push(err, LIB_ERR_SLOT_ALLOC);
+ }
+
+ /* allocate a local endpoint */
+ err = lmp_endpoint_create_in_slot(buflen_words, lmpb->chan.local_cap,
+ &lmpb->chan.endpoint);
+ if (err_is_fail(err)) {
+ /* TODO: free cap slot */
+ return err_push(err, LIB_ERR_ENDPOINT_CREATE);
+ }
+
+ /* allocate an initial receive slot */
+ err = lmp_chan_alloc_recv_slot(&lmpb->chan);
+ if (err_is_fail(err)) {
+ return err;
+ }
+
+ /* setup error handler */
+ lmpb->b.error_handler = error_handler;
+
+ /* setup initial receive handlers */
+ // lmpb->b.rx_vtbl = proc_mgmt_rx_vtbl;
+
+ // connect handlers
+ lmpb->b.change_waitset(&lmpb->b, lmpb->b.waitset);
+ return SYS_ERR_OK;
+}
+
+/**
+ * \brief Accept a new LMP binding in a client from the process manager.
+ *
+ * Should only be used in the process manager.
+ *
+ * \param pmcb Storage for binding state
+ * \param ws Waitset for handling incoming messages
+ * \param buflen_words Size of incoming buffer, in number of words
+ */
+errval_t proc_mgmt_client_lmp_accept(struct proc_mgmt_lmp_binding *lmpb,
+ struct waitset *ws, size_t lmp_buflen_words)
+{
+ errval_t err = init_lmp_binding(lmpb, ws, lmp_buflen_words);
+ if (err_is_fail(err)) {
+ return err;
+ }
+
+ // TODO(razvan): This should probably be something like LMP_PROC_MGMT_ACCEPT
+ lmpb->chan.connstate = LMP_MONITOR_ACCEPT;
+ lmpb->chan.remote_cap = NULL_CAP; // will be sent to us by the client
+
+ // Register for receive notification on our special handler.
+ struct event_closure receive_handler = {
+ .handler = proc_mgmt_accept_recv_handler,
+ .arg = lmpb,
+ };
+ err = lmp_chan_register_recv(&lmpb->chan, ws, receive_handler);
+ if (err_is_fail(err)) {
+ return err; // TODO: cleanup?
+ }
+
+ return SYS_ERR_OK;
+}
"init",
"skb",
"spawnd",
+ "proc_mgmt",
"startd",
"mem_serv",
"monitor",
--- /dev/null
+--------------------------------------------------------------------------
+-- Copyright (c) 2017, ETH Zurich.
+-- All rights reserved.
+--
+-- This file is distributed under the terms in the attached LICENSE file.
+-- If you do not find this file, copies can be found by writing to:
+-- ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
+--
+-- Hakefile for /usr/proc_mgmt
+--
+--------------------------------------------------------------------------
+
+[ build application { target = "proc_mgmt",
+ cFiles = [ "main.c", "service.c" ],
+ addLibraries = libDeps [ "skb", "dist", "lwip" ],
+ flounderDefs = [ "monitor", "monitor_blocking"],
+ flounderExtraDefs = [ ("monitor_blocking",["rpcclient"]) ],
+ flounderBindings = [ "proc_mgmt" ],
+ architectures = [ "x86_64", "x86_32" ]
+ },
+ build application { target = "proc_mgmt",
+ cFiles = [ "main.c", "service.c" ],
+ addLibraries = libDeps [ "skb", "dist", "lwip" ],
+ flounderDefs = [ "monitor", "monitor_blocking"],
+ flounderExtraDefs = [ ("monitor_blocking",["rpcclient"]) ],
+ flounderBindings = [ "proc_mgmt" ],
+ architectures = [ "k1om" ]
+ },
+ build application { target = "proc_mgmt",
+ cFiles = [ "main.c", "service.c" ],
+ addLibraries = libDeps [ "skb", "dist", "lwip" ],
+ flounderDefs = [ "monitor", "monitor_blocking"],
+ flounderExtraDefs = [ ("monitor_blocking",["rpcclient"]) ],
+ flounderBindings = [ "proc_mgmt" ],
+ architectures = [ "armv7", "armv8" ]
+ }
+]
--- /dev/null
+/**
+ * \file
+ * \brief Internal proc_mgmt functions.
+ */
+
+/*
+ * Copyright (c) 2017, ETH Zurich.
+ * All rights reserved.
+ *
+ * This file is distributed under the terms in the attached LICENSE file.
+ * If you do not find this file, copies can be found by writing to:
+ * ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
+ */
+
+#ifndef PROC_MGMT_INTERNAL_H_
+#define PROC_MGMT_INTERNAL_H_
+
+#define SERVICE_BASENAME "proc_mgmt" // the core ID is appended to this
+
+extern coreid_t my_core_id;
+
+errval_t start_service(void);
+
+#endif //PROC_MGMT_INTERNAL_H_
--- /dev/null
+/**
+ * \file
+ * \brief Process management server.
+ */
+
+/*
+ * Copyright (c) 2017, ETH Zurich.
+ * All rights reserved.
+ *
+ * This file is distributed under the terms in the attached LICENSE file.
+ * If you do not find this file, copies can be found by writing to:
+ * ETH Zurich D-INFK, Universitaetstr. 6, CH-8092 Zurich. Attn: Systems Group.
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include <barrelfish/barrelfish.h>
+#include <barrelfish/dispatch.h>
+
+#include "internal.h"
+
+coreid_t my_core_id;
+
+int main(int argc, const char *argv[])
+{
+ errval_t err;
+
+ my_core_id = disp_get_core_id();
+
+ printf("proc_mgmt.%u up.\n", my_core_id);
+
+ err = start_service();
+ if (err_is_fail(err)) {
+ USER_PANIC_ERR(err, "failed to start proc_mgmt service loop");
+ }
+
+ messages_handler_loop();
+}
--- /dev/null
+/**
+ * \file
+ * \brief Process management service.
+ */
+
+/*
+ * Copyright (c) 2017, ETH Zurich.
+ * All rights reserved.
+ *
+ * This file is distributed under the terms in the attached LICENSE file.
+ * If you do not find this file, copies can be found by writing to:
+ * ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
+ */
+
+#include <stdio.h>
+#include <barrelfish/barrelfish.h>
+#include <barrelfish/nameservice_client.h>
+#include <barrelfish/proc_mgmt_client.h>
+#include <if/proc_mgmt_defs.h>
+
+#include "internal.h"
+
+static struct proc_mgmt_rpc_rx_vtbl rpc_rx_vtbl;
+
+static errval_t alloc_ep_handler(struct proc_mgmt_binding *b, errval_t *err,
+ struct capref *ep)
+{
+ struct proc_mgmt_lmp_binding *lmpb = (struct proc_mgmt_lmp_binding*) malloc(
+ sizeof(struct proc_mgmt_lmp_binding));
+ assert(lmpb != NULL);
+
+ *err = proc_mgmt_client_lmp_accept(lmpb, get_default_waitset(),
+ DEFAULT_LMP_BUF_WORDS);
+ if (err_is_ok(*err)) {
+ *ep = lmpb->chan.local_cap;
+
+ // struct proc_mgmt_state *st = (struct proc_mgmt_state*) malloc(
+ // sizeof(struct proc_mgmt_state));
+ // assert(st != NULL);
+ // st->queue.head = st->queue.tail = NULL;
+
+ lmpb->b.rpc_rx_vtbl = rpc_rx_vtbl;
+ // lmpb->b.st = st;
+ } else {
+ free(lmpb);
+ }
+
+ return SYS_ERR_OK;
+}
+
+static errval_t spawn_handler(struct proc_mgmt_binding *b,
+ coreid_t core,
+ const char *path,
+ const char *argvbuf,
+ size_t argvbytes,
+ const char *envbuf,
+ size_t envbytes,
+ uint8_t flags,
+ errval_t *err,
+ struct capref *domainid_cap)
+{
+ return LIB_ERR_NOT_IMPLEMENTED;
+}
+
+static errval_t span_handler(struct proc_mgmt_binding *b,
+ struct capref domainid_cap,
+ coreid_t core,
+ struct capref vroot,
+ struct capref disp_mem,
+ errval_t *err)
+{
+ return LIB_ERR_NOT_IMPLEMENTED;
+}
+
+static errval_t kill_handler(struct proc_mgmt_binding *b,
+ struct capref domainid_cap,
+ errval_t *err)
+{
+ return LIB_ERR_NOT_IMPLEMENTED;
+}
+
+static struct proc_mgmt_rpc_rx_vtbl rpc_rx_vtbl = {
+ .alloc_ep_call = alloc_ep_handler,
+ .spawn_call = spawn_handler,
+ .span_call = span_handler,
+ .kill_call = kill_handler
+};
+
+static void export_cb(void *st, errval_t err, iref_t iref)
+{
+ if (err_is_fail(err)) {
+ USER_PANIC_ERR(err, "export failed");
+ }
+
+ // construct name
+ char namebuf[32];
+ size_t len = snprintf(namebuf, sizeof(namebuf), "%s.%d", SERVICE_BASENAME,
+ my_core_id);
+ assert(len < sizeof(namebuf));
+ namebuf[sizeof(namebuf) - 1] = '\0';
+
+ // register this iref with the name service
+ err = nameservice_register(namebuf, iref);
+ if (err_is_fail(err)) {
+ USER_PANIC_ERR(err, "nameservice_register failed");
+ }
+}
+
+static errval_t connect_cb(void *st, struct proc_mgmt_binding *b)
+{
+ b->rpc_rx_vtbl = rpc_rx_vtbl;
+ return SYS_ERR_OK;
+}
+
+errval_t start_service(void)
+{
+ return proc_mgmt_export(NULL, export_cb, connect_cb, get_default_waitset(),
+ IDC_EXPORT_FLAGS_DEFAULT);
+}