1/*
2 * Copyright 2019, 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/*
13 * The seL4 run-time interface.
14 *
15 * This provides an interface to the values managed by sel4runtime.
16 */
17#include <sel4runtime/stddef.h>
18#include <sel4runtime/stdint.h>
19#include <sel4/sel4.h>
20#include <sel4runtime/thread.h>
21#include <sel4runtime/auxv.h>
22
23#pragma once
24
25/*
26 * Get the name of the process.
27 *
28 * Returns the basename of the first argument in argv.
29 */
30char const *sel4runtime_process_name(void);
31
32/*
33 * Get the argument vector passed to main.
34 */
35char const *const *sel4runtime_argv(void);
36
37/*
38 * Get the length of argument vector passed to main.
39 */
40int sel4runtime_argc(void);
41
42/*
43 * Get the list of environment variables passed to main.
44 */
45char const *const *sel4runtime_envp(void);
46
47/*
48 * Get the list of auxiliary vectors.
49 */
50auxv_t const *sel4runtime_auxv(void);
51
52/*
53 * Get the address of the TLS base register.
54 */
55static inline sel4runtime_uintptr_t sel4runtime_get_tls_base(void);
56
57/*
58 * Set the address of the TLS base register.
59 */
60static inline void sel4runtime_set_tls_base(sel4runtime_uintptr_t tls_base);
61
62/*
63 * Get the bootinfo pointer if the process was provided a bootinfo
64 * cspace descriptor.
65 */
66seL4_BootInfo *sel4runtime_bootinfo(void);
67
68/*
69 * Get the size in bytes needed to store the thread's TLS.
70 */
71sel4runtime_size_t sel4runtime_get_tls_size(void);
72
73/*
74 * Get the offset used to calculate the thread pointer from the
75 * starting address of the thread area.
76 */
77sel4runtime_size_t sel4runtime_get_tp_offset(void);
78
79/*
80 * Check if the TLS for the initial thread is enabled.
81 *
82 * If the TLS for the initial thread was too large to fit inside the
83 * static region of the runtime, this will return false and
84 * sel4runtime_move_initial_tls should be used to initialise it into a
85 * new location.
86 */
87int sel4runtime_initial_tls_enabled(void);
88
89/*
90 * Write the TLS image for a new thread into the provided memory image.
91 * The TLS for the initial thread must be enabled before this is called.
92 *
93 * @returns the pointer to the TLS that should be used to call
94 *          seL4_TCB_SetTLSBase or NULL on error.
95 */
96sel4runtime_uintptr_t sel4runtime_write_tls_image(void *tls_memory);
97
98/*
99 * Move the TLS for the current thread into a new memory location.
100 *
101 * Particularly useful for enabling TLS in the initial process where the
102 * TLS image exeeded the size of the static TLS region in the runtime.
103 *
104 * WARNING: This will not prevent re-initialisation of the TLS for the
105 * initial thread (even by other threads). This should only be used at
106 * the start of a process only if `sel4utils_initial_tls_enabled`
107 * returns false.
108 *
109 * @returns the pointer to the TLS that should be used to call
110 *          seL4_TCB_SetTLSBase.
111 */
112sel4runtime_uintptr_t sel4runtime_move_initial_tls(void *tls_memory);
113
114/*
115 * Writes into a thread_local variable of another thread.
116 *
117 * This assumes that TLS has been initialised for the current thread.
118 */
119#define sel4runtime_set_tls_variable(thread_pointer, variable, value) ({\
120    _Static_assert(\
121        sizeof(variable) == sizeof(value), \
122        "Set value of same size" \
123    ); \
124    typeof (variable) typed_value = value; \
125    __sel4runtime_write_tls_variable( \
126        thread_pointer, \
127        (unsigned char *)&(variable), \
128        (unsigned char *)&(typed_value), \
129        sizeof(typed_value) \
130    ); \
131})
132
133/*
134 * Copies data into the equivalent address in the TLS of another thread.
135 *
136 * This assumes that TLS has been initialised for the current thread.
137 */
138int __sel4runtime_write_tls_variable(
139    sel4runtime_uintptr_t dest_tls_base,
140    unsigned char *local_tls_dest,
141    unsigned char *src,
142    sel4runtime_size_t bytes
143);
144
145/*
146 * Callback function type that can be used to exit a process.
147 */
148typedef void sel4runtime_exit_cb(int code);
149
150/*
151 * Set the callback used to exit a process.
152 *
153 * Returns the current exit function.
154 */
155sel4runtime_exit_cb *sel4runtime_set_exit(sel4runtime_exit_cb *cb);
156
157/*
158 * Callback function type that can be used to exit a process.
159 *
160 * Should return the exit code to be generated.
161 */
162typedef int sel4runtime_pre_exit_cb(int code);
163
164/*
165 * Set the callback called before destructors are run for a prcess exit..
166 *
167 * Returns the current pre-exit function.
168 */
169sel4runtime_pre_exit_cb *sel4runtime_set_pre_exit(sel4runtime_pre_exit_cb *cb);
170
171/*
172 * Exit the runtime.
173 *
174 * This will attempt to suspend the initial thread of the process. Any
175 * threading libraries should register a destructor to trigger any
176 * threads they create to be suspended. They should neve suspend the
177 * current thread.
178 */
179void sel4runtime_exit(int code);
180