blob: f3c9ffa9d096e0fd148508544f4b5cd9d853aa1a [file] [log] [blame]
Andrew Scullf0551c82018-12-15 20:38:47 +00001/*
Andrew Walbran692b3252019-03-07 15:51:31 +00002 * Copyright 2018 The Hafnium Authors.
Andrew Scullf0551c82018-12-15 20:38:47 +00003 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * https://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#pragma once
18
19#include <stdnoreturn.h>
20
Andrew Walbranafabe852019-03-20 17:55:11 +000021#include "hf/fdt.h"
Jose Marinhoa1dfeda2019-02-27 16:46:03 +000022#include "hf/spci.h"
Andrew Scull8d9e1212019-04-05 13:52:55 +010023#include "hf/std.h"
Jose Marinhoa1dfeda2019-02-27 16:46:03 +000024
Jose Marinho75509b42019-04-09 09:34:59 +010025#include "vmapi/hf/spci.h"
26
Andrew Walbranbc342d42019-02-05 16:56:02 +000027#define HFTEST_MAX_TESTS 50
28
Andrew Scullf0551c82018-12-15 20:38:47 +000029/*
30 * Log with the HFTEST_LOG_PREFIX and a new line. The zero is added so there is
31 * always at least one variadic argument.
32 */
33#define HFTEST_LOG(...) HFTEST_LOG_IMPL(__VA_ARGS__, 0)
34#define HFTEST_LOG_IMPL(format, ...) \
35 dlog("%s" format "\n", HFTEST_LOG_PREFIX, __VA_ARGS__)
36
37/* Helper to wrap the argument in quotes. */
38#define HFTEST_STR(str) #str
39
40/*
41 * Sections are names such that when the linker sorts them, all entries for the
42 * same test suite are contiguous and the set up and tear down entries come
43 * before the tests. This order simplifies test discovery in the running image.
44 */
45#define HFTEST_SET_UP_SECTION(suite_name) \
46 HFTEST_STR(.hftest.suite.suite_name .1set_up)
47#define HFTEST_TEAR_DOWN_SECTION(suite_name) \
48 HFTEST_STR(.hftest.suite.suite_name .1tear_down)
49#define HFTEST_TEST_SECTION(suite_name, test_name) \
50 HFTEST_STR(.hftest.suite.suite_name .2test.test_name)
51#define HFTEST_SERVICE_SECTION(service_name) \
52 HFTEST_STR(.hftest.service.service_name)
53
54/* Helpers to construct unique identifiers. */
55#define HFTEST_SET_UP_STRUCT(suite_name) hftest_set_up_##suite_name
56#define HFTEST_TEAR_DOWN_STRUCT(suite_name) hftest_tear_down_##suite_name
57#define HFTEST_TEST_STRUCT(suite_name, test_name) \
58 hftest_test_##suite_name##_##test_name
59#define HFTEST_SERVICE_STRUCT(service_name) hftest_service_##service_name
60
61#define HFTEST_SET_UP_FN(suite_name) hftest_set_up_fn_##suite_name
62#define HFTEST_TEAR_DOWN_FN(suite_name) hftest_tear_down_fn_##suite_name
63#define HFTEST_TEST_FN(suite_name, test_name) \
64 hftest_test_fn_##suite_name##_##test_name
65#define HFTEST_SERVICE_FN(service_name) hftest_service_fn_##service_name
66
Andrew Walbranbc342d42019-02-05 16:56:02 +000067#define HFTEST_SET_UP_CONSTRUCTOR(suite_name) hftest_set_up_ctor_##suite_name
68#define HFTEST_TEAR_DOWN_CONSTRUCTOR(suite_name) \
69 hftest_tear_down_ctor_##suite_name
70#define HFTEST_TEST_CONSTRUCTOR(suite_name, test_name) \
71 hftest_test_ctor_##suite_name##_##test_name
72
Andrew Scullf0551c82018-12-15 20:38:47 +000073/* Register test functions. */
74#define HFTEST_SET_UP(suite_name) \
75 static void HFTEST_SET_UP_FN(suite_name)(void); \
76 const struct hftest_test __attribute__((used)) \
77 __attribute__((section(HFTEST_SET_UP_SECTION(suite_name)))) \
78 HFTEST_SET_UP_STRUCT(suite_name) = { \
79 .suite = #suite_name, \
80 .kind = HFTEST_KIND_SET_UP, \
81 .fn = HFTEST_SET_UP_FN(suite_name), \
82 }; \
Andrew Walbranbc342d42019-02-05 16:56:02 +000083 static void __attribute__((constructor)) \
84 HFTEST_SET_UP_CONSTRUCTOR(suite_name)(void) \
85 { \
86 hftest_register(HFTEST_SET_UP_STRUCT(suite_name)); \
87 } \
Andrew Scullf0551c82018-12-15 20:38:47 +000088 static void HFTEST_SET_UP_FN(suite_name)(void)
89
90#define HFTEST_TEAR_DOWN(suite_name) \
91 static void HFTEST_TEAR_DOWN_FN(suite_name)(void); \
92 const struct hftest_test __attribute__((used)) \
93 __attribute__((section(HFTEST_TEAR_DOWN_SECTION(suite_name)))) \
94 HFTEST_TEAR_DOWN_STRUCT(suite_name) = { \
95 .suite = #suite_name, \
96 .kind = HFTEST_KIND_TEAR_DOWN, \
97 .fn = HFTEST_TEAR_DOWN_FN(suite_name), \
98 }; \
Andrew Walbranbc342d42019-02-05 16:56:02 +000099 static void __attribute__((constructor)) \
100 HFTEST_TEAR_DOWN_CONSTRUCTOR(suite_name)(void) \
101 { \
102 hftest_register(HFTEST_TEAR_DOWN_STRUCT(suite_name)); \
103 } \
Andrew Scullf0551c82018-12-15 20:38:47 +0000104 static void HFTEST_TEAR_DOWN_FN(suite_name)(void)
105
David Brazdil3cc24aa2019-09-27 10:24:41 +0100106#define HFTEST_TEST(suite_name, test_name, long_running) \
Andrew Walbranbc342d42019-02-05 16:56:02 +0000107 static void HFTEST_TEST_FN(suite_name, test_name)(void); \
108 const struct hftest_test __attribute__((used)) __attribute__( \
109 (section(HFTEST_TEST_SECTION(suite_name, test_name)))) \
110 HFTEST_TEST_STRUCT(suite_name, test_name) = { \
111 .suite = #suite_name, \
112 .kind = HFTEST_KIND_TEST, \
113 .name = #test_name, \
David Brazdil3cc24aa2019-09-27 10:24:41 +0100114 .is_long_running = long_running, \
Andrew Walbranbc342d42019-02-05 16:56:02 +0000115 .fn = HFTEST_TEST_FN(suite_name, test_name), \
116 }; \
117 static void __attribute__((constructor)) \
118 HFTEST_TEST_CONSTRUCTOR(suite_name, test_name)(void) \
119 { \
120 hftest_register(HFTEST_TEST_STRUCT(suite_name, test_name)); \
121 } \
Andrew Scullf0551c82018-12-15 20:38:47 +0000122 static void HFTEST_TEST_FN(suite_name, test_name)(void)
123
124#define HFTEST_TEST_SERVICE(service_name) \
125 static void HFTEST_SERVICE_FN(service_name)(void); \
126 const struct hftest_test __attribute__((used)) \
127 __attribute__((section(HFTEST_SERVICE_SECTION(service_name)))) \
128 HFTEST_SERVICE_STRUCT(service_name) = { \
129 .kind = HFTEST_KIND_SERVICE, \
130 .name = #service_name, \
131 .fn = HFTEST_SERVICE_FN(service_name), \
132 }; \
133 static void HFTEST_SERVICE_FN(service_name)(void)
134
135/* Context for tests. */
136struct hftest_context {
137 uint32_t failures;
138 noreturn void (*abort)(void);
139
Andrew Walbranafabe852019-03-20 17:55:11 +0000140 /* These are used in primary VMs. */
141 const struct fdt_header *fdt;
142
Andrew Scullf0551c82018-12-15 20:38:47 +0000143 /* These are used in services. */
Andrew Walbran70bc8622019-10-07 14:15:58 +0100144 void *send;
145 void *recv;
Andrew Walbran2b87c702019-04-16 18:16:05 +0100146 size_t memory_size;
Andrew Scullf0551c82018-12-15 20:38:47 +0000147};
148
149struct hftest_context *hftest_get_context(void);
150
151/* A test case. */
152typedef void (*hftest_test_fn)(void);
153
154enum hftest_kind {
155 HFTEST_KIND_SET_UP = 0,
156 HFTEST_KIND_TEST = 1,
157 HFTEST_KIND_TEAR_DOWN = 2,
158 HFTEST_KIND_SERVICE = 3,
159};
160
161/**
162 * The .hftest section contains an array of this struct which describes the test
163 * functions contained in the image allowing the image to inspect the tests it
164 * contains.
165 */
166struct hftest_test {
167 const char *suite;
168 enum hftest_kind kind;
169 const char *name;
David Brazdil3cc24aa2019-09-27 10:24:41 +0100170 bool is_long_running;
Andrew Scullf0551c82018-12-15 20:38:47 +0000171 hftest_test_fn fn;
172};
173
174/*
175 * This union can store any of the primitive types supported by the assertion
176 * macros.
177 *
178 * It does not include pointers as comparison of pointers is not often needed
179 * and could be a mistake for string comparison. If pointer comparison is needed
180 * and explicit assertion such as ASSERT_PTR_EQ() would be more appropriate.
181 */
182union hftest_any {
183 bool b;
184 char c;
185 signed char sc;
186 unsigned char uc;
187 signed short ss;
188 unsigned short us;
189 signed int si;
190 unsigned int ui;
191 signed long int sli;
192 unsigned long int uli;
193 signed long long int slli;
194 unsigned long long int ulli;
195};
196
197/* _Generic formatting doesn't seem to be supported so doing this manually. */
198/* clang-format off */
199
200/* Select the union member to match the type of the expression. */
201#define hftest_any_get(any, x) \
202 _Generic((x), \
203 bool: (any).b, \
204 char: (any).c, \
205 signed char: (any).sc, \
206 unsigned char: (any).uc, \
207 signed short: (any).ss, \
208 unsigned short: (any).us, \
209 signed int: (any).si, \
210 unsigned int: (any).ui, \
211 signed long int: (any).sli, \
212 unsigned long int: (any).uli, \
213 signed long long int: (any).slli, \
214 unsigned long long int: (any).ulli)
215
216/*
217 * dlog format specifier for types. Note, these aren't the standard specifiers
218 * for the types.
219 */
220#define hftest_dlog_format(x) \
221 _Generic((x), \
222 bool: "%u", \
223 char: "%c", \
224 signed char: "%d", \
225 unsigned char: "%u", \
226 signed short: "%d", \
227 unsigned short: "%u", \
228 signed int: "%d", \
229 unsigned int: "%u", \
230 signed long int: "%d", \
231 unsigned long int: "%u", \
232 signed long long int: "%d", \
233 unsigned long long int: "%u")
234
235/* clang-format on */
236
237#define HFTEST_LOG_FAILURE() \
238 dlog(HFTEST_LOG_PREFIX "Failure: %s:%u\n", __FILE__, __LINE__);
239
240#define HFTEST_ASSERT_OP(lhs, rhs, op, fatal) \
241 do { \
242 union hftest_any lhs_value; \
243 union hftest_any rhs_value; \
244 hftest_any_get(lhs_value, lhs) = (lhs); \
245 hftest_any_get(rhs_value, rhs) = (rhs); \
246 if (!(hftest_any_get(lhs_value, lhs) \
247 op hftest_any_get(rhs_value, rhs))) { \
248 struct hftest_context *ctx = hftest_get_context(); \
249 ++ctx->failures; \
250 HFTEST_LOG_FAILURE(); \
251 dlog(HFTEST_LOG_PREFIX HFTEST_LOG_INDENT \
252 "%s %s %s (%s=", \
253 #lhs, #op, #rhs, #lhs); \
254 dlog(hftest_dlog_format(lhs), \
255 hftest_any_get(lhs_value, lhs)); \
256 dlog(", %s=", #rhs); \
257 dlog(hftest_dlog_format(rhs), \
258 hftest_any_get(rhs_value, rhs)); \
259 dlog(")\n"); \
260 if (fatal) { \
261 ctx->abort(); \
262 } \
263 } \
264 } while (0)
265
Andrew Walbran78a63b72019-03-18 17:28:22 +0000266#define HFTEST_FAIL(fatal, ...) \
267 do { \
268 struct hftest_context *ctx = hftest_get_context(); \
269 ++ctx->failures; \
270 HFTEST_LOG_FAILURE(); \
271 dlog(HFTEST_LOG_PREFIX HFTEST_LOG_INDENT __VA_ARGS__); \
272 dlog("\n"); \
273 if (fatal) { \
274 ctx->abort(); \
275 } \
Andrew Walbranb90daf12018-12-11 14:25:54 +0000276 } while (0)
277
Andrew Scullf0551c82018-12-15 20:38:47 +0000278/**
279 * Select the service to run in a service VM.
280 */
281#define HFTEST_SERVICE_SELECT(vm_id, service, send_buffer) \
282 do { \
283 struct hf_vcpu_run_return run_res; \
Andrew Scull4a867bc2019-04-08 10:15:11 +0100284 uint32_t msg_length = \
285 strnlen_s(service, SERVICE_NAME_MAX_LENGTH); \
Andrew Scullf0551c82018-12-15 20:38:47 +0000286 \
287 /* \
288 * Let the service configure its mailbox and wait for a \
289 * message. \
290 */ \
291 run_res = hf_vcpu_run(vm_id, 0); \
Andrew Scullb06d1752019-02-04 10:15:48 +0000292 ASSERT_EQ(run_res.code, HF_VCPU_RUN_WAIT_FOR_MESSAGE); \
293 ASSERT_EQ(run_res.sleep.ns, HF_SLEEP_INDEFINITE); \
Andrew Scullf0551c82018-12-15 20:38:47 +0000294 \
295 /* Send the selected service to run and let it be handled. */ \
Andrew Walbran70bc8622019-10-07 14:15:58 +0100296 memcpy_s(send_buffer, SPCI_MSG_PAYLOAD_MAX, service, \
Andrew Sculla1aa2ba2019-04-05 11:49:02 +0100297 msg_length); \
Jose Marinhoa1dfeda2019-02-27 16:46:03 +0000298 \
Andrew Walbran70bc8622019-10-07 14:15:58 +0100299 ASSERT_EQ(spci_msg_send(hf_vm_get_id(), vm_id, msg_length, 0) \
300 .func, \
301 SPCI_SUCCESS_32); \
Andrew Scullf0551c82018-12-15 20:38:47 +0000302 run_res = hf_vcpu_run(vm_id, 0); \
303 ASSERT_EQ(run_res.code, HF_VCPU_RUN_YIELD); \
304 } while (0)
305
306#define HFTEST_SERVICE_SEND_BUFFER() hftest_get_context()->send
307#define HFTEST_SERVICE_RECV_BUFFER() hftest_get_context()->recv
Andrew Walbran2b87c702019-04-16 18:16:05 +0100308#define HFTEST_SERVICE_MEMORY_SIZE() hftest_get_context()->memory_size
Andrew Walbranbc342d42019-02-05 16:56:02 +0000309
310void hftest_register(struct hftest_test test);