1/* 2 * Copyright 2017, Data61 3 * Commonwealth Scientific and Industrial Research Organisation (CSIRO) 4 * ABN 41 687 119 230. 5 * 6 * This software may be distributed and modified according to the terms of 7 * the BSD 2-Clause license. Note that NO WARRANTY is provided. 8 * See "LICENSE_BSD2.txt" for details. 9 * 10 * @TAG(DATA61_BSD) 11 */ 12#pragma once 13 14#include <vka/vka.h> 15#include <vspace/vspace.h> 16#include <sel4utils/thread.h> 17#include <sel4utils/process.h> 18#include <sel4utils/mapping.h> 19#include <sel4test/test.h> 20 21#include <sel4platsupport/timer.h> 22#include <platsupport/timer.h> 23 24#include "test.h" 25#include <sel4testsupport/testreporter.h> 26#include <sync/mutex.h> 27 28#define OUR_PRIO (env->priority) 29/* args provided by the user */ 30#define HELPER_THREAD_MAX_ARGS 4 31/* metadata helpers adds */ 32#define HELPER_THREAD_META 4 33/* total args (user + meta) */ 34#define HELPER_THREAD_TOTAL_ARGS (HELPER_THREAD_MAX_ARGS + HELPER_THREAD_META) 35 36#include <sel4test/test.h> 37 38typedef int (*helper_fn_t)(seL4_Word, seL4_Word, seL4_Word, seL4_Word); 39 40typedef struct helper_thread { 41 sel4utils_elf_region_t regions[MAX_REGIONS]; 42 int num_regions; 43 sel4utils_process_t process; 44 45 sel4utils_thread_t thread; 46 vka_object_t local_endpoint; 47 seL4_CPtr fault_endpoint; 48 49 void *arg0; 50 void *arg1; 51 char *args[HELPER_THREAD_TOTAL_ARGS]; 52 char args_strings[HELPER_THREAD_TOTAL_ARGS][WORD_STRING_SIZE]; 53 54 bool is_process; 55} helper_thread_t; 56 57/* Helper thread/process functions */ 58 59/* create a helper in the current vspace and current cspace */ 60void create_helper_thread(env_t env, helper_thread_t *thread); 61/* create a helper with a custom stack size, useful when creating a lot of threads*/ 62void create_helper_thread_custom_stack(env_t env, helper_thread_t *thread, size_t stack_pages); 63 64/* create a helper with a clone of the current vspace loadable elf segments, 65 * and a new cspace */ 66void create_helper_process(env_t env, helper_thread_t *thread); 67void create_helper_process_custom_asid(env_t env, helper_thread_t *thread, seL4_CPtr asid); 68/* create and start a passive thread */ 69int create_passive_thread(env_t env, helper_thread_t *passive, helper_fn_t fn, seL4_CPtr ep, 70 seL4_Word arg1, seL4_Word arg2, seL4_Word arg3); 71/* start an existing (created but not running ) passive thread */ 72int start_passive_thread(env_t env, helper_thread_t *passive, helper_fn_t fn, seL4_CPtr ep, 73 seL4_Word arg1, seL4_Word arg2, seL4_Word arg3); 74/* set a helper threads priority */ 75void set_helper_priority(env_t env, helper_thread_t *thread, seL4_Word prio); 76 77/* set a helper threads max control priority */ 78void set_helper_mcp(env_t env, helper_thread_t *thread, seL4_Word mcp); 79 80/* set a helper threads core affinity. This will have no effect on passive threads. */ 81void set_helper_affinity(env_t env, helper_thread_t *thread, seL4_Word affinity); 82 83/* if CONFIG_KERNEL_MCS is set, set the helpers scheduling parameters */ 84int set_helper_sched_params(UNUSED env_t env, UNUSED helper_thread_t *thread, UNUSED uint64_t budget, 85 UNUSED uint64_t period, seL4_Word badge); 86 87/* set a helper threads timeout fault handler */ 88void set_helper_tfep(env_t env, helper_thread_t *thread, seL4_CPtr tfep); 89 90/* Start a helper. Note: arguments to helper processes will be copied into 91 * the address space of that process. Do not pass pointers to data only in 92 * the local vspace, this will fail. */ 93void start_helper(env_t env, helper_thread_t *thread, helper_fn_t entry_point, 94 seL4_Word arg0, seL4_Word arg1, seL4_Word arg2, seL4_Word arg3); 95 96/* save a threads seL4_UserContext, increment instruction pointer, and resume */ 97int restart_after_syscall(env_t env, helper_thread_t *thread); 98 99/* wait for a helper thread to finish */ 100int wait_for_helper(helper_thread_t *thread); 101 102/* free all resources associated with a helper and tear it down */ 103void cleanup_helper(env_t env, helper_thread_t *thread); 104 105/* retrieve the TCB of a helper thread */ 106seL4_CPtr get_helper_tcb(helper_thread_t *thread); 107/* retrieve the reply object cap of a helper thread (seL4_CapNull if not CONFIG_RT_KERNEL) */ 108seL4_CPtr get_helper_reply(helper_thread_t *thread); 109/* retrieve the sched context cap of a helper thread (seL4_CapNull if not CONFIG_RT_KERNEL) */ 110seL4_CPtr get_helper_sched_context(helper_thread_t *thread); 111 112/* retrieve the IPC buffer address of a helper thread */ 113uintptr_t get_helper_ipc_buffer_addr(helper_thread_t *thread); 114 115uintptr_t get_helper_initial_stack_pointer(helper_thread_t *thread); 116 117/* 118 * Check whether a given region of memory is zeroed out. 119 */ 120int check_zeroes(seL4_Word addr, seL4_Word size_bytes); 121 122/* Determine if two TCBs in the init thread's CSpace are not equal. Note that we 123 * assume the thread is not currently executing. 124 * 125 * Serves as != comparator for caps. Returns 1 for not equal, 0 for equal and -1 for syscall error. 126 */ 127int are_tcbs_distinct(seL4_CPtr tcb1, seL4_CPtr tcb2); 128 129/* cnode_ops wrappers */ 130int cnode_copy(env_t env, seL4_CPtr src, seL4_CPtr dest, seL4_CapRights_t rights); 131int cnode_delete(env_t env, seL4_CPtr slot); 132int cnode_mint(env_t env, seL4_CPtr src, seL4_CPtr dest, seL4_CapRights_t rights, seL4_Word badge); 133int cnode_move(env_t env, seL4_CPtr src, seL4_CPtr dest); 134int cnode_mutate(env_t env, seL4_CPtr src, seL4_CPtr dest); 135int cnode_cancelBadgedSends(env_t env, seL4_CPtr cap); 136int cnode_revoke(env_t env, seL4_CPtr cap); 137int cnode_rotate(env_t env, seL4_CPtr src, seL4_CPtr pivot, seL4_CPtr dest); 138/* non-RT only */ int cnode_savecaller(env_t env, seL4_CPtr cap); 139 140/* IPC buffer operation wrapper */ 141/* Set up the IPC Buffer to receive IPC caps in the already allocated slot slot */ 142void set_cap_receive_path(env_t env, seL4_CPtr slot); 143 144/* Determine whether a given slot in the init thread's CSpace is empty by 145 * examining the error when moving a slot onto itself. 146 * 147 * Serves as == 0 comparator for caps. 148 */ 149int is_slot_empty(env_t env, seL4_Word slot); 150 151/* Get a free slot */ 152seL4_Word get_free_slot(env_t env); 153 154/* busy wait for a period of time. This assumes that you have some thread (such as create_timer_interrupt_thread) 155 * handling the timer interrupts. This can be used instead of sleep in circumstances where you want multiple 156 * threads performing waits */ 157void sleep_busy(env_t env, uint64_t ns); 158 159/* sel4test RPC helpers - sel4test-tests sel4test-tests requesting services from sel4test-driver*/ 160 161/* Request a sleep for at least @ns. Callees to this function will block until 162 * it's waken up and this function then returns. No concurrent calls to sel4test_sleep 163 * are allowed, and trying to do this has undefined behavior. 164 */ 165void sel4test_sleep(env_t env, uint64_t ns); 166 167/* Request a timestamp. Timestamps might not be accurate and report 168 * longer time especially if working with multpile domains 169 */ 170uint64_t sel4test_timestamp(env_t env); 171 172/* Request periodic signals every @ns, at least. 173 * This function is similar to the sel4test_sleep function above, 174 * but will get periodic notifications. 175 * 176 * Tests that request periodic timer using this function call can, if they want, 177 * wait for signals themselves, unlike sleep, on the env->timer_notification. 178 */ 179void sel4test_periodic_start(env_t env, uint64_t ns); 180 181/* Request a timer reset. This should cancel receiving signals from 182 * previous sleep, periodic calls. 183 * 184 * If there were previous calls that set timeouts, sleep or periodic timer, 185 * they will be discarded, and tests will no longer get notifications on 186 * env->timer_notification. 187 * 188 * If this function is not called, and there were previous calls to sleep and/or 189 * periodic timer services, sel4test-driver will keep signaling 190 * the test notification whenever there is a timer interrupt, regardless 191 * of there exists a test waiting on the env->timer_notification or not. 192 */ 193void sel4test_timer_reset(env_t env); 194 195/* This is a helper function part of the sel4test_timer interface. 196 * It simply waits on a valid env->timer_notification. Tests that 197 * do calls to sel4test_rpc_timer_* above and expect notifications 198 * from sel4test-driver can choose to use this function. 199 */ 200void sel4test_ntfn_timer_wait(env_t env); 201 202/* helper for creating a thread to handle timer interrupts */ 203int create_timer_interrupt_thread(env_t env, helper_thread_t *thread); 204