1.1 --- a/libexec/include/exec/external_pager.h Tue Feb 28 22:40:02 2023 +0100
1.2 +++ b/libexec/include/exec/external_pager.h Fri Mar 03 18:15:38 2023 +0100
1.3 @@ -35,6 +35,9 @@
1.4 class ExternalPager : public ExecPager, public ParentPagerObject,
1.5 public NotificationSupport, public Resource
1.6 {
1.7 +protected:
1.8 + l4_cap_idx_t _task, _server, _ipc_gate;
1.9 +
1.10 public:
1.11 explicit ExternalPager(address_t start = 0, address_t end = 0);
1.12
1.13 @@ -45,6 +48,16 @@
1.14 virtual void *interface()
1.15 { return static_cast<ParentPagerObject *>(this); }
1.16
1.17 + /* Task and thread management. */
1.18 +
1.19 + virtual void set_task(l4_cap_idx_t cap);
1.20 + virtual void set_server(l4_cap_idx_t cap);
1.21 + virtual void set_gate(l4_cap_idx_t cap);
1.22 +
1.23 + /* Resource methods. */
1.24 +
1.25 + virtual void close();
1.26 +
1.27 /* Notification methods, implementing PagerObject. */
1.28
1.29 virtual long exception(l4_exc_regs_t regs,
2.1 --- a/libexec/include/exec/process.h Tue Feb 28 22:40:02 2023 +0100
2.2 +++ b/libexec/include/exec/process.h Fri Mar 03 18:15:38 2023 +0100
2.3 @@ -1,7 +1,7 @@
2.4 /*
2.5 * Support for initialising programs in new tasks and threads.
2.6 *
2.7 - * Copyright (C) 2022 Paul Boddie <paul@boddie.org.uk>
2.8 + * Copyright (C) 2022, 2023 Paul Boddie <paul@boddie.org.uk>
2.9 *
2.10 * This program is free software; you can redistribute it and/or
2.11 * modify it under the terms of the GNU General Public License as
2.12 @@ -95,12 +95,14 @@
2.13
2.14 long configure_thread(l4_cap_idx_t server, l4_cap_idx_t mapped_cap = L4_INVALID_CAP);
2.15
2.16 + l4_cap_idx_t get_task();
2.17 +
2.18 long set_parent(l4_cap_idx_t server);
2.19
2.20 long map_capabilities(struct ipc_mapped_cap mapped_caps[],
2.21 bool to_count = true);
2.22
2.23 - long thread_start(l4_addr_t program_start, Stack &st);
2.24 + long thread_start(l4_addr_t program_start, Stack &st, l4_cap_idx_t *thread);
2.25 };
2.26
2.27 /* vim: tabstop=2 expandtab shiftwidth=2
3.1 --- a/libexec/lib/src/external_pager.cc Tue Feb 28 22:40:02 2023 +0100
3.2 +++ b/libexec/lib/src/external_pager.cc Fri Mar 03 18:15:38 2023 +0100
3.3 @@ -20,8 +20,10 @@
3.4 */
3.5
3.6 #include <l4/re/env.h>
3.7 +#include <l4/sys/task.h>
3.8 #include <l4/util/util.h>
3.9
3.10 +#include <ipc/cap_alloc.h>
3.11 #include <ipc/mem_ipc.h>
3.12 #include <mem/memory_utils.h>
3.13 #include <systypes/base.h>
3.14 @@ -46,9 +48,50 @@
3.15
3.16 ipc_server_default_config_type ExternalPager::config()
3.17 {
3.18 - return config_ParentPagerObject;
3.19 + return config_ParentPagerObject;
3.20 +}
3.21 +
3.22 +
3.23 +
3.24 +/* Close the pager. */
3.25 +
3.26 +void ExternalPager::close()
3.27 +{
3.28 + printf("Pager closing...\n");
3.29 +
3.30 + /* Unmap all regions. */
3.31 +
3.32 + MappedRegions::iterator it;
3.33 +
3.34 + for (it = _regions.begin(); it != _regions.end(); it++)
3.35 + {
3.36 + MappedRegion &r = it->second;
3.37 +
3.38 + ipc_detach_dataspace((void *) r.ds_start);
3.39 + }
3.40 }
3.41
3.42 +
3.43 +
3.44 +/* Manage the task and thread capabilities. */
3.45 +
3.46 +void ExternalPager::set_task(l4_cap_idx_t cap)
3.47 +{
3.48 + _task = cap;
3.49 +}
3.50 +
3.51 +void ExternalPager::set_server(l4_cap_idx_t cap)
3.52 +{
3.53 + _server = cap;
3.54 +}
3.55 +
3.56 +void ExternalPager::set_gate(l4_cap_idx_t cap)
3.57 +{
3.58 + _ipc_gate = cap;
3.59 +}
3.60 +
3.61 +
3.62 +
3.63 /* Handle a general exception. */
3.64
3.65 long ExternalPager::exception(l4_exc_regs_t regs, l4_snd_fpage_t *region)
3.66 @@ -165,15 +208,45 @@
3.67 return err;
3.68 }
3.69
3.70 +
3.71 +
3.72 /* Receive signals from a task. */
3.73
3.74 long ExternalPager::signal(unsigned long sig, unsigned long val)
3.75 {
3.76 notify_all(NOTIFY_TASK_SIGNAL, (notify_values_t) {sig, val});
3.77
3.78 + /* Handle the termination event. */
3.79 +
3.80 + if (sig == 0)
3.81 + {
3.82 + /* Once the program exits, the IPC gate connecting the program with its
3.83 + internal pager can be released. */
3.84 +
3.85 + if (l4_is_valid_cap(_ipc_gate))
3.86 + {
3.87 + l4_task_unmap(L4RE_THIS_TASK_CAP, l4_obj_fpage(_ipc_gate, 0, L4_CAP_FPAGE_RWSD), L4_FP_ALL_SPACES);
3.88 + _ipc_gate = L4_INVALID_CAP;
3.89 + }
3.90 +
3.91 + /* Upon exit of the program's internal pager, release the capabilities
3.92 + associated with this server. */
3.93 +
3.94 + else if (l4_is_valid_cap(_task))
3.95 + {
3.96 + /* NOTE: Capability indexes to be obtained from the process creation
3.97 + activity. */
3.98 +
3.99 + l4_task_unmap(_task, l4_obj_fpage(0x13UL << L4_CAP_SHIFT, 0, L4_CAP_FPAGE_RWSD), L4_FP_ALL_SPACES);
3.100 + l4_task_unmap(_task, l4_obj_fpage(0x19UL << L4_CAP_SHIFT, 0, L4_CAP_FPAGE_RWSD), L4_FP_ALL_SPACES);
3.101 + }
3.102 + }
3.103 +
3.104 return L4_EOK;
3.105 }
3.106
3.107 +
3.108 +
3.109 /* Subscribe to notifications. */
3.110
3.111 long ExternalPager::subscribe(l4_cap_idx_t notifier, notify_flags_t flags)
4.1 --- a/libexec/lib/src/process.cc Tue Feb 28 22:40:02 2023 +0100
4.2 +++ b/libexec/lib/src/process.cc Fri Mar 03 18:15:38 2023 +0100
4.3 @@ -1,7 +1,7 @@
4.4 /*
4.5 * Support for initialising programs in new tasks and threads.
4.6 *
4.7 - * Copyright (C) 2022 Paul Boddie <paul@boddie.org.uk>
4.8 + * Copyright (C) 2022, 2023 Paul Boddie <paul@boddie.org.uk>
4.9 *
4.10 * This program is free software; you can redistribute it and/or
4.11 * modify it under the terms of the GNU General Public License as
4.12 @@ -107,6 +107,13 @@
4.13 return l4_error(l4_factory_create_thread(l4re_env()->factory, *thread));
4.14 }
4.15
4.16 +/* Task access. */
4.17 +
4.18 +l4_cap_idx_t Process::get_task()
4.19 +{
4.20 + return _task;
4.21 +}
4.22 +
4.23 /* Configure the task environment. */
4.24
4.25 long Process::configure_task(unsigned int threads)
4.26 @@ -184,12 +191,11 @@
4.27
4.28 /* Create, initialise and start a thread. */
4.29
4.30 -long Process::thread_start(l4_addr_t program_start, Stack &st)
4.31 +long Process::thread_start(l4_addr_t program_start, Stack &st, l4_cap_idx_t *thread)
4.32 {
4.33 - l4_cap_idx_t thread;
4.34 long err;
4.35
4.36 - err = create_thread(&thread);
4.37 + err = create_thread(thread);
4.38
4.39 if (err)
4.40 return err;
4.41 @@ -208,11 +214,11 @@
4.42 l4_thread_control_exc_handler(_env.rm);
4.43 l4_thread_control_bind((l4_utcb_t *) l4_fpage_memaddr(_env.utcb_area), _task);
4.44
4.45 - err = l4_error(l4_thread_control_commit(thread));
4.46 + err = l4_error(l4_thread_control_commit(*thread));
4.47
4.48 if (err)
4.49 {
4.50 - ipc_cap_free(thread);
4.51 + ipc_cap_free(*thread);
4.52 return err;
4.53 }
4.54
4.55 @@ -220,7 +226,7 @@
4.56
4.57 _env.main_thread = allocate_cap();
4.58
4.59 - ipc_map_capability(_task, (struct ipc_mapped_cap) {_env.main_thread, thread, L4_CAP_FPAGE_RWS, 0});
4.60 + ipc_map_capability(_task, (struct ipc_mapped_cap) {_env.main_thread, *thread, L4_CAP_FPAGE_RWS, 0});
4.61
4.62 /* Populate the initial environment in the thread. */
4.63
4.64 @@ -236,7 +242,7 @@
4.65
4.66 /* Set the start details. */
4.67
4.68 - err = l4_error(l4_thread_ex_regs(thread, program_start, st.start_address(), 0));
4.69 + err = l4_error(l4_thread_ex_regs(*thread, program_start, st.start_address(), 0));
4.70
4.71 if (err)
4.72 return err;
4.73 @@ -249,7 +255,7 @@
4.74
4.75 l4_sched_param_t sp = l4_sched_param(L4RE_MAIN_THREAD_PRIO);
4.76
4.77 - return l4_error(l4_scheduler_run_thread(l4re_env()->scheduler, thread, &sp));
4.78 + return l4_error(l4_scheduler_run_thread(l4re_env()->scheduler, *thread, &sp));
4.79 }
4.80
4.81 /* vim: tabstop=2 expandtab shiftwidth=2
5.1 --- a/libexec/lib/src/process_creating.cc Tue Feb 28 22:40:02 2023 +0100
5.2 +++ b/libexec/lib/src/process_creating.cc Fri Mar 03 18:15:38 2023 +0100
5.3 @@ -97,7 +97,12 @@
5.4
5.5 /* Start the pager in a separate thread. */
5.6
5.7 - return ResourceServer(_exec_pager).start_thread(pager);
5.8 + long err = ResourceServer(_exec_pager).start_thread(pager);
5.9 +
5.10 + if (err)
5.11 + return err;
5.12 +
5.13 + return L4_EOK;
5.14 }
5.15
5.16 /* Configure the environment for the task. */
5.17 @@ -224,7 +229,14 @@
5.18
5.19 /* Start the region mapper thread in the appropriate stack. */
5.20
5.21 - return _process.thread_start(_rm_payload->entry_point(), rm_st);
5.22 + l4_cap_idx_t thread;
5.23 + err = _process.thread_start(_rm_payload->entry_point(), rm_st, &thread);
5.24 +
5.25 + if (err)
5.26 + return err;
5.27 +
5.28 + ipc_cap_free_um(thread);
5.29 + return L4_EOK;
5.30 }
5.31
5.32 /* Configure a thread for a program, populate its stack, and start the
5.33 @@ -254,7 +266,14 @@
5.34
5.35 /* Start the program thread in the appropriate stack. */
5.36
5.37 - return _process.thread_start(_program_payload->entry_point(), program_st);
5.38 + l4_cap_idx_t thread;
5.39 + err = _process.thread_start(_program_payload->entry_point(), program_st, &thread);
5.40 +
5.41 + if (err)
5.42 + return err;
5.43 +
5.44 + ipc_cap_free_um(thread);
5.45 + return L4_EOK;
5.46 }
5.47
5.48 /* Start a new process for the given payload, providing the indicated program
5.49 @@ -293,6 +312,12 @@
5.50 if (err)
5.51 return err;
5.52
5.53 + /* Note the task and IPC gate on the pager object. */
5.54 +
5.55 + _exec_pager->set_server(*process);
5.56 + _exec_pager->set_task(_process.get_task());
5.57 + _exec_pager->set_gate(_ipc_gate);
5.58 +
5.59 /* Discard instances created to initialise the process.
5.60 NOTE: The region mapper payload could be retained instead of being
5.61 reconstructed each time. */
6.1 --- a/libexec/rm/region_mapper.cc Tue Feb 28 22:40:02 2023 +0100
6.2 +++ b/libexec/rm/region_mapper.cc Fri Mar 03 18:15:38 2023 +0100
6.3 @@ -1,7 +1,7 @@
6.4 /*
6.5 * A region mapper for deployment in a new task.
6.6 *
6.7 - * Copyright (C) 2022 Paul Boddie <paul@boddie.org.uk>
6.8 + * Copyright (C) 2022, 2023 Paul Boddie <paul@boddie.org.uk>
6.9 *
6.10 * This program is free software; you can redistribute it and/or
6.11 * modify it under the terms of the GNU General Public License as
6.12 @@ -69,7 +69,16 @@
6.13 printf("Pager capability: %lx\n", l4re_env_get_cap("server"));
6.14 printf("Main thread: %lx\n", l4re_env()->main_thread);
6.15
6.16 - ipc_server_loop_for(PagerObject, &exec_pager, "server");
6.17 + /* Initialise the server, enabling notifications. */
6.18 +
6.19 + ipc_server_config_type config;
6.20 + ipc_server_init_for(&config, PagerObject, &exec_pager);
6.21 + config.notifications = 1;
6.22 +
6.23 + /* Bind to the named capability and serve until the IPC gate is released. */
6.24 +
6.25 + ipc_server_bind("server", (l4_umword_t) &config, &config.server);
6.26 + ipc_server_start_config(&config);
6.27
6.28 printf("Ending pager...\n");
6.29 return 0;
7.1 --- a/libfsclient/include/fsclient/process.h Tue Feb 28 22:40:02 2023 +0100
7.2 +++ b/libfsclient/include/fsclient/process.h Fri Mar 03 18:15:38 2023 +0100
7.3 @@ -57,6 +57,7 @@
7.4 /* Principal functions. */
7.5
7.6 process_t *process_new();
7.7 +void process_close(process_t *process);
7.8 void process_init(process_t *process);
7.9 long process_start(process_t *process, int argc, char *argv[]);
7.10
8.1 --- a/libfsclient/lib/src/process.cc Tue Feb 28 22:40:02 2023 +0100
8.2 +++ b/libfsclient/lib/src/process.cc Fri Mar 03 18:15:38 2023 +0100
8.3 @@ -46,16 +46,24 @@
8.4 return process;
8.5 }
8.6
8.7 +/* Discard the given process. */
8.8 +
8.9 +void process_close(process_t *process)
8.10 +{
8.11 + if (process == NULL)
8.12 + return;
8.13 +
8.14 + if (l4_is_valid_cap(process->ref))
8.15 + ipc_cap_free_um(process->ref);
8.16 +
8.17 + process_init(process);
8.18 +}
8.19 +
8.20 /* Initialise the given process structure. */
8.21
8.22 void process_init(process_t *process)
8.23 {
8.24 process->ref = L4_INVALID_CAP;
8.25 -
8.26 - /* Initialise the notifiable section of the structure. */
8.27 -
8.28 - process->notifiable.notifications = 0;
8.29 - process->notifiable.base = (notifiable_base_t *) process;
8.30 }
8.31
8.32 /* Start a process using the given arguments.
8.33 @@ -94,6 +102,11 @@
8.34
8.35 err = creator.start(argc, &process->ref);
8.36
8.37 + /* Initialise the notifiable section of the structure. */
8.38 +
8.39 + process->notifiable.notifications = 0;
8.40 + process->notifiable.base = (notifiable_base_t *) process;
8.41 +
8.42 /* Close the context, although a separate mechanism could permit contexts to
8.43 open several processes. */
8.44
8.45 @@ -187,7 +200,10 @@
8.46
8.47 if (!err && (process->notifiable.notifications & NOTIFY_TASK_SIGNAL) &&
8.48 (process->notifiable.values.sig == 0))
8.49 + {
8.50 process_notify_unsubscribe(process, notifier);
8.51 + process_close(process);
8.52 + }
8.53
8.54 return err;
8.55 }
8.56 @@ -206,7 +222,10 @@
8.57
8.58 if (!err && ((*process)->notifiable.notifications & NOTIFY_TASK_SIGNAL) &&
8.59 ((*process)->notifiable.values.sig == 0))
8.60 + {
8.61 process_notify_unsubscribe(*process, notifier);
8.62 + process_close(*process);
8.63 + }
8.64
8.65 return err;
8.66 }