From 7977ad9f682f9fd2baa8158569ac8067193c3fb0 Mon Sep 17 00:00:00 2001 From: Kent McLeod Date: Mon, 14 Aug 2023 12:41:23 +1000 Subject: [PATCH] aarch64,smc: Add tests for SMC cap behaviors SMC caps are a new cap type for performing SMC calls on aarch64. These tests check that CNode operations behave as expected when manipulating capabilities of this type. Signed-off-by: Kent McLeod --- apps/sel4test-driver/include/test_init_data.h | 3 + apps/sel4test-driver/src/testtypes.c | 4 + apps/sel4test-tests/CMakeLists.txt | 1 + apps/sel4test-tests/src/main.c | 3 + .../src/sel4_arch/aarch64/tests/smc.c | 142 ++++++++++++++++++ 5 files changed, 153 insertions(+) create mode 100644 apps/sel4test-tests/src/sel4_arch/aarch64/tests/smc.c diff --git a/apps/sel4test-driver/include/test_init_data.h b/apps/sel4test-driver/include/test_init_data.h index 15f569e6..636cbf33 100644 --- a/apps/sel4test-driver/include/test_init_data.h +++ b/apps/sel4test-driver/include/test_init_data.h @@ -39,6 +39,9 @@ typedef struct { #ifdef CONFIG_TK1_SMMU seL4_SlotRegion io_space_caps; #endif +#ifdef CONFIG_ALLOW_SMC_CALLS + seL4_CPtr smc_cap; +#endif /* copied (by sel4test-driver) notification cap that tests can wait * on when requesting a time service from sel4test-driver (e.g. sleep), diff --git a/apps/sel4test-driver/src/testtypes.c b/apps/sel4test-driver/src/testtypes.c index 27c8de63..8a9ce7d8 100644 --- a/apps/sel4test-driver/src/testtypes.c +++ b/apps/sel4test-driver/src/testtypes.c @@ -216,6 +216,10 @@ void basic_set_up(uintptr_t e) #endif /* CONFIG_IOMMU */ #ifdef CONFIG_TK1_SMMU env->init->io_space_caps = arch_copy_iospace_caps_to_process(&(env->test_process), &env); +#endif +#ifdef CONFIG_ALLOW_SMC_CALLS + env->init->smc_cap = sel4utils_copy_cap_to_process(&(env->test_process), &env->vka, simple_get_init_cap(&env->simple, + seL4_CapSMC)); #endif env->init->cores = simple_get_core_count(&env->simple); /* copy the sched ctrl caps to the remote process */ diff --git a/apps/sel4test-tests/CMakeLists.txt b/apps/sel4test-tests/CMakeLists.txt index 0f35da44..d58dd351 100644 --- a/apps/sel4test-tests/CMakeLists.txt +++ b/apps/sel4test-tests/CMakeLists.txt @@ -22,6 +22,7 @@ file( src/tests/*.S src/arch/${arch}/*.c src/arch/${KernelArch}/tests/*.c + src/sel4_arch/${KernelSel4Arch}/tests/*.c src/*.cxx src/tests/*.cxx src/arch/${KernelArch}/tests/*.S diff --git a/apps/sel4test-tests/src/main.c b/apps/sel4test-tests/src/main.c index d77a5423..e396250c 100644 --- a/apps/sel4test-tests/src/main.c +++ b/apps/sel4test-tests/src/main.c @@ -203,6 +203,9 @@ int main(int argc, char **argv) #endif #ifdef CONFIG_TK1_SMMU env.io_space_caps = init_data->io_space_caps; +#endif +#ifdef CONFIG_ALLOW_SMC_CALLS + env.smc_cap = init_data->smc_cap; #endif env.cores = init_data->cores; env.num_regions = init_data->num_elf_regions; diff --git a/apps/sel4test-tests/src/sel4_arch/aarch64/tests/smc.c b/apps/sel4test-tests/src/sel4_arch/aarch64/tests/smc.c new file mode 100644 index 00000000..8ecbbb2b --- /dev/null +++ b/apps/sel4test-tests/src/sel4_arch/aarch64/tests/smc.c @@ -0,0 +1,142 @@ +/* + * Copyright 2023, Kry10 Ltd. + * + * SPDX-License-Identifier: BSD-2-Clause + */ +#include + +#include +#include "../../../helpers.h" + +#ifdef CONFIG_ALLOW_SMC_CALLS + +int test_smc_1(env_t env) +{ + + seL4_CPtr dest = get_free_slot(env); + int error = cnode_copy(env, env->smc_cap, dest, seL4_AllRights); + test_error_eq(error, seL4_NoError); + test_assert(!is_slot_empty(env, dest)); + + return sel4test_get_result(); +} +DEFINE_TEST(SMC0001, "SMC Caps can be copied", test_smc_1, true) + +int test_smc_2(env_t env) +{ + + seL4_CPtr dest = get_free_slot(env); + int error = cnode_copy(env, env->smc_cap, dest, seL4_AllRights); + test_error_eq(error, seL4_NoError); + test_assert(!is_slot_empty(env, dest)); + + error = cnode_revoke(env, env->smc_cap); + test_assert(!is_slot_empty(env, dest)); + + return sel4test_get_result(); +} + +DEFINE_TEST(SMC0002, "Copied SMC Caps lose revocable authority", test_smc_2, true) + +int test_smc_3(env_t env) +{ + + seL4_CPtr dest = get_free_slot(env); + int error = cnode_mint(env, env->smc_cap, dest, seL4_AllRights, 1); + test_error_eq(error, seL4_NoError); + test_assert(!is_slot_empty(env, dest)); + + return sel4test_get_result(); +} + +DEFINE_TEST(SMC0003, "Unbadged SMC Caps can be badged", test_smc_3, true) + + +int test_smc_4(env_t env) +{ + + seL4_CPtr dest = get_free_slot(env); + int error = cnode_mint(env, env->smc_cap, dest, seL4_AllRights, 1); + test_error_eq(error, seL4_NoError); + test_assert(!is_slot_empty(env, dest)); + + seL4_CPtr dest2 = get_free_slot(env); + error = cnode_mint(env, dest, dest2, seL4_AllRights, 2); + test_error_eq(error, seL4_IllegalOperation); + test_assert(is_slot_empty(env, dest2)); + + return sel4test_get_result(); +} + +DEFINE_TEST(SMC0004, "Badged SMC caps cannot change badge", test_smc_4, true) + +int test_smc_5(env_t env) +{ + + seL4_CPtr dest = get_free_slot(env); + int error = cnode_mint(env, env->smc_cap, dest, seL4_AllRights, 1); + test_error_eq(error, seL4_NoError); + test_assert(!is_slot_empty(env, dest)); + + seL4_CPtr dest2 = get_free_slot(env); + error = cnode_copy(env, dest, dest2, seL4_AllRights); + test_error_eq(error, seL4_NoError); + test_assert(!is_slot_empty(env, dest2)); + + return sel4test_get_result(); +} +DEFINE_TEST(SMC0005, "Badged SMC caps can be copied", test_smc_5, true) + + +int test_smc_6(env_t env) +{ + + seL4_CPtr dest = get_free_slot(env); + int error = cnode_mint(env, env->smc_cap, dest, seL4_AllRights, 1); + test_error_eq(error, seL4_NoError); + test_assert(!is_slot_empty(env, dest)); + + seL4_CPtr dest2 = get_free_slot(env); + error = cnode_copy(env, dest, dest2, seL4_AllRights); + test_error_eq(error, seL4_NoError); + test_assert(!is_slot_empty(env, dest2)); + + error = cnode_revoke(env, dest); + test_assert(is_slot_empty(env, dest2)); + + return sel4test_get_result(); +} + +DEFINE_TEST(SMC0006, "Original badged SMC caps can revoke copies", test_smc_6, true) + +int test_smc_7(env_t env) +{ + + seL4_CPtr dest = get_free_slot(env); + int error = cnode_mint(env, env->smc_cap, dest, seL4_AllRights, 1); + test_error_eq(error, seL4_NoError); + test_assert(!is_slot_empty(env, dest)); + + seL4_CPtr dest2 = get_free_slot(env); + error = cnode_mint(env, env->smc_cap, dest2, seL4_AllRights, 1); + test_error_eq(error, seL4_NoError); + test_assert(!is_slot_empty(env, dest2)); + + + seL4_CPtr dest3 = get_free_slot(env); + error = cnode_copy(env, dest2, dest3, seL4_AllRights); + test_error_eq(error, seL4_NoError); + test_assert(!is_slot_empty(env, dest3)); + + error = cnode_revoke(env, dest2); + test_assert(is_slot_empty(env, dest3)); + test_assert(!is_slot_empty(env, dest)); + + return sel4test_get_result(); +} + + +DEFINE_TEST(SMC0007, "Original badged SMC caps don't revoke other original badges", test_smc_7, true) + + +#endif