1/*
2 * Copyright 2017, Data61
3 * Commonwealth Scientific and Industrial Research Organisation (CSIRO)
4 * ABN 41 687 119 230.
5 *
6 * This software may be distributed and modified according to the terms of
7 * the BSD 2-Clause license. Note that NO WARRANTY is provided.
8 * See "LICENSE_BSD2.txt" for details.
9 *
10 * @TAG(DATA61_BSD)
11 */
12#pragma once
13
14#include <autoconf.h>
15#include <sel4utils/gen_config.h>
16
17#include <vka/vka.h>
18#include <vspace/vspace.h>
19
20#include <sel4utils/thread.h>
21#include <sel4utils/process_config.h>
22#include <sel4utils/vspace.h>
23#include <sel4utils/elf.h>
24#include <sel4platsupport/timer.h>
25
26#define WORD_STRING_SIZE ((CONFIG_WORD_SIZE / 3) + 1)
27
28typedef struct object_node object_node_t;
29
30struct object_node {
31    vka_object_t object;
32    object_node_t *next;
33};
34
35typedef struct {
36    vka_object_t pd;
37    vspace_t vspace;
38    sel4utils_alloc_data_t data;
39    vka_object_t cspace;
40    uint32_t cspace_size;
41    uint32_t cspace_next_free;
42    sel4utils_thread_t thread;
43    vka_object_t fault_endpoint;
44    void *entry_point;
45    uintptr_t sysinfo;
46    /* cptr (with respect to the process cnode) of the tcb of the first thread (0 means not supplied) */
47    seL4_CPtr dest_tcb_cptr;
48    seL4_Word pagesz;
49    object_node_t *allocated_object_list_head;
50    /* ELF headers that describe the sections of the loaded image (at least as they
51     * existed at load time). Is different to the elf_regions, which have reservations,
52     * these are the original headers from the elf and include nonloaded information regions */
53    int num_elf_phdrs;
54    Elf_Phdr *elf_phdrs;
55    /* if the elf wasn't loaded into the address space, this describes the regions.
56     * this permits lazy loading / copy on write / page sharing / whatever crazy thing
57     * you want to implement */
58    int num_elf_regions;
59    sel4utils_elf_region_t *elf_regions;
60    bool own_vspace;
61    bool own_cspace;
62    bool own_ep;
63} sel4utils_process_t;
64
65/* sel4utils processes start with some caps in their cspace.
66 * These are the caps
67 */
68enum sel4utils_cspace_layout {
69    /* no cap in NULL */
70    SEL4UTILS_NULL_SLOT = 0,
71    /*
72     * The root cnode (with appropriate guard)
73     */
74    SEL4UTILS_CNODE_SLOT = 1,
75    /* The slot on the cspace that fault_endpoint is put if
76     * sel4utils_configure_process is used.
77     */
78    SEL4UTILS_ENDPOINT_SLOT = 2,
79
80    /* The page directory slot */
81    SEL4UTILS_PD_SLOT = 3,
82
83    /* the slot for the asid pool that this thread is in and can create threads
84     * in. 0 if this kernel does not support asid pools */
85    SEL4UTILS_ASID_POOL_SLOT = 4,
86
87    /* the slot for this processes tcb */
88    SEL4UTILS_TCB_SLOT = 5,
89
90    /* the slot for this processes sc */
91    SEL4UTILS_SCHED_CONTEXT_SLOT = 6,
92
93    /* The slot for this processes reply object */
94    SEL4UTILS_REPLY_SLOT = 7,
95
96    /* First free slot in the cspace configured by sel4utils */
97    SEL4UTILS_FIRST_FREE = 8
98};
99
100/**
101 * Start a process, and copy arguments into the processes address space.
102 *
103 * This is intended to use when loading applications of the format:
104 *
105 * int main(int argc, char **argv) { };
106 *
107 * The third argument (in r2 for arm, on stack for ia32) will be the address of the ipc buffer.
108 * This is intended to be loaded by the crt into the data word of the ipc buffer,
109 * or you can just add it to your function prototype.
110 *
111 * Add the following to your crt to use it this way:
112 *
113 * arm: str r2, [r2, #484]
114 * ia32: popl %ebp
115 *       movl %ebp, 484(%ebp)
116 *
117 * @param process initialised sel4utils process struct.
118 * @param vka     vka interface to use for allocation of frames.
119 * @param vspace  the current vspace.
120 * @param argc    the number of arguments.
121 * @param argv    a pointer to an array of strings in the current vspace.
122 * @param resume  1 to start the process, 0 to leave suspended.
123 *
124 * @return -1 on error, 0 on success.
125 *
126 */
127int sel4utils_spawn_process(sel4utils_process_t *process, vka_t *vka, vspace_t *vspace,
128                            int argc, char *argv[], int resume);
129
130/**
131 * Start a process, and copy arguments into the processes address space.
132 *
133 * This is intended for use when loading applications that have a System V ABI compliant
134 * entry point. This means that the entry point should *not* be a 'main' that is expecting
135 * argc and argv in the form as passed here, but should be an _start routine that will
136 * take a stack frame with the arguments on it and construct an appropriate invocation
137 * to a main function. The stack frame passed to the entry point will have an auxv, envp
138 * and argv
139 *
140 * @param process initialised sel4utils process struct.
141 * @param vka     vka interface to use for allocation of frames.
142 * @param vspace  the current vspace.
143 * @param argc    the number of arguments.
144 * @param argv    a pointer to an array of strings in the current vspace.
145 * @param resume  1 to start the process, 0 to leave suspended.
146 *
147 * @return -1 on error, 0 on success.
148 *
149 */
150int sel4utils_spawn_process_v(sel4utils_process_t *process, vka_t *vka, vspace_t *vspace,
151                              int argc, char *argv[], int resume);
152
153/**
154 * This is the function to use if you just want to set up a process as fast as possible.
155 * It creates a simple cspace and vspace for you, allocates a fault endpoint and puts
156 * it into the new cspace. The process will start at priority 0.
157 *
158 * If CONFIG_RT is enabled, it will not have a scheduling context.
159 *
160 * It loads the elf file into the new vspace, parses the elf file and stores the entry point
161 * into process->entry_point.
162 *
163 * It uses the same vka for both allocations - the new process will not have an allocator.
164 *
165 * The process will have just one thread.
166 *
167 * Otherwise, use it as a model for loading processes and use the elf_load.
168 *
169 * WARNING: when launching processes on ia32 please ensure your calling convention
170 * matches that documented in sel4utils_start_thread. Otherwise your arguments
171 * won't come through correctly.
172 *
173 * @param process      uninitialised process struct.
174 * @param vka          allocator to use to allocate objects.
175 * @param vspace vspace allocator for the current vspace.
176 * @param image_name   name of the elf image to load from the cpio archive.
177 *
178 * @return 0 on success, -1 on error.
179 */
180int sel4utils_configure_process(sel4utils_process_t *process, vka_t *vka, vspace_t *vspace,
181                                const char *image_name);
182
183/**
184 * Configure a process with more customisations (Create your own vspace, customise cspace size).
185 *
186 * @param process               uninitialised process struct
187 * @param vka                   allocator to use to allocate objects.
188 * @param spawner_vspace        vspace to use to allocate virtual memory in the current address space.
189 * @param config process config.
190 *
191 * @return 0 on success, -1 on error.
192 */
193int sel4utils_configure_process_custom(sel4utils_process_t *process, vka_t *target_vka,
194                                       vspace_t *spawner_vspace, sel4utils_process_config_t config);
195
196/**
197 * Copy a cap into a process' cspace.
198 *
199 * This will only work if you configured the process using one of the above functions, or
200 * have mimicked their functionality.
201 *
202 * @param process process to copy the cap to
203 * @param src     path in the current cspace to copy the cap from
204 *
205 * @return 0 on failure, otherwise the slot in the processes cspace.
206 */
207seL4_CPtr sel4utils_copy_path_to_process(sel4utils_process_t *process, cspacepath_t src);
208
209/**
210 * Copy a cap into a process' cspace.
211 *
212 * This will only work if you configured the process using one of the above functions, or
213 * have mimicked their functionality.
214 *
215 * @param process process to copy the cap to
216 * @param vka     vka that can translate the cap into a cspacepath_t.
217 * @param cap     cap location in your own cspace.
218 *
219 * @return 0 on failure, otherwise the slot in the processes cspace.
220 */
221seL4_CPtr sel4utils_copy_cap_to_process(sel4utils_process_t *process, vka_t *vka, seL4_CPtr cap);
222
223/**
224 * Move a cap into a process' cspace.
225 *
226 * This will only work if you configured the process using one of the above functions, or
227 * have mimicked their functionality.  Additionally the VKA that is passed in to have the
228 * slot freed can only do this if it is tracking that slot.  IE when moving one of the initial
229 * caps provided by bootinfo such as the IRQ Control Cap the VKA may not be able to free the slot.
230 * Passing in NULL for the VKA will result in no slot being freed.
231 *
232 * @param process process to move the cap to
233 * @param src     path in the current cspace to move the cap from
234 * @param vka     the allocator that owns the cslot the cap is currently in, so it may be freed after the move.
235 *                if NULL, then the original slot will not be freed.
236 *
237 * @return 0 on failure, otherwise the slot in the processes cspace.
238 */
239seL4_CPtr sel4utils_move_cap_to_process(sel4utils_process_t *process, cspacepath_t src, vka_t *from_vka);
240
241/**
242 *
243 * Mint a cap into a process' cspace.
244 *
245 * As above, except mint the cap with rights and data.
246 *
247 * @return 0 on failure, otherwise the slot in the cspace where the new cap is.
248 */
249seL4_CPtr sel4utils_mint_cap_to_process(sel4utils_process_t *process, cspacepath_t src, seL4_CapRights_t rights,
250                                        seL4_Word data);
251
252/**
253 * Destroy a process.
254 *
255 * This will free everything possible associated with a process and teardown the vspace.
256 *
257 * @param process process to destroy
258 * @param vka allocator used to allocate objects for this process
259 */
260void sel4utils_destroy_process(sel4utils_process_t *process, vka_t *vka);
261
262/*
263 * sel4utils default allocated object function for vspaces.
264 *
265 * Stores a list of allocated objects in the process struct and frees them
266 * when sel4utils_destroy_process is called.
267 */
268void sel4utils_allocated_object(void *cookie, vka_object_t object);
269
270/*
271 * Create c-formatted argument list to pass to a process from arbitrarily long amount of words.
272 *
273 * @param strings empty 2d array of chars to populate with word strings.
274 * @param argv empty 1d array of char pointers which will be set up with pointers to
275 *             strings in strings.
276 * @param argc number of words
277 * @param ... list of words to create arguments from.
278 *
279 */
280void sel4utils_create_word_args(char strings[][WORD_STRING_SIZE], char *argv[], int argc, ...);
281
282/*
283 * Get the initial cap equivalent for a sel4utils created process.
284 * This will only work if sel4utils created the processes cspace.
285 *
286 * @param cap initial cap index from sel4/bootinfo_types.h
287 * @return the corresponding cap in a sel4utils launched process.
288 */
289seL4_CPtr sel4utils_process_init_cap(void *data, seL4_CPtr cap);
290
291/*
292 * Helper function for copying timer IRQs and Device untyped caps into another process.
293 *
294 * @param to        struct to store new cap info
295 * @param from      struct containing current cap info
296 * @param vka       vka to create cnodes
297 * @param process   target process to copy caps too
298 *
299 * @return 0 on success.
300 */
301int sel4utils_copy_timer_caps_to_process(timer_objects_t *to, timer_objects_t *from, vka_t *vka,
302                                         sel4utils_process_t *process);
303