# HG changeset patch # User Paul Boddie # Date 1678058092 -3600 # Node ID 86fe98e135bc9f362d8fb33a1fd143b6ae6d72dc # Parent 0acb88011ba2084e54d993ceaa2fab34afe07775 Propagate capability details for the pager and threads in the new task back to the external pager so that it may unmap these resources when the process terminates. diff -r 0acb88011ba2 -r 86fe98e135bc libexec/include/exec/external_pager.h --- a/libexec/include/exec/external_pager.h Sat Mar 04 19:03:27 2023 +0100 +++ b/libexec/include/exec/external_pager.h Mon Mar 06 00:14:52 2023 +0100 @@ -21,6 +21,8 @@ #pragma once +#include + #include #include #include @@ -36,7 +38,8 @@ public NotificationSupport, public Resource { protected: - l4_cap_idx_t _task, _server, _ipc_gate; + l4_cap_idx_t _task, _ipc_gate, _parent, _rparent, _pager, _rpager; + std::vector _threads, _rthreads; public: explicit ExternalPager(address_t start = 0, address_t end = 0); @@ -50,9 +53,11 @@ /* Task and thread management. */ + virtual void add_thread(l4_cap_idx_t cap, l4_cap_idx_t rcap); + virtual void set_gate(l4_cap_idx_t cap); + virtual void set_pager(l4_cap_idx_t cap, l4_cap_idx_t rcap); + virtual void set_parent(l4_cap_idx_t cap, l4_cap_idx_t rcap); virtual void set_task(l4_cap_idx_t cap); - virtual void set_server(l4_cap_idx_t cap); - virtual void set_gate(l4_cap_idx_t cap); /* Resource methods. */ diff -r 0acb88011ba2 -r 86fe98e135bc libexec/include/exec/process.h --- a/libexec/include/exec/process.h Sat Mar 04 19:03:27 2023 +0100 +++ b/libexec/include/exec/process.h Mon Mar 06 00:14:52 2023 +0100 @@ -93,16 +93,16 @@ long configure_task(unsigned int threads = 2); - long configure_thread(l4_cap_idx_t server, l4_cap_idx_t mapped_cap = L4_INVALID_CAP); + long configure_thread(l4_cap_idx_t server, l4_cap_idx_t *mapped_cap = NULL); l4_cap_idx_t get_task(); - long set_parent(l4_cap_idx_t server); + long set_parent(l4_cap_idx_t parent, l4_cap_idx_t *rparent); long map_capabilities(struct ipc_mapped_cap mapped_caps[], bool to_count = true); - long thread_start(l4_addr_t program_start, Stack &st, l4_cap_idx_t *thread); + long thread_start(l4_addr_t program_start, Stack &st, l4_cap_idx_t *thread, l4_cap_idx_t *rthread); }; /* vim: tabstop=2 expandtab shiftwidth=2 diff -r 0acb88011ba2 -r 86fe98e135bc libexec/lib/src/external_pager.cc --- a/libexec/lib/src/external_pager.cc Sat Mar 04 19:03:27 2023 +0100 +++ b/libexec/lib/src/external_pager.cc Mon Mar 06 00:14:52 2023 +0100 @@ -68,6 +68,14 @@ MappedRegion &r = it->second; ipc_detach_dataspace((void *) r.ds_start); + printf("Free %lx\n", r.ds); + ipc_cap_free_um(r.ds); + } + + if (l4_is_valid_cap(_task)) + { + ipc_cap_free_um(_task); + _task = L4_INVALID_CAP; } } @@ -75,14 +83,10 @@ /* Manage the task and thread capabilities. */ -void ExternalPager::set_task(l4_cap_idx_t cap) +void ExternalPager::add_thread(l4_cap_idx_t cap, l4_cap_idx_t rcap) { - _task = cap; -} - -void ExternalPager::set_server(l4_cap_idx_t cap) -{ - _server = cap; + _threads.push_back(cap); + _rthreads.push_back(rcap); } void ExternalPager::set_gate(l4_cap_idx_t cap) @@ -90,6 +94,23 @@ _ipc_gate = cap; } +void ExternalPager::set_pager(l4_cap_idx_t cap, l4_cap_idx_t rcap) +{ + _pager = cap; + _rpager = rcap; +} + +void ExternalPager::set_parent(l4_cap_idx_t cap, l4_cap_idx_t rcap) +{ + _parent = cap; + _rparent = rcap; +} + +void ExternalPager::set_task(l4_cap_idx_t cap) +{ + _task = cap; +} + /* Handle a general exception. */ @@ -185,9 +206,11 @@ { long err = ExecPager::find(start, &size, flags, offset, align); + /* Without an error, attach the dataspace. */ + if (!err) { - /* Attach the provided dataspace. + /* Attach the provided dataspace within this task. This is only done in this implementation to support the paging mechanism. In a region mapper residing within the actual task, the @@ -205,6 +228,11 @@ add(r); } + /* Discard the imported dataspace if its region cannot be accommodated. */ + + else + ipc_cap_free_um(ds); + return err; } @@ -237,10 +265,25 @@ /* NOTE: Capability indexes to be obtained from the process creation activity. */ + /* Log. */ + + l4_task_unmap(_task, l4_obj_fpage(0x05UL << L4_CAP_SHIFT, 0, L4_CAP_FPAGE_RWSD), L4_FP_ALL_SPACES); + /* Parent and pager/region mapper. */ - l4_task_unmap(_task, l4_obj_fpage(0x13UL << L4_CAP_SHIFT, 0, L4_CAP_FPAGE_RWSD), L4_FP_ALL_SPACES); - l4_task_unmap(_task, l4_obj_fpage(0x19UL << L4_CAP_SHIFT, 0, L4_CAP_FPAGE_RWSD), L4_FP_ALL_SPACES); + l4_task_unmap(_task, l4_obj_fpage(_rparent, 0, L4_CAP_FPAGE_RWSD), L4_FP_ALL_SPACES); + l4_task_unmap(_task, l4_obj_fpage(_rpager, 0, L4_CAP_FPAGE_RWSD), L4_FP_ALL_SPACES); + + /* Threads. For some reason, these cannot be released by the process, so + they are also unmapped on its behalf. */ + + std::vector::iterator it; + + for (it = _threads.begin(); it != _threads.end(); it++) + ipc_cap_free_um(*it); + + for (it = _rthreads.begin(); it != _rthreads.end(); it++) + l4_task_unmap(_task, l4_obj_fpage(*it, 0, L4_CAP_FPAGE_RWSD), L4_FP_ALL_SPACES); } } diff -r 0acb88011ba2 -r 86fe98e135bc libexec/lib/src/process.cc --- a/libexec/lib/src/process.cc Sat Mar 04 19:03:27 2023 +0100 +++ b/libexec/lib/src/process.cc Mon Mar 06 00:14:52 2023 +0100 @@ -149,30 +149,32 @@ } /* Configure the thread environment, employing the given server as the region - mapper. */ + mapper. Return the capability index for the server in the new task. */ -long Process::configure_thread(l4_cap_idx_t server, l4_cap_idx_t mapped_cap) +long Process::configure_thread(l4_cap_idx_t server, l4_cap_idx_t *mapped_cap) { /* Employ a distinct region mapper for each thread's environment, this acting as pager. */ - if (l4_is_valid_cap(mapped_cap)) + if ((mapped_cap != NULL) && l4_is_valid_cap(*mapped_cap)) { - _env.rm = mapped_cap; + _env.rm = *mapped_cap; return L4_EOK; } else { _env.rm = allocate_cap(); + *mapped_cap = _env.rm; return ipc_map_capability(_task, (struct ipc_mapped_cap) {_env.rm, server, L4_CAP_FPAGE_RWS, 0}); } } /* Set the parent of the new thread. */ -long Process::set_parent(l4_cap_idx_t server) +long Process::set_parent(l4_cap_idx_t parent, l4_cap_idx_t *rparent) { - return ipc_map_capability(_task, (struct ipc_mapped_cap) {_env.parent, server, L4_CAP_FPAGE_RWS, 0}); + *rparent = _env.parent; + return ipc_map_capability(_task, (struct ipc_mapped_cap) {_env.parent, parent, L4_CAP_FPAGE_RWS, 0}); } /* Map capabilities into the task, counting them if indicated. */ @@ -191,7 +193,7 @@ /* Create, initialise and start a thread. */ -long Process::thread_start(l4_addr_t program_start, Stack &st, l4_cap_idx_t *thread) +long Process::thread_start(l4_addr_t program_start, Stack &st, l4_cap_idx_t *thread, l4_cap_idx_t *rthread) { long err; @@ -255,6 +257,7 @@ l4_sched_param_t sp = l4_sched_param(L4RE_MAIN_THREAD_PRIO); + *rthread = _env.main_thread; return l4_error(l4_scheduler_run_thread(l4re_env()->scheduler, *thread, &sp)); } diff -r 0acb88011ba2 -r 86fe98e135bc libexec/lib/src/process_creating.cc --- a/libexec/lib/src/process_creating.cc Sat Mar 04 19:03:27 2023 +0100 +++ b/libexec/lib/src/process_creating.cc Mon Mar 06 00:14:52 2023 +0100 @@ -109,12 +109,19 @@ long ProcessCreating::configure_task(l4_cap_idx_t pager) { + l4_cap_idx_t rparent; long err = _process.configure_task(); if (err) return err; - return _process.set_parent(pager); + err = _process.set_parent(pager, &rparent); + + if (err) + return err; + + _exec_pager->set_parent(pager, rparent); + return L4_EOK; } /* Create an unbound IPC gate for the region mapper and allocate it in the @@ -212,11 +219,14 @@ /* Configure the environment for the thread, specifying the pager (and exception handler plus region mapper). */ - long err = _process.configure_thread(pager); + l4_cap_idx_t rpager = L4_INVALID_CAP; + long err = _process.configure_thread(pager, &rpager); if (err) return err; + _exec_pager->set_pager(pager, rpager); + /* Populate a thread stack with argument and environment details for the region mapper, plus the initial server capability and region details. */ @@ -229,13 +239,13 @@ /* Start the region mapper thread in the appropriate stack. */ - l4_cap_idx_t thread; - err = _process.thread_start(_rm_payload->entry_point(), rm_st, &thread); + l4_cap_idx_t thread, rthread; + err = _process.thread_start(_rm_payload->entry_point(), rm_st, &thread, &rthread); if (err) return err; - ipc_cap_free_um(thread); + _exec_pager->add_thread(thread, rthread); return L4_EOK; } @@ -251,7 +261,8 @@ /* Configure the environment for the thread, specifying the pager (and exception handler plus region mapper). */ - long err = _process.configure_thread(_ipc_gate, _ipc_gate_cap); + l4_cap_idx_t rpager = _ipc_gate_cap; + long err = _process.configure_thread(_ipc_gate, &rpager); if (err) return err; @@ -266,13 +277,13 @@ /* Start the program thread in the appropriate stack. */ - l4_cap_idx_t thread; - err = _process.thread_start(_program_payload->entry_point(), program_st, &thread); + l4_cap_idx_t thread, rthread; + err = _process.thread_start(_program_payload->entry_point(), program_st, &thread, &rthread); if (err) return err; - ipc_cap_free_um(thread); + _exec_pager->add_thread(thread, rthread); return L4_EOK; } @@ -314,7 +325,6 @@ /* Note the task and IPC gate on the pager object. */ - _exec_pager->set_server(*process); _exec_pager->set_task(_process.get_task()); _exec_pager->set_gate(_ipc_gate);