blob: ee68e72d73a9e53d832fe82bc47876b1b2a81395 [file] [log] [blame]
/*
* Copyright (c) 2023 Intel Corporation.
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/ztest.h>
#include <zephyr/kernel.h>
#include <zephyr/llext/llext.h>
#include <zephyr/llext/buf_loader.h>
#if defined(CONFIG_ARM) /* ARMV7 */ || defined(CONFIG_XTENSA)
#ifndef CONFIG_LLEXT_STORAGE_WRITABLE
const
#endif
static uint8_t hello_world_elf[] __aligned(4) = {
#include "hello_world.inc"
};
#endif
K_THREAD_STACK_DEFINE(llext_stack, 1024);
struct k_thread llext_thread;
#ifdef CONFIG_USERSPACE
void llext_entry(void *arg0, void *arg1, void *arg2)
{
struct llext *ext = arg0;
zassert_ok(llext_call_fn(ext, "hello_world"),
"hello_world call should succeed");
}
#endif /* CONFIG_USERSPACE */
/**
* Attempt to load, list, list symbols, call a fn, and unload a
* hello world extension for each supported architecture
*
* This requires a single linked symbol (printk) and a single
* exported symbol from the extension ( void hello_world(void))
*/
ZTEST(llext, test_llext_simple)
{
const char name[16] = "hello";
struct llext_buf_loader buf_loader =
LLEXT_BUF_LOADER(hello_world_elf, ARRAY_SIZE(hello_world_elf));
struct llext_loader *loader = &buf_loader.loader;
struct llext_load_param ldr_parm = LLEXT_LOAD_PARAM_DEFAULT;
struct llext *ext = NULL;
const void * const printk_fn = llext_find_sym(NULL, "printk");
zassert_equal(printk_fn, printk, "printk should be an exported symbol");
int res = llext_load(loader, name, &ext, &ldr_parm);
zassert_ok(res, "load should succeed");
const void * const hello_world_fn = llext_find_sym(&ext->exp_tab, "hello_world");
zassert_not_null(hello_world_fn, "hello_world should be an exported symbol");
#ifdef CONFIG_USERSPACE
struct k_mem_domain domain;
k_mem_domain_init(&domain, 0, NULL);
res = llext_add_domain(ext, &domain);
zassert_ok(res, "adding partitions to domain should succeed");
/* Should be runnable from newly created thread */
k_thread_create(&llext_thread, llext_stack,
K_THREAD_STACK_SIZEOF(llext_stack),
&llext_entry, ext, NULL, NULL,
1, 0, K_FOREVER);
k_mem_domain_add_thread(&domain, &llext_thread);
k_thread_start(&llext_thread);
k_thread_join(&llext_thread, K_FOREVER);
#else /* CONFIG_USERSPACE */
zassert_ok(llext_call_fn(ext, "hello_world"),
"hello_world call should succeed");
#endif /* CONFIG_USERSPACE */
llext_unload(&ext);
}
ZTEST_SUITE(llext, NULL, NULL, NULL, NULL, NULL);