1.1 --- a/tests/dstest_exec.cc Thu May 05 16:04:01 2022 +0200
1.2 +++ b/tests/dstest_exec.cc Sun May 08 23:51:50 2022 +0200
1.3 @@ -433,18 +433,19 @@
1.4 unsigned char rights;
1.5 };
1.6
1.7 +static long map_capability(l4_cap_idx_t task, struct mapped_cap mapped_cap)
1.8 +{
1.9 + return l4_error(l4_task_map(task, L4RE_THIS_TASK_CAP,
1.10 + l4_obj_fpage(mapped_cap.cap, 0, mapped_cap.rights),
1.11 + l4_map_obj_control(mapped_cap.index, L4_MAP_ITEM_MAP)));
1.12 +}
1.13 +
1.14 static long map_capabilities(l4_cap_idx_t task, struct mapped_cap mapped_caps[])
1.15 {
1.16 long err = L4_EOK;
1.17 - int i = 0;
1.18
1.19 - while (l4_is_valid_cap(mapped_caps[i].cap) && !err)
1.20 - {
1.21 - err = l4_error(l4_task_map(task, L4RE_THIS_TASK_CAP,
1.22 - l4_obj_fpage(mapped_caps[i].cap, 0, mapped_caps[i].rights),
1.23 - l4_map_obj_control(mapped_caps[i].index, L4_MAP_ITEM_MAP)));
1.24 - i++;
1.25 - }
1.26 + for (int i = 0; l4_is_valid_cap(mapped_caps[i].cap) && !err; i++)
1.27 + err = map_capability(task, mapped_caps[i]);
1.28
1.29 return err;
1.30 }
1.31 @@ -474,19 +475,28 @@
1.32 char *_auxv_end;
1.33 int _env_entries;
1.34
1.35 + /* L4Re environment region. */
1.36 +
1.37 + l4re_env_t *_env;
1.38 +
1.39 public:
1.40 - /* Start address and environment structure. */
1.41 + /* Start address. */
1.42
1.43 l4_addr_t start;
1.44 - l4re_env_t *env;
1.45 - l4_fpage_t utcb_fpage;
1.46
1.47 /* Initialise a stack in a memory segment. */
1.48
1.49 - explicit Stack(Segment &segment, l4_fpage_t utcb_fpage)
1.50 - : _segment(segment), utcb_fpage(utcb_fpage)
1.51 + explicit Stack(Segment &segment)
1.52 + : _segment(segment)
1.53 {
1.54 _element = (l4_umword_t *) (segment.buf + segment.size);
1.55 +
1.56 + /* Add a terminator for any additional initial capabilities. */
1.57 +
1.58 + l4re_env_cap_entry_t *entry = (l4re_env_cap_entry_t *) _element;
1.59 +
1.60 + *(--entry) = l4re_env_cap_entry_t();
1.61 + _element = (l4_umword_t *) entry;
1.62 }
1.63
1.64 /* Push any additional initial capabilities. */
1.65 @@ -495,8 +505,6 @@
1.66 {
1.67 l4re_env_cap_entry_t *entry = (l4re_env_cap_entry_t *) _element;
1.68
1.69 - *(--entry) = l4re_env_cap_entry_t();
1.70 -
1.71 while ((entries != NULL) && (entries->cap != L4_INVALID_CAP))
1.72 *(--entry) = *entries;
1.73
1.74 @@ -552,21 +560,18 @@
1.75
1.76 void push_l4re_env()
1.77 {
1.78 - env = (l4re_env_t *) _element;
1.79 - env--;
1.80 + _env = (l4re_env_t *) _element;
1.81 + _env--;
1.82 + _element = (l4_umword_t *) _env;
1.83 + }
1.84
1.85 - env->factory = L4_BASE_FACTORY_CAP;
1.86 - env->main_thread = L4_BASE_THREAD_CAP;
1.87 - env->log = L4_BASE_LOG_CAP;
1.88 - env->scheduler = L4_BASE_SCHEDULER_CAP;
1.89 - env->rm = 0x11 << L4_CAP_SHIFT;
1.90 - env->mem_alloc = 0x12 << L4_CAP_SHIFT;
1.91 - env->first_free_cap = 0x15;
1.92 - env->caps = (l4re_env_cap_entry_t *) (_segment.region_address(_caps));
1.93 - env->utcb_area = utcb_fpage;
1.94 - env->first_free_utcb = l4_fpage_memaddr(utcb_fpage) + L4_UTCB_OFFSET;
1.95 + /* Set the common environment, introducing the reference to additional
1.96 + capabilities. */
1.97
1.98 - _element = (l4_umword_t *) env;
1.99 + void set_l4re_env(l4re_env_t *env)
1.100 + {
1.101 + memcpy(_env, env, sizeof(l4re_env_t));
1.102 + _env->caps = (l4re_env_cap_entry_t *) (_segment.region_address(_caps));
1.103 }
1.104
1.105 /* Push the auxiliary vector. */
1.106 @@ -583,7 +588,7 @@
1.107
1.108 /* L4Re global environment pointer. */
1.109
1.110 - *(--auxv_base) = {0xf1, _segment.region_address((char *) env)};
1.111 + *(--auxv_base) = {0xf1, _segment.region_address((char *) _env)};
1.112
1.113 /* Apparently required entries.
1.114 NOTE: The user/group identifiers should be obtained from the broader
1.115 @@ -668,12 +673,10 @@
1.116 return _segment.region_address(adjusted);
1.117 }
1.118
1.119 - /* Populate stack with additional capabilities. */
1.120 + /* Populate the stack with arguments and initial environment. */
1.121
1.122 void populate(int argc, char *argv[], char *envp[])
1.123 {
1.124 - push_cap_entries(NULL);
1.125 -
1.126 /* Populate stack with environment and argument values. */
1.127
1.128 push_env(envp);
1.129 @@ -698,94 +701,154 @@
1.130
1.131
1.132
1.133 -class Environment
1.134 +class Process
1.135 {
1.136 protected:
1.137 - Stack &_st;
1.138 - l4_cap_idx_t task = L4_INVALID_CAP, thread = L4_INVALID_CAP;
1.139 + l4_cap_idx_t _task = L4_INVALID_CAP;
1.140 +
1.141 + /* Capability index definitions. */
1.142 +
1.143 l4_cap_idx_t _pager_cap = 0x10 << L4_CAP_SHIFT;
1.144 + l4_cap_idx_t _rm_cap = 0x11 << L4_CAP_SHIFT;
1.145 + l4_cap_idx_t _ma_cap = 0x12 << L4_CAP_SHIFT;
1.146 + unsigned int _first_cap = 0x15;
1.147
1.148 -public:
1.149 - explicit Environment(Stack &st)
1.150 - : _st(st)
1.151 - {
1.152 - }
1.153 + /* UTCB details. */
1.154 +
1.155 + l4_addr_t _utcb_start;
1.156 +
1.157 + /* Common environment details. */
1.158 +
1.159 + l4re_env_t _env;
1.160 +
1.161 + /* Task and thread initialisation. */
1.162
1.163 long create_task()
1.164 {
1.165 - task = ipc_cap_alloc();
1.166 + _task = ipc_cap_alloc();
1.167
1.168 - if (l4_is_invalid_cap(task))
1.169 + if (l4_is_invalid_cap(_task))
1.170 return -L4_ENOMEM;
1.171
1.172 - return l4_error(l4_factory_create_task(l4re_env()->factory, task, _st.utcb_fpage));
1.173 + return l4_error(l4_factory_create_task(l4re_env()->factory, _task, _env.utcb_area));
1.174 + }
1.175 +
1.176 + long create_thread(l4_cap_idx_t *thread)
1.177 + {
1.178 + *thread = ipc_cap_alloc();
1.179 +
1.180 + if (l4_is_invalid_cap(*thread))
1.181 + return -L4_ENOMEM;
1.182 +
1.183 + return l4_error(l4_factory_create_thread(l4re_env()->factory, *thread));
1.184 }
1.185
1.186 - long create_thread()
1.187 +public:
1.188 + explicit Process()
1.189 {
1.190 - thread = ipc_cap_alloc();
1.191 + /* Obtain UTCB area details for the task. */
1.192 +
1.193 + l4_fpage_t utcb_fpage = get_utcb_fpage();
1.194 +
1.195 + _utcb_start = l4_fpage_memaddr(utcb_fpage);
1.196
1.197 - if (l4_is_invalid_cap(thread))
1.198 - return -L4_ENOMEM;
1.199 + /* Populate the common initial environment for the threads. */
1.200
1.201 - return l4_error(l4_factory_create_thread(l4re_env()->factory, thread));
1.202 + _env.factory = L4_BASE_FACTORY_CAP;
1.203 + _env.main_thread = L4_BASE_THREAD_CAP;
1.204 + _env.log = L4_BASE_LOG_CAP;
1.205 + _env.scheduler = L4_BASE_SCHEDULER_CAP;
1.206 + _env.rm = _rm_cap;
1.207 + _env.mem_alloc = _ma_cap;
1.208 + _env.first_free_cap = _first_cap;
1.209 + _env.utcb_area = utcb_fpage;
1.210 + _env.first_free_utcb = l4_fpage_memaddr(utcb_fpage) + L4_UTCB_OFFSET;
1.211 }
1.212
1.213 /* Configure the task environment. */
1.214
1.215 long configure(l4_cap_idx_t server)
1.216 {
1.217 + long err = create_task();
1.218 +
1.219 + if (err)
1.220 + return err;
1.221 +
1.222 /* Map the KIP into the task. */
1.223
1.224 l4_addr_t kip_start = (l4_addr_t) l4re_kip();
1.225
1.226 - long err = l4_error(l4_task_map(task, L4RE_THIS_TASK_CAP,
1.227 - l4_fpage(kip_start, L4_PAGESHIFT, L4_FPAGE_RX),
1.228 - kip_start));
1.229 + err = l4_error(l4_task_map(_task, L4RE_THIS_TASK_CAP,
1.230 + l4_fpage(kip_start, L4_PAGESHIFT, L4_FPAGE_RX),
1.231 + kip_start));
1.232
1.233 if (err)
1.234 return err;
1.235
1.236 /* Define capability mappings for the new task. */
1.237
1.238 - l4re_env_t *env = _st.env;
1.239 -
1.240 struct mapped_cap mapped_caps[] = {
1.241 - {L4_BASE_TASK_CAP, task, L4_CAP_FPAGE_RWS},
1.242 + {L4_BASE_TASK_CAP, _task, L4_CAP_FPAGE_RWS},
1.243 {_pager_cap, server, L4_CAP_FPAGE_RWS},
1.244 - {env->rm, server, L4_CAP_FPAGE_RWS},
1.245 - {env->main_thread, thread, L4_CAP_FPAGE_RWS},
1.246 - {env->factory, l4re_env()->factory, L4_CAP_FPAGE_RWS},
1.247 - {env->log, l4re_env()->log, L4_CAP_FPAGE_RWS},
1.248 - {env->scheduler, l4re_env()->scheduler, L4_CAP_FPAGE_RWS},
1.249 - {env->mem_alloc, l4re_env()->mem_alloc, L4_CAP_FPAGE_RWS},
1.250 + {_env.rm, server, L4_CAP_FPAGE_RWS},
1.251 + {_env.factory, l4re_env()->factory, L4_CAP_FPAGE_RWS},
1.252 + {_env.log, l4re_env()->log, L4_CAP_FPAGE_RWS},
1.253 + {_env.scheduler, l4re_env()->scheduler, L4_CAP_FPAGE_RWS},
1.254 + {_env.mem_alloc, l4re_env()->mem_alloc, L4_CAP_FPAGE_RWS},
1.255 {0, L4_INVALID_CAP, 0},
1.256 };
1.257
1.258 - return map_capabilities(task, mapped_caps);
1.259 + return map_capabilities(_task, mapped_caps);
1.260 }
1.261
1.262 - /* Initialise the thread. */
1.263 + /* Create, initialise and start a thread. */
1.264
1.265 - long thread_init(l4_addr_t program_start)
1.266 + long thread_start(l4_addr_t program_start, Stack &st)
1.267 {
1.268 - l4_thread_control_start();
1.269 - l4_thread_control_pager(_pager_cap);
1.270 - l4_thread_control_exc_handler(_pager_cap);
1.271 - l4_thread_control_bind((l4_utcb_t *) l4_fpage_memaddr(_st.utcb_fpage), task);
1.272 + l4_cap_idx_t thread;
1.273 + long err;
1.274
1.275 - long err = l4_error(l4_thread_control_commit(thread));
1.276 + err = create_thread(&thread);
1.277
1.278 if (err)
1.279 return err;
1.280
1.281 - return l4_error(l4_thread_ex_regs(thread, program_start, _st.start, 0));
1.282 - }
1.283 + /* Initialise the thread with pager, UTCB and task details. */
1.284 +
1.285 + l4_thread_control_start();
1.286 + l4_thread_control_pager(_pager_cap);
1.287 + l4_thread_control_exc_handler(_pager_cap);
1.288 + l4_thread_control_bind((l4_utcb_t *) _utcb_start, _task);
1.289 +
1.290 + err = l4_error(l4_thread_control_commit(thread));
1.291 +
1.292 + if (err)
1.293 + {
1.294 + ipc_cap_free(thread);
1.295 + return err;
1.296 + }
1.297 +
1.298 + /* Map the thread capability to the task. */
1.299
1.300 - /* Start the thread. */
1.301 + map_capability(_task, (struct mapped_cap) {_env.main_thread, thread, L4_CAP_FPAGE_RWS});
1.302 +
1.303 + /* Populate the initial environment in the thread. */
1.304 +
1.305 + st.set_l4re_env(&_env);
1.306 +
1.307 + /* Set the start details. */
1.308 +
1.309 + err = l4_error(l4_thread_ex_regs(thread, program_start, st.start, 0));
1.310
1.311 - long thread_start()
1.312 - {
1.313 + if (err)
1.314 + return err;
1.315 +
1.316 + /* Select a new address for the next thread. */
1.317 +
1.318 + _utcb_start += L4_UTCB_OFFSET;
1.319 +
1.320 + /* Start the thread. */
1.321 +
1.322 l4_sched_param_t sp = l4_sched_param(L4RE_MAIN_THREAD_PRIO);
1.323
1.324 return l4_error(l4_scheduler_run_thread(l4re_env()->scheduler, thread, &sp));
1.325 @@ -867,43 +930,6 @@
1.326 }
1.327 }
1.328
1.329 - /* Populate the stack with argument and environment details. */
1.330 -
1.331 - Stack st(stack, get_utcb_fpage());
1.332 - Environment environment(st);
1.333 -
1.334 - /* NOTE: Environment vector is currently not defined. */
1.335 -
1.336 - char *envp[] = {NULL};
1.337 -
1.338 - st.populate(argc - 1, argv + 1, envp);
1.339 -
1.340 - /* Create a new task and thread. */
1.341 -
1.342 - err = environment.create_task();
1.343 -
1.344 - if (err)
1.345 - {
1.346 - printf("Could not create task.\n");
1.347 - return 1;
1.348 - }
1.349 -
1.350 - err = environment.create_thread();
1.351 -
1.352 - if (err)
1.353 - {
1.354 - printf("Could not create thread.\n");
1.355 - return 1;
1.356 - }
1.357 -
1.358 - err = environment.thread_init(program_start);
1.359 -
1.360 - if (err)
1.361 - {
1.362 - printf("Could not configure thread.\n");
1.363 - return 1;
1.364 - }
1.365 -
1.366 /* Start the pager. */
1.367
1.368 ipc_server_config_type config;
1.369 @@ -937,19 +963,31 @@
1.370 /* Configure the environment for the task, specifying the pager (and exception
1.371 handler plus region mapper). */
1.372
1.373 - err = environment.configure(config.server);
1.374 + Process process;
1.375 +
1.376 + err = process.configure(config.server);
1.377
1.378 if (err)
1.379 {
1.380 - printf("Could not map capabilities into task.\n");
1.381 + printf("Could not configure task.\n");
1.382 return 1;
1.383 }
1.384
1.385 - /* Start the new thread. */
1.386 + /* Populate a thread stack with argument and environment details. */
1.387 +
1.388 + Stack st(stack);
1.389 +
1.390 + /* NOTE: Environment vector is currently not defined. */
1.391 +
1.392 + char *envp[] = {NULL};
1.393 +
1.394 + st.populate(argc - 1, argv + 1, envp);
1.395 +
1.396 + /* Start the new thread in the given stack. */
1.397
1.398 printf("Run thread...\n");
1.399
1.400 - err = environment.thread_start();
1.401 + err = process.thread_start(program_start, st);
1.402
1.403 if (err)
1.404 {