1.1 --- a/tests/dstest_exec.cc Tue May 10 16:50:21 2022 +0200
1.2 +++ b/tests/dstest_exec.cc Tue May 10 22:39:15 2022 +0200
1.3 @@ -22,16 +22,11 @@
1.4 #include <l4/re/env.h>
1.5 #include <l4/re/l4aux.h>
1.6 #include <l4/sys/err.h>
1.7 -#include <l4/sys/factory.h>
1.8 -#include <l4/sys/task.h>
1.9 -#include <l4/sys/thread.h>
1.10 #include <l4/util/elf.h>
1.11 #include <l4/util/util.h>
1.12
1.13 -#include <l4/libloader/adjust_stack>
1.14 -
1.15 +#include <exec/process.h>
1.16 #include <fsclient/client.h>
1.17 -#include <ipc/cap_alloc.h>
1.18 #include <ipc/mem_ipc.h>
1.19 #include <ipc/server.h>
1.20 #include <mem/memory_utils.h>
1.21 @@ -51,151 +46,6 @@
1.22
1.23
1.24
1.25 -/* UTCB properties.
1.26 - See: moe/server/src/loader.cc */
1.27 -
1.28 -enum ipc_exec_utcb
1.29 -{
1.30 - Default_max_threads = 16,
1.31 -#ifdef ARCH_mips
1.32 - Utcb_area_start = 0x73000000,
1.33 -#else
1.34 - Utcb_area_start = 0xb3000000,
1.35 -#endif
1.36 -};
1.37 -
1.38 -static l4_fpage_t get_utcb_fpage()
1.39 -{
1.40 - /* UTCB location and size. */
1.41 -
1.42 - int utcb_log2size = page_order(Default_max_threads * L4_UTCB_OFFSET);
1.43 -
1.44 - /* Round up to at least one page. */
1.45 -
1.46 - if (utcb_log2size < L4_PAGESHIFT)
1.47 - utcb_log2size = L4_PAGESHIFT;
1.48 -
1.49 - return l4_fpage(Utcb_area_start, utcb_log2size, 0);
1.50 -}
1.51 -
1.52 -
1.53 -
1.54 -/* Mapped region data structures. */
1.55 -
1.56 -class MappedRegion
1.57 -{
1.58 -public:
1.59 - l4_addr_t start;
1.60 - unsigned int log2size;
1.61 - l4_umword_t flags;
1.62 - l4_addr_t map_start;
1.63 -
1.64 - explicit MappedRegion()
1.65 - : start(0), log2size(0), flags(0), map_start(0)
1.66 - {
1.67 - }
1.68 -
1.69 - explicit MappedRegion(l4_addr_t start, unsigned int log2size,
1.70 - l4_umword_t flags, l4_addr_t map_start)
1.71 - : start(start), log2size(log2size), flags(flags), map_start(map_start)
1.72 - {
1.73 - }
1.74 -};
1.75 -
1.76 -
1.77 -
1.78 -/* Program segment abstraction. */
1.79 -
1.80 -class Segment
1.81 -{
1.82 -protected:
1.83 - MappedRegion _region;
1.84 -
1.85 -public:
1.86 - /* Allocated memory. */
1.87 -
1.88 - char *buf;
1.89 - l4re_ds_t ds;
1.90 -
1.91 - /* Segment base and corresponding region base. */
1.92 -
1.93 - l4_addr_t base, region_base;
1.94 -
1.95 - /* Segment size and corresponding region size. */
1.96 -
1.97 - offset_t size, region_size;
1.98 -
1.99 - /* Offset of segment content within the region. */
1.100 -
1.101 - offset_t region_offset;
1.102 -
1.103 - /* Access flags. */
1.104 -
1.105 - l4re_rm_flags_t flags;
1.106 -
1.107 - /* File access details. */
1.108 -
1.109 - offset_t file_offset, file_contents;
1.110 -
1.111 - explicit Segment(offset_t base, offset_t size, l4re_rm_flags_t flags,
1.112 - offset_t file_offset = 0, offset_t file_contents = 0)
1.113 - : base(base), size(size), flags(flags), file_offset(file_offset), file_contents(file_contents)
1.114 - {
1.115 - region_base = trunc(base, L4_PAGESIZE);
1.116 - region_offset = base - region_base;
1.117 - region_size = round(size, L4_PAGESIZE);
1.118 - }
1.119 -
1.120 - long allocate();
1.121 -
1.122 - long fill(file_t *file);
1.123 -
1.124 - MappedRegion ®ion();
1.125 -
1.126 - l4_addr_t region_address(char *address);
1.127 -
1.128 - l4_addr_t region_address(l4_addr_t address);
1.129 -};
1.130 -
1.131 -long Segment::allocate()
1.132 -{
1.133 - return ipc_allocate_align(size, L4RE_RM_F_SEARCH_ADDR | flags,
1.134 - L4_PAGESHIFT, (void **) &buf, &ds);
1.135 -}
1.136 -
1.137 -long Segment::fill(file_t *file)
1.138 -{
1.139 - if (!file_contents)
1.140 - return L4_EOK;
1.141 -
1.142 - memset(buf, 0, region_size);
1.143 - client_seek(file, file_offset, SEEK_SET);
1.144 - offset_t nread = client_read(file, buf + region_offset, file_contents);
1.145 -
1.146 - if (nread < file_contents)
1.147 - return -L4_EIO;
1.148 - else
1.149 - return L4_EOK;
1.150 -}
1.151 -
1.152 -MappedRegion &Segment::region()
1.153 -{
1.154 - _region = MappedRegion((l4_addr_t) buf, page_order(region_size), flags, region_base);
1.155 - return _region;
1.156 -}
1.157 -
1.158 -l4_addr_t Segment::region_address(char *address)
1.159 -{
1.160 - return (l4_addr_t) ((address - buf) + (char *) region_base);
1.161 -}
1.162 -
1.163 -l4_addr_t Segment::region_address(l4_addr_t address)
1.164 -{
1.165 - return (address - (l4_addr_t) buf) + region_base;
1.166 -}
1.167 -
1.168 -
1.169 -
1.170 /* A simple system pager also acting as a region mapper. */
1.171
1.172 typedef std::map<l4_addr_t, MappedRegion> MappedRegions;
1.173 @@ -425,465 +275,6 @@
1.174
1.175
1.176
1.177 -/* Capability mapping definitions for the new task. */
1.178 -
1.179 -struct mapped_cap
1.180 -{
1.181 - l4_umword_t index;
1.182 - l4_cap_idx_t cap;
1.183 - unsigned char rights;
1.184 -};
1.185 -
1.186 -static long map_capability(l4_cap_idx_t task, struct mapped_cap mapped_cap)
1.187 -{
1.188 - return l4_error(l4_task_map(task, L4RE_THIS_TASK_CAP,
1.189 - l4_obj_fpage(mapped_cap.cap, 0, mapped_cap.rights),
1.190 - l4_map_obj_control(mapped_cap.index, L4_MAP_ITEM_MAP)));
1.191 -}
1.192 -
1.193 -static long map_capabilities(l4_cap_idx_t task, struct mapped_cap mapped_caps[])
1.194 -{
1.195 - long err = L4_EOK;
1.196 -
1.197 - for (int i = 0; l4_is_valid_cap(mapped_caps[i].cap) && !err; i++)
1.198 - err = map_capability(task, mapped_caps[i]);
1.199 -
1.200 - return err;
1.201 -}
1.202 -
1.203 -
1.204 -
1.205 -/* A stack abstraction. */
1.206 -
1.207 -class Stack
1.208 -{
1.209 - struct auxv_entry
1.210 - {
1.211 - l4_umword_t key, value;
1.212 - };
1.213 -
1.214 -protected:
1.215 - Segment &_segment;
1.216 -
1.217 - /* Next element pointer. */
1.218 -
1.219 - l4_umword_t *_element;
1.220 -
1.221 - /* Stack section properties. */
1.222 -
1.223 - l4_addr_t _caps;
1.224 - char *_arg_top, *_env_top;
1.225 - char **_argv;
1.226 - char *_auxv_end;
1.227 - int _env_entries;
1.228 -
1.229 - /* L4Re auxiliary and environment regions. */
1.230 -
1.231 - l4re_aux_t *_aux;
1.232 - l4re_env_t *_env;
1.233 -
1.234 -public:
1.235 - /* Start address. */
1.236 -
1.237 - l4_addr_t start;
1.238 -
1.239 - /* Initialise a stack in a memory segment. */
1.240 -
1.241 - explicit Stack(Segment &segment)
1.242 - : _segment(segment)
1.243 - {
1.244 - _element = (l4_umword_t *) (segment.buf + segment.size);
1.245 -
1.246 - /* Add a terminator for any additional initial capabilities. */
1.247 -
1.248 - l4re_env_cap_entry_t *entry = (l4re_env_cap_entry_t *) _element;
1.249 -
1.250 - *(--entry) = l4re_env_cap_entry_t();
1.251 - _element = (l4_umword_t *) entry;
1.252 - }
1.253 -
1.254 - /* Push any additional initial capabilities. */
1.255 -
1.256 - void push_cap_entries(l4re_env_cap_entry_t *entries)
1.257 - {
1.258 - l4re_env_cap_entry_t *entry = (l4re_env_cap_entry_t *) _element;
1.259 -
1.260 - while ((entries != NULL) && (entries->cap != L4_INVALID_CAP))
1.261 - *(--entry) = *entries;
1.262 -
1.263 - _caps = (l4_addr_t) entry;
1.264 - _element = (l4_umword_t *) entry;
1.265 - }
1.266 -
1.267 - /* Push environment values in reverse order. */
1.268 -
1.269 - void push_string(char *s)
1.270 - {
1.271 - char *arg = (char *) _element;
1.272 - char *arg_last = arg;
1.273 -
1.274 - arg -= round(strlen(s) + 1, sizeof(l4_umword_t));
1.275 -
1.276 - memset(arg, 0, arg_last - arg);
1.277 - memcpy(arg, s, strlen(s));
1.278 -
1.279 - _element = (l4_umword_t *) arg;
1.280 - }
1.281 -
1.282 - /* Push environment values in reverse order. */
1.283 -
1.284 - void push_env(char *envp[])
1.285 - {
1.286 - _env_top = (char *) _element;
1.287 - _env_entries = 0;
1.288 -
1.289 - for (; *envp != NULL; envp++, _env_entries++)
1.290 - push_string(*envp);
1.291 - }
1.292 -
1.293 - /* Push argument values in reverse order. */
1.294 -
1.295 - void push_args(int argc, char *argv[])
1.296 - {
1.297 - _arg_top = (char *) _element;
1.298 -
1.299 - for (int i = 0; i < argc; i++)
1.300 - push_string(argv[i]);
1.301 - }
1.302 -
1.303 - /* Loader flags, debugging flags, and the KIP capability index.
1.304 - See: generate_l4aux in Remote_app_model */
1.305 -
1.306 - void push_l4re_aux()
1.307 - {
1.308 - _aux = (l4re_aux_t *) _element;
1.309 - _aux--;
1.310 - _element = (l4_umword_t *) _aux;
1.311 - }
1.312 -
1.313 - void push_l4re_env()
1.314 - {
1.315 - _env = (l4re_env_t *) _element;
1.316 - _env--;
1.317 - _element = (l4_umword_t *) _env;
1.318 - }
1.319 -
1.320 - /* Set the common auxiliary information. */
1.321 -
1.322 - void set_l4re_aux(l4re_aux_t *aux)
1.323 - {
1.324 - memcpy(_aux, aux, sizeof(l4re_aux_t));
1.325 -
1.326 - /* Take the binary name from the first program argument. */
1.327 -
1.328 - _aux->binary = (char *) _argv[0];
1.329 - }
1.330 -
1.331 - /* Set the common environment, introducing the reference to additional
1.332 - capabilities. */
1.333 -
1.334 - void set_l4re_env(l4re_env_t *env)
1.335 - {
1.336 - memcpy(_env, env, sizeof(l4re_env_t));
1.337 - _env->caps = (l4re_env_cap_entry_t *) (_segment.region_address(_caps));
1.338 - }
1.339 -
1.340 - /* Push the auxiliary vector. */
1.341 -
1.342 - void push_auxv()
1.343 - {
1.344 - _auxv_end = (char *) _element;
1.345 -
1.346 - struct auxv_entry *auxv_base = (struct auxv_entry *) _element;
1.347 -
1.348 - /* AUXV NULL. */
1.349 -
1.350 - *(--auxv_base) = {0, 0};
1.351 -
1.352 - /* L4Re global environment pointer. */
1.353 -
1.354 - *(--auxv_base) = {0xf1, _segment.region_address((char *) _env)};
1.355 -
1.356 - /* L4Re auxiliary structure pointer. */
1.357 -
1.358 - *(--auxv_base) = {0xf0, _segment.region_address((char *) _aux)};
1.359 -
1.360 - /* Apparently required entries.
1.361 - NOTE: The user/group identifiers should be obtained from the broader
1.362 - environment. */
1.363 -
1.364 - *(--auxv_base) = {AT_PAGESZ, L4_PAGESIZE};
1.365 - *(--auxv_base) = {AT_UID, 0};
1.366 - *(--auxv_base) = {AT_EUID, 0};
1.367 - *(--auxv_base) = {AT_GID, 0};
1.368 - *(--auxv_base) = {AT_EGID, 0};
1.369 -
1.370 - _element = (l4_umword_t *) auxv_base;
1.371 - }
1.372 -
1.373 - /* Fill the stack in reverse with an address, returning the size of the
1.374 - value. */
1.375 -
1.376 - offset_t write_address(char *arg, char **addr, char *s)
1.377 - {
1.378 - offset_t size = round(strlen(s) + 1, sizeof(l4_umword_t));
1.379 -
1.380 - *addr = (char *) _segment.region_address(arg - size);
1.381 - return size;
1.382 - }
1.383 -
1.384 - /* Populate stack with environment pointers, employing a pointer ordering
1.385 - that is the reverse of the value ordering. */
1.386 -
1.387 - void push_envp(char *envp[])
1.388 - {
1.389 - /* Write the terminating element. */
1.390 -
1.391 - *(--_element) = 0;
1.392 -
1.393 - /* Reserve space and fill the stack from the top inwards. */
1.394 -
1.395 - char **ep = (char **) (_element - _env_entries);
1.396 - char *arg = _env_top;
1.397 -
1.398 - for (; *envp != NULL; envp++, ep++)
1.399 - arg -= write_address(arg, ep, *envp);
1.400 -
1.401 - _element -= _env_entries;
1.402 - }
1.403 -
1.404 - /* Populate stack with argument pointers and count, employing a pointer
1.405 - ordering that is the reverse of the value ordering. */
1.406 -
1.407 - void push_argv(int argc, char *argv[])
1.408 - {
1.409 - /* Write the terminating element. */
1.410 -
1.411 - *(--_element) = 0;
1.412 -
1.413 - /* Reserve space and fill the stack from the top inwards. */
1.414 -
1.415 - _argv = (char **) (_element - argc);
1.416 - char *arg = _arg_top;
1.417 -
1.418 - for (int i = 0; i < argc; i++)
1.419 - arg -= write_address(arg, &_argv[i], argv[i]);
1.420 -
1.421 - /* Write the count. */
1.422 -
1.423 - _element -= argc;
1.424 -
1.425 - *(--_element) = argc;
1.426 - }
1.427 -
1.428 - /* Adjust the stack alignment and return the stack address. */
1.429 -
1.430 - l4_addr_t align_stack()
1.431 - {
1.432 - char *current = (char *) _element;
1.433 - char *adjusted = Ldr::adjust_sp(current, NULL);
1.434 -
1.435 - if (adjusted != current)
1.436 - memmove(adjusted, (const void *) current, _auxv_end - current);
1.437 -
1.438 - _element = (l4_umword_t *) adjusted;
1.439 -
1.440 - return _segment.region_address(adjusted);
1.441 - }
1.442 -
1.443 - /* Populate the stack with arguments and initial environment. */
1.444 -
1.445 - void populate(int argc, char *argv[], char *envp[])
1.446 - {
1.447 - /* Populate stack with environment and argument values. */
1.448 -
1.449 - push_env(envp);
1.450 - push_args(argc, argv);
1.451 -
1.452 - /* Push L4Re flags, environment and auxiliary vector. */
1.453 -
1.454 - push_l4re_aux();
1.455 - push_l4re_env();
1.456 - push_auxv();
1.457 -
1.458 - /* Push environment and argument pointers. */
1.459 -
1.460 - push_envp(envp);
1.461 - push_argv(argc, argv);
1.462 -
1.463 - /* Adjust the stack alignment. */
1.464 -
1.465 - start = align_stack();
1.466 - }
1.467 -};
1.468 -
1.469 -
1.470 -
1.471 -class Process
1.472 -{
1.473 -protected:
1.474 - l4_cap_idx_t _task = L4_INVALID_CAP;
1.475 -
1.476 - /* Capability index definitions. */
1.477 -
1.478 - l4_cap_idx_t _pager_cap = 0x10 << L4_CAP_SHIFT;
1.479 - l4_cap_idx_t _rm_cap = 0x11 << L4_CAP_SHIFT;
1.480 - l4_cap_idx_t _ma_cap = 0x12 << L4_CAP_SHIFT;
1.481 - l4_cap_idx_t _kip_cap = 0x14 << L4_CAP_SHIFT;
1.482 - unsigned int _first_cap = 0x15;
1.483 -
1.484 - /* UTCB details. */
1.485 -
1.486 - l4_addr_t _utcb_start;
1.487 -
1.488 - /* Common environment details. */
1.489 -
1.490 - l4re_aux_t _aux;
1.491 - l4re_env_t _env;
1.492 -
1.493 - /* Task and thread initialisation. */
1.494 -
1.495 - long create_task()
1.496 - {
1.497 - _task = ipc_cap_alloc();
1.498 -
1.499 - if (l4_is_invalid_cap(_task))
1.500 - return -L4_ENOMEM;
1.501 -
1.502 - return l4_error(l4_factory_create_task(l4re_env()->factory, _task, _env.utcb_area));
1.503 - }
1.504 -
1.505 - long create_thread(l4_cap_idx_t *thread)
1.506 - {
1.507 - *thread = ipc_cap_alloc();
1.508 -
1.509 - if (l4_is_invalid_cap(*thread))
1.510 - return -L4_ENOMEM;
1.511 -
1.512 - return l4_error(l4_factory_create_thread(l4re_env()->factory, *thread));
1.513 - }
1.514 -
1.515 -public:
1.516 - explicit Process()
1.517 - {
1.518 - /* Obtain UTCB area details for the task. */
1.519 -
1.520 - l4_fpage_t utcb_fpage = get_utcb_fpage();
1.521 -
1.522 - _utcb_start = l4_fpage_memaddr(utcb_fpage);
1.523 -
1.524 - /* Populate the common initial environment for the threads. */
1.525 -
1.526 - _env.factory = L4_BASE_FACTORY_CAP;
1.527 - _env.main_thread = L4_BASE_THREAD_CAP;
1.528 - _env.log = L4_BASE_LOG_CAP;
1.529 - _env.scheduler = L4_BASE_SCHEDULER_CAP;
1.530 - _env.rm = _rm_cap;
1.531 - _env.mem_alloc = _ma_cap;
1.532 - _env.first_free_cap = _first_cap;
1.533 - _env.utcb_area = utcb_fpage;
1.534 - _env.first_free_utcb = l4_fpage_memaddr(utcb_fpage) + L4_UTCB_OFFSET;
1.535 -
1.536 - /* Populate auxiliary information. */
1.537 -
1.538 - _aux.kip_ds = _kip_cap;
1.539 - _aux.dbg_lvl = 0;
1.540 - _aux.ldr_flags = 0;
1.541 - }
1.542 -
1.543 - /* Configure the task environment. */
1.544 -
1.545 - long configure(l4_cap_idx_t server)
1.546 - {
1.547 - long err = create_task();
1.548 -
1.549 - if (err)
1.550 - return err;
1.551 -
1.552 - /* Map the KIP into the task. */
1.553 -
1.554 - l4_addr_t kip_start = (l4_addr_t) l4re_kip();
1.555 -
1.556 - err = l4_error(l4_task_map(_task, L4RE_THIS_TASK_CAP,
1.557 - l4_fpage(kip_start, L4_PAGESHIFT, L4_FPAGE_RX),
1.558 - kip_start));
1.559 -
1.560 - if (err)
1.561 - return err;
1.562 -
1.563 - /* Define capability mappings for the new task. */
1.564 -
1.565 - struct mapped_cap mapped_caps[] = {
1.566 - {L4_BASE_TASK_CAP, _task, L4_CAP_FPAGE_RWS},
1.567 - {_pager_cap, server, L4_CAP_FPAGE_RWS},
1.568 - {_env.rm, server, L4_CAP_FPAGE_RWS},
1.569 - {_env.factory, l4re_env()->factory, L4_CAP_FPAGE_RWS},
1.570 - {_env.log, l4re_env()->log, L4_CAP_FPAGE_RWS},
1.571 - {_env.scheduler, l4re_env()->scheduler, L4_CAP_FPAGE_RWS},
1.572 - {_env.mem_alloc, l4re_env()->mem_alloc, L4_CAP_FPAGE_RWS},
1.573 - {0, L4_INVALID_CAP, 0},
1.574 - };
1.575 -
1.576 - return map_capabilities(_task, mapped_caps);
1.577 - }
1.578 -
1.579 - /* Create, initialise and start a thread. */
1.580 -
1.581 - long thread_start(l4_addr_t program_start, Stack &st)
1.582 - {
1.583 - l4_cap_idx_t thread;
1.584 - long err;
1.585 -
1.586 - err = create_thread(&thread);
1.587 -
1.588 - if (err)
1.589 - return err;
1.590 -
1.591 - /* Initialise the thread with pager, UTCB and task details. */
1.592 -
1.593 - l4_thread_control_start();
1.594 - l4_thread_control_pager(_pager_cap);
1.595 - l4_thread_control_exc_handler(_pager_cap);
1.596 - l4_thread_control_bind((l4_utcb_t *) _utcb_start, _task);
1.597 -
1.598 - err = l4_error(l4_thread_control_commit(thread));
1.599 -
1.600 - if (err)
1.601 - {
1.602 - ipc_cap_free(thread);
1.603 - return err;
1.604 - }
1.605 -
1.606 - /* Map the thread capability to the task. */
1.607 -
1.608 - map_capability(_task, (struct mapped_cap) {_env.main_thread, thread, L4_CAP_FPAGE_RWS});
1.609 -
1.610 - /* Populate the initial environment in the thread. */
1.611 -
1.612 - st.set_l4re_aux(&_aux);
1.613 - st.set_l4re_env(&_env);
1.614 -
1.615 - /* Set the start details. */
1.616 -
1.617 - err = l4_error(l4_thread_ex_regs(thread, program_start, st.start, 0));
1.618 -
1.619 - if (err)
1.620 - return err;
1.621 -
1.622 - /* Select a new address for the next thread. */
1.623 -
1.624 - _utcb_start += L4_UTCB_OFFSET;
1.625 -
1.626 - /* Start the thread. */
1.627 -
1.628 - l4_sched_param_t sp = l4_sched_param(L4RE_MAIN_THREAD_PRIO);
1.629 -
1.630 - return l4_error(l4_scheduler_run_thread(l4re_env()->scheduler, thread, &sp));
1.631 - }
1.632 -};
1.633 -
1.634 -
1.635 -
1.636 class PayloadBase
1.637 {
1.638 public: