7
7
#include <zephyr/ztest.h>
8
8
#include <zephyr/kernel.h>
9
9
#include <zephyr/llext/llext.h>
10
+ #include <zephyr/llext/symbol.h>
10
11
#include <zephyr/llext/buf_loader.h>
11
12
#include <zephyr/logging/log.h>
12
13
#include <zephyr/sys/libc-hooks.h>
13
-
14
14
#include "syscalls_ext.h"
15
+ #include "threads_kernel_objects_ext.h"
16
+
15
17
16
18
LOG_MODULE_REGISTER (test_llext_simple );
17
19
@@ -28,8 +30,9 @@ struct llext_test {
28
30
size_t buf_len ;
29
31
30
32
LLEXT_CONST uint8_t * buf ;
31
- };
32
33
34
+ void (* perm_setup )(struct k_thread * llext_thread );
35
+ };
33
36
34
37
35
38
K_THREAD_STACK_DEFINE (llext_stack , 1024 );
@@ -45,6 +48,9 @@ void llext_entry(void *arg0, void *arg1, void *arg2)
45
48
}
46
49
#endif /* CONFIG_USERSPACE */
47
50
51
+
52
+ /* syscalls test */
53
+
48
54
int z_impl_ext_syscall_ok (int a )
49
55
{
50
56
return a + 1 ;
@@ -58,6 +64,33 @@ static inline int z_vrfy_ext_syscall_ok(int a)
58
64
#include <syscalls/ext_syscall_ok_mrsh.c>
59
65
#endif /* CONFIG_USERSPACE */
60
66
67
+
68
+ /* threads kernel objects test */
69
+
70
+ /* For these to be accessible from user space, they must be top-level globals
71
+ * in the Zephyr image. Also, macros that add objects to special linker sections,
72
+ * such as K_THREAD_STACK_DEFINE, do not work properly from extensions code.
73
+ */
74
+ K_SEM_DEFINE (my_sem , 1 , 1 );
75
+ EXPORT_SYMBOL (my_sem );
76
+ struct k_thread my_thread ;
77
+ EXPORT_SYMBOL (my_thread );
78
+ K_THREAD_STACK_DEFINE (my_thread_stack , MY_THREAD_STACK_SIZE );
79
+ EXPORT_SYMBOL (my_thread_stack );
80
+
81
+ #ifdef CONFIG_USERSPACE
82
+ /* Allow the user space test thread to access global objects */
83
+ static void threads_objects_perm_setup (struct k_thread * llext_thread )
84
+ {
85
+ k_object_access_grant (& my_sem , llext_thread );
86
+ k_object_access_grant (& my_thread , llext_thread );
87
+ k_object_access_grant (& my_thread_stack , llext_thread );
88
+ }
89
+ #else
90
+ /* No need to set up permissions for supervisor mode */
91
+ #define threads_objects_perm_setup NULL
92
+ #endif /* CONFIG_USERSPACE */
93
+
61
94
void load_call_unload (struct llext_test * test_case )
62
95
{
63
96
struct llext_buf_loader buf_loader =
@@ -108,6 +141,14 @@ void load_call_unload(struct llext_test *test_case)
108
141
109
142
k_mem_domain_add_thread (& domain , & llext_thread );
110
143
144
+ /* Even in supervisor mode, initialize permissions on objects used in
145
+ * the test by this thread, so that user mode descendant threads can
146
+ * inherit these permissions.
147
+ */
148
+ if (test_case -> perm_setup ) {
149
+ test_case -> perm_setup (& llext_thread );
150
+ }
151
+
111
152
k_thread_start (& llext_thread );
112
153
k_thread_join (& llext_thread , K_FOREVER );
113
154
@@ -123,11 +164,14 @@ void load_call_unload(struct llext_test *test_case)
123
164
124
165
k_mem_domain_add_thread (& domain , & llext_thread );
125
166
167
+ if (test_case -> perm_setup ) {
168
+ test_case -> perm_setup (& llext_thread );
169
+ }
170
+
126
171
k_thread_start (& llext_thread );
127
172
k_thread_join (& llext_thread , K_FOREVER );
128
173
}
129
174
130
-
131
175
#else /* CONFIG_USERSPACE */
132
176
zassert_ok (llext_call_fn (ext , "test_entry" ),
133
177
"test_entry call should succeed" );
@@ -143,43 +187,50 @@ void load_call_unload(struct llext_test *test_case)
143
187
* unloading each extension which may itself excercise various APIs provided by
144
188
* Zephyr.
145
189
*/
146
- #define LLEXT_LOAD_UNLOAD (_name , _userspace ) \
190
+ #define LLEXT_LOAD_UNLOAD (_name , _userspace , _perm_setup ) \
147
191
ZTEST(llext, test_load_unload_##_name) \
148
192
{ \
149
193
struct llext_test test_case = { \
150
194
.name = STRINGIFY(_name), \
151
195
.try_userspace = _userspace, \
152
196
.buf_len = ARRAY_SIZE(_name ## _ext), \
153
197
.buf = _name ## _ext, \
198
+ .perm_setup = _perm_setup, \
154
199
}; \
155
200
load_call_unload(&test_case); \
156
201
}
157
202
static LLEXT_CONST uint8_t hello_world_ext [] __aligned (4 ) = {
158
203
#include "hello_world.inc"
159
204
};
160
- LLEXT_LOAD_UNLOAD (hello_world , false)
205
+ LLEXT_LOAD_UNLOAD (hello_world , false, NULL )
161
206
162
207
static LLEXT_CONST uint8_t logging_ext [] __aligned (4 ) = {
163
208
#include "logging.inc"
164
209
};
165
- LLEXT_LOAD_UNLOAD (logging , true)
210
+ LLEXT_LOAD_UNLOAD (logging , true, NULL )
166
211
167
212
static LLEXT_CONST uint8_t relative_jump_ext [] __aligned (4 ) = {
168
213
#include "relative_jump.inc"
169
214
};
170
- LLEXT_LOAD_UNLOAD (relative_jump , true)
215
+ LLEXT_LOAD_UNLOAD (relative_jump , true, NULL )
171
216
172
217
static LLEXT_CONST uint8_t object_ext [] __aligned (4 ) = {
173
218
#include "object.inc"
174
219
};
175
- LLEXT_LOAD_UNLOAD (object , true)
220
+ LLEXT_LOAD_UNLOAD (object , true, NULL )
176
221
177
222
static LLEXT_CONST uint8_t syscalls_ext [] __aligned (4 ) = {
178
223
#include "syscalls.inc"
179
224
};
180
- LLEXT_LOAD_UNLOAD (syscalls , true)
225
+ LLEXT_LOAD_UNLOAD (syscalls , true, NULL )
226
+
227
+ static LLEXT_CONST uint8_t threads_kernel_objects_ext [] __aligned (4 ) = {
228
+ #include "threads_kernel_objects.inc"
229
+ };
230
+ LLEXT_LOAD_UNLOAD (threads_kernel_objects , true, threads_objects_perm_setup )
181
231
#endif /* ! LOADER_BUILD_ONLY */
182
232
233
+
183
234
/*
184
235
* Ensure that EXPORT_SYMBOL does indeed provide a symbol and a valid address
185
236
* to it.
0 commit comments