1.1 --- a/tests/dstest_exec.cc Thu Feb 16 18:44:41 2023 +0100
1.2 +++ b/tests/dstest_exec.cc Thu Feb 16 18:45:23 2023 +0100
1.3 @@ -1,7 +1,7 @@
1.4 /*
1.5 * Support for executing code in new tasks and threads.
1.6 *
1.7 - * Copyright (C) 2022 Paul Boddie <paul@boddie.org.uk>
1.8 + * Copyright (C) 2022, 2023 Paul Boddie <paul@boddie.org.uk>
1.9 *
1.10 * This program is free software; you can redistribute it and/or
1.11 * modify it under the terms of the GNU General Public License as
1.12 @@ -23,54 +23,11 @@
1.13 #include <l4/sys/err.h>
1.14 #include <l4/util/util.h>
1.15
1.16 -#include <exec/elf.h>
1.17 -#include <exec/external_pager.h>
1.18 -#include <exec/memory.h>
1.19 -#include <exec/process.h>
1.20 -#include <ipc/cap_alloc.h>
1.21 -#include <ipc/map.h>
1.22 -#include <ipc/server.h>
1.23 +#include <exec/process_creator.h>
1.24 +#include <systypes/fcntl.h>
1.25
1.26 #include <stdio.h>
1.27
1.28 -#include <pthread-l4.h>
1.29 -#include <pthread.h>
1.30 -
1.31 -#include "parent_pager_object_server.h"
1.32 -
1.33 -
1.34 -
1.35 -/* External system-level pager for the region mapper in a created task. The
1.36 - allocated regions requested by the region mapper are constrained to an area
1.37 - of memory that must not overlap with the area reserved for the program being
1.38 - run. */
1.39 -
1.40 -static ExternalPager exec_pager(0, 10 * L4_PAGESIZE);
1.41 -
1.42 -static const offset_t initial_stack_size = 16 * L4_PAGESIZE;
1.43 -
1.44 -
1.45 -
1.46 -/* Start the system pager in a separate thread. */
1.47 -
1.48 -static long start_pager(ipc_server_config_type &config)
1.49 -{
1.50 - pthread_t pager_thread;
1.51 - pthread_attr_t attr;
1.52 -
1.53 - pthread_attr_init(&attr);
1.54 - pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
1.55 -
1.56 - ipc_server_init_for(&config, ParentPagerObject, &exec_pager);
1.57 -
1.58 - long err = pthread_create(&pager_thread, &attr, ipc_server_start_mainloop, &config);
1.59 -
1.60 - if (err)
1.61 - return err;
1.62 -
1.63 - return ipc_server_start_config_thread(&config, pthread_l4_cap(pager_thread));
1.64 -}
1.65 -
1.66
1.67
1.68 int main(int argc, char *argv[])
1.69 @@ -79,251 +36,27 @@
1.70
1.71 if (argc < 3)
1.72 {
1.73 - printf("Need a program to run as the region mapper and a main program.\n");
1.74 + printf("Need a region mapper and the actual program to run.\n");
1.75 return 1;
1.76 }
1.77
1.78 - /* Define the different payloads. */
1.79 -
1.80 char *rm_filename = argv[1];
1.81 char *program_filename = argv[2];
1.82
1.83 - /* Initialise the memory segments of the region mapper. These are mapped into
1.84 - this task so that we may access them. */
1.85 -
1.86 - ExplicitSegment rm_stack(Utcb_area_start - initial_stack_size, initial_stack_size, L4_FPAGE_RW);
1.87 - Payload *rm_payload;
1.88 -
1.89 - if (exec_get_payload(rm_filename, &rm_payload, true))
1.90 - {
1.91 - printf("Could not initialise region mapper: %s\n", rm_filename);
1.92 - return 1;
1.93 - }
1.94 -
1.95 - if (rm_stack.allocate(true))
1.96 - {
1.97 - printf("Could not allocate region mapper stack.\n");
1.98 - return 1;
1.99 - }
1.100 -
1.101 - /* Initialise the memory segments of the actual program. These are not mapped
1.102 - into this task, instead being accessed by the region mapper in the new
1.103 - task. */
1.104 -
1.105 - ExplicitSegment program_stack(Utcb_area_start - initial_stack_size * 2, initial_stack_size, L4_FPAGE_RW);
1.106 - Payload *program_payload;
1.107 -
1.108 - if (exec_get_payload(program_filename, &program_payload, false))
1.109 - {
1.110 - printf("Could not initialise program: %s\n", program_filename);
1.111 - return 1;
1.112 - }
1.113 -
1.114 - if (program_stack.allocate(true))
1.115 - {
1.116 - printf("Could not allocate program stack.\n");
1.117 - return 1;
1.118 - }
1.119 -
1.120 - /* Initialise pager regions for the region mapper. */
1.121 -
1.122 - for (unsigned int i = 0; i < rm_payload->segments(); i++)
1.123 - {
1.124 - if (rm_payload->segment(i)->loadable())
1.125 - exec_pager.add(rm_payload->segment(i)->region());
1.126 - }
1.127 -
1.128 - exec_pager.add(rm_stack.region());
1.129 -
1.130 - /* Start the pager in a separate thread. */
1.131 -
1.132 - ipc_server_config_type config;
1.133 -
1.134 - printf("Starting pager thread...\n");
1.135 + ProcessCreator creator(rm_filename);
1.136 + file_t *program_file = client_open(program_filename, O_RDONLY);
1.137
1.138 - err = start_pager(config);
1.139 -
1.140 - if (err)
1.141 - {
1.142 - printf("Could not start pager.\n");
1.143 - return 1;
1.144 - }
1.145 -
1.146 - /* Configure the environment for the task, reserving two threads. */
1.147 -
1.148 - Process process;
1.149 -
1.150 - err = process.configure_task();
1.151 -
1.152 - if (err)
1.153 - {
1.154 - printf("Could not configure task.\n");
1.155 - return 1;
1.156 - }
1.157 -
1.158 - /* Configure the environment for the thread, specifying the pager (and
1.159 - exception handler plus region mapper). */
1.160 -
1.161 - err = process.configure_thread(config.server);
1.162 -
1.163 - if (err)
1.164 + if (!client_opened(program_file))
1.165 {
1.166 - printf("Could not configure thread.\n");
1.167 - return 1;
1.168 - }
1.169 -
1.170 - err = process.set_parent(config.server);
1.171 -
1.172 - if (err)
1.173 - {
1.174 - printf("Could not map parent to task.\n");
1.175 - return 1;
1.176 - }
1.177 -
1.178 - /* Create an unbound IPC gate for the region mapper. */
1.179 -
1.180 - l4_cap_idx_t ipc_gate = ipc_cap_alloc();
1.181 -
1.182 - if (l4_is_invalid_cap(ipc_gate))
1.183 - {
1.184 - printf("Could not allocate IPC gate capability.\n");
1.185 - return 1;
1.186 - }
1.187 -
1.188 - err = l4_error(l4_factory_create_gate(l4re_env()->factory, ipc_gate, L4_INVALID_CAP, 0));
1.189 -
1.190 - if (err)
1.191 - {
1.192 - printf("Could not create IPC gate.\n");
1.193 + printf("Could not open program file.\n");
1.194 return 1;
1.195 }
1.196
1.197 - /* Define regions employing dataspaces to provide program segments.
1.198 -
1.199 - Define capabilities for mapping, including region dataspace capabilities,
1.200 - the stack dataspace capability, and the server capability.
1.201 -
1.202 - Here, the arrays are sized for the maximum number of regions and
1.203 - capabilities, but in practice only the loadable segments are used, leaving
1.204 - fewer elements utilised. A terminating entry is employed to indicate the
1.205 - limit of utilised elements. */
1.206 -
1.207 - struct exec_region rm_regions[rm_payload->segments() + 2];
1.208 - struct ipc_mapped_cap rm_mapped_caps[rm_payload->segments() + 3];
1.209 - l4_cap_idx_t mapped_cap;
1.210 - unsigned int rm_index = 0;
1.211 -
1.212 - for (unsigned int i = 0; i < program_payload->segments(); i++)
1.213 - {
1.214 - Segment *s = program_payload->segment(i);
1.215 -
1.216 - if (s->loadable())
1.217 - {
1.218 - mapped_cap = process.allocate_cap();
1.219 - rm_regions[rm_index] = s->exec_region();
1.220 - rm_mapped_caps[rm_index] = (struct ipc_mapped_cap) {mapped_cap, rm_regions[rm_index].ds, L4_CAP_FPAGE_RWS, 0};
1.221 - rm_regions[rm_index].ds = mapped_cap;
1.222 - rm_index++;
1.223 - }
1.224 - }
1.225 -
1.226 - /* Introduce the stack region and capability. */
1.227 -
1.228 - mapped_cap = process.allocate_cap();
1.229 - rm_regions[rm_index] = program_stack.exec_region();
1.230 - rm_mapped_caps[rm_index] = (struct ipc_mapped_cap) {mapped_cap, program_stack.exec_region().ds, L4_CAP_FPAGE_RWS, 0};
1.231 - rm_regions[rm_index].ds = mapped_cap;
1.232 - rm_index++;
1.233 -
1.234 - /* Terminate the region array. */
1.235 -
1.236 - rm_regions[rm_index] = (struct exec_region) {0, 0, 0, L4_INVALID_CAP};
1.237 -
1.238 - /* Introduce the server capability. */
1.239 -
1.240 - l4_cap_idx_t ipc_gate_cap = process.allocate_cap();
1.241 -
1.242 - printf("Mapping %lx to %lx in task.\n", ipc_gate, ipc_gate_cap);
1.243 -
1.244 - rm_mapped_caps[rm_index] = (struct ipc_mapped_cap) {ipc_gate_cap, ipc_gate, L4_CAP_FPAGE_RWS, L4_FPAGE_C_OBJ_RIGHTS};
1.245 - rm_index++;
1.246 -
1.247 - /* Terminate the capability array. */
1.248 -
1.249 - rm_mapped_caps[rm_index] = (struct ipc_mapped_cap) {0, L4_INVALID_CAP, 0, 0};
1.250 -
1.251 - /* Map these additional capabilities. */
1.252 -
1.253 - printf("Map additional capabilities...\n");
1.254 -
1.255 - process.map_capabilities(rm_mapped_caps, false);
1.256 -
1.257 - /* Define the IPC gate as an initial capability to be acquired by the region
1.258 - mapper via the l4re_env API. The capability index is assigned above when
1.259 - mapping the capability and encoded in the entry below. */
1.260 -
1.261 - l4re_env_cap_entry_t rm_init_caps[] = {
1.262 - l4re_env_cap_entry_t("server", ipc_gate_cap, L4_CAP_FPAGE_RWS),
1.263 - l4re_env_cap_entry_t()
1.264 - };
1.265 -
1.266 - /* NOTE: Environment vector is currently not defined. */
1.267 -
1.268 - char *envp[] = {NULL};
1.269 -
1.270 - /* Populate a thread stack with argument and environment details for the
1.271 - region mapper, plus the initial server capability and region details. */
1.272 -
1.273 - printf("Populating region mapper stack...\n");
1.274 -
1.275 - Stack rm_st(rm_stack);
1.276 -
1.277 - rm_st.set_init_caps(rm_init_caps);
1.278 - rm_st.set_regions(rm_regions);
1.279 - rm_st.populate(1, argv + 1, envp);
1.280 -
1.281 - /* Start the region mapper thread in the appropriate stack. */
1.282 -
1.283 - printf("Run region mapper thread...\n");
1.284 -
1.285 - err = process.thread_start(rm_payload->entry_point(), rm_st);
1.286 + err = creator.start(program_file, argc - 2, (const char **) argv + 2);
1.287
1.288 if (err)
1.289 {
1.290 - printf("Could not run thread for region mapper.\n");
1.291 - return 1;
1.292 - }
1.293 -
1.294 - /* Configure the environment for the thread, specifying the pager (and
1.295 - exception handler plus region mapper). */
1.296 -
1.297 - err = process.configure_thread(ipc_gate, ipc_gate_cap);
1.298 -
1.299 - if (err)
1.300 - {
1.301 - printf("Could not configure task.\n");
1.302 - return 1;
1.303 - }
1.304 -
1.305 - /* Populate a thread stack with argument and environment details for the
1.306 - actual program. The server capability should be assigned to the region
1.307 - mapper capability slot already. */
1.308 -
1.309 - printf("Populating program stack...\n");
1.310 -
1.311 - Stack program_st(program_stack);
1.312 -
1.313 - program_st.populate(argc - 2, argv + 2, envp);
1.314 -
1.315 - /* Start the program thread in the appropriate stack. */
1.316 -
1.317 - printf("Run program thread...\n");
1.318 -
1.319 - err = process.thread_start(program_payload->entry_point(), program_st);
1.320 -
1.321 - if (err)
1.322 - {
1.323 - printf("Could not run thread for program: %s\n", l4sys_errtostr(err));
1.324 + printf("Could not start process: %s\n", l4sys_errtostr(err));
1.325 return 1;
1.326 }
1.327