# HG changeset patch # User Paul Boddie # Date 1655049857 -7200 # Node ID c0758a6af0ff5f3b03a3fea0a8b5ab8f927ae99a # Parent 1483c00724a191ce8dd6264791218dcda78cbb4f Added support for more stack information. Introduced control over attaching dataspaces when allocating and filling segment regions. Introduced support for multiple threads to the process abstraction, also adding a general method for capability mapping to the created task. diff -r 1483c00724a1 -r c0758a6af0ff libexec/include/exec/memory.h --- a/libexec/include/exec/memory.h Sun Jun 12 17:50:58 2022 +0200 +++ b/libexec/include/exec/memory.h Sun Jun 12 18:04:17 2022 +0200 @@ -26,7 +26,9 @@ -long exec_get_payload(const char *filename, Payload **payload); +/* Initialisation functions. */ + +long exec_get_payload(const char *filename, Payload **payload, bool attach); /* vim: tabstop=2 expandtab shiftwidth=2 */ diff -r 1483c00724a1 -r c0758a6af0ff libexec/include/exec/process.h --- a/libexec/include/exec/process.h Sun Jun 12 17:50:58 2022 +0200 +++ b/libexec/include/exec/process.h Sun Jun 12 18:04:17 2022 +0200 @@ -50,17 +50,18 @@ enum exec_task_caps { - L4_EXEC_PAGER_CAP = 0x10 << L4_CAP_SHIFT, - L4_EXEC_RM_CAP = 0x11 << L4_CAP_SHIFT, - L4_EXEC_MA_CAP = 0x12 << L4_CAP_SHIFT, - L4_EXEC_KIP_CAP = 0x14 << L4_CAP_SHIFT, + L4_EXEC_PAGER_CAP = 0x10UL << L4_CAP_SHIFT, + L4_EXEC_RM_CAP = 0x11UL << L4_CAP_SHIFT, + L4_EXEC_MA_CAP = 0x12UL << L4_CAP_SHIFT, + L4_EXEC_KIP_CAP = 0x14UL << L4_CAP_SHIFT, }; -/* The default first free capability index must follow those above. */ +/* The default first free capability index must follow those above. Any + additional initial capabilities must elevate the index below. */ enum exec_task_cap_indexes { - L4_EXEC_FIRST_FREE_CAP_INDEX = 0x15, + L4_EXEC_FIRST_FREE_CAP_INDEX = 0x15UL, }; @@ -81,6 +82,10 @@ l4re_aux_t _aux; l4re_env_t _env; + /* Mapped capability details. */ + + unsigned int _num_mapped_caps = 0; + /* Task and thread initialisation. */ long create_task(); @@ -88,9 +93,14 @@ long create_thread(l4_cap_idx_t *thread); public: - explicit Process(); + explicit Process(int reserved_threads = 1); + + long configure_task(); - long configure(l4_cap_idx_t server); + long configure_thread(l4_cap_idx_t server); + + long map_capabilities(struct ipc_mapped_cap mapped_caps[], + bool to_count = true); long thread_start(l4_addr_t program_start, Stack &st); }; diff -r 1483c00724a1 -r c0758a6af0ff libexec/include/exec/segment.h --- a/libexec/include/exec/segment.h Sun Jun 12 17:50:58 2022 +0200 +++ b/libexec/include/exec/segment.h Sun Jun 12 18:04:17 2022 +0200 @@ -26,6 +26,7 @@ #include +#include #include @@ -36,6 +37,7 @@ { protected: MappedRegion _region; + struct exec_region _exec_region; /* Allocated memory. */ @@ -61,15 +63,17 @@ public: virtual ~Segment(); + l4_cap_idx_t cap(); + char *address(); offset_t size(); /* Segment population methods. */ - long allocate(); + long allocate(bool attach); - long fill(file_t *file); + long fill(file_t *file, bool attach); /* Mapped region methods. */ @@ -81,6 +85,8 @@ /* Generic property access. */ + struct exec_region &exec_region(); + virtual bool loadable() = 0; virtual offset_t file_contents() = 0; virtual offset_t file_offset() = 0; diff -r 1483c00724a1 -r c0758a6af0ff libexec/include/exec/stack.h --- a/libexec/include/exec/stack.h Sun Jun 12 17:50:58 2022 +0200 +++ b/libexec/include/exec/stack.h Sun Jun 12 18:04:17 2022 +0200 @@ -22,8 +22,8 @@ #pragma once #include -#include +#include #include @@ -34,13 +34,6 @@ { protected: - /* Auxiliary vector key-value pair. */ - - struct auxv_entry - { - l4_umword_t key, value; - }; - /* Program segment holding the stack contents. */ Segment &_segment; @@ -51,25 +44,30 @@ /* Stack section properties. */ - l4_addr_t _caps; + l4_addr_t _regions = 0; + l4_addr_t _caps = 0; + int _num_caps = 0; char *_arg_top, *_env_top; char **_argv; char *_auxv_end; - int _env_entries; + int _env_entries = 0; /* L4Re auxiliary and environment regions. */ l4re_aux_t *_aux; l4re_env_t *_env; + /* Any indicated initial capabilities and regions. */ + + l4re_env_cap_entry_t *_cap_entries = NULL; + struct exec_region *_region_entries = NULL; + /* Stack pointer start address. */ l4_addr_t _start; /* Internal stack population methods. */ - void push_cap_entries(l4re_env_cap_entry_t *entries); - void push_string(char *s); void push_env(char *envp[]); @@ -82,6 +80,10 @@ void push_auxv(); + void push_init_caps(); + + void push_regions(); + offset_t write_address(char *arg, char **addr, char *s); void push_envp(char *envp[]); @@ -93,6 +95,10 @@ public: explicit Stack(Segment &segment); + void set_init_caps(l4re_env_cap_entry_t *entries); + + void set_regions(struct exec_region *regions); + void set_l4re_aux(l4re_aux_t *aux); void set_l4re_env(l4re_env_t *env); diff -r 1483c00724a1 -r c0758a6af0ff libexec/lib/src/Makefile --- a/libexec/lib/src/Makefile Sun Jun 12 17:50:58 2022 +0200 +++ b/libexec/lib/src/Makefile Sun Jun 12 18:04:17 2022 +0200 @@ -34,7 +34,9 @@ # Normal source files. -PLAIN_SRC_CC = elf.cc memory.cc pager.cc process.cc segment.cc stack.cc +PLAIN_SRC_CC = \ + common.cc elf.cc memory.cc pager.cc \ + process.cc segment.cc stack.cc # Normal definitions. diff -r 1483c00724a1 -r c0758a6af0ff libexec/lib/src/memory.cc --- a/libexec/lib/src/memory.cc Sun Jun 12 17:50:58 2022 +0200 +++ b/libexec/lib/src/memory.cc Sun Jun 12 18:04:17 2022 +0200 @@ -33,7 +33,7 @@ /* Obtain the payload as a dataspace. */ -long exec_get_payload(const char *filename, Payload **payload) +long exec_get_payload(const char *filename, Payload **payload, bool attach) { file_t *file = client_open(filename, O_RDONLY); @@ -86,10 +86,10 @@ return -L4_EIO; } - err = segment->fill(rfile); + err = segment->fill(rfile, attach); } else - err = segment->allocate(); + err = segment->allocate(attach); if (err) { diff -r 1483c00724a1 -r c0758a6af0ff libexec/lib/src/process.cc --- a/libexec/lib/src/process.cc Sun Jun 12 17:50:58 2022 +0200 +++ b/libexec/lib/src/process.cc Sun Jun 12 18:04:17 2022 +0200 @@ -50,7 +50,7 @@ /* Initialise a new process, this being an abstraction for a new task with some threads. */ -Process::Process() +Process::Process(int reserved_threads) { /* Obtain UTCB area details for the task. */ @@ -68,7 +68,7 @@ _env.mem_alloc = L4_EXEC_MA_CAP; _env.first_free_cap = L4_EXEC_FIRST_FREE_CAP_INDEX; _env.utcb_area = utcb_fpage; - _env.first_free_utcb = l4_fpage_memaddr(utcb_fpage) + L4_UTCB_OFFSET; + _env.first_free_utcb = l4_fpage_memaddr(utcb_fpage) + reserved_threads * L4_UTCB_OFFSET; /* Populate auxiliary information. */ @@ -101,7 +101,7 @@ /* Configure the task environment. */ -long Process::configure(l4_cap_idx_t server) +long Process::configure_task() { long err = create_task(); @@ -123,8 +123,6 @@ struct ipc_mapped_cap mapped_caps[] = { {L4_BASE_TASK_CAP, _task, L4_CAP_FPAGE_RWS}, - {L4_EXEC_PAGER_CAP, server, L4_CAP_FPAGE_RWS}, - {_env.rm, server, L4_CAP_FPAGE_RWS}, {_env.factory, l4re_env()->factory, L4_CAP_FPAGE_RWS}, {_env.log, l4re_env()->log, L4_CAP_FPAGE_RWS}, {_env.scheduler, l4re_env()->scheduler, L4_CAP_FPAGE_RWS}, @@ -132,7 +130,28 @@ {0, L4_INVALID_CAP, 0}, }; - return ipc_map_capabilities(_task, mapped_caps); + return map_capabilities(mapped_caps, false); +} + +/* Configure the thread environment. */ + +long Process::configure_thread(l4_cap_idx_t server) +{ + struct ipc_mapped_cap mapped_caps[] = { + {L4_EXEC_PAGER_CAP, server, L4_CAP_FPAGE_RWS}, + {_env.rm, server, L4_CAP_FPAGE_RWS}, + {0, L4_INVALID_CAP, 0}, + }; + + return map_capabilities(mapped_caps, false); +} + +/* Map capabilities into the task, counting them if indicated. */ + +long Process::map_capabilities(struct ipc_mapped_cap mapped_caps[], + bool to_count) +{ + return ipc_map_capabilities(_task, mapped_caps, to_count ? &_num_mapped_caps : NULL); } /* Create, initialise and start a thread. */ @@ -166,6 +185,10 @@ ipc_map_capability(_task, (struct ipc_mapped_cap) {_env.main_thread, thread, L4_CAP_FPAGE_RWS}); + /* Update the environment for any mapped capabilities. */ + + _env.first_free_cap = L4_EXEC_FIRST_FREE_CAP_INDEX + _num_mapped_caps; + /* Populate the initial environment in the thread. */ st.set_l4re_aux(&_aux); diff -r 1483c00724a1 -r c0758a6af0ff libexec/lib/src/segment.cc --- a/libexec/lib/src/segment.cc Sun Jun 12 17:50:58 2022 +0200 +++ b/libexec/lib/src/segment.cc Sun Jun 12 18:04:17 2022 +0200 @@ -49,6 +49,13 @@ _region_allocated_size = round(region_size() + _region_content_offset, L4_PAGESIZE); } +/* Return the capability of the dataspace providing the memory. */ + +l4_cap_idx_t Segment::cap() +{ + return _ds; +} + /* Return the address of allocated memory. */ char *Segment::address() @@ -65,29 +72,49 @@ /* Allocate a writable region for the segment. */ -long Segment::allocate() +long Segment::allocate(bool attach) { - return ipc_allocate_align(_region_allocated_size, L4RE_RM_F_SEARCH_ADDR | L4RE_RM_F_RW, - L4_PAGESHIFT, (void **) &_buf, &_ds); + if (attach) + return ipc_allocate_align(_region_allocated_size, + L4RE_RM_F_SEARCH_ADDR | L4RE_RM_F_RW, + L4_PAGESHIFT, (void **) &_buf, &_ds); + else + return ipc_new_dataspace(_region_allocated_size, + L4RE_RM_F_SEARCH_ADDR | L4RE_RM_F_RW, + L4_PAGESHIFT, &_ds); } /* Fill a segment region with file content. */ -long Segment::fill(file_t *file) +long Segment::fill(file_t *file, bool attach) { - /* Provide the exposed file contents in a masked memory mapped region. */ + /* Provide the exposed file contents in a masked memory mapped region, or if + not attaching the region, merely request access via a dataspace. */ - _buf = (char *) client_mmap(file, + if (attach) + { + _buf = (char *) client_mmap(file, + file_offset() - _region_content_offset, + _region_allocated_size, + file_offset(), + file_offset() + file_contents(), + region_flags()); + if (_buf == NULL) + return -L4_EIO; + } + else + { + long err = file_mmap_only(file, file_offset() - _region_content_offset, _region_allocated_size, file_offset(), - file_offset() + file_contents(), - region_flags()); + file_offset() + file_contents()); + if (err) + return err; + } - if (_buf == NULL) - return -L4_EIO; - else - return L4_EOK; + _ds = file->ref; + return L4_EOK; } /* Define and return the mapped region for the segment. */ @@ -98,6 +125,14 @@ return _region; } +/* Define and return the region dataspace details. */ + +struct exec_region &Segment::exec_region() +{ + _exec_region = (struct exec_region) {_region_base, _region_allocated_size, region_flags(), _ds}; + return _exec_region; +} + /* Return the mapped address corresponding to the given address. */ l4_addr_t Segment::region_address(char *address) diff -r 1483c00724a1 -r c0758a6af0ff libexec/lib/src/stack.cc --- a/libexec/lib/src/stack.cc Sun Jun 12 17:50:58 2022 +0200 +++ b/libexec/lib/src/stack.cc Sun Jun 12 18:04:17 2022 +0200 @@ -26,7 +26,6 @@ #include -#include #include #include "stack.h" @@ -39,23 +38,58 @@ : _segment(segment) { _element = (l4_umword_t *) (segment.address() + segment.size()); +} - /* Add a terminator for any additional initial capabilities. */ +/* Set any additional initial capabilities. */ + +void Stack::set_init_caps(l4re_env_cap_entry_t *entries) +{ + _cap_entries = entries; +} + +/* Set any indicated memory regions. */ + +void Stack::set_regions(struct exec_region *regions) +{ + _region_entries = regions; +} - l4re_env_cap_entry_t *entry = (l4re_env_cap_entry_t *) _element; +/* Push any indicated memory regions. */ + +void Stack::push_regions() +{ + struct exec_region *region = (struct exec_region *) _element; + struct exec_region *regions = _region_entries; + + /* Terminate the regions with a null entry. */ - *(--entry) = l4re_env_cap_entry_t(); - _element = (l4_umword_t *) entry; + *(--region) = (struct exec_region) {0, 0, 0, L4_INVALID_CAP}; + + for (; (regions != NULL) && (regions->ds != L4_INVALID_CAP); regions++) + { + *(--region) = *regions; + } + + _regions = (l4_addr_t) region; + _element = (l4_umword_t *) region; } /* Push any additional initial capabilities. */ -void Stack::push_cap_entries(l4re_env_cap_entry_t *entries) +void Stack::push_init_caps() { l4re_env_cap_entry_t *entry = (l4re_env_cap_entry_t *) _element; + l4re_env_cap_entry_t *entries = _cap_entries; - while ((entries != NULL) && (entries->cap != L4_INVALID_CAP)) + /* Terminate the capabilities with a null entry. */ + + *(--entry) = l4re_env_cap_entry_t(); + + for (; (entries != NULL) && (entries->flags != ~0UL); entries++) + { *(--entry) = *entries; + _num_caps++; + } _caps = (l4_addr_t) entry; _element = (l4_umword_t *) entry; @@ -102,6 +136,15 @@ void Stack::push_l4re_aux() { + /* Regions for the region mapper. */ + + if (_regions) + *(--_element) = _segment.region_address((char *) _regions); + else + *(--_element) = 0; + + /* Reserve space for the actual L4Re auxiliary structure. */ + _aux = (l4re_aux_t *) _element; _aux--; _element = (l4_umword_t *) _aux; @@ -239,6 +282,11 @@ void Stack::populate(int argc, char *argv[], char *envp[]) { + /* Populate stack with any regions and capabilities. */ + + push_regions(); + push_init_caps(); + /* Populate stack with environment and argument values. */ push_env(envp); diff -r 1483c00724a1 -r c0758a6af0ff libipc/include/ipc/map.h --- a/libipc/include/ipc/map.h Sun Jun 12 17:50:58 2022 +0200 +++ b/libipc/include/ipc/map.h Sun Jun 12 18:04:17 2022 +0200 @@ -34,6 +34,10 @@ long ipc_map_capability(l4_cap_idx_t task, struct ipc_mapped_cap mapped_cap); -long ipc_map_capabilities(l4_cap_idx_t task, struct ipc_mapped_cap mapped_caps[]); +long ipc_map_capabilities(l4_cap_idx_t task, struct ipc_mapped_cap mapped_caps[], + unsigned int *count); EXTERN_C_END + +/* vim: tabstop=2 expandtab shiftwidth=2 +*/ diff -r 1483c00724a1 -r c0758a6af0ff libipc/lib/src/map.c --- a/libipc/lib/src/map.c Sun Jun 12 17:50:58 2022 +0200 +++ b/libipc/lib/src/map.c Sun Jun 12 18:04:17 2022 +0200 @@ -39,13 +39,18 @@ /* Map several capabilities to another task. */ -long ipc_map_capabilities(l4_cap_idx_t task, struct ipc_mapped_cap mapped_caps[]) +long ipc_map_capabilities(l4_cap_idx_t task, struct ipc_mapped_cap mapped_caps[], + unsigned int *count) { long err = L4_EOK; + unsigned int i; - for (int i = 0; l4_is_valid_cap(mapped_caps[i].cap) && !err; i++) + for (i = 0; l4_is_valid_cap(mapped_caps[i].cap) && !err; i++) err = ipc_map_capability(task, mapped_caps[i]); + if (count != NULL) + *count = i + 1; + return err; } diff -r 1483c00724a1 -r c0758a6af0ff tests/dstest_exec.cc --- a/tests/dstest_exec.cc Sun Jun 12 17:50:58 2022 +0200 +++ b/tests/dstest_exec.cc Sun Jun 12 18:04:17 2022 +0200 @@ -58,13 +58,13 @@ ExplicitSegment stack(Utcb_area_start - initial_stack_size, initial_stack_size, L4_FPAGE_RW); Payload *payload; - if (exec_get_payload(argv[1], &payload)) + if (exec_get_payload(argv[1], &payload, true)) { printf("Could not initialise program.\n"); return 1; } - if (stack.allocate()) + if (stack.allocate(true)) { printf("Could not allocate stack.\n"); return 1; @@ -113,7 +113,7 @@ Process process; - err = process.configure(config.server); + err = process.configure_task(); if (err) { @@ -121,6 +121,14 @@ return 1; } + err = process.configure_thread(config.server); + + if (err) + { + printf("Could not configure thread.\n"); + return 1; + } + /* Populate a thread stack with argument and environment details. */ Stack st(stack);