1 /*
2  * Copyright (c) 2024 Intel Corporation
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <app_api.h>
8 
9 #include <zephyr/kernel.h>
10 #include <zephyr/llext/llext.h>
11 #include <zephyr/llext/buf_loader.h>
12 #include <zephyr/app_memory/mem_domain.h>
13 
14 #ifdef LOAD_AND_RUN_EXTENSION
15 static const unsigned char extension_llext[] = {
16 	#include <extension.inc>
17 };
18 static const size_t extension_llext_len = ARRAY_SIZE(extension_llext);
19 #endif
20 
21 #define STACK_SIZE 1024
22 #define HEAP_SIZE 1024
23 
24 #ifdef LOAD_AND_RUN_EXTENSION
25 struct k_thread kernel_thread, user_thread;
26 
27 K_THREAD_STACK_DEFINE(stack_kernel, STACK_SIZE);
28 K_THREAD_STACK_DEFINE(stack_user, STACK_SIZE);
29 
30 K_HEAP_DEFINE(heap_kernel, HEAP_SIZE);
31 K_HEAP_DEFINE(heap_user, HEAP_SIZE);
32 
thread_entry(void * p1,void * p2,void * p3)33 static void thread_entry(void *p1, void *p2, void *p3)
34 {
35 	int bar;
36 	int (*start_fn)(int) = p1;
37 
38 	printk("Calling extension from %s\n",
39 	       k_is_user_context() ? "user" : "kernel");
40 
41 	if (k_is_user_context()) {
42 		bar = 42;
43 	} else {
44 		bar = 43;
45 	}
46 
47 	start_fn(bar);
48 }
49 
load_and_run_extension(int thread_flags,struct k_thread * thread,struct k_mem_domain * domain,k_thread_stack_t * stack,struct k_heap * heap,struct llext ** ext)50 void load_and_run_extension(int thread_flags, struct k_thread *thread,
51 			    struct k_mem_domain *domain,
52 			    k_thread_stack_t *stack, struct k_heap *heap,
53 			    struct llext **ext)
54 {
55 	struct llext_buf_loader buf_loader = LLEXT_BUF_LOADER(extension_llext,
56 							      extension_llext_len);
57 	struct llext_loader *loader = &buf_loader.loader;
58 	struct llext_load_param ldr_parm = LLEXT_LOAD_PARAM_DEFAULT;
59 	int (*start_fn)(int bar);
60 
61 	llext_load(loader, "extension", ext, &ldr_parm);
62 	start_fn = llext_find_sym(&(*ext)->exp_tab, "start");
63 
64 	llext_add_domain(*ext, domain);
65 
66 	k_thread_create(thread, stack, STACK_SIZE,
67 			thread_entry, start_fn, NULL, NULL, -1,
68 			K_INHERIT_PERMS | thread_flags,
69 			K_FOREVER);
70 	k_mem_domain_add_thread(domain, thread);
71 	k_thread_heap_assign(thread, heap);
72 
73 	k_thread_start(thread);
74 	k_thread_join(thread, K_FOREVER);
75 
76 	llext_unload(ext);
77 }
78 #endif
79 
main(void)80 int main(void)
81 {
82 #ifdef LOAD_AND_RUN_EXTENSION
83 	struct k_mem_domain domain_kernel, domain_user;
84 	struct llext *ext_kernel, *ext_user;
85 
86 	k_mem_domain_init(&domain_kernel, 0, NULL);
87 	k_mem_domain_init(&domain_user, 0, NULL);
88 
89 	load_and_run_extension(0, &kernel_thread, &domain_kernel,
90 			       stack_kernel, &heap_kernel, &ext_kernel);
91 	load_and_run_extension(K_USER, &user_thread, &domain_user,
92 			       stack_user, &heap_user, &ext_user);
93 
94 	printk("Done\n");
95 #else
96 	printk("Extension not loaded\n");
97 #endif
98 	return 0;
99 }
100