1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/libexec/Control Tue May 10 22:39:15 2022 +0200
1.3 @@ -0,0 +1,3 @@
1.4 +requires: libstdc++ libc libmem libipc libsystypes libfsclient
1.5 +provides: libexec
1.6 +maintainer: paul@boddie.org.uk
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2.2 +++ b/libexec/Makefile Tue May 10 22:39:15 2022 +0200
2.3 @@ -0,0 +1,4 @@
2.4 +PKGDIR ?= .
2.5 +L4DIR ?= $(PKGDIR)/../../..
2.6 +
2.7 +include $(L4DIR)/mk/subdir.mk
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
3.2 +++ b/libexec/include/Makefile Tue May 10 22:39:15 2022 +0200
3.3 @@ -0,0 +1,7 @@
3.4 +PKGDIR ?= ..
3.5 +L4DIR ?= $(PKGDIR)/../../..
3.6 +
3.7 +PKGNAME = libexec
3.8 +CONTRIB_HEADERS = 1
3.9 +
3.10 +include $(L4DIR)/mk/include.mk
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
4.2 +++ b/libexec/include/exec/mapped_region.h Tue May 10 22:39:15 2022 +0200
4.3 @@ -0,0 +1,51 @@
4.4 +/*
4.5 + * Mapped memory region support.
4.6 + *
4.7 + * Copyright (C) 2022 Paul Boddie <paul@boddie.org.uk>
4.8 + *
4.9 + * This program is free software; you can redistribute it and/or
4.10 + * modify it under the terms of the GNU General Public License as
4.11 + * published by the Free Software Foundation; either version 2 of
4.12 + * the License, or (at your option) any later version.
4.13 + *
4.14 + * This program is distributed in the hope that it will be useful,
4.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
4.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4.17 + * GNU General Public License for more details.
4.18 + *
4.19 + * You should have received a copy of the GNU General Public License
4.20 + * along with this program; if not, write to the Free Software
4.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
4.22 + * Boston, MA 02110-1301, USA
4.23 + */
4.24 +
4.25 +#pragma once
4.26 +
4.27 +#include <l4/sys/types.h>
4.28 +
4.29 +
4.30 +
4.31 +/* A mapped region abstraction. */
4.32 +
4.33 +class MappedRegion
4.34 +{
4.35 +public:
4.36 + l4_addr_t start;
4.37 + unsigned int log2size;
4.38 + l4_umword_t flags;
4.39 + l4_addr_t map_start;
4.40 +
4.41 + explicit MappedRegion()
4.42 + : start(0), log2size(0), flags(0), map_start(0)
4.43 + {
4.44 + }
4.45 +
4.46 + explicit MappedRegion(l4_addr_t start, unsigned int log2size,
4.47 + l4_umword_t flags, l4_addr_t map_start)
4.48 + : start(start), log2size(log2size), flags(flags), map_start(map_start)
4.49 + {
4.50 + }
4.51 +};
4.52 +
4.53 +/* vim: tabstop=2 expandtab shiftwidth=2
4.54 +*/
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
5.2 +++ b/libexec/include/exec/process.h Tue May 10 22:39:15 2022 +0200
5.3 @@ -0,0 +1,99 @@
5.4 +/*
5.5 + * Support for initialising programs in new tasks and threads.
5.6 + *
5.7 + * Copyright (C) 2022 Paul Boddie <paul@boddie.org.uk>
5.8 + *
5.9 + * This program is free software; you can redistribute it and/or
5.10 + * modify it under the terms of the GNU General Public License as
5.11 + * published by the Free Software Foundation; either version 2 of
5.12 + * the License, or (at your option) any later version.
5.13 + *
5.14 + * This program is distributed in the hope that it will be useful,
5.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
5.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
5.17 + * GNU General Public License for more details.
5.18 + *
5.19 + * You should have received a copy of the GNU General Public License
5.20 + * along with this program; if not, write to the Free Software
5.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
5.22 + * Boston, MA 02110-1301, USA
5.23 + */
5.24 +
5.25 +#pragma once
5.26 +
5.27 +#include <l4/re/env.h>
5.28 +#include <l4/re/l4aux.h>
5.29 +#include <l4/sys/factory.h>
5.30 +#include <l4/sys/task.h>
5.31 +#include <l4/sys/thread.h>
5.32 +
5.33 +#include <exec/stack.h>
5.34 +
5.35 +
5.36 +
5.37 +/* UTCB properties.
5.38 + See: moe/server/src/loader.cc */
5.39 +
5.40 +enum exec_utcb
5.41 +{
5.42 + Default_max_threads = 16,
5.43 +#ifdef ARCH_mips
5.44 + Utcb_area_start = 0x73000000,
5.45 +#else
5.46 + Utcb_area_start = 0xb3000000,
5.47 +#endif
5.48 +};
5.49 +
5.50 +
5.51 +
5.52 +/* Capability index definitions. */
5.53 +
5.54 +enum exec_task_caps
5.55 +{
5.56 + L4_EXEC_PAGER_CAP = 0x10 << L4_CAP_SHIFT,
5.57 + L4_EXEC_RM_CAP = 0x11 << L4_CAP_SHIFT,
5.58 + L4_EXEC_MA_CAP = 0x12 << L4_CAP_SHIFT,
5.59 + L4_EXEC_KIP_CAP = 0x14 << L4_CAP_SHIFT,
5.60 +};
5.61 +
5.62 +/* The default first free capability index must follow those above. */
5.63 +
5.64 +enum exec_task_cap_indexes
5.65 +{
5.66 + L4_EXEC_FIRST_FREE_CAP_INDEX = 0x15,
5.67 +};
5.68 +
5.69 +
5.70 +
5.71 +/* A process abstraction. */
5.72 +
5.73 +class Process
5.74 +{
5.75 +protected:
5.76 + l4_cap_idx_t _task = L4_INVALID_CAP;
5.77 +
5.78 + /* UTCB details. */
5.79 +
5.80 + l4_addr_t _utcb_start;
5.81 +
5.82 + /* Common environment details. */
5.83 +
5.84 + l4re_aux_t _aux;
5.85 + l4re_env_t _env;
5.86 +
5.87 + /* Task and thread initialisation. */
5.88 +
5.89 + long create_task();
5.90 +
5.91 + long create_thread(l4_cap_idx_t *thread);
5.92 +
5.93 +public:
5.94 + explicit Process();
5.95 +
5.96 + long configure(l4_cap_idx_t server);
5.97 +
5.98 + long thread_start(l4_addr_t program_start, Stack &st);
5.99 +};
5.100 +
5.101 +/* vim: tabstop=2 expandtab shiftwidth=2
5.102 +*/
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
6.2 +++ b/libexec/include/exec/segment.h Tue May 10 22:39:15 2022 +0200
6.3 @@ -0,0 +1,81 @@
6.4 +/*
6.5 + * Program memory segment support.
6.6 + *
6.7 + * Copyright (C) 2022 Paul Boddie <paul@boddie.org.uk>
6.8 + *
6.9 + * This program is free software; you can redistribute it and/or
6.10 + * modify it under the terms of the GNU General Public License as
6.11 + * published by the Free Software Foundation; either version 2 of
6.12 + * the License, or (at your option) any later version.
6.13 + *
6.14 + * This program is distributed in the hope that it will be useful,
6.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
6.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
6.17 + * GNU General Public License for more details.
6.18 + *
6.19 + * You should have received a copy of the GNU General Public License
6.20 + * along with this program; if not, write to the Free Software
6.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
6.22 + * Boston, MA 02110-1301, USA
6.23 + */
6.24 +
6.25 +#pragma once
6.26 +
6.27 +#include <l4/re/c/dataspace.h>
6.28 +#include <l4/re/c/rm.h>
6.29 +
6.30 +#include <fsclient/client.h>
6.31 +
6.32 +#include <exec/mapped_region.h>
6.33 +
6.34 +
6.35 +
6.36 +/* Program segment abstraction. */
6.37 +
6.38 +class Segment
6.39 +{
6.40 +protected:
6.41 + MappedRegion _region;
6.42 +
6.43 +public:
6.44 + /* Allocated memory. */
6.45 +
6.46 + char *buf;
6.47 + l4re_ds_t ds;
6.48 +
6.49 + /* Segment base and corresponding region base. */
6.50 +
6.51 + l4_addr_t base, region_base;
6.52 +
6.53 + /* Segment size and corresponding region size. */
6.54 +
6.55 + offset_t size, region_size;
6.56 +
6.57 + /* Offset of segment content within the region. */
6.58 +
6.59 + offset_t region_offset;
6.60 +
6.61 + /* Access flags. */
6.62 +
6.63 + l4re_rm_flags_t flags;
6.64 +
6.65 + /* File access details. */
6.66 +
6.67 + offset_t file_offset, file_contents;
6.68 +
6.69 + explicit Segment(offset_t base, offset_t size, l4re_rm_flags_t flags,
6.70 + offset_t file_offset = 0, offset_t file_contents = 0);
6.71 +
6.72 + long allocate();
6.73 +
6.74 + long fill(file_t *file);
6.75 +
6.76 + MappedRegion ®ion();
6.77 +
6.78 + l4_addr_t region_address(char *address);
6.79 +
6.80 + l4_addr_t region_address(l4_addr_t address);
6.81 +};
6.82 +
6.83 +/* vim: tabstop=2 expandtab shiftwidth=2
6.84 +*/
7.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
7.2 +++ b/libexec/include/exec/stack.h Tue May 10 22:39:15 2022 +0200
7.3 @@ -0,0 +1,106 @@
7.4 +/*
7.5 + * Stack support for new tasks and threads.
7.6 + *
7.7 + * Copyright (C) 2022 Paul Boddie <paul@boddie.org.uk>
7.8 + *
7.9 + * This program is free software; you can redistribute it and/or
7.10 + * modify it under the terms of the GNU General Public License as
7.11 + * published by the Free Software Foundation; either version 2 of
7.12 + * the License, or (at your option) any later version.
7.13 + *
7.14 + * This program is distributed in the hope that it will be useful,
7.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
7.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
7.17 + * GNU General Public License for more details.
7.18 + *
7.19 + * You should have received a copy of the GNU General Public License
7.20 + * along with this program; if not, write to the Free Software
7.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
7.22 + * Boston, MA 02110-1301, USA
7.23 + */
7.24 +
7.25 +#pragma once
7.26 +
7.27 +#include <l4/re/env.h>
7.28 +#include <l4/re/l4aux.h>
7.29 +
7.30 +#include <exec/segment.h>
7.31 +
7.32 +
7.33 +
7.34 +/* A stack abstraction. */
7.35 +
7.36 +class Stack
7.37 +{
7.38 +protected:
7.39 +
7.40 + /* Auxiliary vector key-value pair. */
7.41 +
7.42 + struct auxv_entry
7.43 + {
7.44 + l4_umword_t key, value;
7.45 + };
7.46 +
7.47 + /* Program segment holding the stack contents. */
7.48 +
7.49 + Segment &_segment;
7.50 +
7.51 + /* Next element pointer. */
7.52 +
7.53 + l4_umword_t *_element;
7.54 +
7.55 + /* Stack section properties. */
7.56 +
7.57 + l4_addr_t _caps;
7.58 + char *_arg_top, *_env_top;
7.59 + char **_argv;
7.60 + char *_auxv_end;
7.61 + int _env_entries;
7.62 +
7.63 + /* L4Re auxiliary and environment regions. */
7.64 +
7.65 + l4re_aux_t *_aux;
7.66 + l4re_env_t *_env;
7.67 +
7.68 + /* Stack pointer start address. */
7.69 +
7.70 + l4_addr_t _start;
7.71 +
7.72 + /* Internal stack population methods. */
7.73 +
7.74 + void push_cap_entries(l4re_env_cap_entry_t *entries);
7.75 +
7.76 + void push_string(char *s);
7.77 +
7.78 + void push_env(char *envp[]);
7.79 +
7.80 + void push_args(int argc, char *argv[]);
7.81 +
7.82 + void push_l4re_aux();
7.83 +
7.84 + void push_l4re_env();
7.85 +
7.86 + void push_auxv();
7.87 +
7.88 + offset_t write_address(char *arg, char **addr, char *s);
7.89 +
7.90 + void push_envp(char *envp[]);
7.91 +
7.92 + void push_argv(int argc, char *argv[]);
7.93 +
7.94 + l4_addr_t align_stack();
7.95 +
7.96 +public:
7.97 + explicit Stack(Segment &segment);
7.98 +
7.99 + void set_l4re_aux(l4re_aux_t *aux);
7.100 +
7.101 + void set_l4re_env(l4re_env_t *env);
7.102 +
7.103 + void populate(int argc, char *argv[], char *envp[]);
7.104 +
7.105 + l4_addr_t start_address();
7.106 +};
7.107 +
7.108 +/* vim: tabstop=2 expandtab shiftwidth=2
7.109 +*/
8.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
8.2 +++ b/libexec/lib/Makefile Tue May 10 22:39:15 2022 +0200
8.3 @@ -0,0 +1,4 @@
8.4 +PKGDIR ?= ..
8.5 +L4DIR ?= $(PKGDIR)/../../..
8.6 +
8.7 +include $(L4DIR)/mk/subdir.mk
9.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
9.2 +++ b/libexec/lib/src/Makefile Tue May 10 22:39:15 2022 +0200
9.3 @@ -0,0 +1,12 @@
9.4 +PKGDIR ?= ../..
9.5 +L4DIR ?= $(PKGDIR)/../../..
9.6 +
9.7 +TARGET = libexec.a libexec.so
9.8 +PC_FILENAME = libexec
9.9 +SRC_CC = process.cc segment.cc stack.cc
9.10 +REQUIRES_LIBS = l4re_c-util libmem libipc libstdc++ libsystypes libfsclient
9.11 +
9.12 +PRIVATE_INCDIR += $(PKGDIR)/include/exec
9.13 +CONTRIB_INCDIR = libexec
9.14 +
9.15 +include $(L4DIR)/mk/lib.mk
10.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
10.2 +++ b/libexec/lib/src/process.cc Tue May 10 22:39:15 2022 +0200
10.3 @@ -0,0 +1,193 @@
10.4 +/*
10.5 + * Support for initialising programs in new tasks and threads.
10.6 + *
10.7 + * Copyright (C) 2022 Paul Boddie <paul@boddie.org.uk>
10.8 + *
10.9 + * This program is free software; you can redistribute it and/or
10.10 + * modify it under the terms of the GNU General Public License as
10.11 + * published by the Free Software Foundation; either version 2 of
10.12 + * the License, or (at your option) any later version.
10.13 + *
10.14 + * This program is distributed in the hope that it will be useful,
10.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
10.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10.17 + * GNU General Public License for more details.
10.18 + *
10.19 + * You should have received a copy of the GNU General Public License
10.20 + * along with this program; if not, write to the Free Software
10.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
10.22 + * Boston, MA 02110-1301, USA
10.23 + */
10.24 +
10.25 +#include <l4/sys/err.h>
10.26 +#include <l4/sys/scheduler.h>
10.27 +
10.28 +#include <exec/process.h>
10.29 +#include <ipc/cap_alloc.h>
10.30 +#include <ipc/map.h>
10.31 +#include <mem/memory_utils.h>
10.32 +
10.33 +
10.34 +
10.35 +/* Obtain a flexpage defining the UTCB area location and size in a new task. */
10.36 +
10.37 +static l4_fpage_t get_utcb_fpage()
10.38 +{
10.39 + /* UTCB location and size. */
10.40 +
10.41 + int utcb_log2size = page_order(Default_max_threads * L4_UTCB_OFFSET);
10.42 +
10.43 + /* Round up to at least one page. */
10.44 +
10.45 + if (utcb_log2size < L4_PAGESHIFT)
10.46 + utcb_log2size = L4_PAGESHIFT;
10.47 +
10.48 + return l4_fpage(Utcb_area_start, utcb_log2size, 0);
10.49 +}
10.50 +
10.51 +
10.52 +
10.53 +/* Initialise a new process, this being an abstraction for a new task with some
10.54 + threads. */
10.55 +
10.56 +Process::Process()
10.57 +{
10.58 + /* Obtain UTCB area details for the task. */
10.59 +
10.60 + l4_fpage_t utcb_fpage = get_utcb_fpage();
10.61 +
10.62 + _utcb_start = l4_fpage_memaddr(utcb_fpage);
10.63 +
10.64 + /* Populate the common initial environment for the threads. */
10.65 +
10.66 + _env.factory = L4_BASE_FACTORY_CAP;
10.67 + _env.main_thread = L4_BASE_THREAD_CAP;
10.68 + _env.log = L4_BASE_LOG_CAP;
10.69 + _env.scheduler = L4_BASE_SCHEDULER_CAP;
10.70 + _env.rm = L4_EXEC_RM_CAP;
10.71 + _env.mem_alloc = L4_EXEC_MA_CAP;
10.72 + _env.first_free_cap = L4_EXEC_FIRST_FREE_CAP_INDEX;
10.73 + _env.utcb_area = utcb_fpage;
10.74 + _env.first_free_utcb = l4_fpage_memaddr(utcb_fpage) + L4_UTCB_OFFSET;
10.75 +
10.76 + /* Populate auxiliary information. */
10.77 +
10.78 + _aux.kip_ds = L4_EXEC_KIP_CAP;
10.79 + _aux.dbg_lvl = 0;
10.80 + _aux.ldr_flags = 0;
10.81 +}
10.82 +
10.83 +/* Task and thread initialisation. */
10.84 +
10.85 +long Process::create_task()
10.86 +{
10.87 + _task = ipc_cap_alloc();
10.88 +
10.89 + if (l4_is_invalid_cap(_task))
10.90 + return -L4_ENOMEM;
10.91 +
10.92 + return l4_error(l4_factory_create_task(l4re_env()->factory, _task, _env.utcb_area));
10.93 +}
10.94 +
10.95 +long Process::create_thread(l4_cap_idx_t *thread)
10.96 +{
10.97 + *thread = ipc_cap_alloc();
10.98 +
10.99 + if (l4_is_invalid_cap(*thread))
10.100 + return -L4_ENOMEM;
10.101 +
10.102 + return l4_error(l4_factory_create_thread(l4re_env()->factory, *thread));
10.103 +}
10.104 +
10.105 +/* Configure the task environment. */
10.106 +
10.107 +long Process::configure(l4_cap_idx_t server)
10.108 +{
10.109 + long err = create_task();
10.110 +
10.111 + if (err)
10.112 + return err;
10.113 +
10.114 + /* Map the KIP into the task. */
10.115 +
10.116 + l4_addr_t kip_start = (l4_addr_t) l4re_kip();
10.117 +
10.118 + err = l4_error(l4_task_map(_task, L4RE_THIS_TASK_CAP,
10.119 + l4_fpage(kip_start, L4_PAGESHIFT, L4_FPAGE_RX),
10.120 + kip_start));
10.121 +
10.122 + if (err)
10.123 + return err;
10.124 +
10.125 + /* Define capability mappings for the new task. */
10.126 +
10.127 + struct ipc_mapped_cap mapped_caps[] = {
10.128 + {L4_BASE_TASK_CAP, _task, L4_CAP_FPAGE_RWS},
10.129 + {L4_EXEC_PAGER_CAP, server, L4_CAP_FPAGE_RWS},
10.130 + {_env.rm, server, L4_CAP_FPAGE_RWS},
10.131 + {_env.factory, l4re_env()->factory, L4_CAP_FPAGE_RWS},
10.132 + {_env.log, l4re_env()->log, L4_CAP_FPAGE_RWS},
10.133 + {_env.scheduler, l4re_env()->scheduler, L4_CAP_FPAGE_RWS},
10.134 + {_env.mem_alloc, l4re_env()->mem_alloc, L4_CAP_FPAGE_RWS},
10.135 + {0, L4_INVALID_CAP, 0},
10.136 + };
10.137 +
10.138 + return ipc_map_capabilities(_task, mapped_caps);
10.139 +}
10.140 +
10.141 +/* Create, initialise and start a thread. */
10.142 +
10.143 +long Process::thread_start(l4_addr_t program_start, Stack &st)
10.144 +{
10.145 + l4_cap_idx_t thread;
10.146 + long err;
10.147 +
10.148 + err = create_thread(&thread);
10.149 +
10.150 + if (err)
10.151 + return err;
10.152 +
10.153 + /* Initialise the thread with pager, UTCB and task details. */
10.154 +
10.155 + l4_thread_control_start();
10.156 + l4_thread_control_pager(L4_EXEC_PAGER_CAP);
10.157 + l4_thread_control_exc_handler(L4_EXEC_PAGER_CAP);
10.158 + l4_thread_control_bind((l4_utcb_t *) _utcb_start, _task);
10.159 +
10.160 + err = l4_error(l4_thread_control_commit(thread));
10.161 +
10.162 + if (err)
10.163 + {
10.164 + ipc_cap_free(thread);
10.165 + return err;
10.166 + }
10.167 +
10.168 + /* Map the thread capability to the task. */
10.169 +
10.170 + ipc_map_capability(_task, (struct ipc_mapped_cap) {_env.main_thread, thread, L4_CAP_FPAGE_RWS});
10.171 +
10.172 + /* Populate the initial environment in the thread. */
10.173 +
10.174 + st.set_l4re_aux(&_aux);
10.175 + st.set_l4re_env(&_env);
10.176 +
10.177 + /* Set the start details. */
10.178 +
10.179 + err = l4_error(l4_thread_ex_regs(thread, program_start, st.start_address(), 0));
10.180 +
10.181 + if (err)
10.182 + return err;
10.183 +
10.184 + /* Select a new address for the next thread. */
10.185 +
10.186 + _utcb_start += L4_UTCB_OFFSET;
10.187 +
10.188 + /* Start the thread. */
10.189 +
10.190 + l4_sched_param_t sp = l4_sched_param(L4RE_MAIN_THREAD_PRIO);
10.191 +
10.192 + return l4_error(l4_scheduler_run_thread(l4re_env()->scheduler, thread, &sp));
10.193 +}
10.194 +
10.195 +/* vim: tabstop=2 expandtab shiftwidth=2
10.196 +*/
11.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
11.2 +++ b/libexec/lib/src/segment.cc Tue May 10 22:39:15 2022 +0200
11.3 @@ -0,0 +1,92 @@
11.4 +/*
11.5 + * Program memory segment support.
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/sys/err.h>
11.26 +
11.27 +#include <ipc/mem_ipc.h>
11.28 +#include <mem/memory_utils.h>
11.29 +
11.30 +#include <stdio.h>
11.31 +#include <string.h>
11.32 +
11.33 +#include "segment.h"
11.34 +
11.35 +
11.36 +
11.37 +/* Initialise a memory segment. */
11.38 +
11.39 +Segment::Segment(offset_t base, offset_t size, l4re_rm_flags_t flags,
11.40 + offset_t file_offset, offset_t file_contents)
11.41 +: base(base), size(size), flags(flags), file_offset(file_offset),
11.42 + file_contents(file_contents)
11.43 +{
11.44 + region_base = trunc(base, L4_PAGESIZE);
11.45 + region_offset = base - region_base;
11.46 + region_size = round(size, L4_PAGESIZE);
11.47 +}
11.48 +
11.49 +/* Allocate a region for the segment. */
11.50 +
11.51 +long Segment::allocate()
11.52 +{
11.53 + return ipc_allocate_align(size, L4RE_RM_F_SEARCH_ADDR | flags,
11.54 + L4_PAGESHIFT, (void **) &buf, &ds);
11.55 +}
11.56 +
11.57 +/* Fill a segment region with file content. */
11.58 +
11.59 +long Segment::fill(file_t *file)
11.60 +{
11.61 + if (!file_contents)
11.62 + return L4_EOK;
11.63 +
11.64 + memset(buf, 0, region_size);
11.65 + client_seek(file, file_offset, SEEK_SET);
11.66 + offset_t nread = client_read(file, buf + region_offset, file_contents);
11.67 +
11.68 + if (nread < file_contents)
11.69 + return -L4_EIO;
11.70 + else
11.71 + return L4_EOK;
11.72 +}
11.73 +
11.74 +/* Define and return the mapped region for the segment. */
11.75 +
11.76 +MappedRegion &Segment::region()
11.77 +{
11.78 + _region = MappedRegion((l4_addr_t) buf, page_order(region_size), flags, region_base);
11.79 + return _region;
11.80 +}
11.81 +
11.82 +/* Return the mapped address corresponding to the given address. */
11.83 +
11.84 +l4_addr_t Segment::region_address(char *address)
11.85 +{
11.86 + return (l4_addr_t) ((address - buf) + (char *) region_base);
11.87 +}
11.88 +
11.89 +l4_addr_t Segment::region_address(l4_addr_t address)
11.90 +{
11.91 + return (address - (l4_addr_t) buf) + region_base;
11.92 +}
11.93 +
11.94 +/* vim: tabstop=2 expandtab shiftwidth=2
11.95 +*/
12.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
12.2 +++ b/libexec/lib/src/stack.cc Tue May 10 22:39:15 2022 +0200
12.3 @@ -0,0 +1,271 @@
12.4 +/*
12.5 + * Stack support for new tasks and threads.
12.6 + *
12.7 + * Copyright (C) 2022 Paul Boddie <paul@boddie.org.uk>
12.8 + *
12.9 + * This program is free software; you can redistribute it and/or
12.10 + * modify it under the terms of the GNU General Public License as
12.11 + * published by the Free Software Foundation; either version 2 of
12.12 + * the License, or (at your option) any later version.
12.13 + *
12.14 + * This program is distributed in the hope that it will be useful,
12.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
12.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12.17 + * GNU General Public License for more details.
12.18 + *
12.19 + * You should have received a copy of the GNU General Public License
12.20 + * along with this program; if not, write to the Free Software
12.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
12.22 + * Boston, MA 02110-1301, USA
12.23 + */
12.24 +
12.25 +#include <l4/util/elf.h>
12.26 +#include <l4/util/util.h>
12.27 +
12.28 +#include <l4/libloader/adjust_stack>
12.29 +
12.30 +#include <mem/memory_utils.h>
12.31 +
12.32 +#include <stdio.h>
12.33 +#include <string.h>
12.34 +
12.35 +#include "stack.h"
12.36 +
12.37 +
12.38 +
12.39 +/* Initialise a stack in a memory segment. */
12.40 +
12.41 +Stack::Stack(Segment &segment)
12.42 +: _segment(segment)
12.43 +{
12.44 + _element = (l4_umword_t *) (segment.buf + segment.size);
12.45 +
12.46 + /* Add a terminator for any additional initial capabilities. */
12.47 +
12.48 + l4re_env_cap_entry_t *entry = (l4re_env_cap_entry_t *) _element;
12.49 +
12.50 + *(--entry) = l4re_env_cap_entry_t();
12.51 + _element = (l4_umword_t *) entry;
12.52 +}
12.53 +
12.54 +/* Push any additional initial capabilities. */
12.55 +
12.56 +void Stack::push_cap_entries(l4re_env_cap_entry_t *entries)
12.57 +{
12.58 + l4re_env_cap_entry_t *entry = (l4re_env_cap_entry_t *) _element;
12.59 +
12.60 + while ((entries != NULL) && (entries->cap != L4_INVALID_CAP))
12.61 + *(--entry) = *entries;
12.62 +
12.63 + _caps = (l4_addr_t) entry;
12.64 + _element = (l4_umword_t *) entry;
12.65 +}
12.66 +
12.67 +/* Push environment values in reverse order. */
12.68 +
12.69 +void Stack::push_string(char *s)
12.70 +{
12.71 + char *arg = (char *) _element;
12.72 + char *arg_last = arg;
12.73 +
12.74 + arg -= round(strlen(s) + 1, sizeof(l4_umword_t));
12.75 +
12.76 + memset(arg, 0, arg_last - arg);
12.77 + memcpy(arg, s, strlen(s));
12.78 +
12.79 + _element = (l4_umword_t *) arg;
12.80 +}
12.81 +
12.82 +/* Push environment values in reverse order. */
12.83 +
12.84 +void Stack::push_env(char *envp[])
12.85 +{
12.86 + _env_top = (char *) _element;
12.87 + _env_entries = 0;
12.88 +
12.89 + for (; *envp != NULL; envp++, _env_entries++)
12.90 + push_string(*envp);
12.91 +}
12.92 +
12.93 +/* Push argument values in reverse order. */
12.94 +
12.95 +void Stack::push_args(int argc, char *argv[])
12.96 +{
12.97 + _arg_top = (char *) _element;
12.98 +
12.99 + for (int i = 0; i < argc; i++)
12.100 + push_string(argv[i]);
12.101 +}
12.102 +
12.103 +/* Loader flags, debugging flags, and the KIP capability index.
12.104 + See: generate_l4aux in Remote_app_model */
12.105 +
12.106 +void Stack::push_l4re_aux()
12.107 +{
12.108 + _aux = (l4re_aux_t *) _element;
12.109 + _aux--;
12.110 + _element = (l4_umword_t *) _aux;
12.111 +}
12.112 +
12.113 +void Stack::push_l4re_env()
12.114 +{
12.115 + _env = (l4re_env_t *) _element;
12.116 + _env--;
12.117 + _element = (l4_umword_t *) _env;
12.118 +}
12.119 +
12.120 +/* Set the common auxiliary information. */
12.121 +
12.122 +void Stack::set_l4re_aux(l4re_aux_t *aux)
12.123 +{
12.124 + memcpy(_aux, aux, sizeof(l4re_aux_t));
12.125 +
12.126 + /* Take the binary name from the first program argument. */
12.127 +
12.128 + _aux->binary = (char *) _argv[0];
12.129 +}
12.130 +
12.131 +/* Set the common environment, introducing the reference to additional
12.132 + capabilities. */
12.133 +
12.134 +void Stack::set_l4re_env(l4re_env_t *env)
12.135 +{
12.136 + memcpy(_env, env, sizeof(l4re_env_t));
12.137 + _env->caps = (l4re_env_cap_entry_t *) (_segment.region_address(_caps));
12.138 +}
12.139 +
12.140 +/* Push the auxiliary vector. */
12.141 +
12.142 +void Stack::push_auxv()
12.143 +{
12.144 + _auxv_end = (char *) _element;
12.145 +
12.146 + struct auxv_entry *auxv_base = (struct auxv_entry *) _element;
12.147 +
12.148 + *(--auxv_base) = {AT_NULL, 0};
12.149 +
12.150 + /* L4Re global environment pointer. */
12.151 +
12.152 + *(--auxv_base) = {AT_L4_ENV, _segment.region_address((char *) _env)};
12.153 +
12.154 + /* L4Re auxiliary structure pointer. */
12.155 +
12.156 + *(--auxv_base) = {AT_L4_AUX, _segment.region_address((char *) _aux)};
12.157 +
12.158 + /* Apparently required entries.
12.159 + NOTE: The user/group identifiers should be obtained from the broader
12.160 + environment. */
12.161 +
12.162 + *(--auxv_base) = {AT_PAGESZ, L4_PAGESIZE};
12.163 + *(--auxv_base) = {AT_UID, 0};
12.164 + *(--auxv_base) = {AT_EUID, 0};
12.165 + *(--auxv_base) = {AT_GID, 0};
12.166 + *(--auxv_base) = {AT_EGID, 0};
12.167 +
12.168 + _element = (l4_umword_t *) auxv_base;
12.169 +}
12.170 +
12.171 +/* Fill the stack in reverse with an address, returning the size of the
12.172 + value. */
12.173 +
12.174 +offset_t Stack::write_address(char *arg, char **addr, char *s)
12.175 +{
12.176 + offset_t size = round(strlen(s) + 1, sizeof(l4_umword_t));
12.177 +
12.178 + *addr = (char *) _segment.region_address(arg - size);
12.179 + return size;
12.180 +}
12.181 +
12.182 +/* Populate stack with environment pointers, employing a pointer ordering
12.183 + that is the reverse of the value ordering. */
12.184 +
12.185 +void Stack::push_envp(char *envp[])
12.186 +{
12.187 + /* Write the terminating element. */
12.188 +
12.189 + *(--_element) = 0;
12.190 +
12.191 + /* Reserve space and fill the stack from the top inwards. */
12.192 +
12.193 + char **ep = (char **) (_element - _env_entries);
12.194 + char *arg = _env_top;
12.195 +
12.196 + for (; *envp != NULL; envp++, ep++)
12.197 + arg -= write_address(arg, ep, *envp);
12.198 +
12.199 + _element -= _env_entries;
12.200 +}
12.201 +
12.202 +/* Populate stack with argument pointers and count, employing a pointer
12.203 + ordering that is the reverse of the value ordering. */
12.204 +
12.205 +void Stack::push_argv(int argc, char *argv[])
12.206 +{
12.207 + /* Write the terminating element. */
12.208 +
12.209 + *(--_element) = 0;
12.210 +
12.211 + /* Reserve space and fill the stack from the top inwards. */
12.212 +
12.213 + _argv = (char **) (_element - argc);
12.214 + char *arg = _arg_top;
12.215 +
12.216 + for (int i = 0; i < argc; i++)
12.217 + arg -= write_address(arg, &_argv[i], argv[i]);
12.218 +
12.219 + /* Write the count. */
12.220 +
12.221 + _element -= argc;
12.222 +
12.223 + *(--_element) = argc;
12.224 +}
12.225 +
12.226 +/* Adjust the stack alignment and return the stack address. */
12.227 +
12.228 +l4_addr_t Stack::align_stack()
12.229 +{
12.230 + char *current = (char *) _element;
12.231 + char *adjusted = Ldr::adjust_sp(current, NULL);
12.232 +
12.233 + if (adjusted != current)
12.234 + memmove(adjusted, (const void *) current, _auxv_end - current);
12.235 +
12.236 + _element = (l4_umword_t *) adjusted;
12.237 +
12.238 + return _segment.region_address(adjusted);
12.239 +}
12.240 +
12.241 +/* Populate the stack with arguments and initial environment. */
12.242 +
12.243 +void Stack::populate(int argc, char *argv[], char *envp[])
12.244 +{
12.245 + /* Populate stack with environment and argument values. */
12.246 +
12.247 + push_env(envp);
12.248 + push_args(argc, argv);
12.249 +
12.250 + /* Push L4Re flags, environment and auxiliary vector. */
12.251 +
12.252 + push_l4re_aux();
12.253 + push_l4re_env();
12.254 + push_auxv();
12.255 +
12.256 + /* Push environment and argument pointers. */
12.257 +
12.258 + push_envp(envp);
12.259 + push_argv(argc, argv);
12.260 +
12.261 + /* Adjust the stack alignment, setting the start address. */
12.262 +
12.263 + _start = align_stack();
12.264 +}
12.265 +
12.266 +/* Return the stack pointer start address in the mapped program segment. */
12.267 +
12.268 +l4_addr_t Stack::start_address()
12.269 +{
12.270 + return _start;
12.271 +}
12.272 +
12.273 +/* vim: tabstop=2 expandtab shiftwidth=2
12.274 +*/
13.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
13.2 +++ b/libipc/include/ipc/map.h Tue May 10 22:39:15 2022 +0200
13.3 @@ -0,0 +1,39 @@
13.4 +/*
13.5 + * Capability mapping between tasks.
13.6 + *
13.7 + * Copyright (C) 2022 Paul Boddie <paul@boddie.org.uk>
13.8 + *
13.9 + * This program is free software; you can redistribute it and/or
13.10 + * modify it under the terms of the GNU General Public License as
13.11 + * published by the Free Software Foundation; either version 2 of
13.12 + * the License, or (at your option) any later version.
13.13 + *
13.14 + * This program is distributed in the hope that it will be useful,
13.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
13.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13.17 + * GNU General Public License for more details.
13.18 + *
13.19 + * You should have received a copy of the GNU General Public License
13.20 + * along with this program; if not, write to the Free Software
13.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
13.22 + * Boston, MA 02110-1301, USA
13.23 + */
13.24 +
13.25 +#pragma once
13.26 +
13.27 +#include <l4/sys/types.h>
13.28 +
13.29 +EXTERN_C_BEGIN
13.30 +
13.31 +struct ipc_mapped_cap
13.32 +{
13.33 + l4_umword_t index;
13.34 + l4_cap_idx_t cap;
13.35 + unsigned char rights;
13.36 +};
13.37 +
13.38 +long ipc_map_capability(l4_cap_idx_t task, struct ipc_mapped_cap mapped_cap);
13.39 +
13.40 +long ipc_map_capabilities(l4_cap_idx_t task, struct ipc_mapped_cap mapped_caps[]);
13.41 +
13.42 +EXTERN_C_END
14.1 --- a/libipc/lib/src/Makefile Tue May 10 16:50:21 2022 +0200
14.2 +++ b/libipc/lib/src/Makefile Tue May 10 22:39:15 2022 +0200
14.3 @@ -3,7 +3,7 @@
14.4
14.5 TARGET = libipc.a libipc.so
14.6 PC_FILENAME = libipc
14.7 -SRC_C = cap_alloc.c direct.c irq.c mem_ipc.c message.c semaphore.c server.c thread.c util_ipc.c
14.8 +SRC_C = cap_alloc.c direct.c irq.c map.c mem_ipc.c message.c semaphore.c server.c thread.c util_ipc.c
14.9 REQUIRES_LIBS = l4re_c-util
14.10
14.11 PRIVATE_INCDIR += $(PKGDIR)/include/ipc
15.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
15.2 +++ b/libipc/lib/src/map.c Tue May 10 22:39:15 2022 +0200
15.3 @@ -0,0 +1,52 @@
15.4 +/*
15.5 + * Capability mapping between tasks.
15.6 + *
15.7 + * Copyright (C) 2022 Paul Boddie <paul@boddie.org.uk>
15.8 + *
15.9 + * This program is free software; you can redistribute it and/or
15.10 + * modify it under the terms of the GNU General Public License as
15.11 + * published by the Free Software Foundation; either version 2 of
15.12 + * the License, or (at your option) any later version.
15.13 + *
15.14 + * This program is distributed in the hope that it will be useful,
15.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
15.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15.17 + * GNU General Public License for more details.
15.18 + *
15.19 + * You should have received a copy of the GNU General Public License
15.20 + * along with this program; if not, write to the Free Software
15.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
15.22 + * Boston, MA 02110-1301, USA
15.23 + */
15.24 +
15.25 +#include <l4/re/consts.h>
15.26 +#include <l4/sys/err.h>
15.27 +#include <l4/sys/ipc.h>
15.28 +#include <l4/sys/task.h>
15.29 +
15.30 +#include "map.h"
15.31 +
15.32 +
15.33 +
15.34 +/* Map a capability to another task. */
15.35 +
15.36 +long ipc_map_capability(l4_cap_idx_t task, struct ipc_mapped_cap mapped_cap)
15.37 +{
15.38 + return l4_error(l4_task_map(task, L4RE_THIS_TASK_CAP,
15.39 + l4_obj_fpage(mapped_cap.cap, 0, mapped_cap.rights),
15.40 + l4_map_obj_control(mapped_cap.index, L4_MAP_ITEM_MAP)));
15.41 +}
15.42 +
15.43 +/* Map several capabilities to another task. */
15.44 +
15.45 +long ipc_map_capabilities(l4_cap_idx_t task, struct ipc_mapped_cap mapped_caps[])
15.46 +{
15.47 + long err = L4_EOK;
15.48 +
15.49 + for (int i = 0; l4_is_valid_cap(mapped_caps[i].cap) && !err; i++)
15.50 + err = ipc_map_capability(task, mapped_caps[i]);
15.51 +
15.52 + return err;
15.53 +}
15.54 +
15.55 +// vim: tabstop=2 expandtab shiftwidth=2
16.1 --- a/tests/Control Tue May 10 16:50:21 2022 +0200
16.2 +++ b/tests/Control Tue May 10 22:39:15 2022 +0200
16.3 @@ -1,3 +1,3 @@
16.4 -requires: libstdc++ libc libipc libfsclient libmem libext2fs libext2fs_blockserver libe2access_blockserver fstest_files
16.5 +requires: libstdc++ libc libexec libipc libfsclient libmem libext2fs libext2fs_blockserver libe2access_blockserver fstest_files
16.6 provides: fstests
16.7 maintainer: paul@boddie.org.uk
17.1 --- a/tests/Makefile Tue May 10 16:50:21 2022 +0200
17.2 +++ b/tests/Makefile Tue May 10 22:39:15 2022 +0200
17.3 @@ -71,7 +71,7 @@
17.4 PLAIN_SRC_CC_dstest_exec = dstest_exec.cc
17.5 SRC_CC_dstest_exec = $(PLAIN_SRC_CC_dstest_exec) $(SERVER_INTERFACES_SRC_CC)
17.6
17.7 -REQUIRES_LIBS = l4re_c-util libfsclient libmem libipc libstdc++ libsystypes libe2access_blockserver
17.8 +REQUIRES_LIBS = l4re_c-util libexec libfsclient libmem libipc libstdc++ libsystypes libe2access_blockserver
17.9 PRIVATE_INCDIR = $(IDL_BUILD_DIR) $(IDL_EXPORT_DIR)
17.10
17.11 include $(L4DIR)/mk/prog.mk
18.1 --- a/tests/dstest_exec.cc Tue May 10 16:50:21 2022 +0200
18.2 +++ b/tests/dstest_exec.cc Tue May 10 22:39:15 2022 +0200
18.3 @@ -22,16 +22,11 @@
18.4 #include <l4/re/env.h>
18.5 #include <l4/re/l4aux.h>
18.6 #include <l4/sys/err.h>
18.7 -#include <l4/sys/factory.h>
18.8 -#include <l4/sys/task.h>
18.9 -#include <l4/sys/thread.h>
18.10 #include <l4/util/elf.h>
18.11 #include <l4/util/util.h>
18.12
18.13 -#include <l4/libloader/adjust_stack>
18.14 -
18.15 +#include <exec/process.h>
18.16 #include <fsclient/client.h>
18.17 -#include <ipc/cap_alloc.h>
18.18 #include <ipc/mem_ipc.h>
18.19 #include <ipc/server.h>
18.20 #include <mem/memory_utils.h>
18.21 @@ -51,151 +46,6 @@
18.22
18.23
18.24
18.25 -/* UTCB properties.
18.26 - See: moe/server/src/loader.cc */
18.27 -
18.28 -enum ipc_exec_utcb
18.29 -{
18.30 - Default_max_threads = 16,
18.31 -#ifdef ARCH_mips
18.32 - Utcb_area_start = 0x73000000,
18.33 -#else
18.34 - Utcb_area_start = 0xb3000000,
18.35 -#endif
18.36 -};
18.37 -
18.38 -static l4_fpage_t get_utcb_fpage()
18.39 -{
18.40 - /* UTCB location and size. */
18.41 -
18.42 - int utcb_log2size = page_order(Default_max_threads * L4_UTCB_OFFSET);
18.43 -
18.44 - /* Round up to at least one page. */
18.45 -
18.46 - if (utcb_log2size < L4_PAGESHIFT)
18.47 - utcb_log2size = L4_PAGESHIFT;
18.48 -
18.49 - return l4_fpage(Utcb_area_start, utcb_log2size, 0);
18.50 -}
18.51 -
18.52 -
18.53 -
18.54 -/* Mapped region data structures. */
18.55 -
18.56 -class MappedRegion
18.57 -{
18.58 -public:
18.59 - l4_addr_t start;
18.60 - unsigned int log2size;
18.61 - l4_umword_t flags;
18.62 - l4_addr_t map_start;
18.63 -
18.64 - explicit MappedRegion()
18.65 - : start(0), log2size(0), flags(0), map_start(0)
18.66 - {
18.67 - }
18.68 -
18.69 - explicit MappedRegion(l4_addr_t start, unsigned int log2size,
18.70 - l4_umword_t flags, l4_addr_t map_start)
18.71 - : start(start), log2size(log2size), flags(flags), map_start(map_start)
18.72 - {
18.73 - }
18.74 -};
18.75 -
18.76 -
18.77 -
18.78 -/* Program segment abstraction. */
18.79 -
18.80 -class Segment
18.81 -{
18.82 -protected:
18.83 - MappedRegion _region;
18.84 -
18.85 -public:
18.86 - /* Allocated memory. */
18.87 -
18.88 - char *buf;
18.89 - l4re_ds_t ds;
18.90 -
18.91 - /* Segment base and corresponding region base. */
18.92 -
18.93 - l4_addr_t base, region_base;
18.94 -
18.95 - /* Segment size and corresponding region size. */
18.96 -
18.97 - offset_t size, region_size;
18.98 -
18.99 - /* Offset of segment content within the region. */
18.100 -
18.101 - offset_t region_offset;
18.102 -
18.103 - /* Access flags. */
18.104 -
18.105 - l4re_rm_flags_t flags;
18.106 -
18.107 - /* File access details. */
18.108 -
18.109 - offset_t file_offset, file_contents;
18.110 -
18.111 - explicit Segment(offset_t base, offset_t size, l4re_rm_flags_t flags,
18.112 - offset_t file_offset = 0, offset_t file_contents = 0)
18.113 - : base(base), size(size), flags(flags), file_offset(file_offset), file_contents(file_contents)
18.114 - {
18.115 - region_base = trunc(base, L4_PAGESIZE);
18.116 - region_offset = base - region_base;
18.117 - region_size = round(size, L4_PAGESIZE);
18.118 - }
18.119 -
18.120 - long allocate();
18.121 -
18.122 - long fill(file_t *file);
18.123 -
18.124 - MappedRegion ®ion();
18.125 -
18.126 - l4_addr_t region_address(char *address);
18.127 -
18.128 - l4_addr_t region_address(l4_addr_t address);
18.129 -};
18.130 -
18.131 -long Segment::allocate()
18.132 -{
18.133 - return ipc_allocate_align(size, L4RE_RM_F_SEARCH_ADDR | flags,
18.134 - L4_PAGESHIFT, (void **) &buf, &ds);
18.135 -}
18.136 -
18.137 -long Segment::fill(file_t *file)
18.138 -{
18.139 - if (!file_contents)
18.140 - return L4_EOK;
18.141 -
18.142 - memset(buf, 0, region_size);
18.143 - client_seek(file, file_offset, SEEK_SET);
18.144 - offset_t nread = client_read(file, buf + region_offset, file_contents);
18.145 -
18.146 - if (nread < file_contents)
18.147 - return -L4_EIO;
18.148 - else
18.149 - return L4_EOK;
18.150 -}
18.151 -
18.152 -MappedRegion &Segment::region()
18.153 -{
18.154 - _region = MappedRegion((l4_addr_t) buf, page_order(region_size), flags, region_base);
18.155 - return _region;
18.156 -}
18.157 -
18.158 -l4_addr_t Segment::region_address(char *address)
18.159 -{
18.160 - return (l4_addr_t) ((address - buf) + (char *) region_base);
18.161 -}
18.162 -
18.163 -l4_addr_t Segment::region_address(l4_addr_t address)
18.164 -{
18.165 - return (address - (l4_addr_t) buf) + region_base;
18.166 -}
18.167 -
18.168 -
18.169 -
18.170 /* A simple system pager also acting as a region mapper. */
18.171
18.172 typedef std::map<l4_addr_t, MappedRegion> MappedRegions;
18.173 @@ -425,465 +275,6 @@
18.174
18.175
18.176
18.177 -/* Capability mapping definitions for the new task. */
18.178 -
18.179 -struct mapped_cap
18.180 -{
18.181 - l4_umword_t index;
18.182 - l4_cap_idx_t cap;
18.183 - unsigned char rights;
18.184 -};
18.185 -
18.186 -static long map_capability(l4_cap_idx_t task, struct mapped_cap mapped_cap)
18.187 -{
18.188 - return l4_error(l4_task_map(task, L4RE_THIS_TASK_CAP,
18.189 - l4_obj_fpage(mapped_cap.cap, 0, mapped_cap.rights),
18.190 - l4_map_obj_control(mapped_cap.index, L4_MAP_ITEM_MAP)));
18.191 -}
18.192 -
18.193 -static long map_capabilities(l4_cap_idx_t task, struct mapped_cap mapped_caps[])
18.194 -{
18.195 - long err = L4_EOK;
18.196 -
18.197 - for (int i = 0; l4_is_valid_cap(mapped_caps[i].cap) && !err; i++)
18.198 - err = map_capability(task, mapped_caps[i]);
18.199 -
18.200 - return err;
18.201 -}
18.202 -
18.203 -
18.204 -
18.205 -/* A stack abstraction. */
18.206 -
18.207 -class Stack
18.208 -{
18.209 - struct auxv_entry
18.210 - {
18.211 - l4_umword_t key, value;
18.212 - };
18.213 -
18.214 -protected:
18.215 - Segment &_segment;
18.216 -
18.217 - /* Next element pointer. */
18.218 -
18.219 - l4_umword_t *_element;
18.220 -
18.221 - /* Stack section properties. */
18.222 -
18.223 - l4_addr_t _caps;
18.224 - char *_arg_top, *_env_top;
18.225 - char **_argv;
18.226 - char *_auxv_end;
18.227 - int _env_entries;
18.228 -
18.229 - /* L4Re auxiliary and environment regions. */
18.230 -
18.231 - l4re_aux_t *_aux;
18.232 - l4re_env_t *_env;
18.233 -
18.234 -public:
18.235 - /* Start address. */
18.236 -
18.237 - l4_addr_t start;
18.238 -
18.239 - /* Initialise a stack in a memory segment. */
18.240 -
18.241 - explicit Stack(Segment &segment)
18.242 - : _segment(segment)
18.243 - {
18.244 - _element = (l4_umword_t *) (segment.buf + segment.size);
18.245 -
18.246 - /* Add a terminator for any additional initial capabilities. */
18.247 -
18.248 - l4re_env_cap_entry_t *entry = (l4re_env_cap_entry_t *) _element;
18.249 -
18.250 - *(--entry) = l4re_env_cap_entry_t();
18.251 - _element = (l4_umword_t *) entry;
18.252 - }
18.253 -
18.254 - /* Push any additional initial capabilities. */
18.255 -
18.256 - void push_cap_entries(l4re_env_cap_entry_t *entries)
18.257 - {
18.258 - l4re_env_cap_entry_t *entry = (l4re_env_cap_entry_t *) _element;
18.259 -
18.260 - while ((entries != NULL) && (entries->cap != L4_INVALID_CAP))
18.261 - *(--entry) = *entries;
18.262 -
18.263 - _caps = (l4_addr_t) entry;
18.264 - _element = (l4_umword_t *) entry;
18.265 - }
18.266 -
18.267 - /* Push environment values in reverse order. */
18.268 -
18.269 - void push_string(char *s)
18.270 - {
18.271 - char *arg = (char *) _element;
18.272 - char *arg_last = arg;
18.273 -
18.274 - arg -= round(strlen(s) + 1, sizeof(l4_umword_t));
18.275 -
18.276 - memset(arg, 0, arg_last - arg);
18.277 - memcpy(arg, s, strlen(s));
18.278 -
18.279 - _element = (l4_umword_t *) arg;
18.280 - }
18.281 -
18.282 - /* Push environment values in reverse order. */
18.283 -
18.284 - void push_env(char *envp[])
18.285 - {
18.286 - _env_top = (char *) _element;
18.287 - _env_entries = 0;
18.288 -
18.289 - for (; *envp != NULL; envp++, _env_entries++)
18.290 - push_string(*envp);
18.291 - }
18.292 -
18.293 - /* Push argument values in reverse order. */
18.294 -
18.295 - void push_args(int argc, char *argv[])
18.296 - {
18.297 - _arg_top = (char *) _element;
18.298 -
18.299 - for (int i = 0; i < argc; i++)
18.300 - push_string(argv[i]);
18.301 - }
18.302 -
18.303 - /* Loader flags, debugging flags, and the KIP capability index.
18.304 - See: generate_l4aux in Remote_app_model */
18.305 -
18.306 - void push_l4re_aux()
18.307 - {
18.308 - _aux = (l4re_aux_t *) _element;
18.309 - _aux--;
18.310 - _element = (l4_umword_t *) _aux;
18.311 - }
18.312 -
18.313 - void push_l4re_env()
18.314 - {
18.315 - _env = (l4re_env_t *) _element;
18.316 - _env--;
18.317 - _element = (l4_umword_t *) _env;
18.318 - }
18.319 -
18.320 - /* Set the common auxiliary information. */
18.321 -
18.322 - void set_l4re_aux(l4re_aux_t *aux)
18.323 - {
18.324 - memcpy(_aux, aux, sizeof(l4re_aux_t));
18.325 -
18.326 - /* Take the binary name from the first program argument. */
18.327 -
18.328 - _aux->binary = (char *) _argv[0];
18.329 - }
18.330 -
18.331 - /* Set the common environment, introducing the reference to additional
18.332 - capabilities. */
18.333 -
18.334 - void set_l4re_env(l4re_env_t *env)
18.335 - {
18.336 - memcpy(_env, env, sizeof(l4re_env_t));
18.337 - _env->caps = (l4re_env_cap_entry_t *) (_segment.region_address(_caps));
18.338 - }
18.339 -
18.340 - /* Push the auxiliary vector. */
18.341 -
18.342 - void push_auxv()
18.343 - {
18.344 - _auxv_end = (char *) _element;
18.345 -
18.346 - struct auxv_entry *auxv_base = (struct auxv_entry *) _element;
18.347 -
18.348 - /* AUXV NULL. */
18.349 -
18.350 - *(--auxv_base) = {0, 0};
18.351 -
18.352 - /* L4Re global environment pointer. */
18.353 -
18.354 - *(--auxv_base) = {0xf1, _segment.region_address((char *) _env)};
18.355 -
18.356 - /* L4Re auxiliary structure pointer. */
18.357 -
18.358 - *(--auxv_base) = {0xf0, _segment.region_address((char *) _aux)};
18.359 -
18.360 - /* Apparently required entries.
18.361 - NOTE: The user/group identifiers should be obtained from the broader
18.362 - environment. */
18.363 -
18.364 - *(--auxv_base) = {AT_PAGESZ, L4_PAGESIZE};
18.365 - *(--auxv_base) = {AT_UID, 0};
18.366 - *(--auxv_base) = {AT_EUID, 0};
18.367 - *(--auxv_base) = {AT_GID, 0};
18.368 - *(--auxv_base) = {AT_EGID, 0};
18.369 -
18.370 - _element = (l4_umword_t *) auxv_base;
18.371 - }
18.372 -
18.373 - /* Fill the stack in reverse with an address, returning the size of the
18.374 - value. */
18.375 -
18.376 - offset_t write_address(char *arg, char **addr, char *s)
18.377 - {
18.378 - offset_t size = round(strlen(s) + 1, sizeof(l4_umword_t));
18.379 -
18.380 - *addr = (char *) _segment.region_address(arg - size);
18.381 - return size;
18.382 - }
18.383 -
18.384 - /* Populate stack with environment pointers, employing a pointer ordering
18.385 - that is the reverse of the value ordering. */
18.386 -
18.387 - void push_envp(char *envp[])
18.388 - {
18.389 - /* Write the terminating element. */
18.390 -
18.391 - *(--_element) = 0;
18.392 -
18.393 - /* Reserve space and fill the stack from the top inwards. */
18.394 -
18.395 - char **ep = (char **) (_element - _env_entries);
18.396 - char *arg = _env_top;
18.397 -
18.398 - for (; *envp != NULL; envp++, ep++)
18.399 - arg -= write_address(arg, ep, *envp);
18.400 -
18.401 - _element -= _env_entries;
18.402 - }
18.403 -
18.404 - /* Populate stack with argument pointers and count, employing a pointer
18.405 - ordering that is the reverse of the value ordering. */
18.406 -
18.407 - void push_argv(int argc, char *argv[])
18.408 - {
18.409 - /* Write the terminating element. */
18.410 -
18.411 - *(--_element) = 0;
18.412 -
18.413 - /* Reserve space and fill the stack from the top inwards. */
18.414 -
18.415 - _argv = (char **) (_element - argc);
18.416 - char *arg = _arg_top;
18.417 -
18.418 - for (int i = 0; i < argc; i++)
18.419 - arg -= write_address(arg, &_argv[i], argv[i]);
18.420 -
18.421 - /* Write the count. */
18.422 -
18.423 - _element -= argc;
18.424 -
18.425 - *(--_element) = argc;
18.426 - }
18.427 -
18.428 - /* Adjust the stack alignment and return the stack address. */
18.429 -
18.430 - l4_addr_t align_stack()
18.431 - {
18.432 - char *current = (char *) _element;
18.433 - char *adjusted = Ldr::adjust_sp(current, NULL);
18.434 -
18.435 - if (adjusted != current)
18.436 - memmove(adjusted, (const void *) current, _auxv_end - current);
18.437 -
18.438 - _element = (l4_umword_t *) adjusted;
18.439 -
18.440 - return _segment.region_address(adjusted);
18.441 - }
18.442 -
18.443 - /* Populate the stack with arguments and initial environment. */
18.444 -
18.445 - void populate(int argc, char *argv[], char *envp[])
18.446 - {
18.447 - /* Populate stack with environment and argument values. */
18.448 -
18.449 - push_env(envp);
18.450 - push_args(argc, argv);
18.451 -
18.452 - /* Push L4Re flags, environment and auxiliary vector. */
18.453 -
18.454 - push_l4re_aux();
18.455 - push_l4re_env();
18.456 - push_auxv();
18.457 -
18.458 - /* Push environment and argument pointers. */
18.459 -
18.460 - push_envp(envp);
18.461 - push_argv(argc, argv);
18.462 -
18.463 - /* Adjust the stack alignment. */
18.464 -
18.465 - start = align_stack();
18.466 - }
18.467 -};
18.468 -
18.469 -
18.470 -
18.471 -class Process
18.472 -{
18.473 -protected:
18.474 - l4_cap_idx_t _task = L4_INVALID_CAP;
18.475 -
18.476 - /* Capability index definitions. */
18.477 -
18.478 - l4_cap_idx_t _pager_cap = 0x10 << L4_CAP_SHIFT;
18.479 - l4_cap_idx_t _rm_cap = 0x11 << L4_CAP_SHIFT;
18.480 - l4_cap_idx_t _ma_cap = 0x12 << L4_CAP_SHIFT;
18.481 - l4_cap_idx_t _kip_cap = 0x14 << L4_CAP_SHIFT;
18.482 - unsigned int _first_cap = 0x15;
18.483 -
18.484 - /* UTCB details. */
18.485 -
18.486 - l4_addr_t _utcb_start;
18.487 -
18.488 - /* Common environment details. */
18.489 -
18.490 - l4re_aux_t _aux;
18.491 - l4re_env_t _env;
18.492 -
18.493 - /* Task and thread initialisation. */
18.494 -
18.495 - long create_task()
18.496 - {
18.497 - _task = ipc_cap_alloc();
18.498 -
18.499 - if (l4_is_invalid_cap(_task))
18.500 - return -L4_ENOMEM;
18.501 -
18.502 - return l4_error(l4_factory_create_task(l4re_env()->factory, _task, _env.utcb_area));
18.503 - }
18.504 -
18.505 - long create_thread(l4_cap_idx_t *thread)
18.506 - {
18.507 - *thread = ipc_cap_alloc();
18.508 -
18.509 - if (l4_is_invalid_cap(*thread))
18.510 - return -L4_ENOMEM;
18.511 -
18.512 - return l4_error(l4_factory_create_thread(l4re_env()->factory, *thread));
18.513 - }
18.514 -
18.515 -public:
18.516 - explicit Process()
18.517 - {
18.518 - /* Obtain UTCB area details for the task. */
18.519 -
18.520 - l4_fpage_t utcb_fpage = get_utcb_fpage();
18.521 -
18.522 - _utcb_start = l4_fpage_memaddr(utcb_fpage);
18.523 -
18.524 - /* Populate the common initial environment for the threads. */
18.525 -
18.526 - _env.factory = L4_BASE_FACTORY_CAP;
18.527 - _env.main_thread = L4_BASE_THREAD_CAP;
18.528 - _env.log = L4_BASE_LOG_CAP;
18.529 - _env.scheduler = L4_BASE_SCHEDULER_CAP;
18.530 - _env.rm = _rm_cap;
18.531 - _env.mem_alloc = _ma_cap;
18.532 - _env.first_free_cap = _first_cap;
18.533 - _env.utcb_area = utcb_fpage;
18.534 - _env.first_free_utcb = l4_fpage_memaddr(utcb_fpage) + L4_UTCB_OFFSET;
18.535 -
18.536 - /* Populate auxiliary information. */
18.537 -
18.538 - _aux.kip_ds = _kip_cap;
18.539 - _aux.dbg_lvl = 0;
18.540 - _aux.ldr_flags = 0;
18.541 - }
18.542 -
18.543 - /* Configure the task environment. */
18.544 -
18.545 - long configure(l4_cap_idx_t server)
18.546 - {
18.547 - long err = create_task();
18.548 -
18.549 - if (err)
18.550 - return err;
18.551 -
18.552 - /* Map the KIP into the task. */
18.553 -
18.554 - l4_addr_t kip_start = (l4_addr_t) l4re_kip();
18.555 -
18.556 - err = l4_error(l4_task_map(_task, L4RE_THIS_TASK_CAP,
18.557 - l4_fpage(kip_start, L4_PAGESHIFT, L4_FPAGE_RX),
18.558 - kip_start));
18.559 -
18.560 - if (err)
18.561 - return err;
18.562 -
18.563 - /* Define capability mappings for the new task. */
18.564 -
18.565 - struct mapped_cap mapped_caps[] = {
18.566 - {L4_BASE_TASK_CAP, _task, L4_CAP_FPAGE_RWS},
18.567 - {_pager_cap, server, L4_CAP_FPAGE_RWS},
18.568 - {_env.rm, server, L4_CAP_FPAGE_RWS},
18.569 - {_env.factory, l4re_env()->factory, L4_CAP_FPAGE_RWS},
18.570 - {_env.log, l4re_env()->log, L4_CAP_FPAGE_RWS},
18.571 - {_env.scheduler, l4re_env()->scheduler, L4_CAP_FPAGE_RWS},
18.572 - {_env.mem_alloc, l4re_env()->mem_alloc, L4_CAP_FPAGE_RWS},
18.573 - {0, L4_INVALID_CAP, 0},
18.574 - };
18.575 -
18.576 - return map_capabilities(_task, mapped_caps);
18.577 - }
18.578 -
18.579 - /* Create, initialise and start a thread. */
18.580 -
18.581 - long thread_start(l4_addr_t program_start, Stack &st)
18.582 - {
18.583 - l4_cap_idx_t thread;
18.584 - long err;
18.585 -
18.586 - err = create_thread(&thread);
18.587 -
18.588 - if (err)
18.589 - return err;
18.590 -
18.591 - /* Initialise the thread with pager, UTCB and task details. */
18.592 -
18.593 - l4_thread_control_start();
18.594 - l4_thread_control_pager(_pager_cap);
18.595 - l4_thread_control_exc_handler(_pager_cap);
18.596 - l4_thread_control_bind((l4_utcb_t *) _utcb_start, _task);
18.597 -
18.598 - err = l4_error(l4_thread_control_commit(thread));
18.599 -
18.600 - if (err)
18.601 - {
18.602 - ipc_cap_free(thread);
18.603 - return err;
18.604 - }
18.605 -
18.606 - /* Map the thread capability to the task. */
18.607 -
18.608 - map_capability(_task, (struct mapped_cap) {_env.main_thread, thread, L4_CAP_FPAGE_RWS});
18.609 -
18.610 - /* Populate the initial environment in the thread. */
18.611 -
18.612 - st.set_l4re_aux(&_aux);
18.613 - st.set_l4re_env(&_env);
18.614 -
18.615 - /* Set the start details. */
18.616 -
18.617 - err = l4_error(l4_thread_ex_regs(thread, program_start, st.start, 0));
18.618 -
18.619 - if (err)
18.620 - return err;
18.621 -
18.622 - /* Select a new address for the next thread. */
18.623 -
18.624 - _utcb_start += L4_UTCB_OFFSET;
18.625 -
18.626 - /* Start the thread. */
18.627 -
18.628 - l4_sched_param_t sp = l4_sched_param(L4RE_MAIN_THREAD_PRIO);
18.629 -
18.630 - return l4_error(l4_scheduler_run_thread(l4re_env()->scheduler, thread, &sp));
18.631 - }
18.632 -};
18.633 -
18.634 -
18.635 -
18.636 class PayloadBase
18.637 {
18.638 public: