diff --git a/kernel/userspace.c b/kernel/userspace.c index 62ac831181dfb..a9adb59e5bd1e 100644 --- a/kernel/userspace.c +++ b/kernel/userspace.c @@ -760,7 +760,7 @@ static u32_t handler_bad_syscall(u32_t bad_id, u32_t arg2, u32_t arg3, { printk("Bad system call id %u invoked\n", bad_id); z_arch_syscall_oops(ssf); - CODE_UNREACHABLE; + CODE_UNREACHABLE; /* LCOV_EXCL_LINE */ } static u32_t handler_no_syscall(u32_t arg1, u32_t arg2, u32_t arg3, @@ -768,7 +768,7 @@ static u32_t handler_no_syscall(u32_t arg1, u32_t arg2, u32_t arg3, { printk("Unimplemented system call\n"); z_arch_syscall_oops(ssf); - CODE_UNREACHABLE; + CODE_UNREACHABLE; /* LCOV_EXCL_LINE */ } #include diff --git a/tests/kernel/mem_protect/userspace/src/main.c b/tests/kernel/mem_protect/userspace/src/main.c index 3a7a312c38ca9..4eb34e04078b4 100644 --- a/tests/kernel/mem_protect/userspace/src/main.c +++ b/tests/kernel/mem_protect/userspace/src/main.c @@ -1085,6 +1085,52 @@ void test_stack_buffer(void) } +void z_impl_missing_syscall(void) +{ + /* Shouldn't ever get here; no handler function compiled */ + k_panic(); +} + +void test_unimplemented_syscall(void) +{ + expect_fault = true; + expected_reason = REASON_KERNEL_OOPS; + + missing_syscall(); +} + +void test_bad_syscall(void) +{ + expect_fault = true; + expected_reason = REASON_KERNEL_OOPS; + + z_arch_syscall_invoke0(INT_MAX); + +} + +static struct k_sem recycle_sem; + + +void test_object_recycle(void) +{ + struct _k_object *ko; + int perms_count = 0; + + ko = z_object_find(&recycle_sem); + (void)memset(ko->perms, 0xFF, sizeof(ko->perms)); + + z_object_recycle(&recycle_sem); + zassert_true(ko != NULL, "kernel object not found"); + zassert_true(ko->flags & K_OBJ_FLAG_INITIALIZED, + "object wasn't marked as initialized"); + + for (int i = 0; i < CONFIG_MAX_THREAD_BYTES; i++) { + perms_count += popcount(ko->perms[i]); + } + + zassert_true(perms_count == 1, "invalid number of thread permissions"); +} + void test_main(void) { struct k_mem_partition *parts[] = {&part0, &part1, @@ -1135,7 +1181,10 @@ void test_main(void) ztest_unit_test(domain_add_part_context_switch), ztest_unit_test(domain_remove_part_context_switch), ztest_unit_test(domain_remove_thread_context_switch), - ztest_unit_test(test_stack_buffer) + ztest_unit_test(test_stack_buffer), + ztest_user_unit_test(test_unimplemented_syscall), + ztest_user_unit_test(test_bad_syscall), + ztest_unit_test(test_object_recycle) ); ztest_run_test_suite(userspace); } diff --git a/tests/kernel/mem_protect/userspace/src/test_syscall.h b/tests/kernel/mem_protect/userspace/src/test_syscall.h index cb00a8b41d0a6..8e7debac21e1a 100644 --- a/tests/kernel/mem_protect/userspace/src/test_syscall.h +++ b/tests/kernel/mem_protect/userspace/src/test_syscall.h @@ -9,6 +9,7 @@ __syscall void stack_info_get(u32_t *start_addr, u32_t *size); __syscall int check_perms(void *addr, size_t size, int write); +__syscall void missing_syscall(void); #include diff --git a/tests/kernel/threads/dynamic_thread/prj.conf b/tests/kernel/threads/dynamic_thread/prj.conf index 07cda4ba9d38c..804af8ea9a889 100644 --- a/tests/kernel/threads/dynamic_thread/prj.conf +++ b/tests/kernel/threads/dynamic_thread/prj.conf @@ -1,3 +1,3 @@ CONFIG_ZTEST=y CONFIG_TEST_USERSPACE=y -CONFIG_HEAP_MEM_POOL_SIZE=2048 +CONFIG_HEAP_MEM_POOL_SIZE=4096 diff --git a/tests/kernel/threads/dynamic_thread/src/main.c b/tests/kernel/threads/dynamic_thread/src/main.c index 6e57ad1065304..ac1651a779322 100644 --- a/tests/kernel/threads/dynamic_thread/src/main.c +++ b/tests/kernel/threads/dynamic_thread/src/main.c @@ -10,8 +10,6 @@ #define STACKSIZE (256 + CONFIG_TEST_EXTRA_STACKSIZE) -#if defined(CONFIG_USERSPACE) && defined(CONFIG_DYNAMIC_OBJECTS) - static K_THREAD_STACK_DEFINE(dyn_thread_stack, STACKSIZE); static K_SEM_DEFINE(start_sem, 0, 1); static K_SEM_DEFINE(end_sem, 0, 1); @@ -106,25 +104,56 @@ static void test_dyn_thread_perms(void) TC_PRINT("===== must have access denied on k_sem %p\n", &end_sem); } -#else /* (CONFIG_USERSPACE && CONFIG_DYNAMIC_OBJECTS) */ +static struct k_thread *dynamic_threads[CONFIG_MAX_THREAD_BYTES * 8]; -static void prep(void) +static void test_thread_index_management(void) { -} + int i, ctr = 0; -static void create_dynamic_thread(void) -{ - TC_PRINT("Test skipped. Userspace and dynamic objects required.\n"); - ztest_test_skip(); -} + /* Create thread objects until we run out of ids */ + while (true) { + struct k_thread *t = k_object_alloc(K_OBJ_THREAD); -static void test_dyn_thread_perms(void) -{ - TC_PRINT("Test skipped. Userspace and dynamic objects required.\n"); - ztest_test_skip(); -} + if (t == NULL) { + break; + } -#endif /* !(CONFIG_USERSPACE && CONFIG_DYNAMIC_OBJECTS) */ + dynamic_threads[ctr] = t; + ctr++; + } + + zassert_true(ctr != 0, "unable to create any thread objects"); + + TC_PRINT("created %d thread objects\n", ctr); + + /* Show that the above NULL return value wasn't because we ran out of + * heap space/ + */ + void *blob = k_malloc(256); + zassert_true(blob != NULL, "out of heap memory"); + + /* Free one of the threads... */ + k_object_free(dynamic_threads[0]); + + /* And show that we can now create another one, the freed thread's + * index should have been garbage collected. + */ + dynamic_threads[0] = k_object_alloc(K_OBJ_THREAD); + zassert_true(dynamic_threads[0] != NULL, + "couldn't create thread object\n"); + + /* TODO: Implement a test that shows that thread IDs are properly + * recycled when a thread object is garbage collected due to references + * dropping to zero. For example, we ought to be able to exit here + * without calling k_object_free() on any of the threads we created + * here; their references would drop to zero and they would be + * automatically freed. However, it is known that the thread IDs are + * not properly recycled when this happens, see #17023. + */ + for (i = 0; i < ctr; i++) { + k_object_free(dynamic_threads[i]); + } +} /** * @ingroup kernel_thread_tests @@ -160,7 +189,8 @@ void test_main(void) ztest_test_suite(thread_dynamic, ztest_unit_test(test_kernel_create_dyn_user_thread), ztest_user_unit_test(test_user_create_dyn_user_thread), - ztest_unit_test(test_dyn_thread_perms) + ztest_unit_test(test_dyn_thread_perms), + ztest_unit_test(test_thread_index_management) ); ztest_run_test_suite(thread_dynamic); } diff --git a/tests/kernel/threads/dynamic_thread/testcase.yaml b/tests/kernel/threads/dynamic_thread/testcase.yaml index e15af02969b18..7e0e832328d30 100644 --- a/tests/kernel/threads/dynamic_thread/testcase.yaml +++ b/tests/kernel/threads/dynamic_thread/testcase.yaml @@ -1,3 +1,4 @@ tests: kernel.threads.dynamic: tags: kernel threads userspace ignore_faults + filter: CONFIG_ARCH_HAS_USERSPACE