1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/conf/dstest_exec.cfg Tue Apr 26 16:36:17 2022 +0200
1.3 @@ -0,0 +1,50 @@
1.4 +-- vim:set ft=lua:
1.5 +
1.6 +local L4 = require("L4");
1.7 +
1.8 +local l = L4.default_loader;
1.9 +
1.10 +local pipe_server = l:new_channel();
1.11 +
1.12 +l:startv({
1.13 + caps = {
1.14 + server = pipe_server:svr(),
1.15 + },
1.16 + log = { "pipes", "r" },
1.17 + },
1.18 + "rom/dstest_pipe_server", "10");
1.19 +
1.20 +local block_server = l:new_channel();
1.21 +
1.22 +l:startv({
1.23 + caps = {
1.24 + server = block_server:svr(),
1.25 + },
1.26 + log = { "blocksvr", "r" },
1.27 + },
1.28 + "rom/dstest_block_server", "10");
1.29 +
1.30 +local ext2svr = l:new_channel();
1.31 +
1.32 +l:startv({
1.33 + caps = {
1.34 + blocksvr = block_server,
1.35 + pipes = pipe_server,
1.36 + ext2svr = ext2svr:svr(),
1.37 + },
1.38 + log = { "ext2svr", "y" },
1.39 + },
1.40 + "rom/dstest_ext2_server", "blocksvr", "rom/e2test.fs", "10", "ext2svr");
1.41 +
1.42 +-- Obtain user filesystems with umask 0022 (18).
1.43 +
1.44 +local open_for_user = 6;
1.45 +local ext2svr_paulb = L4.cast(L4.Proto.Factory, ext2svr):create(open_for_user, 1000, 1000, 18);
1.46 +
1.47 +l:startv({
1.48 + caps = {
1.49 + server = ext2svr_paulb,
1.50 + },
1.51 + log = { "client", "g" },
1.52 + },
1.53 + "rom/dstest_exec", "home/paulb/dstest_exec_payload");
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2.2 +++ b/conf/dstest_exec.list Tue Apr 26 16:36:17 2022 +0200
2.3 @@ -0,0 +1,28 @@
2.4 +entry dstest_exec
2.5 +roottask moe rom/dstest_exec.cfg
2.6 +module dstest_exec.cfg
2.7 +module e2test.fs
2.8 +module l4re
2.9 +module ned
2.10 +module dstest_exec
2.11 +module dstest_ext2_server
2.12 +module dstest_block_server
2.13 +module dstest_pipe_server
2.14 +module lib4re-c.so
2.15 +module lib4re-c-util.so
2.16 +module lib4re.so
2.17 +module lib4re-util.so
2.18 +module libc_be_l4refile.so
2.19 +module libc_be_l4re.so
2.20 +module libc_be_socket_noop.so
2.21 +module libc_support_misc.so
2.22 +module libdl.so
2.23 +module libipc.so
2.24 +module libl4sys-direct.so
2.25 +module libl4sys.so
2.26 +module libl4util.so
2.27 +module libld-l4.so
2.28 +module libpthread.so
2.29 +module libstdc++.so
2.30 +module libsupc++.so
2.31 +module libuc_c.so
3.1 --- a/libipc/include/ipc/mem_ipc.h Tue Apr 26 16:34:54 2022 +0200
3.2 +++ b/libipc/include/ipc/mem_ipc.h Tue Apr 26 16:36:17 2022 +0200
3.3 @@ -1,7 +1,7 @@
3.4 /*
3.5 * Memory sharing abstractions.
3.6 *
3.7 - * Copyright (C) 2018, 2019, 2021 Paul Boddie <paul@boddie.org.uk>
3.8 + * Copyright (C) 2018, 2019, 2021, 2022 Paul Boddie <paul@boddie.org.uk>
3.9 *
3.10 * This program is free software; you can redistribute it and/or
3.11 * modify it under the terms of the GNU General Public License as
3.12 @@ -22,14 +22,26 @@
3.13 #pragma once
3.14
3.15 #include <l4/re/c/dataspace.h>
3.16 +#include <l4/re/c/rm.h>
3.17 #include <l4/sys/types.h>
3.18
3.19 EXTERN_C_BEGIN
3.20
3.21 long ipc_allocate(unsigned long size, void **addr, l4re_ds_t *ds);
3.22 +
3.23 +long ipc_allocate_align(unsigned long size, l4re_rm_flags_t flags,
3.24 + unsigned char align, void **addr, l4re_ds_t *ds);
3.25 +
3.26 long ipc_new_dataspace(l4_cap_idx_t cap, l4_mword_t size, l4_umword_t flags, l4_umword_t align);
3.27 +
3.28 long ipc_attach_dataspace(l4re_ds_t ds, unsigned long size, void **addr);
3.29 +
3.30 +long ipc_attach_dataspace_align(l4re_ds_t ds, unsigned long size,
3.31 + l4re_rm_flags_t flags, unsigned char align,
3.32 + void **addr);
3.33 +
3.34 long ipc_detach_dataspace(void *addr);
3.35 +
3.36 long ipc_dataspace_size(l4_cap_idx_t cap, unsigned long *size);
3.37
3.38 EXTERN_C_END
4.1 --- a/libipc/lib/src/mem_ipc.c Tue Apr 26 16:34:54 2022 +0200
4.2 +++ b/libipc/lib/src/mem_ipc.c Tue Apr 26 16:36:17 2022 +0200
4.3 @@ -1,7 +1,7 @@
4.4 /*
4.5 * Memory sharing abstractions.
4.6 *
4.7 - * Copyright (C) 2018, 2019, 2021 Paul Boddie <paul@boddie.org.uk>
4.8 + * Copyright (C) 2018, 2019, 2021, 2022 Paul Boddie <paul@boddie.org.uk>
4.9 *
4.10 * This program is free software; you can redistribute it and/or
4.11 * modify it under the terms of the GNU General Public License as
4.12 @@ -20,7 +20,6 @@
4.13 */
4.14
4.15 #include <l4/re/c/mem_alloc.h>
4.16 -#include <l4/re/c/rm.h>
4.17 #include <l4/sys/err.h>
4.18 #include <l4/sys/types.h>
4.19
4.20 @@ -40,6 +39,13 @@
4.21
4.22 long ipc_allocate(unsigned long size, void **addr, l4re_ds_t *ds)
4.23 {
4.24 + return ipc_allocate_align(size, L4RE_RM_F_SEARCH_ADDR | L4RE_RM_F_RW,
4.25 + L4_PAGESHIFT, addr, ds);
4.26 +}
4.27 +
4.28 +long ipc_allocate_align(unsigned long size, l4re_rm_flags_t flags,
4.29 + unsigned char align, void **addr, l4re_ds_t *ds)
4.30 +{
4.31 /* Allocate a capability for the dataspace. */
4.32
4.33 *ds = ipc_cap_alloc();
4.34 @@ -49,13 +55,13 @@
4.35
4.36 /* Allocate and attach the memory for the dataspace. */
4.37
4.38 - if (ipc_new_dataspace(*ds, size, 0, 0))
4.39 + if (ipc_new_dataspace(*ds, size, 0, align))
4.40 {
4.41 ipc_cap_free_um(*ds);
4.42 return -L4_ENOMEM;
4.43 }
4.44
4.45 - if (ipc_attach_dataspace(*ds, size, addr))
4.46 + if (ipc_attach_dataspace_align(*ds, size, flags, align, addr))
4.47 {
4.48 ipc_cap_free_um(*ds);
4.49 return -L4_ENOMEM;
4.50 @@ -75,6 +81,14 @@
4.51
4.52 long ipc_attach_dataspace(l4re_ds_t ds, unsigned long size, void **addr)
4.53 {
4.54 + return ipc_attach_dataspace_align(ds, size, L4RE_RM_F_SEARCH_ADDR | L4RE_RM_F_RW,
4.55 + L4_PAGESHIFT, addr);
4.56 +}
4.57 +
4.58 +long ipc_attach_dataspace_align(l4re_ds_t ds, unsigned long size,
4.59 + l4re_rm_flags_t flags, unsigned char align,
4.60 + void **addr)
4.61 +{
4.62 long err;
4.63
4.64 err = ipc_semaphore_down(ipc_mem_semaphore);
4.65 @@ -84,8 +98,7 @@
4.66 /* The region manager has changed, requiring rights flags for successful use
4.67 of the mapped region. */
4.68
4.69 - err = l4re_rm_attach(addr, size, L4RE_RM_F_SEARCH_ADDR | L4RE_RM_F_RW, ds, 0,
4.70 - L4_PAGESHIFT);
4.71 + err = l4re_rm_attach(addr, size, flags, ds, 0, align);
4.72
4.73 ipc_semaphore_up(ipc_mem_semaphore);
4.74
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
5.2 +++ b/libsystypes/idl/system_pager.idl Tue Apr 26 16:36:17 2022 +0200
5.3 @@ -0,0 +1,19 @@
5.4 +#include <l4/sys/types.h> /* L4_PROTO_EXCEPTION, L4_PROTO_PAGE_FAULT */
5.5 +#include <l4/sys/utcb.h> /* l4_exc_regs_t */
5.6 +
5.7 +/* A system pager interface. */
5.8 +
5.9 +interface SystemPager
5.10 +{
5.11 + /* Handle an exception involving the given register values, returning a
5.12 + flexpage to remedy the exception. */
5.13 +
5.14 + [opcode(L4_PROTO_EXCEPTION)]
5.15 + void exception(in l4_exc_regs_t regs, out fpage region);
5.16 +
5.17 + /* Handle a page fault involving the given page fault address and program
5.18 + counter, returning a flexpage to provide such a mapping. */
5.19 +
5.20 + [opcode(L4_PROTO_PAGE_FAULT)]
5.21 + void page_fault(in l4_umword_t pfa, in l4_umword_t pc, out fpage region);
5.22 +};
6.1 --- a/test_files/Makefile Tue Apr 26 16:34:54 2022 +0200
6.2 +++ b/test_files/Makefile Tue Apr 26 16:36:17 2022 +0200
6.3 @@ -4,12 +4,21 @@
6.4 E2ACCESS_DIR = $(PKGDIR)/../libe2access/host
6.5 TARGET = $(PKGDIR)/../conf/e2test.fs
6.6
6.7 +PROGRAMS = $(PKGDIR_OBJ)/_programs
6.8 +
6.9 include $(L4DIR)/mk/Makeconf
6.10 +include $(OBJ_BASE)/l4defs.mk.inc
6.11 +
6.12 +PROGRAMS_DIR = $(PKGDIR_OBJ)/programs/OBJ-$(L4_SYSTEM)-l4f
6.13
6.14 # Special rules to build the test filesystem.
6.15
6.16 -all:: $(TARGET)
6.17 +all:: $(TARGET) $(PROGRAMS)
6.18
6.19 -$(TARGET):
6.20 +$(TARGET): $(PROGRAMS)
6.21 make -C $(E2ACCESS_DIR)
6.22 - $(PKGDIR)/mk_e2test.sh -q $(PKGDIR) $(E2ACCESS_DIR) $@
6.23 + $(PKGDIR)/mk_e2test.sh -q $(PKGDIR) $(PROGRAMS_DIR) $(E2ACCESS_DIR) $@
6.24 +
6.25 +$(PROGRAMS):
6.26 + make -C $(PKGDIR)/programs $(MKFLAGS)
6.27 + touch $@
7.1 --- a/test_files/mk_e2test.sh Tue Apr 26 16:34:54 2022 +0200
7.2 +++ b/test_files/mk_e2test.sh Tue Apr 26 16:36:17 2022 +0200
7.3 @@ -31,14 +31,16 @@
7.4 fi
7.5
7.6 PKGDIR=$(realpath "$1")
7.7 -E2ACCESS_DIR=$(realpath "$2")
7.8 -TARGET=$(realpath "$3")
7.9 +PROGRAMS_DIR=$(realpath "$2")
7.10 +E2ACCESS_DIR=$(realpath "$3")
7.11 +TARGET=$(realpath "$4")
7.12
7.13 -if [ ! -e "$PKGDIR" ] || [ ! -e "$E2ACCESS_DIR" ] || [ ! "$TARGET" ] ; then
7.14 +if [ ! -e "$PKGDIR" ] || [ ! -e "$PROGRAMS_DIR" ] || [ ! -e "$E2ACCESS_DIR" ] || [ ! "$TARGET" ] ; then
7.15 cat 1>&2 <<EOF
7.16 -Usage: $PROGNAME [ -q ] <package directory> <e2access directory> <target>
7.17 +Usage: $PROGNAME [ -q ] <package directory> <programs directory> <e2access directory> <target>
7.18
7.19 Package directory: $PKGDIR
7.20 +Programs directory: $PROGRAMS_DIR
7.21 e2access directory: $E2ACCESS_DIR
7.22 Target filesystem: $TARGET
7.23 EOF
7.24 @@ -102,10 +104,14 @@
7.25
7.26 cd ..
7.27
7.28 -# Put a file in the directory above.
7.29 +# Put file in the created home directory.
7.30
7.31 cp "$PKGDIR/../docs/LICENCE.txt" .
7.32
7.33 +# Put some programs in the same place.
7.34 +
7.35 +cp "$PROGRAMS_DIR/dstest_"* .
7.36 +
7.37 # Leave the filesystem root.
7.38
7.39 cd ../..
7.40 @@ -124,7 +130,7 @@
7.41
7.42 # Add the directories and files to the image.
7.43
7.44 -for DIR in home/paulb/private home/paulb/public home/paulb/shared home/paulb/many home/paulb ; do
7.45 +for DIR in home/paulb home/paulb/private home/paulb/public home/paulb/shared home/paulb/many ; do
7.46 e2access mkdir "$DIR"
7.47 e2access copy-in $(find "$DIR" -maxdepth 1 -type f | sort) "$DIR"
7.48 done
8.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
8.2 +++ b/test_files/programs/Makefile Tue Apr 26 16:36:17 2022 +0200
8.3 @@ -0,0 +1,12 @@
8.4 +PKGDIR ?= ..
8.5 +L4DIR ?= $(PKGDIR)/../../..
8.6 +
8.7 +TARGET = dstest_exec_payload
8.8 +
8.9 +MODE = static
8.10 +
8.11 +SRC_C_dstest_exec_payload = exec_payload.c
8.12 +
8.13 +REQUIRES_LIBS = libc
8.14 +
8.15 +include $(L4DIR)/mk/prog.mk
9.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
9.2 +++ b/test_files/programs/exec_payload.c Tue Apr 26 16:36:17 2022 +0200
9.3 @@ -0,0 +1,33 @@
9.4 +/*
9.5 + * A test of executing code in a new task.
9.6 + *
9.7 + * Copyright (C) 2022 Paul Boddie <paul@boddie.org.uk>
9.8 + *
9.9 + * This program is free software; you can redistribute it and/or
9.10 + * modify it under the terms of the GNU General Public License as
9.11 + * published by the Free Software Foundation; either version 2 of
9.12 + * the License, or (at your option) any later version.
9.13 + *
9.14 + * This program is distributed in the hope that it will be useful,
9.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
9.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9.17 + * GNU General Public License for more details.
9.18 + *
9.19 + * You should have received a copy of the GNU General Public License
9.20 + * along with this program; if not, write to the Free Software
9.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
9.22 + * Boston, MA 02110-1301, USA
9.23 + */
9.24 +
9.25 +#include <stdio.h>
9.26 +
9.27 +
9.28 +
9.29 +int main(int argc, char *argv[])
9.30 +{
9.31 + printf("Hello from exec_payload.c!\n");
9.32 + return 0;
9.33 +}
9.34 +
9.35 +/* vim: tabstop=2 expandtab shiftwidth=2
9.36 +*/
10.1 --- a/tests/Makefile Tue Apr 26 16:34:54 2022 +0200
10.2 +++ b/tests/Makefile Tue Apr 26 16:36:17 2022 +0200
10.3 @@ -12,10 +12,35 @@
10.4 dstest_file_rename \
10.5 dstest_host_client \
10.6 dstest_pipe_client \
10.7 - dstest_test_client
10.8 + dstest_test_client \
10.9 + dstest_map_test \
10.10 + dstest_exec
10.11
10.12 MODE = static
10.13
10.14 +# Locations for interface input and generated output.
10.15 +
10.16 +IDL_DIR = $(PKGDIR)/../libsystypes/idl
10.17 +IDL_MK_DIR = $(L4DIR)/idl4re/mk
10.18 +IDL_BUILD_DIR = .
10.19 +IDL_EXPORT_DIR = .
10.20 +
10.21 +include $(IDL_MK_DIR)/idl.mk
10.22 +
10.23 +# Individual interfaces.
10.24 +
10.25 +CLIENT_INTERFACES_CC = system_pager
10.26 +
10.27 +SERVER_INTERFACES_CC = system_pager
10.28 +
10.29 +# Generated and plain source files.
10.30 +
10.31 +CLIENT_INTERFACES_SRC_CC = $(call interfaces_to_client_cc,$(CLIENT_INTERFACES_CC))
10.32 +
10.33 +SERVER_INTERFACES_SRC_CC = $(call interfaces_to_server_cc,$(SERVER_INTERFACES_CC))
10.34 +
10.35 +# Normal source files.
10.36 +
10.37 SRC_CC_dstest_block_client = dstest_block_client.cc
10.38
10.39 SRC_CC_dstest_block_client_simple = dstest_block_client_simple.cc
10.40 @@ -40,6 +65,14 @@
10.41
10.42 SRC_CC_dstest_test_client = dstest_test_client.cc
10.43
10.44 +PLAIN_SRC_CC_dstest_exec = dstest_exec.cc
10.45 +SRC_CC_dstest_exec = $(PLAIN_SRC_CC_dstest_exec) $(SERVER_INTERFACES_SRC_CC) \
10.46 + $(CLIENT_INTERFACES_SRC_CC)
10.47 +
10.48 REQUIRES_LIBS = l4re_c-util libfsclient libmem libipc libstdc++ libsystypes libe2access_blockserver
10.49 +PRIVATE_INCDIR = $(IDL_BUILD_DIR) $(IDL_EXPORT_DIR)
10.50
10.51 include $(L4DIR)/mk/prog.mk
10.52 +include $(IDL_MK_DIR)/interface_rules.mk
10.53 +
10.54 +$(PLAIN_SRC_CC_dstest_exec): $(SERVER_INTERFACES_SRC_CC) $(CLIENT_INTERFACES_SRC_CC)
11.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
11.2 +++ b/tests/dstest_exec.cc Tue Apr 26 16:36:17 2022 +0200
11.3 @@ -0,0 +1,414 @@
11.4 +/*
11.5 + * Support for executing code in new tasks and threads.
11.6 + *
11.7 + * Copyright (C) 2022 Paul Boddie <paul@boddie.org.uk>
11.8 + *
11.9 + * This program is free software; you can redistribute it and/or
11.10 + * modify it under the terms of the GNU General Public License as
11.11 + * published by the Free Software Foundation; either version 2 of
11.12 + * the License, or (at your option) any later version.
11.13 + *
11.14 + * This program is distributed in the hope that it will be useful,
11.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
11.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11.17 + * GNU General Public License for more details.
11.18 + *
11.19 + * You should have received a copy of the GNU General Public License
11.20 + * along with this program; if not, write to the Free Software
11.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
11.22 + * Boston, MA 02110-1301, USA
11.23 + */
11.24 +
11.25 +#include <l4/re/env.h>
11.26 +#include <l4/sys/err.h>
11.27 +#include <l4/sys/factory.h>
11.28 +#include <l4/sys/task.h>
11.29 +#include <l4/sys/thread.h>
11.30 +#include <l4/util/bitops.h> /* l4util_log2 */
11.31 +
11.32 +#include <fsclient/client.h>
11.33 +#include <ipc/cap_alloc.h>
11.34 +#include <ipc/mem_ipc.h>
11.35 +#include <ipc/server.h>
11.36 +#include <systypes/fcntl.h>
11.37 +
11.38 +#include <stdio.h>
11.39 +#include <stdlib.h>
11.40 +#include <string.h>
11.41 +
11.42 +#include <pthread-l4.h>
11.43 +#include <pthread.h>
11.44 +
11.45 +#include "system_pager_interface.h"
11.46 +#include "system_pager_server.h"
11.47 +
11.48 +
11.49 +
11.50 +/* A simple system pager. */
11.51 +
11.52 +class ExecPager : public SystemPager
11.53 +{
11.54 +public:
11.55 + l4_addr_t buf, buf_start;
11.56 + unsigned int buf_log2size;
11.57 +
11.58 + virtual long exception(l4_exc_regs_t regs,
11.59 + l4_snd_fpage_t *region);
11.60 +
11.61 + virtual long page_fault(l4_umword_t pfa, l4_umword_t pc,
11.62 + l4_snd_fpage_t *region);
11.63 +};
11.64 +
11.65 +long ExecPager::exception(l4_exc_regs_t regs, l4_snd_fpage_t *region)
11.66 +{
11.67 + (void) region;
11.68 +
11.69 + printf("exception(...) -> pfa = %lx, pc = %lx\n", l4_utcb_exc_pfa(®s), l4_utcb_exc_pc(®s));
11.70 + return L4_EOK;
11.71 +}
11.72 +
11.73 +long ExecPager::page_fault(l4_umword_t pfa, l4_umword_t pc, l4_snd_fpage_t *region)
11.74 +{
11.75 + l4_umword_t addr = pfa & ~7UL, flags = pfa & 7;
11.76 +
11.77 + printf("page_fault(%lx, %lx) -> %lx (%lx)...\n", pfa, pc, addr, flags);
11.78 +
11.79 + if ((addr >= buf_start) && (addr < buf_start + (1UL << buf_log2size)))
11.80 + {
11.81 + region->fpage = l4_fpage(buf, buf_log2size, L4_FPAGE_RX);
11.82 + region->snd_base = buf_start;
11.83 +
11.84 + return L4_EOK;
11.85 + }
11.86 +
11.87 + return -L4_ENOMEM;
11.88 +}
11.89 +
11.90 +
11.91 +
11.92 +static ExecPager exec_pager;
11.93 +
11.94 +static void init_pager(ipc_server_config_type *config, l4_addr_t buf,
11.95 + unsigned int buf_log2size, l4_addr_t buf_start)
11.96 +{
11.97 + exec_pager.buf = buf;
11.98 + exec_pager.buf_log2size = buf_log2size;
11.99 + exec_pager.buf_start = buf_start;
11.100 +
11.101 + ipc_server_init_config(config);
11.102 +
11.103 + config->expected_items = SystemPager_expected_items;
11.104 + config->handler = (ipc_server_handler_type) handle_SystemPager;
11.105 + config->handler_obj = static_cast<SystemPager *>(&exec_pager);
11.106 +}
11.107 +
11.108 +static long start_pager(ipc_server_config_type *config, pthread_t thread)
11.109 +{
11.110 + config->config_thread = 1;
11.111 + config->thread = pthread_l4_cap(thread);
11.112 +
11.113 + printf("Starting pager thread...\n");
11.114 + return ipc_server_start_config(config);
11.115 +}
11.116 +
11.117 +
11.118 +
11.119 +/* UTCB properties.
11.120 + See: moe/server/src/loader.cc */
11.121 +
11.122 +enum ipc_exec_utcb
11.123 +{
11.124 + Default_max_threads = 16,
11.125 +#ifdef ARCH_mips
11.126 + Utcb_area_start = 0x73000000,
11.127 +#else
11.128 + Utcb_area_start = 0xb3000000,
11.129 +#endif
11.130 +};
11.131 +
11.132 +
11.133 +
11.134 +static int find_region_exp(offset_t size)
11.135 +{
11.136 + int exp = l4util_log2(size);
11.137 +
11.138 + if ((1UL << exp) < size)
11.139 + return exp + 1;
11.140 + else
11.141 + return exp;
11.142 +}
11.143 +
11.144 +static offset_t find_region_size(offset_t size)
11.145 +{
11.146 + return 1 << find_region_exp(size);
11.147 +}
11.148 +
11.149 +int main(int argc, char *argv[])
11.150 +{
11.151 + long err;
11.152 +
11.153 + if (argc < 2)
11.154 + {
11.155 + printf("Need a program to run.\n");
11.156 + return 1;
11.157 + }
11.158 +
11.159 + /* Allocate capabilities for the task and thread. */
11.160 +
11.161 + l4_cap_idx_t task, thread;
11.162 +
11.163 + task = ipc_cap_alloc();
11.164 +
11.165 + if (l4_is_invalid_cap(task))
11.166 + {
11.167 + printf("Could not allocate task.\n");
11.168 + return 1;
11.169 + }
11.170 +
11.171 + thread = ipc_cap_alloc();
11.172 +
11.173 + if (l4_is_invalid_cap(thread))
11.174 + {
11.175 + printf("Could not allocate thread.\n");
11.176 + return 1;
11.177 + }
11.178 +
11.179 + /* Obtain the payload as a dataspace. */
11.180 +
11.181 + file_t *file = client_open(argv[1], O_RDONLY);
11.182 +
11.183 + if (file == NULL)
11.184 + {
11.185 + printf("Could not read file: %s\n", argv[1]);
11.186 + return 1;
11.187 + }
11.188 +
11.189 + /* Copy the entire payload to a new dataspace. */
11.190 +
11.191 + char *buf;
11.192 + offset_t nread;
11.193 + offset_t region_size = find_region_size(4000000);
11.194 + l4re_ds_t region_ds;
11.195 +
11.196 + err = ipc_allocate_align(region_size, L4RE_RM_F_SEARCH_ADDR | L4RE_RM_F_RWX,
11.197 + find_region_exp(4000000), (void **) &buf, ®ion_ds);
11.198 +
11.199 + if (err)
11.200 + {
11.201 + printf("Could not reserve memory.\n");
11.202 + return 1;
11.203 + }
11.204 +
11.205 + printf("Reading from file into %p.\n", buf);
11.206 +
11.207 + nread = client_read(file, buf, 4000000);
11.208 +
11.209 + printf("Read %ld from file.\n", nread);
11.210 +
11.211 + if (memcmp(buf + 0xae3, "\x31\xed", 2))
11.212 + {
11.213 + printf("Did not find expected instructions at start.\n");
11.214 + return 1;
11.215 + }
11.216 +
11.217 + /* UTCB location and size. */
11.218 +
11.219 + l4_addr_t utcb_start = Utcb_area_start;
11.220 + int utcb_log2size = find_region_exp(Default_max_threads * L4_UTCB_OFFSET);
11.221 +
11.222 + /* Round up to at least one page. */
11.223 +
11.224 + if (utcb_log2size < L4_PAGESHIFT)
11.225 + utcb_log2size = L4_PAGESHIFT;
11.226 +
11.227 + /* KIP allocation. */
11.228 +
11.229 + l4_addr_t kip_start = (l4_addr_t) l4re_kip();
11.230 +
11.231 + printf("KIP at %lx.\n", kip_start);
11.232 +
11.233 + /* Create a new task and thread. */
11.234 +
11.235 + l4_fpage_t utcb_fpage = l4_fpage(utcb_start, utcb_log2size, 0);
11.236 +
11.237 + err = l4_error(l4_factory_create_task(l4re_env()->factory, task, utcb_fpage));
11.238 +
11.239 + if (err)
11.240 + {
11.241 + printf("Could not create task.\n");
11.242 + return 1;
11.243 + }
11.244 +
11.245 + err = l4_error(l4_factory_create_thread(l4re_env()->factory, thread));
11.246 +
11.247 + if (err)
11.248 + {
11.249 + printf("Could not create thread.\n");
11.250 + return 1;
11.251 + }
11.252 +
11.253 + /* Start the pager. */
11.254 +
11.255 + ipc_server_config_type config;
11.256 + pthread_t pager_thread;
11.257 + pthread_attr_t attr;
11.258 +
11.259 + pthread_attr_init(&attr);
11.260 + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
11.261 +
11.262 + init_pager(&config, (l4_addr_t) buf, find_region_exp(file->size), 0x1000000);
11.263 +
11.264 + err = pthread_create(&pager_thread, &attr, ipc_server_start_mainloop, &config);
11.265 +
11.266 + if (err)
11.267 + {
11.268 + printf("Could not start pager thread.\n");
11.269 + return 1;
11.270 + }
11.271 +
11.272 + err = start_pager(&config, pager_thread);
11.273 +
11.274 + if (err)
11.275 + {
11.276 + printf("Could not start pager.\n");
11.277 + return 1;
11.278 + }
11.279 +
11.280 + /* Map the pager capability into the region manager/mapper slot. */
11.281 +
11.282 + err = l4_error(l4_task_map(task, L4RE_THIS_TASK_CAP,
11.283 + l4_obj_fpage(config.server, 0, L4_CAP_FPAGE_RWS),
11.284 + l4_map_obj_control(0x10 << L4_CAP_SHIFT, L4_MAP_ITEM_MAP)));
11.285 +
11.286 + if (err)
11.287 + {
11.288 + printf("Could not map pager capability into task.\n");
11.289 + return 1;
11.290 + }
11.291 +
11.292 + /* Map the KIP into the task. */
11.293 +
11.294 + err = l4_error(l4_task_map(task, L4RE_THIS_TASK_CAP,
11.295 + l4_fpage(kip_start, L4_PAGESHIFT, L4_FPAGE_RX),
11.296 + kip_start));
11.297 +
11.298 + if (err)
11.299 + {
11.300 + printf("Could not map KIP into task.\n");
11.301 + return 1;
11.302 + }
11.303 +
11.304 + err = l4_error(l4_task_map(task, L4RE_THIS_TASK_CAP,
11.305 + l4_obj_fpage(task, 0, L4_CAP_FPAGE_RWS),
11.306 + l4_map_obj_control(L4_BASE_TASK_CAP, L4_MAP_ITEM_MAP)));
11.307 +
11.308 + if (err)
11.309 + {
11.310 + printf("Could not map task capability into task.\n");
11.311 + return 1;
11.312 + }
11.313 +
11.314 + err = l4_error(l4_task_map(task, L4RE_THIS_TASK_CAP,
11.315 + l4_obj_fpage(thread, 0, L4_CAP_FPAGE_RWS),
11.316 + l4_map_obj_control(L4_BASE_THREAD_CAP, L4_MAP_ITEM_MAP)));
11.317 +
11.318 + if (err)
11.319 + {
11.320 + printf("Could not map thread capability into task.\n");
11.321 + return 1;
11.322 + }
11.323 +
11.324 + err = l4_error(l4_task_map(task, L4RE_THIS_TASK_CAP,
11.325 + l4_obj_fpage(l4re_env()->factory, 0, L4_CAP_FPAGE_RWS),
11.326 + l4_map_obj_control(L4_BASE_FACTORY_CAP, L4_MAP_ITEM_MAP)));
11.327 +
11.328 + if (err)
11.329 + {
11.330 + printf("Could not map factory capability into task.\n");
11.331 + return 1;
11.332 + }
11.333 +
11.334 + err = l4_error(l4_task_map(task, L4RE_THIS_TASK_CAP,
11.335 + l4_obj_fpage(l4re_env()->log, 0, L4_CAP_FPAGE_RWS),
11.336 + l4_map_obj_control(L4_BASE_LOG_CAP, L4_MAP_ITEM_MAP)));
11.337 +
11.338 + if (err)
11.339 + {
11.340 + printf("Could not map log capability into task.\n");
11.341 + return 1;
11.342 + }
11.343 +
11.344 + err = l4_error(l4_task_map(task, L4RE_THIS_TASK_CAP,
11.345 + l4_obj_fpage(l4re_env()->scheduler, 0, L4_CAP_FPAGE_RWS),
11.346 + l4_map_obj_control(L4_BASE_SCHEDULER_CAP, L4_MAP_ITEM_MAP)));
11.347 +
11.348 + if (err)
11.349 + {
11.350 + printf("Could not map scheduler capability into task.\n");
11.351 + return 1;
11.352 + }
11.353 +
11.354 + /* Configure the thread with the region manager acting as pager and exception
11.355 + handler. The UTCB will be situated at an address supported by a dataspace
11.356 + attached to the new task. */
11.357 +
11.358 + printf("Configure thread...\n");
11.359 +
11.360 + l4_thread_control_start();
11.361 + l4_thread_control_pager(0x10 << L4_CAP_SHIFT);
11.362 + l4_thread_control_exc_handler(0x10 << L4_CAP_SHIFT);
11.363 + l4_thread_control_bind((l4_utcb_t *) utcb_start, task);
11.364 + err = l4_error(l4_thread_control_commit(thread));
11.365 +
11.366 + if (err)
11.367 + {
11.368 + printf("Could not configure thread.\n");
11.369 + return 1;
11.370 + }
11.371 +
11.372 + /* Map the payload into the new task. */
11.373 +
11.374 + printf("Map %p with size %ld (2 ** %d).\n", buf, file->size, find_region_exp(file->size));
11.375 +
11.376 + l4_fpage_t payload_fpage = l4_fpage((l4_addr_t) buf, find_region_exp(file->size), L4_FPAGE_RX);
11.377 +
11.378 + err = l4_error(l4_task_map(task, L4RE_THIS_TASK_CAP, payload_fpage, 0x1000000));
11.379 +
11.380 + if (err)
11.381 + {
11.382 + printf("Could not map payload into task.\n");
11.383 + return 1;
11.384 + }
11.385 +
11.386 + /* Start the new thread. */
11.387 +
11.388 + printf("Schedule thread...\n");
11.389 +
11.390 + err = l4_error(l4_thread_ex_regs(thread, 0x1000ae3, 0x2000000 /* stack top */, 0));
11.391 +
11.392 + if (err)
11.393 + {
11.394 + printf("Could not set thread registers.\n");
11.395 + return 1;
11.396 + }
11.397 +
11.398 + printf("Run thread...\n");
11.399 +
11.400 + l4_sched_param_t sp = l4_sched_param(L4RE_MAIN_THREAD_PRIO);
11.401 +
11.402 + err = l4_error(l4_scheduler_run_thread(l4re_env()->scheduler, thread, &sp));
11.403 +
11.404 + if (err)
11.405 + {
11.406 + printf("Could not run thread.\n");
11.407 + return 1;
11.408 + }
11.409 +
11.410 + printf("Finished.\n");
11.411 + while (1);
11.412 +
11.413 + return 0;
11.414 +}
11.415 +
11.416 +/* vim: tabstop=2 expandtab shiftwidth=2
11.417 +*/