# HG changeset patch # User Paul Boddie # Date 1650983777 -7200 # Node ID 2f085a61c06bec8adabcf62c255ccf25e29b934d # Parent f7b1aaad7f8661de3d5e6c372e9b5a2e7dc0a1fd Added an investigation into the creation of tasks and loading of programs. diff -r f7b1aaad7f86 -r 2f085a61c06b conf/dstest_exec.cfg --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/conf/dstest_exec.cfg Tue Apr 26 16:36:17 2022 +0200 @@ -0,0 +1,50 @@ +-- vim:set ft=lua: + +local L4 = require("L4"); + +local l = L4.default_loader; + +local pipe_server = l:new_channel(); + +l:startv({ + caps = { + server = pipe_server:svr(), + }, + log = { "pipes", "r" }, + }, + "rom/dstest_pipe_server", "10"); + +local block_server = l:new_channel(); + +l:startv({ + caps = { + server = block_server:svr(), + }, + log = { "blocksvr", "r" }, + }, + "rom/dstest_block_server", "10"); + +local ext2svr = l:new_channel(); + +l:startv({ + caps = { + blocksvr = block_server, + pipes = pipe_server, + ext2svr = ext2svr:svr(), + }, + log = { "ext2svr", "y" }, + }, + "rom/dstest_ext2_server", "blocksvr", "rom/e2test.fs", "10", "ext2svr"); + +-- Obtain user filesystems with umask 0022 (18). + +local open_for_user = 6; +local ext2svr_paulb = L4.cast(L4.Proto.Factory, ext2svr):create(open_for_user, 1000, 1000, 18); + +l:startv({ + caps = { + server = ext2svr_paulb, + }, + log = { "client", "g" }, + }, + "rom/dstest_exec", "home/paulb/dstest_exec_payload"); diff -r f7b1aaad7f86 -r 2f085a61c06b conf/dstest_exec.list --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/conf/dstest_exec.list Tue Apr 26 16:36:17 2022 +0200 @@ -0,0 +1,28 @@ +entry dstest_exec +roottask moe rom/dstest_exec.cfg +module dstest_exec.cfg +module e2test.fs +module l4re +module ned +module dstest_exec +module dstest_ext2_server +module dstest_block_server +module dstest_pipe_server +module lib4re-c.so +module lib4re-c-util.so +module lib4re.so +module lib4re-util.so +module libc_be_l4refile.so +module libc_be_l4re.so +module libc_be_socket_noop.so +module libc_support_misc.so +module libdl.so +module libipc.so +module libl4sys-direct.so +module libl4sys.so +module libl4util.so +module libld-l4.so +module libpthread.so +module libstdc++.so +module libsupc++.so +module libuc_c.so diff -r f7b1aaad7f86 -r 2f085a61c06b libipc/include/ipc/mem_ipc.h --- a/libipc/include/ipc/mem_ipc.h Tue Apr 26 16:34:54 2022 +0200 +++ b/libipc/include/ipc/mem_ipc.h Tue Apr 26 16:36:17 2022 +0200 @@ -1,7 +1,7 @@ /* * Memory sharing abstractions. * - * Copyright (C) 2018, 2019, 2021 Paul Boddie + * Copyright (C) 2018, 2019, 2021, 2022 Paul Boddie * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -22,14 +22,26 @@ #pragma once #include +#include #include EXTERN_C_BEGIN long ipc_allocate(unsigned long size, void **addr, l4re_ds_t *ds); + +long ipc_allocate_align(unsigned long size, l4re_rm_flags_t flags, + unsigned char align, void **addr, l4re_ds_t *ds); + long ipc_new_dataspace(l4_cap_idx_t cap, l4_mword_t size, l4_umword_t flags, l4_umword_t align); + long ipc_attach_dataspace(l4re_ds_t ds, unsigned long size, void **addr); + +long ipc_attach_dataspace_align(l4re_ds_t ds, unsigned long size, + l4re_rm_flags_t flags, unsigned char align, + void **addr); + long ipc_detach_dataspace(void *addr); + long ipc_dataspace_size(l4_cap_idx_t cap, unsigned long *size); EXTERN_C_END diff -r f7b1aaad7f86 -r 2f085a61c06b libipc/lib/src/mem_ipc.c --- a/libipc/lib/src/mem_ipc.c Tue Apr 26 16:34:54 2022 +0200 +++ b/libipc/lib/src/mem_ipc.c Tue Apr 26 16:36:17 2022 +0200 @@ -1,7 +1,7 @@ /* * Memory sharing abstractions. * - * Copyright (C) 2018, 2019, 2021 Paul Boddie + * Copyright (C) 2018, 2019, 2021, 2022 Paul Boddie * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -20,7 +20,6 @@ */ #include -#include #include #include @@ -40,6 +39,13 @@ long ipc_allocate(unsigned long size, void **addr, l4re_ds_t *ds) { + return ipc_allocate_align(size, L4RE_RM_F_SEARCH_ADDR | L4RE_RM_F_RW, + L4_PAGESHIFT, addr, ds); +} + +long ipc_allocate_align(unsigned long size, l4re_rm_flags_t flags, + unsigned char align, void **addr, l4re_ds_t *ds) +{ /* Allocate a capability for the dataspace. */ *ds = ipc_cap_alloc(); @@ -49,13 +55,13 @@ /* Allocate and attach the memory for the dataspace. */ - if (ipc_new_dataspace(*ds, size, 0, 0)) + if (ipc_new_dataspace(*ds, size, 0, align)) { ipc_cap_free_um(*ds); return -L4_ENOMEM; } - if (ipc_attach_dataspace(*ds, size, addr)) + if (ipc_attach_dataspace_align(*ds, size, flags, align, addr)) { ipc_cap_free_um(*ds); return -L4_ENOMEM; @@ -75,6 +81,14 @@ long ipc_attach_dataspace(l4re_ds_t ds, unsigned long size, void **addr) { + return ipc_attach_dataspace_align(ds, size, L4RE_RM_F_SEARCH_ADDR | L4RE_RM_F_RW, + L4_PAGESHIFT, addr); +} + +long ipc_attach_dataspace_align(l4re_ds_t ds, unsigned long size, + l4re_rm_flags_t flags, unsigned char align, + void **addr) +{ long err; err = ipc_semaphore_down(ipc_mem_semaphore); @@ -84,8 +98,7 @@ /* The region manager has changed, requiring rights flags for successful use of the mapped region. */ - err = l4re_rm_attach(addr, size, L4RE_RM_F_SEARCH_ADDR | L4RE_RM_F_RW, ds, 0, - L4_PAGESHIFT); + err = l4re_rm_attach(addr, size, flags, ds, 0, align); ipc_semaphore_up(ipc_mem_semaphore); diff -r f7b1aaad7f86 -r 2f085a61c06b libsystypes/idl/system_pager.idl --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libsystypes/idl/system_pager.idl Tue Apr 26 16:36:17 2022 +0200 @@ -0,0 +1,19 @@ +#include /* L4_PROTO_EXCEPTION, L4_PROTO_PAGE_FAULT */ +#include /* l4_exc_regs_t */ + +/* A system pager interface. */ + +interface SystemPager +{ + /* Handle an exception involving the given register values, returning a + flexpage to remedy the exception. */ + + [opcode(L4_PROTO_EXCEPTION)] + void exception(in l4_exc_regs_t regs, out fpage region); + + /* Handle a page fault involving the given page fault address and program + counter, returning a flexpage to provide such a mapping. */ + + [opcode(L4_PROTO_PAGE_FAULT)] + void page_fault(in l4_umword_t pfa, in l4_umword_t pc, out fpage region); +}; diff -r f7b1aaad7f86 -r 2f085a61c06b test_files/Makefile --- a/test_files/Makefile Tue Apr 26 16:34:54 2022 +0200 +++ b/test_files/Makefile Tue Apr 26 16:36:17 2022 +0200 @@ -4,12 +4,21 @@ E2ACCESS_DIR = $(PKGDIR)/../libe2access/host TARGET = $(PKGDIR)/../conf/e2test.fs +PROGRAMS = $(PKGDIR_OBJ)/_programs + include $(L4DIR)/mk/Makeconf +include $(OBJ_BASE)/l4defs.mk.inc + +PROGRAMS_DIR = $(PKGDIR_OBJ)/programs/OBJ-$(L4_SYSTEM)-l4f # Special rules to build the test filesystem. -all:: $(TARGET) +all:: $(TARGET) $(PROGRAMS) -$(TARGET): +$(TARGET): $(PROGRAMS) make -C $(E2ACCESS_DIR) - $(PKGDIR)/mk_e2test.sh -q $(PKGDIR) $(E2ACCESS_DIR) $@ + $(PKGDIR)/mk_e2test.sh -q $(PKGDIR) $(PROGRAMS_DIR) $(E2ACCESS_DIR) $@ + +$(PROGRAMS): + make -C $(PKGDIR)/programs $(MKFLAGS) + touch $@ diff -r f7b1aaad7f86 -r 2f085a61c06b test_files/mk_e2test.sh --- a/test_files/mk_e2test.sh Tue Apr 26 16:34:54 2022 +0200 +++ b/test_files/mk_e2test.sh Tue Apr 26 16:36:17 2022 +0200 @@ -31,14 +31,16 @@ fi PKGDIR=$(realpath "$1") -E2ACCESS_DIR=$(realpath "$2") -TARGET=$(realpath "$3") +PROGRAMS_DIR=$(realpath "$2") +E2ACCESS_DIR=$(realpath "$3") +TARGET=$(realpath "$4") -if [ ! -e "$PKGDIR" ] || [ ! -e "$E2ACCESS_DIR" ] || [ ! "$TARGET" ] ; then +if [ ! -e "$PKGDIR" ] || [ ! -e "$PROGRAMS_DIR" ] || [ ! -e "$E2ACCESS_DIR" ] || [ ! "$TARGET" ] ; then cat 1>&2 < +Usage: $PROGNAME [ -q ] Package directory: $PKGDIR +Programs directory: $PROGRAMS_DIR e2access directory: $E2ACCESS_DIR Target filesystem: $TARGET EOF @@ -102,10 +104,14 @@ cd .. -# Put a file in the directory above. +# Put file in the created home directory. cp "$PKGDIR/../docs/LICENCE.txt" . +# Put some programs in the same place. + +cp "$PROGRAMS_DIR/dstest_"* . + # Leave the filesystem root. cd ../.. @@ -124,7 +130,7 @@ # Add the directories and files to the image. -for DIR in home/paulb/private home/paulb/public home/paulb/shared home/paulb/many home/paulb ; do +for DIR in home/paulb home/paulb/private home/paulb/public home/paulb/shared home/paulb/many ; do e2access mkdir "$DIR" e2access copy-in $(find "$DIR" -maxdepth 1 -type f | sort) "$DIR" done diff -r f7b1aaad7f86 -r 2f085a61c06b test_files/programs/Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test_files/programs/Makefile Tue Apr 26 16:36:17 2022 +0200 @@ -0,0 +1,12 @@ +PKGDIR ?= .. +L4DIR ?= $(PKGDIR)/../../.. + +TARGET = dstest_exec_payload + +MODE = static + +SRC_C_dstest_exec_payload = exec_payload.c + +REQUIRES_LIBS = libc + +include $(L4DIR)/mk/prog.mk diff -r f7b1aaad7f86 -r 2f085a61c06b test_files/programs/exec_payload.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test_files/programs/exec_payload.c Tue Apr 26 16:36:17 2022 +0200 @@ -0,0 +1,33 @@ +/* + * A test of executing code in a new task. + * + * Copyright (C) 2022 Paul Boddie + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA + */ + +#include + + + +int main(int argc, char *argv[]) +{ + printf("Hello from exec_payload.c!\n"); + return 0; +} + +/* vim: tabstop=2 expandtab shiftwidth=2 +*/ diff -r f7b1aaad7f86 -r 2f085a61c06b tests/Makefile --- a/tests/Makefile Tue Apr 26 16:34:54 2022 +0200 +++ b/tests/Makefile Tue Apr 26 16:36:17 2022 +0200 @@ -12,10 +12,35 @@ dstest_file_rename \ dstest_host_client \ dstest_pipe_client \ - dstest_test_client + dstest_test_client \ + dstest_map_test \ + dstest_exec MODE = static +# Locations for interface input and generated output. + +IDL_DIR = $(PKGDIR)/../libsystypes/idl +IDL_MK_DIR = $(L4DIR)/idl4re/mk +IDL_BUILD_DIR = . +IDL_EXPORT_DIR = . + +include $(IDL_MK_DIR)/idl.mk + +# Individual interfaces. + +CLIENT_INTERFACES_CC = system_pager + +SERVER_INTERFACES_CC = system_pager + +# Generated and plain source files. + +CLIENT_INTERFACES_SRC_CC = $(call interfaces_to_client_cc,$(CLIENT_INTERFACES_CC)) + +SERVER_INTERFACES_SRC_CC = $(call interfaces_to_server_cc,$(SERVER_INTERFACES_CC)) + +# Normal source files. + SRC_CC_dstest_block_client = dstest_block_client.cc SRC_CC_dstest_block_client_simple = dstest_block_client_simple.cc @@ -40,6 +65,14 @@ SRC_CC_dstest_test_client = dstest_test_client.cc +PLAIN_SRC_CC_dstest_exec = dstest_exec.cc +SRC_CC_dstest_exec = $(PLAIN_SRC_CC_dstest_exec) $(SERVER_INTERFACES_SRC_CC) \ + $(CLIENT_INTERFACES_SRC_CC) + REQUIRES_LIBS = l4re_c-util libfsclient libmem libipc libstdc++ libsystypes libe2access_blockserver +PRIVATE_INCDIR = $(IDL_BUILD_DIR) $(IDL_EXPORT_DIR) include $(L4DIR)/mk/prog.mk +include $(IDL_MK_DIR)/interface_rules.mk + +$(PLAIN_SRC_CC_dstest_exec): $(SERVER_INTERFACES_SRC_CC) $(CLIENT_INTERFACES_SRC_CC) diff -r f7b1aaad7f86 -r 2f085a61c06b tests/dstest_exec.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/dstest_exec.cc Tue Apr 26 16:36:17 2022 +0200 @@ -0,0 +1,414 @@ +/* + * Support for executing code in new tasks and threads. + * + * Copyright (C) 2022 Paul Boddie + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA + */ + +#include +#include +#include +#include +#include +#include /* l4util_log2 */ + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include "system_pager_interface.h" +#include "system_pager_server.h" + + + +/* A simple system pager. */ + +class ExecPager : public SystemPager +{ +public: + l4_addr_t buf, buf_start; + unsigned int buf_log2size; + + virtual long exception(l4_exc_regs_t regs, + l4_snd_fpage_t *region); + + virtual long page_fault(l4_umword_t pfa, l4_umword_t pc, + l4_snd_fpage_t *region); +}; + +long ExecPager::exception(l4_exc_regs_t regs, l4_snd_fpage_t *region) +{ + (void) region; + + printf("exception(...) -> pfa = %lx, pc = %lx\n", l4_utcb_exc_pfa(®s), l4_utcb_exc_pc(®s)); + return L4_EOK; +} + +long ExecPager::page_fault(l4_umword_t pfa, l4_umword_t pc, l4_snd_fpage_t *region) +{ + l4_umword_t addr = pfa & ~7UL, flags = pfa & 7; + + printf("page_fault(%lx, %lx) -> %lx (%lx)...\n", pfa, pc, addr, flags); + + if ((addr >= buf_start) && (addr < buf_start + (1UL << buf_log2size))) + { + region->fpage = l4_fpage(buf, buf_log2size, L4_FPAGE_RX); + region->snd_base = buf_start; + + return L4_EOK; + } + + return -L4_ENOMEM; +} + + + +static ExecPager exec_pager; + +static void init_pager(ipc_server_config_type *config, l4_addr_t buf, + unsigned int buf_log2size, l4_addr_t buf_start) +{ + exec_pager.buf = buf; + exec_pager.buf_log2size = buf_log2size; + exec_pager.buf_start = buf_start; + + ipc_server_init_config(config); + + config->expected_items = SystemPager_expected_items; + config->handler = (ipc_server_handler_type) handle_SystemPager; + config->handler_obj = static_cast(&exec_pager); +} + +static long start_pager(ipc_server_config_type *config, pthread_t thread) +{ + config->config_thread = 1; + config->thread = pthread_l4_cap(thread); + + printf("Starting pager thread...\n"); + return ipc_server_start_config(config); +} + + + +/* UTCB properties. + See: moe/server/src/loader.cc */ + +enum ipc_exec_utcb +{ + Default_max_threads = 16, +#ifdef ARCH_mips + Utcb_area_start = 0x73000000, +#else + Utcb_area_start = 0xb3000000, +#endif +}; + + + +static int find_region_exp(offset_t size) +{ + int exp = l4util_log2(size); + + if ((1UL << exp) < size) + return exp + 1; + else + return exp; +} + +static offset_t find_region_size(offset_t size) +{ + return 1 << find_region_exp(size); +} + +int main(int argc, char *argv[]) +{ + long err; + + if (argc < 2) + { + printf("Need a program to run.\n"); + return 1; + } + + /* Allocate capabilities for the task and thread. */ + + l4_cap_idx_t task, thread; + + task = ipc_cap_alloc(); + + if (l4_is_invalid_cap(task)) + { + printf("Could not allocate task.\n"); + return 1; + } + + thread = ipc_cap_alloc(); + + if (l4_is_invalid_cap(thread)) + { + printf("Could not allocate thread.\n"); + return 1; + } + + /* Obtain the payload as a dataspace. */ + + file_t *file = client_open(argv[1], O_RDONLY); + + if (file == NULL) + { + printf("Could not read file: %s\n", argv[1]); + return 1; + } + + /* Copy the entire payload to a new dataspace. */ + + char *buf; + offset_t nread; + offset_t region_size = find_region_size(4000000); + l4re_ds_t region_ds; + + err = ipc_allocate_align(region_size, L4RE_RM_F_SEARCH_ADDR | L4RE_RM_F_RWX, + find_region_exp(4000000), (void **) &buf, ®ion_ds); + + if (err) + { + printf("Could not reserve memory.\n"); + return 1; + } + + printf("Reading from file into %p.\n", buf); + + nread = client_read(file, buf, 4000000); + + printf("Read %ld from file.\n", nread); + + if (memcmp(buf + 0xae3, "\x31\xed", 2)) + { + printf("Did not find expected instructions at start.\n"); + return 1; + } + + /* UTCB location and size. */ + + l4_addr_t utcb_start = Utcb_area_start; + int utcb_log2size = find_region_exp(Default_max_threads * L4_UTCB_OFFSET); + + /* Round up to at least one page. */ + + if (utcb_log2size < L4_PAGESHIFT) + utcb_log2size = L4_PAGESHIFT; + + /* KIP allocation. */ + + l4_addr_t kip_start = (l4_addr_t) l4re_kip(); + + printf("KIP at %lx.\n", kip_start); + + /* Create a new task and thread. */ + + l4_fpage_t utcb_fpage = l4_fpage(utcb_start, utcb_log2size, 0); + + err = l4_error(l4_factory_create_task(l4re_env()->factory, task, utcb_fpage)); + + if (err) + { + printf("Could not create task.\n"); + return 1; + } + + err = l4_error(l4_factory_create_thread(l4re_env()->factory, thread)); + + if (err) + { + printf("Could not create thread.\n"); + return 1; + } + + /* Start the pager. */ + + ipc_server_config_type config; + pthread_t pager_thread; + pthread_attr_t attr; + + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); + + init_pager(&config, (l4_addr_t) buf, find_region_exp(file->size), 0x1000000); + + err = pthread_create(&pager_thread, &attr, ipc_server_start_mainloop, &config); + + if (err) + { + printf("Could not start pager thread.\n"); + return 1; + } + + err = start_pager(&config, pager_thread); + + if (err) + { + printf("Could not start pager.\n"); + return 1; + } + + /* Map the pager capability into the region manager/mapper slot. */ + + err = l4_error(l4_task_map(task, L4RE_THIS_TASK_CAP, + l4_obj_fpage(config.server, 0, L4_CAP_FPAGE_RWS), + l4_map_obj_control(0x10 << L4_CAP_SHIFT, L4_MAP_ITEM_MAP))); + + if (err) + { + printf("Could not map pager capability into task.\n"); + return 1; + } + + /* Map the KIP into the task. */ + + err = l4_error(l4_task_map(task, L4RE_THIS_TASK_CAP, + l4_fpage(kip_start, L4_PAGESHIFT, L4_FPAGE_RX), + kip_start)); + + if (err) + { + printf("Could not map KIP into task.\n"); + return 1; + } + + err = l4_error(l4_task_map(task, L4RE_THIS_TASK_CAP, + l4_obj_fpage(task, 0, L4_CAP_FPAGE_RWS), + l4_map_obj_control(L4_BASE_TASK_CAP, L4_MAP_ITEM_MAP))); + + if (err) + { + printf("Could not map task capability into task.\n"); + return 1; + } + + err = l4_error(l4_task_map(task, L4RE_THIS_TASK_CAP, + l4_obj_fpage(thread, 0, L4_CAP_FPAGE_RWS), + l4_map_obj_control(L4_BASE_THREAD_CAP, L4_MAP_ITEM_MAP))); + + if (err) + { + printf("Could not map thread capability into task.\n"); + return 1; + } + + err = l4_error(l4_task_map(task, L4RE_THIS_TASK_CAP, + l4_obj_fpage(l4re_env()->factory, 0, L4_CAP_FPAGE_RWS), + l4_map_obj_control(L4_BASE_FACTORY_CAP, L4_MAP_ITEM_MAP))); + + if (err) + { + printf("Could not map factory capability into task.\n"); + return 1; + } + + err = l4_error(l4_task_map(task, L4RE_THIS_TASK_CAP, + l4_obj_fpage(l4re_env()->log, 0, L4_CAP_FPAGE_RWS), + l4_map_obj_control(L4_BASE_LOG_CAP, L4_MAP_ITEM_MAP))); + + if (err) + { + printf("Could not map log capability into task.\n"); + return 1; + } + + err = l4_error(l4_task_map(task, L4RE_THIS_TASK_CAP, + l4_obj_fpage(l4re_env()->scheduler, 0, L4_CAP_FPAGE_RWS), + l4_map_obj_control(L4_BASE_SCHEDULER_CAP, L4_MAP_ITEM_MAP))); + + if (err) + { + printf("Could not map scheduler capability into task.\n"); + return 1; + } + + /* Configure the thread with the region manager acting as pager and exception + handler. The UTCB will be situated at an address supported by a dataspace + attached to the new task. */ + + printf("Configure thread...\n"); + + l4_thread_control_start(); + l4_thread_control_pager(0x10 << L4_CAP_SHIFT); + l4_thread_control_exc_handler(0x10 << L4_CAP_SHIFT); + l4_thread_control_bind((l4_utcb_t *) utcb_start, task); + err = l4_error(l4_thread_control_commit(thread)); + + if (err) + { + printf("Could not configure thread.\n"); + return 1; + } + + /* Map the payload into the new task. */ + + printf("Map %p with size %ld (2 ** %d).\n", buf, file->size, find_region_exp(file->size)); + + l4_fpage_t payload_fpage = l4_fpage((l4_addr_t) buf, find_region_exp(file->size), L4_FPAGE_RX); + + err = l4_error(l4_task_map(task, L4RE_THIS_TASK_CAP, payload_fpage, 0x1000000)); + + if (err) + { + printf("Could not map payload into task.\n"); + return 1; + } + + /* Start the new thread. */ + + printf("Schedule thread...\n"); + + err = l4_error(l4_thread_ex_regs(thread, 0x1000ae3, 0x2000000 /* stack top */, 0)); + + if (err) + { + printf("Could not set thread registers.\n"); + return 1; + } + + printf("Run thread...\n"); + + l4_sched_param_t sp = l4_sched_param(L4RE_MAIN_THREAD_PRIO); + + err = l4_error(l4_scheduler_run_thread(l4re_env()->scheduler, thread, &sp)); + + if (err) + { + printf("Could not run thread.\n"); + return 1; + } + + printf("Finished.\n"); + while (1); + + return 0; +} + +/* vim: tabstop=2 expandtab shiftwidth=2 +*/