1.1 --- a/libexec/include/exec/external_pager.h Sat Mar 04 19:03:27 2023 +0100
1.2 +++ b/libexec/include/exec/external_pager.h Mon Mar 06 00:14:52 2023 +0100
1.3 @@ -21,6 +21,8 @@
1.4
1.5 #pragma once
1.6
1.7 +#include <vector>
1.8 +
1.9 #include <exec/pager.h>
1.10 #include <fsserver/notification.h>
1.11 #include <fsserver/resource.h>
1.12 @@ -36,7 +38,8 @@
1.13 public NotificationSupport, public Resource
1.14 {
1.15 protected:
1.16 - l4_cap_idx_t _task, _server, _ipc_gate;
1.17 + l4_cap_idx_t _task, _ipc_gate, _parent, _rparent, _pager, _rpager;
1.18 + std::vector<l4_cap_idx_t> _threads, _rthreads;
1.19
1.20 public:
1.21 explicit ExternalPager(address_t start = 0, address_t end = 0);
1.22 @@ -50,9 +53,11 @@
1.23
1.24 /* Task and thread management. */
1.25
1.26 + virtual void add_thread(l4_cap_idx_t cap, l4_cap_idx_t rcap);
1.27 + virtual void set_gate(l4_cap_idx_t cap);
1.28 + virtual void set_pager(l4_cap_idx_t cap, l4_cap_idx_t rcap);
1.29 + virtual void set_parent(l4_cap_idx_t cap, l4_cap_idx_t rcap);
1.30 virtual void set_task(l4_cap_idx_t cap);
1.31 - virtual void set_server(l4_cap_idx_t cap);
1.32 - virtual void set_gate(l4_cap_idx_t cap);
1.33
1.34 /* Resource methods. */
1.35
2.1 --- a/libexec/include/exec/process.h Sat Mar 04 19:03:27 2023 +0100
2.2 +++ b/libexec/include/exec/process.h Mon Mar 06 00:14:52 2023 +0100
2.3 @@ -93,16 +93,16 @@
2.4
2.5 long configure_task(unsigned int threads = 2);
2.6
2.7 - long configure_thread(l4_cap_idx_t server, l4_cap_idx_t mapped_cap = L4_INVALID_CAP);
2.8 + long configure_thread(l4_cap_idx_t server, l4_cap_idx_t *mapped_cap = NULL);
2.9
2.10 l4_cap_idx_t get_task();
2.11
2.12 - long set_parent(l4_cap_idx_t server);
2.13 + long set_parent(l4_cap_idx_t parent, l4_cap_idx_t *rparent);
2.14
2.15 long map_capabilities(struct ipc_mapped_cap mapped_caps[],
2.16 bool to_count = true);
2.17
2.18 - long thread_start(l4_addr_t program_start, Stack &st, l4_cap_idx_t *thread);
2.19 + long thread_start(l4_addr_t program_start, Stack &st, l4_cap_idx_t *thread, l4_cap_idx_t *rthread);
2.20 };
2.21
2.22 /* vim: tabstop=2 expandtab shiftwidth=2
3.1 --- a/libexec/lib/src/external_pager.cc Sat Mar 04 19:03:27 2023 +0100
3.2 +++ b/libexec/lib/src/external_pager.cc Mon Mar 06 00:14:52 2023 +0100
3.3 @@ -68,6 +68,14 @@
3.4 MappedRegion &r = it->second;
3.5
3.6 ipc_detach_dataspace((void *) r.ds_start);
3.7 + printf("Free %lx\n", r.ds);
3.8 + ipc_cap_free_um(r.ds);
3.9 + }
3.10 +
3.11 + if (l4_is_valid_cap(_task))
3.12 + {
3.13 + ipc_cap_free_um(_task);
3.14 + _task = L4_INVALID_CAP;
3.15 }
3.16 }
3.17
3.18 @@ -75,14 +83,10 @@
3.19
3.20 /* Manage the task and thread capabilities. */
3.21
3.22 -void ExternalPager::set_task(l4_cap_idx_t cap)
3.23 +void ExternalPager::add_thread(l4_cap_idx_t cap, l4_cap_idx_t rcap)
3.24 {
3.25 - _task = cap;
3.26 -}
3.27 -
3.28 -void ExternalPager::set_server(l4_cap_idx_t cap)
3.29 -{
3.30 - _server = cap;
3.31 + _threads.push_back(cap);
3.32 + _rthreads.push_back(rcap);
3.33 }
3.34
3.35 void ExternalPager::set_gate(l4_cap_idx_t cap)
3.36 @@ -90,6 +94,23 @@
3.37 _ipc_gate = cap;
3.38 }
3.39
3.40 +void ExternalPager::set_pager(l4_cap_idx_t cap, l4_cap_idx_t rcap)
3.41 +{
3.42 + _pager = cap;
3.43 + _rpager = rcap;
3.44 +}
3.45 +
3.46 +void ExternalPager::set_parent(l4_cap_idx_t cap, l4_cap_idx_t rcap)
3.47 +{
3.48 + _parent = cap;
3.49 + _rparent = rcap;
3.50 +}
3.51 +
3.52 +void ExternalPager::set_task(l4_cap_idx_t cap)
3.53 +{
3.54 + _task = cap;
3.55 +}
3.56 +
3.57
3.58
3.59 /* Handle a general exception. */
3.60 @@ -185,9 +206,11 @@
3.61 {
3.62 long err = ExecPager::find(start, &size, flags, offset, align);
3.63
3.64 + /* Without an error, attach the dataspace. */
3.65 +
3.66 if (!err)
3.67 {
3.68 - /* Attach the provided dataspace.
3.69 + /* Attach the provided dataspace within this task.
3.70
3.71 This is only done in this implementation to support the paging
3.72 mechanism. In a region mapper residing within the actual task, the
3.73 @@ -205,6 +228,11 @@
3.74 add(r);
3.75 }
3.76
3.77 + /* Discard the imported dataspace if its region cannot be accommodated. */
3.78 +
3.79 + else
3.80 + ipc_cap_free_um(ds);
3.81 +
3.82 return err;
3.83 }
3.84
3.85 @@ -237,10 +265,25 @@
3.86 /* NOTE: Capability indexes to be obtained from the process creation
3.87 activity. */
3.88
3.89 + /* Log. */
3.90 +
3.91 + l4_task_unmap(_task, l4_obj_fpage(0x05UL << L4_CAP_SHIFT, 0, L4_CAP_FPAGE_RWSD), L4_FP_ALL_SPACES);
3.92 +
3.93 /* Parent and pager/region mapper. */
3.94
3.95 - l4_task_unmap(_task, l4_obj_fpage(0x13UL << L4_CAP_SHIFT, 0, L4_CAP_FPAGE_RWSD), L4_FP_ALL_SPACES);
3.96 - l4_task_unmap(_task, l4_obj_fpage(0x19UL << L4_CAP_SHIFT, 0, L4_CAP_FPAGE_RWSD), L4_FP_ALL_SPACES);
3.97 + l4_task_unmap(_task, l4_obj_fpage(_rparent, 0, L4_CAP_FPAGE_RWSD), L4_FP_ALL_SPACES);
3.98 + l4_task_unmap(_task, l4_obj_fpage(_rpager, 0, L4_CAP_FPAGE_RWSD), L4_FP_ALL_SPACES);
3.99 +
3.100 + /* Threads. For some reason, these cannot be released by the process, so
3.101 + they are also unmapped on its behalf. */
3.102 +
3.103 + std::vector<l4_cap_idx_t>::iterator it;
3.104 +
3.105 + for (it = _threads.begin(); it != _threads.end(); it++)
3.106 + ipc_cap_free_um(*it);
3.107 +
3.108 + for (it = _rthreads.begin(); it != _rthreads.end(); it++)
3.109 + l4_task_unmap(_task, l4_obj_fpage(*it, 0, L4_CAP_FPAGE_RWSD), L4_FP_ALL_SPACES);
3.110 }
3.111 }
3.112
4.1 --- a/libexec/lib/src/process.cc Sat Mar 04 19:03:27 2023 +0100
4.2 +++ b/libexec/lib/src/process.cc Mon Mar 06 00:14:52 2023 +0100
4.3 @@ -149,30 +149,32 @@
4.4 }
4.5
4.6 /* Configure the thread environment, employing the given server as the region
4.7 - mapper. */
4.8 + mapper. Return the capability index for the server in the new task. */
4.9
4.10 -long Process::configure_thread(l4_cap_idx_t server, l4_cap_idx_t mapped_cap)
4.11 +long Process::configure_thread(l4_cap_idx_t server, l4_cap_idx_t *mapped_cap)
4.12 {
4.13 /* Employ a distinct region mapper for each thread's environment, this acting
4.14 as pager. */
4.15
4.16 - if (l4_is_valid_cap(mapped_cap))
4.17 + if ((mapped_cap != NULL) && l4_is_valid_cap(*mapped_cap))
4.18 {
4.19 - _env.rm = mapped_cap;
4.20 + _env.rm = *mapped_cap;
4.21 return L4_EOK;
4.22 }
4.23 else
4.24 {
4.25 _env.rm = allocate_cap();
4.26 + *mapped_cap = _env.rm;
4.27 return ipc_map_capability(_task, (struct ipc_mapped_cap) {_env.rm, server, L4_CAP_FPAGE_RWS, 0});
4.28 }
4.29 }
4.30
4.31 /* Set the parent of the new thread. */
4.32
4.33 -long Process::set_parent(l4_cap_idx_t server)
4.34 +long Process::set_parent(l4_cap_idx_t parent, l4_cap_idx_t *rparent)
4.35 {
4.36 - return ipc_map_capability(_task, (struct ipc_mapped_cap) {_env.parent, server, L4_CAP_FPAGE_RWS, 0});
4.37 + *rparent = _env.parent;
4.38 + return ipc_map_capability(_task, (struct ipc_mapped_cap) {_env.parent, parent, L4_CAP_FPAGE_RWS, 0});
4.39 }
4.40
4.41 /* Map capabilities into the task, counting them if indicated. */
4.42 @@ -191,7 +193,7 @@
4.43
4.44 /* Create, initialise and start a thread. */
4.45
4.46 -long Process::thread_start(l4_addr_t program_start, Stack &st, l4_cap_idx_t *thread)
4.47 +long Process::thread_start(l4_addr_t program_start, Stack &st, l4_cap_idx_t *thread, l4_cap_idx_t *rthread)
4.48 {
4.49 long err;
4.50
4.51 @@ -255,6 +257,7 @@
4.52
4.53 l4_sched_param_t sp = l4_sched_param(L4RE_MAIN_THREAD_PRIO);
4.54
4.55 + *rthread = _env.main_thread;
4.56 return l4_error(l4_scheduler_run_thread(l4re_env()->scheduler, *thread, &sp));
4.57 }
4.58
5.1 --- a/libexec/lib/src/process_creating.cc Sat Mar 04 19:03:27 2023 +0100
5.2 +++ b/libexec/lib/src/process_creating.cc Mon Mar 06 00:14:52 2023 +0100
5.3 @@ -109,12 +109,19 @@
5.4
5.5 long ProcessCreating::configure_task(l4_cap_idx_t pager)
5.6 {
5.7 + l4_cap_idx_t rparent;
5.8 long err = _process.configure_task();
5.9
5.10 if (err)
5.11 return err;
5.12
5.13 - return _process.set_parent(pager);
5.14 + err = _process.set_parent(pager, &rparent);
5.15 +
5.16 + if (err)
5.17 + return err;
5.18 +
5.19 + _exec_pager->set_parent(pager, rparent);
5.20 + return L4_EOK;
5.21 }
5.22
5.23 /* Create an unbound IPC gate for the region mapper and allocate it in the
5.24 @@ -212,11 +219,14 @@
5.25 /* Configure the environment for the thread, specifying the pager (and
5.26 exception handler plus region mapper). */
5.27
5.28 - long err = _process.configure_thread(pager);
5.29 + l4_cap_idx_t rpager = L4_INVALID_CAP;
5.30 + long err = _process.configure_thread(pager, &rpager);
5.31
5.32 if (err)
5.33 return err;
5.34
5.35 + _exec_pager->set_pager(pager, rpager);
5.36 +
5.37 /* Populate a thread stack with argument and environment details for the
5.38 region mapper, plus the initial server capability and region details. */
5.39
5.40 @@ -229,13 +239,13 @@
5.41
5.42 /* Start the region mapper thread in the appropriate stack. */
5.43
5.44 - l4_cap_idx_t thread;
5.45 - err = _process.thread_start(_rm_payload->entry_point(), rm_st, &thread);
5.46 + l4_cap_idx_t thread, rthread;
5.47 + err = _process.thread_start(_rm_payload->entry_point(), rm_st, &thread, &rthread);
5.48
5.49 if (err)
5.50 return err;
5.51
5.52 - ipc_cap_free_um(thread);
5.53 + _exec_pager->add_thread(thread, rthread);
5.54 return L4_EOK;
5.55 }
5.56
5.57 @@ -251,7 +261,8 @@
5.58 /* Configure the environment for the thread, specifying the pager (and
5.59 exception handler plus region mapper). */
5.60
5.61 - long err = _process.configure_thread(_ipc_gate, _ipc_gate_cap);
5.62 + l4_cap_idx_t rpager = _ipc_gate_cap;
5.63 + long err = _process.configure_thread(_ipc_gate, &rpager);
5.64
5.65 if (err)
5.66 return err;
5.67 @@ -266,13 +277,13 @@
5.68
5.69 /* Start the program thread in the appropriate stack. */
5.70
5.71 - l4_cap_idx_t thread;
5.72 - err = _process.thread_start(_program_payload->entry_point(), program_st, &thread);
5.73 + l4_cap_idx_t thread, rthread;
5.74 + err = _process.thread_start(_program_payload->entry_point(), program_st, &thread, &rthread);
5.75
5.76 if (err)
5.77 return err;
5.78
5.79 - ipc_cap_free_um(thread);
5.80 + _exec_pager->add_thread(thread, rthread);
5.81 return L4_EOK;
5.82 }
5.83
5.84 @@ -314,7 +325,6 @@
5.85
5.86 /* Note the task and IPC gate on the pager object. */
5.87
5.88 - _exec_pager->set_server(*process);
5.89 _exec_pager->set_task(_process.get_task());
5.90 _exec_pager->set_gate(_ipc_gate);
5.91