1.1 --- a/tests/dstest_exec.cc Tue May 03 01:01:30 2022 +0200
1.2 +++ b/tests/dstest_exec.cc Wed May 04 01:16:08 2022 +0200
1.3 @@ -50,6 +50,36 @@
1.4
1.5
1.6
1.7 +/* UTCB properties.
1.8 + See: moe/server/src/loader.cc */
1.9 +
1.10 +enum ipc_exec_utcb
1.11 +{
1.12 + Default_max_threads = 16,
1.13 +#ifdef ARCH_mips
1.14 + Utcb_area_start = 0x73000000,
1.15 +#else
1.16 + Utcb_area_start = 0xb3000000,
1.17 +#endif
1.18 +};
1.19 +
1.20 +static l4_fpage_t get_utcb_fpage()
1.21 +{
1.22 + /* UTCB location and size. */
1.23 +
1.24 + l4_addr_t utcb_start = Utcb_area_start;
1.25 + int utcb_log2size = page_order(Default_max_threads * L4_UTCB_OFFSET);
1.26 +
1.27 + /* Round up to at least one page. */
1.28 +
1.29 + if (utcb_log2size < L4_PAGESHIFT)
1.30 + utcb_log2size = L4_PAGESHIFT;
1.31 +
1.32 + return l4_fpage(utcb_start, utcb_log2size, 0);
1.33 +}
1.34 +
1.35 +
1.36 +
1.37 /* Region data structures. */
1.38
1.39 class Region
1.40 @@ -395,136 +425,373 @@
1.41
1.42
1.43
1.44 -static l4_addr_t populate_stack(Segment &stack, int argc, char *argv[], l4_fpage_t utcb_fpage)
1.45 -{
1.46 - /* Populate stack with additional capabilities. */
1.47 -
1.48 - l4re_env_cap_entry_t *stack_env_cap = (l4re_env_cap_entry_t *) (stack.buf + stack.size);
1.49 +/* Capability mapping definitions for the new task. */
1.50
1.51 - /* Special invalid/terminating environment capability entry. */
1.52 -
1.53 - *(--stack_env_cap) = l4re_env_cap_entry_t();
1.54 -
1.55 - printf("Stack region end: %p\n", stack_env_cap);
1.56 -
1.57 - l4_addr_t caps_start = (l4_addr_t) stack_env_cap;
1.58 - l4_umword_t *stack_element = (l4_umword_t *) stack_env_cap;
1.59 +struct mapped_cap
1.60 +{
1.61 + l4_umword_t index;
1.62 + l4_cap_idx_t cap;
1.63 + unsigned char rights;
1.64 +};
1.65
1.66 - /* Populate stack with argument values. */
1.67 +static long map_capabilities(l4_cap_idx_t task, struct mapped_cap mapped_caps[])
1.68 +{
1.69 + long err = L4_EOK;
1.70 + int i = 0;
1.71
1.72 - char *stack_arg = (char *) stack_element;
1.73 - char *stack_arg_top = stack_arg;
1.74 - int arg;
1.75 -
1.76 - for (arg = argc - 1; arg >= 0; arg--)
1.77 + while (l4_is_valid_cap(mapped_caps[i].cap) && !err)
1.78 {
1.79 - char *stack_arg_last = stack_arg;
1.80 -
1.81 - stack_arg -= round(strlen(argv[arg]) + 1, sizeof(l4_umword_t));
1.82 -
1.83 - memset(stack_arg, 0, stack_arg_last - stack_arg);
1.84 - memcpy(stack_arg, argv[arg], strlen(argv[arg]));
1.85 -
1.86 - printf("Stack L4 program argument: %p / %lx\n", stack_arg, stack.region_address(stack_arg));
1.87 + err = l4_error(l4_task_map(task, L4RE_THIS_TASK_CAP,
1.88 + l4_obj_fpage(mapped_caps[i].cap, 0, mapped_caps[i].rights),
1.89 + l4_map_obj_control(mapped_caps[i].index, L4_MAP_ITEM_MAP)));
1.90 + i++;
1.91 }
1.92
1.93 - stack_element = (l4_umword_t *) stack_arg;
1.94 + return err;
1.95 +}
1.96 +
1.97 +
1.98 +
1.99 +/* A stack abstraction. */
1.100 +
1.101 +class Stack
1.102 +{
1.103 + struct auxv_entry
1.104 + {
1.105 + l4_umword_t key, value;
1.106 + };
1.107 +
1.108 +protected:
1.109 + Segment &_segment;
1.110 +
1.111 + /* Next element pointer. */
1.112 +
1.113 + l4_umword_t *_element;
1.114 +
1.115 + /* Stack section properties. */
1.116 +
1.117 + l4_addr_t _caps;
1.118 + char *_arg_top, *_env_top;
1.119 + char *_auxv_end;
1.120 + int _env_entries;
1.121 +
1.122 +public:
1.123 + /* Start address and environment structure. */
1.124 +
1.125 + l4_addr_t start;
1.126 + l4re_env_t *env;
1.127 + l4_fpage_t utcb_fpage;
1.128 +
1.129 + /* Initialise a stack in a memory segment. */
1.130 +
1.131 + explicit Stack(Segment &segment, l4_fpage_t utcb_fpage)
1.132 + : _segment(segment), utcb_fpage(utcb_fpage)
1.133 + {
1.134 + _element = (l4_umword_t *) (segment.buf + segment.size);
1.135 + }
1.136 +
1.137 + /* Push any additional initial capabilities. */
1.138 +
1.139 + void push_cap_entries(l4re_env_cap_entry_t *entries)
1.140 + {
1.141 + l4re_env_cap_entry_t *entry = (l4re_env_cap_entry_t *) _element;
1.142 +
1.143 + *(--entry) = l4re_env_cap_entry_t();
1.144 +
1.145 + while ((entries != NULL) && (entries->cap != L4_INVALID_CAP))
1.146 + *(--entry) = *entries;
1.147 +
1.148 + _caps = (l4_addr_t) entry;
1.149 + _element = (l4_umword_t *) entry;
1.150 + }
1.151 +
1.152 + /* Push environment values in reverse order. */
1.153 +
1.154 + void push_string(char *s)
1.155 + {
1.156 + char *arg = (char *) _element;
1.157 + char *arg_last = arg;
1.158 +
1.159 + arg -= round(strlen(s) + 1, sizeof(l4_umword_t));
1.160 +
1.161 + memset(arg, 0, arg_last - arg);
1.162 + memcpy(arg, s, strlen(s));
1.163 +
1.164 + _element = (l4_umword_t *) arg;
1.165 + }
1.166 +
1.167 + /* Push environment values in reverse order. */
1.168 +
1.169 + void push_env(char *envp[])
1.170 + {
1.171 + _env_top = (char *) _element;
1.172 + _env_entries = 0;
1.173 +
1.174 + for (; *envp != NULL; envp++, _env_entries++)
1.175 + push_string(*envp);
1.176 + }
1.177 +
1.178 + /* Push argument values in reverse order. */
1.179 +
1.180 + void push_args(int argc, char *argv[])
1.181 + {
1.182 + _arg_top = (char *) _element;
1.183 +
1.184 + for (int i = 0; i < argc; i++)
1.185 + push_string(argv[i]);
1.186 + }
1.187
1.188 /* Loader flags, debugging flags, and the KIP capability index.
1.189 See: generate_l4aux in Remote_app_model */
1.190
1.191 - *(--stack_element) = 0;
1.192 - *(--stack_element) = 0;
1.193 - *(--stack_element) = 0x14 << L4_CAP_SHIFT;
1.194 + void push_l4re_flags()
1.195 + {
1.196 + *(--_element) = 0;
1.197 + *(--_element) = 0;
1.198 + *(--_element) = 0x14 << L4_CAP_SHIFT;
1.199 + }
1.200 +
1.201 + void push_l4re_env()
1.202 + {
1.203 + env = (l4re_env_t *) _element;
1.204 + env--;
1.205
1.206 - printf("Stack L4 aux elements: %p / %lx\n", stack_element, stack.region_address((char *) stack_element));
1.207 + env->factory = L4_BASE_FACTORY_CAP;
1.208 + env->main_thread = L4_BASE_THREAD_CAP;
1.209 + env->log = L4_BASE_LOG_CAP;
1.210 + env->scheduler = L4_BASE_SCHEDULER_CAP;
1.211 + env->rm = 0x11 << L4_CAP_SHIFT;
1.212 + env->mem_alloc = 0x12 << L4_CAP_SHIFT;
1.213 + env->first_free_cap = 0x15;
1.214 + env->caps = (l4re_env_cap_entry_t *) (_segment.region_address(_caps));
1.215 + env->utcb_area = utcb_fpage;
1.216 + env->first_free_utcb = l4_fpage_memaddr(utcb_fpage) + L4_UTCB_OFFSET;
1.217
1.218 - /* Populate stack with standard capabilities. */
1.219 -
1.220 - l4re_env_t *env = (l4re_env_t *) stack_element;
1.221 + _element = (l4_umword_t *) env;
1.222 + }
1.223
1.224 - env--;
1.225 - env->factory = L4_BASE_FACTORY_CAP;
1.226 - env->main_thread = L4_BASE_THREAD_CAP;
1.227 - env->log = L4_BASE_LOG_CAP;
1.228 - env->scheduler = L4_BASE_SCHEDULER_CAP;
1.229 - env->rm = 0x11 << L4_CAP_SHIFT;
1.230 - env->mem_alloc = 0x12 << L4_CAP_SHIFT;
1.231 - env->first_free_cap = 0x15;
1.232 - env->caps = (l4re_env_cap_entry_t *) (stack.region_address(caps_start));
1.233 - env->utcb_area = utcb_fpage;
1.234 - env->first_free_utcb = l4_fpage_memaddr(utcb_fpage) + L4_UTCB_OFFSET;
1.235 + /* Push the auxiliary vector. */
1.236 +
1.237 + void push_auxv()
1.238 + {
1.239 + _auxv_end = (char *) _element;
1.240 +
1.241 + struct auxv_entry *auxv_base = (struct auxv_entry *) _element;
1.242 +
1.243 + /* AUXV NULL. */
1.244 +
1.245 + *(--auxv_base) = {0, 0};
1.246
1.247 - stack_element = (l4_umword_t *) env;
1.248 + /* L4Re global environment pointer. */
1.249
1.250 - /* Populate stack with AUXV. */
1.251 -
1.252 - /* AUXV NULL. */
1.253 + *(--auxv_base) = {0xf1, _segment.region_address((char *) env)};
1.254
1.255 - *(--stack_element) = 0;
1.256 - *(--stack_element) = 0;
1.257 + /* Apparently required entries.
1.258 + NOTE: The user/group identifiers should be obtained from the broader
1.259 + environment. */
1.260
1.261 - /* L4Re global environment pointer. */
1.262 -
1.263 - *(--stack_element) = stack.region_address((char *) env);
1.264 - *(--stack_element) = 0xf1;
1.265 + *(--auxv_base) = {AT_PAGESZ, L4_PAGESIZE};
1.266 + *(--auxv_base) = {AT_UID, 0};
1.267 + *(--auxv_base) = {AT_EUID, 0};
1.268 + *(--auxv_base) = {AT_GID, 0};
1.269 + *(--auxv_base) = {AT_EGID, 0};
1.270
1.271 - /* Apparently required entries. */
1.272 + _element = (l4_umword_t *) auxv_base;
1.273 + }
1.274 +
1.275 + /* Fill the stack in reverse with an address, returning the size of the
1.276 + value. */
1.277
1.278 - *(--stack_element) = L4_PAGESIZE;
1.279 - *(--stack_element) = AT_PAGESZ;
1.280 + offset_t write_address(char *arg, char **addr, char *s)
1.281 + {
1.282 + offset_t size = round(strlen(s) + 1, sizeof(l4_umword_t));
1.283
1.284 - *(--stack_element) = 0;
1.285 - *(--stack_element) = AT_UID;
1.286 + *addr = (char *) _segment.region_address(arg - size);
1.287 + return size;
1.288 + }
1.289
1.290 - *(--stack_element) = 0;
1.291 - *(--stack_element) = AT_EUID;
1.292 + /* Populate stack with environment pointers, employing a pointer ordering
1.293 + that is the reverse of the value ordering. */
1.294 +
1.295 + void push_envp(char *envp[])
1.296 + {
1.297 + /* Write the terminating element. */
1.298
1.299 - *(--stack_element) = 0;
1.300 - *(--stack_element) = AT_GID;
1.301 + *(--_element) = 0;
1.302
1.303 - *(--stack_element) = 0;
1.304 - *(--stack_element) = AT_EGID;
1.305 + /* Reserve space and fill the stack from the top inwards. */
1.306 +
1.307 + char **ep = (char **) (_element - _env_entries);
1.308 + char *arg = _env_top;
1.309
1.310 - l4_addr_t stack_data_end = (l4_addr_t) stack_element;
1.311 + for (; *envp != NULL; envp++, ep++)
1.312 + arg -= write_address(arg, ep, *envp);
1.313
1.314 - printf("Stack L4 data: %lx / %lx\n", stack_data_end, stack.region_address(stack_data_end));
1.315 + _element -= _env_entries;
1.316 + }
1.317
1.318 - /* No environment pointers. */
1.319 + /* Populate stack with argument pointers and count, employing a pointer
1.320 + ordering that is the reverse of the value ordering. */
1.321
1.322 - *(--stack_element) = 0;
1.323 + void push_argv(int argc, char *argv[])
1.324 + {
1.325 + /* Write the terminating element. */
1.326
1.327 - /* Populate stack with argument pointers and count. */
1.328 + *(--_element) = 0;
1.329
1.330 - *(--stack_element) = 0;
1.331 + /* Reserve space and fill the stack from the top inwards. */
1.332 +
1.333 + char **ap = (char **) (_element - argc);
1.334 + char *arg = _arg_top;
1.335
1.336 - stack_arg = stack_arg_top;
1.337 + for (int i = 0; i < argc; i++)
1.338 + arg -= write_address(arg, &ap[i], argv[i]);
1.339
1.340 - for (arg = argc - 1; arg >= 0; arg--)
1.341 - {
1.342 - stack_arg -= round(strlen(argv[arg]) + 1, sizeof(l4_umword_t));
1.343 - *(--stack_element) = (l4_umword_t) (stack.region_address(stack_arg));
1.344 + /* Write the count. */
1.345 +
1.346 + _element -= argc;
1.347 +
1.348 + *(--_element) = argc;
1.349 }
1.350
1.351 - *(--stack_element) = argc;
1.352 + /* Adjust the stack alignment and return the stack address. */
1.353 +
1.354 + l4_addr_t align_stack()
1.355 + {
1.356 + char *current = (char *) _element;
1.357 + char *adjusted = Ldr::adjust_sp(current, NULL);
1.358 +
1.359 + if (adjusted != current)
1.360 + memmove(adjusted, (const void *) current, _auxv_end - current);
1.361 +
1.362 + _element = (l4_umword_t *) adjusted;
1.363 +
1.364 + return _segment.region_address(adjusted);
1.365 + }
1.366 +
1.367 + /* Populate stack with additional capabilities. */
1.368
1.369 - char *stack_adjusted = Ldr::adjust_sp((char *) stack_element, NULL);
1.370 + void populate(int argc, char *argv[], char *envp[])
1.371 + {
1.372 + push_cap_entries(NULL);
1.373 +
1.374 + /* Populate stack with environment and argument values. */
1.375 +
1.376 + push_env(envp);
1.377 + push_args(argc, argv);
1.378 +
1.379 + /* Push L4Re flags, environment and auxiliary vector. */
1.380 +
1.381 + push_l4re_flags();
1.382 + push_l4re_env();
1.383 + push_auxv();
1.384 +
1.385 + /* Push environment and argument pointers. */
1.386
1.387 - /* Adjust the stack alignment. */
1.388 + push_envp(envp);
1.389 + push_argv(argc, argv);
1.390 +
1.391 + /* Adjust the stack alignment. */
1.392 +
1.393 + start = align_stack();
1.394 + }
1.395 +};
1.396 +
1.397 +
1.398
1.399 - if (stack_adjusted != (char *) stack_element)
1.400 - memmove(stack_adjusted, (const void *) stack_element, stack_data_end - (l4_addr_t) stack_element);
1.401 +class Environment
1.402 +{
1.403 +protected:
1.404 + Stack &_st;
1.405 + l4_cap_idx_t task = L4_INVALID_CAP, thread = L4_INVALID_CAP;
1.406 + l4_cap_idx_t _pager_cap = 0x10 << L4_CAP_SHIFT;
1.407 +
1.408 +public:
1.409 + explicit Environment(Stack &st)
1.410 + : _st(st)
1.411 + {
1.412 + }
1.413 +
1.414 + long create_task()
1.415 + {
1.416 + task = ipc_cap_alloc();
1.417 +
1.418 + if (l4_is_invalid_cap(task))
1.419 + return -L4_ENOMEM;
1.420 +
1.421 + return l4_error(l4_factory_create_task(l4re_env()->factory, task, _st.utcb_fpage));
1.422 + }
1.423
1.424 - l4_umword_t *stack_adjusted_element = (l4_umword_t *) stack_adjusted;
1.425 + long create_thread()
1.426 + {
1.427 + thread = ipc_cap_alloc();
1.428 +
1.429 + if (l4_is_invalid_cap(thread))
1.430 + return -L4_ENOMEM;
1.431 +
1.432 + return l4_error(l4_factory_create_thread(l4re_env()->factory, thread));
1.433 + }
1.434 +
1.435 + /* Configure the task environment. */
1.436
1.437 - printf("%ld %lx %lx\n", stack_adjusted_element[0], stack_adjusted_element[1], stack_adjusted_element[2]);
1.438 + long configure(l4_cap_idx_t server)
1.439 + {
1.440 + /* Map the KIP into the task. */
1.441 +
1.442 + l4_addr_t kip_start = (l4_addr_t) l4re_kip();
1.443 +
1.444 + long err = l4_error(l4_task_map(task, L4RE_THIS_TASK_CAP,
1.445 + l4_fpage(kip_start, L4_PAGESHIFT, L4_FPAGE_RX),
1.446 + kip_start));
1.447 +
1.448 + if (err)
1.449 + return err;
1.450 +
1.451 + /* Define capability mappings for the new task. */
1.452 +
1.453 + l4re_env_t *env = _st.env;
1.454
1.455 - l4_addr_t stack_start = stack.region_address(stack_adjusted);
1.456 + struct mapped_cap mapped_caps[] = {
1.457 + {L4_BASE_TASK_CAP, task, L4_CAP_FPAGE_RWS},
1.458 + {_pager_cap, server, L4_CAP_FPAGE_RWS},
1.459 + {env->rm, server, L4_CAP_FPAGE_RWS},
1.460 + {env->main_thread, thread, L4_CAP_FPAGE_RWS},
1.461 + {env->factory, l4re_env()->factory, L4_CAP_FPAGE_RWS},
1.462 + {env->log, l4re_env()->log, L4_CAP_FPAGE_RWS},
1.463 + {env->scheduler, l4re_env()->scheduler, L4_CAP_FPAGE_RWS},
1.464 + {env->mem_alloc, l4re_env()->mem_alloc, L4_CAP_FPAGE_RWS},
1.465 + {0, L4_INVALID_CAP, 0},
1.466 + };
1.467 +
1.468 + return map_capabilities(task, mapped_caps);
1.469 + }
1.470 +
1.471 + /* Initialise the thread. */
1.472
1.473 - printf("Stack L4 start: %p / %lx\n", stack_adjusted, stack.region_address(stack_adjusted));
1.474 + long thread_init(l4_addr_t program_start)
1.475 + {
1.476 + l4_thread_control_start();
1.477 + l4_thread_control_pager(_pager_cap);
1.478 + l4_thread_control_exc_handler(_pager_cap);
1.479 + l4_thread_control_bind((l4_utcb_t *) l4_fpage_memaddr(_st.utcb_fpage), task);
1.480 +
1.481 + long err = l4_error(l4_thread_control_commit(thread));
1.482 +
1.483 + if (err)
1.484 + return err;
1.485
1.486 - return stack_start;
1.487 -}
1.488 + return l4_error(l4_thread_ex_regs(thread, program_start, _st.start, 0));
1.489 + }
1.490 +
1.491 + /* Start the thread. */
1.492 +
1.493 + long thread_start()
1.494 + {
1.495 + l4_sched_param_t sp = l4_sched_param(L4RE_MAIN_THREAD_PRIO);
1.496 +
1.497 + return l4_error(l4_scheduler_run_thread(l4re_env()->scheduler, thread, &sp));
1.498 + }
1.499 +};
1.500
1.501
1.502
1.503 @@ -550,48 +817,6 @@
1.504
1.505
1.506
1.507 -/* UTCB properties.
1.508 - See: moe/server/src/loader.cc */
1.509 -
1.510 -enum ipc_exec_utcb
1.511 -{
1.512 - Default_max_threads = 16,
1.513 -#ifdef ARCH_mips
1.514 - Utcb_area_start = 0x73000000,
1.515 -#else
1.516 - Utcb_area_start = 0xb3000000,
1.517 -#endif
1.518 -};
1.519 -
1.520 -
1.521 -
1.522 -/* Capability mapping definitions for the new task. */
1.523 -
1.524 -struct mapped_cap
1.525 -{
1.526 - l4_cap_idx_t cap;
1.527 - unsigned char rights;
1.528 - l4_umword_t spot;
1.529 -};
1.530 -
1.531 -static long map_capabilities(l4_cap_idx_t task, struct mapped_cap mapped_caps[])
1.532 -{
1.533 - long err = L4_EOK;
1.534 - int i = 0;
1.535 -
1.536 - while (l4_is_valid_cap(mapped_caps[i].cap) && !err)
1.537 - {
1.538 - err = l4_error(l4_task_map(task, L4RE_THIS_TASK_CAP,
1.539 - l4_obj_fpage(mapped_caps[i].cap, 0, mapped_caps[i].rights),
1.540 - l4_map_obj_control(mapped_caps[i].spot, L4_MAP_ITEM_MAP)));
1.541 - i++;
1.542 - }
1.543 -
1.544 - return err;
1.545 -}
1.546 -
1.547 -
1.548 -
1.549 int main(int argc, char *argv[])
1.550 {
1.551 long err;
1.552 @@ -602,21 +827,6 @@
1.553 return 1;
1.554 }
1.555
1.556 - /* Allocate capabilities for the task and thread. */
1.557 -
1.558 - l4_cap_idx_t caps[2];
1.559 -
1.560 - err = ipc_cap_alloc_many(caps, 2);
1.561 -
1.562 - if (err)
1.563 - {
1.564 - printf("Could not allocate capabilities.\n");
1.565 - return 1;
1.566 - }
1.567 -
1.568 - l4_cap_idx_t &task = caps[0];
1.569 - l4_cap_idx_t &thread = caps[1];
1.570 -
1.571 /* Obtain the payload as a dataspace. */
1.572
1.573 file_t *file = client_open(argv[1], O_RDONLY);
1.574 @@ -634,7 +844,7 @@
1.575
1.576 Segment program(0x1000000, 0x28326, L4_FPAGE_RWX, 0, 0x28326);
1.577 Segment data(0x1029360, 0x8068, L4_FPAGE_RW, 0x28360, 0x2058);
1.578 - Segment stack(0x80000000, 16 * L4_PAGESIZE, L4_FPAGE_RW);
1.579 + Segment stack(0x80000000 - 16 * L4_PAGESIZE, 16 * L4_PAGESIZE, L4_FPAGE_RW);
1.580 Segment *segments[] = {&program, &data, &stack, NULL};
1.581 Segment **segment;
1.582
1.583 @@ -657,37 +867,20 @@
1.584 }
1.585 }
1.586
1.587 - if (memcmp(program.buf + program_start - program.region_base, "\x31\xed", 2))
1.588 - {
1.589 - printf("Did not find expected instructions at start.\n");
1.590 - return 1;
1.591 - }
1.592 -
1.593 - /* UTCB location and size. */
1.594 -
1.595 - l4_addr_t utcb_start = Utcb_area_start;
1.596 - int utcb_log2size = page_order(Default_max_threads * L4_UTCB_OFFSET);
1.597 -
1.598 - /* Round up to at least one page. */
1.599 -
1.600 - if (utcb_log2size < L4_PAGESHIFT)
1.601 - utcb_log2size = L4_PAGESHIFT;
1.602 -
1.603 - l4_fpage_t utcb_fpage = l4_fpage(utcb_start, utcb_log2size, 0);
1.604 -
1.605 - /* KIP allocation. */
1.606 -
1.607 - l4_addr_t kip_start = (l4_addr_t) l4re_kip();
1.608 -
1.609 - printf("KIP at %lx.\n", kip_start);
1.610 -
1.611 /* Populate the stack with argument and environment details. */
1.612
1.613 - l4_addr_t stack_start = populate_stack(stack, argc - 1, argv + 1, utcb_fpage);
1.614 + Stack st(stack, get_utcb_fpage());
1.615 + Environment environment(st);
1.616 +
1.617 + /* NOTE: Environment vector is currently not defined. */
1.618 +
1.619 + char *envp[] = {NULL};
1.620 +
1.621 + st.populate(argc - 1, argv + 1, envp);
1.622
1.623 /* Create a new task and thread. */
1.624
1.625 - err = l4_error(l4_factory_create_task(l4re_env()->factory, task, utcb_fpage));
1.626 + err = environment.create_task();
1.627
1.628 if (err)
1.629 {
1.630 @@ -695,7 +888,7 @@
1.631 return 1;
1.632 }
1.633
1.634 - err = l4_error(l4_factory_create_thread(l4re_env()->factory, thread));
1.635 + err = environment.create_thread();
1.636
1.637 if (err)
1.638 {
1.639 @@ -703,6 +896,14 @@
1.640 return 1;
1.641 }
1.642
1.643 + err = environment.thread_init(program_start);
1.644 +
1.645 + if (err)
1.646 + {
1.647 + printf("Could not configure thread.\n");
1.648 + return 1;
1.649 + }
1.650 +
1.651 /* Start the pager. */
1.652
1.653 ipc_server_config_type config;
1.654 @@ -733,77 +934,22 @@
1.655 return 1;
1.656 }
1.657
1.658 - /* Define capability mappings for the new task. */
1.659 + /* Configure the environment for the task, specifying the pager (and exception
1.660 + handler plus region mapper). */
1.661
1.662 - struct mapped_cap mapped_caps[] = {
1.663 - {config.server, L4_CAP_FPAGE_RWS, 0x10 << L4_CAP_SHIFT},
1.664 - {config.server, L4_CAP_FPAGE_RWS, 0x11 << L4_CAP_SHIFT},
1.665 - {task, L4_CAP_FPAGE_RWS, L4_BASE_TASK_CAP},
1.666 - {thread, L4_CAP_FPAGE_RWS, L4_BASE_THREAD_CAP},
1.667 - {l4re_env()->factory, L4_CAP_FPAGE_RWS, L4_BASE_FACTORY_CAP},
1.668 - {l4re_env()->log, L4_CAP_FPAGE_RWS, L4_BASE_LOG_CAP},
1.669 - {l4re_env()->scheduler, L4_CAP_FPAGE_RWS, L4_BASE_SCHEDULER_CAP},
1.670 - {l4re_env()->mem_alloc, L4_CAP_FPAGE_RWS, 0x12 << L4_CAP_SHIFT},
1.671 - {L4_INVALID_CAP, 0, 0},
1.672 - };
1.673 -
1.674 - err = map_capabilities(task, mapped_caps);
1.675 + err = environment.configure(config.server);
1.676
1.677 if (err)
1.678 {
1.679 - printf("Could not capabilities into task.\n");
1.680 - return 1;
1.681 - }
1.682 -
1.683 - /* Map the KIP into the task. */
1.684 -
1.685 - err = l4_error(l4_task_map(task, L4RE_THIS_TASK_CAP,
1.686 - l4_fpage(kip_start, L4_PAGESHIFT, L4_FPAGE_RX),
1.687 - kip_start));
1.688 -
1.689 - if (err)
1.690 - {
1.691 - printf("Could not map KIP into task.\n");
1.692 - return 1;
1.693 - }
1.694 -
1.695 - /* Configure the thread with the region manager acting as pager and exception
1.696 - handler. The UTCB will be situated at an address supported by a dataspace
1.697 - attached to the new task. */
1.698 -
1.699 - printf("Configure thread...\n");
1.700 -
1.701 - l4_thread_control_start();
1.702 - l4_thread_control_pager(0x10 << L4_CAP_SHIFT);
1.703 - l4_thread_control_exc_handler(0x10 << L4_CAP_SHIFT);
1.704 - l4_thread_control_bind((l4_utcb_t *) utcb_start, task);
1.705 - err = l4_error(l4_thread_control_commit(thread));
1.706 -
1.707 - if (err)
1.708 - {
1.709 - printf("Could not configure thread.\n");
1.710 + printf("Could not map capabilities into task.\n");
1.711 return 1;
1.712 }
1.713
1.714 /* Start the new thread. */
1.715
1.716 - printf("Schedule thread...\n");
1.717 -
1.718 - printf("Stack at 0x%lx mapped to region at 0x%lx.\n", stack_start, stack.region_base);
1.719 -
1.720 - err = l4_error(l4_thread_ex_regs(thread, program_start, stack_start, 0));
1.721 -
1.722 - if (err)
1.723 - {
1.724 - printf("Could not set thread registers.\n");
1.725 - return 1;
1.726 - }
1.727 -
1.728 printf("Run thread...\n");
1.729
1.730 - l4_sched_param_t sp = l4_sched_param(L4RE_MAIN_THREAD_PRIO);
1.731 -
1.732 - err = l4_error(l4_scheduler_run_thread(l4re_env()->scheduler, thread, &sp));
1.733 + err = environment.thread_start();
1.734
1.735 if (err)
1.736 {