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 13/* Include Kconfig variables. */ 14#include <autoconf.h> 15#include <sel4test-driver/gen_config.h> 16 17#include <assert.h> 18#include <stdio.h> 19 20/* Our headers are not C++ friendly */ 21extern "C" { 22 23#include <sel4/sel4.h> 24 25#include "../helpers.h" 26 27} 28 29#define POLL_DELAY_NS 4000000 30 31typedef int (*test_func_t)(seL4_Word /* id */, env_t env /* env */); 32 33static int 34own_domain_success(struct env *env) 35{ 36 int error; 37 38 error = seL4_DomainSet_Set(env->domain, CONFIG_NUM_DOMAINS - 1, 39 env->tcb); 40 return (error == seL4_NoError) ? SUCCESS : FAILURE; 41} 42 43static int 44own_domain_baddom(struct env *env) 45{ 46 int error; 47 48 error = seL4_DomainSet_Set(env->domain, CONFIG_NUM_DOMAINS + 10, 49 env->tcb); 50 return (error == seL4_InvalidArgument) ? SUCCESS : FAILURE; 51} 52 53static int 54own_domain_badcap(struct env *env) 55{ 56 int error; 57 58 error = seL4_DomainSet_Set(env->tcb, 0, 59 env->tcb); 60 return (error == seL4_IllegalOperation) ? SUCCESS : FAILURE; 61} 62 63int fdom1(seL4_Word id, env_t env) 64{ 65 int countdown = 50; 66 67 while (countdown > 0) { 68 sleep_busy(env, POLL_DELAY_NS); 69 --countdown; 70 ZF_LOGD("%2d, ", (int)id); 71 } 72 73 return sel4test_get_result(); 74} 75 76/* This is a very simple (and rather stupid) C++ usage. Proves that a template 77 * can be defined but is not good C++ */ 78template<bool shift, typename F> 79static int 80test_domains(struct env *env, F func) 81{ 82 83 UNUSED int error; 84 helper_thread_t thread[CONFIG_NUM_DOMAINS]; 85 86 for (int i = 0; i < CONFIG_NUM_DOMAINS; ++i) { 87 create_helper_thread(env, &thread[i]); 88 set_helper_priority(env, &thread[i], 64); 89 error = seL4_DomainSet_Set(env->domain, (seL4_Word)i, get_helper_tcb(&thread[i])); 90 assert(error == seL4_NoError); 91 } 92 93 for (int i = 0; i < CONFIG_NUM_DOMAINS; ++i) { 94 start_helper(env, &thread[i], (helper_fn_t) func, i, (seL4_Word) env, 0, 0); 95 } 96 97 if (CONFIG_NUM_DOMAINS > 1 && shift) { 98 sel4test_sleep(env, POLL_DELAY_NS * 2); 99 error = seL4_DomainSet_Set(env->domain, CONFIG_NUM_DOMAINS - 1, get_helper_tcb(&thread[0])); 100 assert(error == seL4_NoError); 101 } 102 103 for (int i = 0; i < CONFIG_NUM_DOMAINS; ++i) { 104 wait_for_helper(&thread[i]); 105 cleanup_helper(env, &thread[i]); 106 } 107 108 return sel4test_get_result(); 109} 110 111/* The output from this test should show alternating "domain blocks", with, 112 * within each, a single thread printing. For example: 113 * 114 * 00, 00, ..., 00, 01, 01, ..., 01, 00, 00, ..., 00, 01, 01, ..., 01, etc. 115 * +-------------+ +-------------+ +-------------+ +-------------+ 116 * block 0 block 1 block 0 block 1 117 */ 118static int 119test_run_domains(struct env* env) 120{ 121 return test_domains<false>(env, fdom1); 122} 123DEFINE_TEST(DOMAINS0004, "Run threads in domains()", test_run_domains, config_set(CONFIG_HAVE_TIMER)) 124 125/* The output of this test differs from that of DOMAINS0004 in that the thread 126 * in domain 0 is moved into domain 1 after a short delay. This should be 127 * visible in the output, where the "domain block" for domain 1 should contain 128 * the alternating output of threads 0 and 1. For example: 129 * 130 * 00, 00, ..., 00, 01, 00, 01, 00, ..., 01, 01, 01, 01 131 * +-------------+ +------------------+ +------------+ 132 * initial block alterations final block 133 * (due to delay) (after shift) (01 catches up) 134 */ 135static int 136test_run_domains_shift(struct env* env) 137{ 138 return test_domains<true>(env, fdom1); 139} 140DEFINE_TEST(DOMAINS0005, "Move thread between domains()", test_run_domains_shift, config_set(CONFIG_HAVE_TIMER) && CONFIG_NUM_DOMAINS > 1) 141 142static int 143test_own_domain1(struct env* env) 144{ 145 return own_domain_success(env); 146} 147DEFINE_TEST(DOMAINS0001, "Change domain successfully()", test_own_domain1, true) 148 149static int 150test_own_domain2(struct env* env) 151{ 152 return own_domain_baddom(env); 153} 154DEFINE_TEST(DOMAINS0002, "Try non-existant domain()", test_own_domain2, true) 155 156static int 157test_own_domain3(struct env* env) 158{ 159 return own_domain_badcap(env); 160} 161DEFINE_TEST(DOMAINS0003, "Invoke non-domain cap()", test_own_domain3, true) 162