1 /* 2 * Copyright 2018 The Hafnium Authors. 3 * 4 * Use of this source code is governed by a BSD-style 5 * license that can be found in the LICENSE file or at 6 * https://opensource.org/licenses/BSD-3-Clause. 7 */ 8 9 #pragma once 10 11 #include "hf/fdt.h" 12 #include "hf/ffa.h" 13 #include "hf/ffa_partition_manifest.h" 14 #include "hf/std.h" 15 16 #include "vmapi/hf/ffa.h" 17 18 #define HFTEST_MAX_TESTS 50 19 20 /* 21 * Log with the HFTEST_LOG_PREFIX and a new line. The newline is passed as 22 * an argument so there is always at least one variadic argument. 23 */ 24 #define HFTEST_LOG(...) HFTEST_LOG_IMPL(__VA_ARGS__, "\n") 25 #define HFTEST_LOG_IMPL(format, ...) \ 26 dlog(HFTEST_LOG_PREFIX format "%s", __VA_ARGS__) 27 28 /* Helper to wrap the argument in quotes. */ 29 #define HFTEST_STR(str) #str 30 31 /* 32 * Sections are names such that when the linker sorts them, all entries for the 33 * same test suite are contiguous and the set up and tear down entries come 34 * before the tests. This order simplifies test discovery in the running image. 35 */ 36 #define HFTEST_SET_UP_SECTION(suite_name) \ 37 HFTEST_STR(.hftest.suite.suite_name.1set_up) 38 #define HFTEST_TEAR_DOWN_SECTION(suite_name) \ 39 HFTEST_STR(.hftest.suite.suite_name.1tear_down) 40 #define HFTEST_TEST_SECTION(suite_name, test_name) \ 41 HFTEST_STR(.hftest.suite.suite_name.2test.test_name) 42 #define HFTEST_SERVICE_SET_UP_SECTION(service_name) \ 43 HFTEST_STR(.hftest.service_set_up.service_name) 44 #define HFTEST_SERVICE_SECTION(service_name) \ 45 HFTEST_STR(.hftest.service.service_name) 46 47 /* Helpers to construct unique identifiers. */ 48 #define HFTEST_SET_UP_STRUCT(suite_name) hftest_set_up_##suite_name 49 #define HFTEST_TEAR_DOWN_STRUCT(suite_name) hftest_tear_down_##suite_name 50 #define HFTEST_TEST_STRUCT(suite_name, test_name) \ 51 hftest_test_##suite_name##_##test_name 52 #define HFTEST_SERVICE_SET_UP_STRUCT(service_name) \ 53 hftest_service_set_up_##service_name 54 #define HFTEST_SERVICE_STRUCT(service_name) hftest_service_##service_name 55 56 #define HFTEST_SET_UP_FN(suite_name) hftest_set_up_fn_##suite_name 57 #define HFTEST_TEAR_DOWN_FN(suite_name) hftest_tear_down_fn_##suite_name 58 #define HFTEST_TEST_FN(suite_name, test_name) \ 59 hftest_test_fn_##suite_name##_##test_name 60 #define HFTEST_SERVICE_SET_UP_FN(service_name) \ 61 hftest_service_set_up_fn_##service_name 62 #define HFTEST_SERVICE_FN(service_name) hftest_service_fn_##service_name 63 64 #define HFTEST_SET_UP_CONSTRUCTOR(suite_name) hftest_set_up_ctor_##suite_name 65 #define HFTEST_TEAR_DOWN_CONSTRUCTOR(suite_name) \ 66 hftest_tear_down_ctor_##suite_name 67 #define HFTEST_TEST_CONSTRUCTOR(suite_name, test_name) \ 68 hftest_test_ctor_##suite_name##_##test_name 69 70 /* Register test functions. */ 71 #define HFTEST_SET_UP(suite_name) \ 72 static void HFTEST_SET_UP_FN(suite_name)(void); \ 73 [[gnu::used]] [[gnu::section(HFTEST_SET_UP_SECTION(suite_name))]] \ 74 const struct hftest_test HFTEST_SET_UP_STRUCT(suite_name) = { \ 75 .suite = #suite_name, \ 76 .kind = HFTEST_KIND_SET_UP, \ 77 .fn = HFTEST_SET_UP_FN(suite_name), \ 78 }; \ 79 static void HFTEST_SET_UP_FN(suite_name)(void) 80 81 #define HFTEST_TEAR_DOWN(suite_name) \ 82 static void HFTEST_TEAR_DOWN_FN(suite_name)(void); \ 83 [[gnu::used]] [[gnu::section(HFTEST_TEAR_DOWN_SECTION(suite_name))]] \ 84 const struct hftest_test HFTEST_TEAR_DOWN_STRUCT(suite_name) = { \ 85 .suite = #suite_name, \ 86 .kind = HFTEST_KIND_TEAR_DOWN, \ 87 .fn = HFTEST_TEAR_DOWN_FN(suite_name), \ 88 }; \ 89 static void HFTEST_TEAR_DOWN_FN(suite_name)(void) 90 91 #define HFTEST_TEST(suite_name, test_name, long_running, precon_fn) \ 92 static void HFTEST_TEST_FN(suite_name, test_name)(void); \ 93 [[gnu::used]] [[gnu::section( \ 94 HFTEST_TEST_SECTION(suite_name, test_name))]] \ 95 const struct hftest_test HFTEST_TEST_STRUCT(suite_name, test_name) = { \ 96 .suite = #suite_name, \ 97 .kind = HFTEST_KIND_TEST, \ 98 .name = #test_name, \ 99 .is_long_running = (long_running), \ 100 .fn = HFTEST_TEST_FN(suite_name, test_name), \ 101 .precondition = (precon_fn), \ 102 }; \ 103 static void HFTEST_TEST_FN(suite_name, test_name)(void) 104 105 #define HFTEST_SERVICE_SET_UP(service_name) \ 106 static void HFTEST_SERVICE_SET_UP_FN(service_name)(void); \ 107 [[gnu::used]] [[gnu::section( \ 108 HFTEST_SERVICE_SET_UP_SECTION(service_name))]] \ 109 const struct hftest_test HFTEST_SERVICE_SET_UP_STRUCT( \ 110 service_name) = { \ 111 .name = #service_name, \ 112 .kind = HFTEST_KIND_SERVICE_SET_UP, \ 113 .fn = HFTEST_SERVICE_SET_UP_FN(service_name), \ 114 }; \ 115 static void HFTEST_SERVICE_SET_UP_FN(service_name)(void) 116 117 #define HFTEST_TEST_SERVICE(service_name) \ 118 static void HFTEST_SERVICE_FN(service_name)(void); \ 119 [[gnu::used]] [[gnu::section(HFTEST_SERVICE_SECTION(service_name))]] \ 120 const struct hftest_test HFTEST_SERVICE_STRUCT(service_name) = { \ 121 .kind = HFTEST_KIND_SERVICE, \ 122 .name = #service_name, \ 123 .fn = HFTEST_SERVICE_FN(service_name), \ 124 .precondition = NULL, \ 125 }; \ 126 static void HFTEST_SERVICE_FN(service_name)(void) 127 128 /* Context for tests. */ 129 struct hftest_context { 130 uint32_t failures; 131 void (*abort)(void); 132 133 /* These are used in primary VMs. */ 134 const struct fdt *fdt; 135 bool is_ffa_manifest_parsed; 136 struct ffa_partition_manifest partition_manifest; 137 138 /* These are used in services. */ 139 void *send; 140 void *recv; 141 size_t memory_size; 142 ffa_id_t dir_req_source_id; 143 }; 144 145 struct hftest_context *hftest_get_context(void); 146 147 /* A test case. */ 148 typedef void (*hftest_test_fn)(void); 149 typedef bool (*hftest_test_precondition)(void); 150 151 enum hftest_kind { 152 HFTEST_KIND_SET_UP = 0, 153 HFTEST_KIND_TEST = 1, 154 HFTEST_KIND_TEAR_DOWN = 2, 155 HFTEST_KIND_SERVICE_SET_UP = 3, 156 HFTEST_KIND_SERVICE = 4, 157 }; 158 159 /** 160 * The .hftest section contains an array of this struct which describes the test 161 * functions contained in the image allowing the image to inspect the tests it 162 * contains. 163 */ 164 /* NOLINTNEXTLINE(clang-analyzer-optin.performance.Padding) */ 165 struct hftest_test { 166 const char *suite; 167 enum hftest_kind kind; 168 const char *name; 169 bool is_long_running; 170 hftest_test_fn fn; 171 hftest_test_precondition precondition; 172 }; 173 174 /* _Generic formatting doesn't seem to be supported so doing this manually. */ 175 /* clang-format off */ 176 #define HFTEST_LOG_FAILURE() \ 177 dlog(HFTEST_LOG_PREFIX "Failure: %s:%u\n", __FILE__, __LINE__); 178 179 #ifdef HFTEST_OPTIMIZE_FOR_SIZE 180 #define HFTEST_LOG_ASSERT_DETAILS(lhs, rhs, op) 181 #else /* HFTEST_OPTIMIZE_FOR_SIZE */ 182 #define HFTEST_LOG_ASSERT_DETAILS(lhs, rhs, op) \ 183 do { \ 184 dlog(HFTEST_LOG_PREFIX "assertion failed: `%s %s %s`\n", #lhs, #op, #rhs); \ 185 dlog(_Generic(lhs_value, \ 186 bool: HFTEST_LOG_PREFIX "lhs = %hhu (%#02hhx)", \ 187 char: HFTEST_LOG_PREFIX "lhs = '%c' (%#02hhx)", \ 188 signed char: HFTEST_LOG_PREFIX "lhs = %hhd (%#02hhx)", \ 189 unsigned char: HFTEST_LOG_PREFIX "lhs = %hhu (%#02hhx)", \ 190 signed short: HFTEST_LOG_PREFIX "lhs = %hd (%#04hx)", \ 191 unsigned short: HFTEST_LOG_PREFIX "lhs = %hu (%#04hx)", \ 192 signed int: HFTEST_LOG_PREFIX "lhs = %d (%#08x)", \ 193 unsigned int: HFTEST_LOG_PREFIX "lhs = %u (%#08x)", \ 194 signed long: HFTEST_LOG_PREFIX "lhs = %ld (%#016lx)", \ 195 unsigned long: HFTEST_LOG_PREFIX "lhs = %lu (%#016lx)", \ 196 signed long long: HFTEST_LOG_PREFIX "lhs = %lld (%#016llx)", \ 197 unsigned long long: HFTEST_LOG_PREFIX "lhs = %llu (%#016llx)" \ 198 ), lhs_value, lhs_value); \ 199 dlog(_Generic(rhs_value, \ 200 bool: HFTEST_LOG_PREFIX "rhs = %hhu (%#02hhx)", \ 201 char: HFTEST_LOG_PREFIX "rhs = '%c' (%#02hhx)", \ 202 signed char: HFTEST_LOG_PREFIX "rhs = %hhd (%#02hhx)", \ 203 unsigned char: HFTEST_LOG_PREFIX "rhs = %hhu (%#02hhx)", \ 204 signed short: HFTEST_LOG_PREFIX "rhs = %hd (%#04hx)", \ 205 unsigned short: HFTEST_LOG_PREFIX "rhs = %hu (%#04hx)", \ 206 signed int: HFTEST_LOG_PREFIX "rhs = %d (%#08x)", \ 207 unsigned int: HFTEST_LOG_PREFIX "rhs = %u (%#08x)", \ 208 signed long: HFTEST_LOG_PREFIX "rhs = %ld (%#016lx)", \ 209 unsigned long: HFTEST_LOG_PREFIX "rhs = %lu (%#016lx)", \ 210 signed long long: HFTEST_LOG_PREFIX "rhs = %lld (%#016llx)", \ 211 unsigned long long: HFTEST_LOG_PREFIX "rhs = %llu (%#016llx)" \ 212 ), rhs_value, rhs_value); \ 213 } while (0) 214 #endif /* HFTEST_OPTIMIZE_FOR_SIZE */ 215 /* clang-format on */ 216 217 #ifdef HFTEST_OPTIMIZE_FOR_SIZE 218 #define HFTEST_LOG_ASSERT_STRING_DETAILS(lhs, rhs, op) 219 #else /* HFTEST_OPTIMIZE_FOR_SIZE */ 220 #define HFTEST_LOG_ASSERT_STRING_DETAILS(lhs, rhs, op) \ 221 do { \ 222 dlog(HFTEST_LOG_PREFIX "assertion failed: `%s %s %s`\n", #lhs, \ 223 #op, #rhs); \ 224 dlog(HFTEST_LOG_PREFIX "lhs = \"%s\"\n", lhs_value); \ 225 dlog(HFTEST_LOG_PREFIX "rhs = \"%s\"\n", rhs_value); \ 226 dlog("\n"); \ 227 } while (0) 228 229 #endif /* HFTEST_OPTIMIZE_FOR_SIZE */ 230 231 #define HFTEST_ASSERT_OP(lhs, rhs, op, fatal) \ 232 do { \ 233 typeof(lhs) lhs_value = lhs; \ 234 typeof(rhs) rhs_value = rhs; \ 235 if (!(lhs_value op rhs_value)) { \ 236 struct hftest_context *ctx = hftest_get_context(); \ 237 ++ctx->failures; \ 238 HFTEST_LOG_FAILURE(); \ 239 HFTEST_LOG_ASSERT_DETAILS(lhs, rhs, op); \ 240 if (fatal) { \ 241 ctx->abort(); \ 242 } \ 243 } \ 244 } while (0) 245 246 #define HFTEST_ASSERT_STRING_OP(lhs, rhs, op, fatal) \ 247 do { \ 248 char *lhs_value = (lhs); \ 249 char *rhs_value = (rhs); \ 250 /* NOLINTNEXTLINE(bugprone-macro-parentheses) */ \ 251 if (!(strncmp(lhs_value, rhs_value, RSIZE_MAX) op 0)) { \ 252 struct hftest_context *ctx = hftest_get_context(); \ 253 ++ctx->failures; \ 254 HFTEST_LOG_FAILURE(); \ 255 HFTEST_LOG_ASSERT_STRING_DETAILS(lhs, rhs, op); \ 256 if (fatal) { \ 257 ctx->abort(); \ 258 } \ 259 } \ 260 } while (0) 261 262 #define HFTEST_FAIL(fatal, ...) \ 263 do { \ 264 struct hftest_context *ctx = hftest_get_context(); \ 265 ++ctx->failures; \ 266 HFTEST_LOG_FAILURE(); \ 267 dlog(HFTEST_LOG_PREFIX HFTEST_LOG_INDENT __VA_ARGS__); \ 268 dlog("\n"); \ 269 if (fatal) { \ 270 ctx->abort(); \ 271 } \ 272 } while (0) 273 274 /** 275 * Select the service to run in a service VM. 276 */ 277 #define HFTEST_SERVICE_SELECT(vm_id, service, send_buffer, vcpu_id) \ 278 do { \ 279 struct ffa_value res; \ 280 uint32_t msg_length = \ 281 strnlen_s(service, SERVICE_NAME_MAX_LENGTH); \ 282 struct ffa_partition_msg *message = \ 283 (struct ffa_partition_msg *)(send_buffer); \ 284 \ 285 /* \ 286 * If service is a Secondary VM, let the service configure \ 287 * its mailbox and wait for a message. \ 288 */ \ 289 if (ffa_is_vm_id(vm_id)) { \ 290 res = ffa_run(vm_id, vcpu_id); \ 291 ASSERT_EQ(res.func, FFA_MSG_WAIT_32); \ 292 ASSERT_EQ(res.arg2, FFA_SLEEP_INDEFINITE); \ 293 } \ 294 \ 295 /* \ 296 * Send the selected service to run and let it be \ 297 * handled. \ 298 */ \ 299 ffa_rxtx_header_init(&message->header, hf_vm_get_id(), vm_id, \ 300 msg_length); \ 301 memcpy_s(message->payload, FFA_PARTITION_MSG_PAYLOAD_MAX, \ 302 service, msg_length); \ 303 res = ffa_msg_send2(0); \ 304 \ 305 ASSERT_EQ(res.func, FFA_SUCCESS_32); \ 306 res = ffa_run(vm_id, vcpu_id); \ 307 ASSERT_EQ(res.func, FFA_YIELD_32); \ 308 } while (0) 309 310 #define HFTEST_SERVICE_SEND_BUFFER() hftest_get_context()->send 311 #define HFTEST_SERVICE_RECV_BUFFER() hftest_get_context()->recv 312 #define HFTEST_SERVICE_MEMORY_SIZE() hftest_get_context()->memory_size 313