L4Re/departure

Changeset

319:74c69ab2320e
2022-05-04 Paul Boddie raw files shortlog changelog graph Introduced various abstractions for the stack and program environment.
tests/dstest_exec.cc (file)
     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    {