blob: 8573eca9a3c11bdc6029a93590f3620e19bbc294 [file] [log] [blame]
Andrew Scull18834872018-10-12 11:48:09 +01001/*
Andrew Walbran692b3252019-03-07 15:51:31 +00002 * Copyright 2018 The Hafnium Authors.
Andrew Scull18834872018-10-12 11:48:09 +01003 *
Andrew Walbrane959ec12020-06-17 15:01:09 +01004 * 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.
Andrew Scull18834872018-10-12 11:48:09 +01007 */
8
Andrew Scullf0551c82018-12-15 20:38:47 +00009#include "hf/arch/vm/power_mgmt.h"
10
Andrew Walbranafabe852019-03-20 17:55:11 +000011#include "hf/boot_params.h"
12#include "hf/fdt_handler.h"
Andrew Scullbc7189d2018-08-14 09:35:13 +010013#include "hf/memiter.h"
Andrew Scull8d9e1212019-04-05 13:52:55 +010014#include "hf/std.h"
Andrew Scullbc7189d2018-08-14 09:35:13 +010015
David Brazdil3ad6e542019-09-13 17:17:09 +010016#include "hftest_common.h"
Andrew Walbran1e7c7742019-12-13 17:10:02 +000017#include "test/hftest.h"
Andrew Scullbc7189d2018-08-14 09:35:13 +010018
19HFTEST_ENABLE();
20
Andrew Walbranbc342d42019-02-05 16:56:02 +000021static struct hftest_test hftest_constructed[HFTEST_MAX_TESTS];
22static size_t hftest_count;
23static struct hftest_test *hftest_list;
Andrew Scullbc7189d2018-08-14 09:35:13 +010024
Andrew Scullf0551c82018-12-15 20:38:47 +000025static struct hftest_context global_context;
26
27struct hftest_context *hftest_get_context(void)
28{
29 return &global_context;
30}
31
Andrew Walbranbc342d42019-02-05 16:56:02 +000032/**
33 * Adds the given test information to the global list, to be used by
34 * `hftest_use_registered_list`.
35 */
36void hftest_register(struct hftest_test test)
Andrew Scullbc7189d2018-08-14 09:35:13 +010037{
Andrew Walbranbc342d42019-02-05 16:56:02 +000038 if (hftest_count < HFTEST_MAX_TESTS) {
39 hftest_constructed[hftest_count++] = test;
40 } else {
Andrew Walbran78a63b72019-03-18 17:28:22 +000041 HFTEST_FAIL(true, "Too many tests");
Andrew Walbranbc342d42019-02-05 16:56:02 +000042 }
43}
44
45/**
46 * Uses the list of tests registered by `hftest_register(...)` as the ones to
47 * run.
48 */
49void hftest_use_registered_list(void)
50{
51 hftest_list = hftest_constructed;
52}
53
54/**
55 * Uses the given list of tests as the ones to run.
56 */
57void hftest_use_list(struct hftest_test list[], size_t count)
58{
59 hftest_list = list;
60 hftest_count = count;
61}
62
63/**
64 * Writes out a JSON structure describing the available tests.
65 */
66void hftest_json(void)
67{
Andrew Scullbc7189d2018-08-14 09:35:13 +010068 const char *suite = NULL;
Andrew Walbranbc342d42019-02-05 16:56:02 +000069 size_t i;
Andrew Scullbc7189d2018-08-14 09:35:13 +010070 size_t suites_in_image = 0;
71 size_t tests_in_suite = 0;
72
73 HFTEST_LOG("{");
74 HFTEST_LOG(" \"suites\": [");
Andrew Walbranbc342d42019-02-05 16:56:02 +000075 for (i = 0; i < hftest_count; ++i) {
76 struct hftest_test *test = &hftest_list[i];
Andrew Scullbc7189d2018-08-14 09:35:13 +010077 if (test->suite != suite) {
78 /* Close out previously open suite. */
79 if (tests_in_suite) {
80 HFTEST_LOG(" ]");
81 HFTEST_LOG(" },");
82 }
83 /* Move onto new suite. */
84 ++suites_in_image;
85 suite = test->suite;
86 tests_in_suite = 0;
87 HFTEST_LOG(" {");
88 HFTEST_LOG(" \"name\": \"%s\",", test->suite);
89 }
90 if (test->kind == HFTEST_KIND_SET_UP) {
91 HFTEST_LOG(" \"setup\": true,");
92 }
93 if (test->kind == HFTEST_KIND_TEAR_DOWN) {
94 HFTEST_LOG(" \"teardown\": true,");
95 }
96 if (test->kind == HFTEST_KIND_TEST) {
J-Alvesd459b562022-12-05 14:56:33 +000097 /*
98 * If test has a precondition, run respective function.
99 * If it returns false, then the current setup is not
100 * meant to run the test. Hence, we must skip it.
101 */
102 bool skip_test = test->precondition != NULL &&
103 !test->precondition();
104
Andrew Scullbc7189d2018-08-14 09:35:13 +0100105 if (!tests_in_suite) {
106 HFTEST_LOG(" \"tests\": [");
107 }
Andrew Scullf0551c82018-12-15 20:38:47 +0000108 /*
109 * It's easier to put the comma at the start of the line
Andrew Scull2b5fbad2019-04-05 13:55:56 +0100110 * than the end even though the JSON looks a bit funky.
Andrew Scullf0551c82018-12-15 20:38:47 +0000111 */
David Brazdil3cc24aa2019-09-27 10:24:41 +0100112 HFTEST_LOG(" %c{", tests_in_suite ? ',' : ' ');
113 HFTEST_LOG(" \"name\": \"%s\",", test->name);
J-Alvesd459b562022-12-05 14:56:33 +0000114 HFTEST_LOG(" \"is_long_running\": %s,",
David Brazdil3cc24aa2019-09-27 10:24:41 +0100115 test->is_long_running ? "true" : "false");
J-Alvesd459b562022-12-05 14:56:33 +0000116 HFTEST_LOG(" \"skip_test\": %s",
117 skip_test ? "true" : "false");
David Brazdil3cc24aa2019-09-27 10:24:41 +0100118 HFTEST_LOG(" }");
Andrew Scullbc7189d2018-08-14 09:35:13 +0100119 ++tests_in_suite;
120 }
121 }
122 if (tests_in_suite) {
123 HFTEST_LOG(" ]");
124 HFTEST_LOG(" }");
125 }
126 HFTEST_LOG(" ]");
127 HFTEST_LOG("}");
128}
129
Andrew Walbranbc342d42019-02-05 16:56:02 +0000130/**
131 * Logs a failure message and shut down.
132 */
Andrew Sculla59f9bc2019-04-03 15:24:35 +0100133noreturn void abort(void)
Andrew Scullf0551c82018-12-15 20:38:47 +0000134{
135 HFTEST_LOG("FAIL");
Andrew Walbranc6903d12019-03-05 18:28:20 +0000136 arch_power_off();
Andrew Scullf0551c82018-12-15 20:38:47 +0000137}
138
Andrew Scullbc7189d2018-08-14 09:35:13 +0100139static void run_test(hftest_test_fn set_up, hftest_test_fn test,
David Brazdilb856be62020-03-25 10:14:55 +0000140 hftest_test_fn tear_down, const struct fdt *fdt)
Andrew Scullbc7189d2018-08-14 09:35:13 +0100141{
Andrew Scullf0551c82018-12-15 20:38:47 +0000142 /* Prepare the context. */
143 struct hftest_context *ctx = hftest_get_context();
Andrew Scull2b5fbad2019-04-05 13:55:56 +0100144 memset_s(ctx, sizeof(*ctx), 0, sizeof(*ctx));
Andrew Scullf0551c82018-12-15 20:38:47 +0000145 ctx->abort = abort;
Andrew Walbranafabe852019-03-20 17:55:11 +0000146 ctx->fdt = fdt;
Andrew Scullbc7189d2018-08-14 09:35:13 +0100147
Andrew Scullf0551c82018-12-15 20:38:47 +0000148 /* Run any set up functions. */
Andrew Scullbc7189d2018-08-14 09:35:13 +0100149 if (set_up) {
Andrew Scullf0551c82018-12-15 20:38:47 +0000150 set_up();
151 if (ctx->failures) {
152 abort();
Andrew Scullbc7189d2018-08-14 09:35:13 +0100153 }
154 }
155
Andrew Scullf0551c82018-12-15 20:38:47 +0000156 /* Run the test. */
157 test();
158 if (ctx->failures) {
159 abort();
Andrew Scullbc7189d2018-08-14 09:35:13 +0100160 }
161
Andrew Scullf0551c82018-12-15 20:38:47 +0000162 /* Run any tear down functions. */
Andrew Scullbc7189d2018-08-14 09:35:13 +0100163 if (tear_down) {
Andrew Scullf0551c82018-12-15 20:38:47 +0000164 tear_down();
165 if (ctx->failures) {
166 abort();
Andrew Scullbc7189d2018-08-14 09:35:13 +0100167 }
168 }
169
Andrew Scullf0551c82018-12-15 20:38:47 +0000170 HFTEST_LOG("FINISHED");
Andrew Scullbc7189d2018-08-14 09:35:13 +0100171}
172
Andrew Walbranbc342d42019-02-05 16:56:02 +0000173/**
174 * Runs the given test case.
175 */
Andrew Walbranafabe852019-03-20 17:55:11 +0000176void hftest_run(struct memiter suite_name, struct memiter test_name,
David Brazdilb856be62020-03-25 10:14:55 +0000177 const struct fdt *fdt)
Andrew Scullbc7189d2018-08-14 09:35:13 +0100178{
Andrew Walbranbc342d42019-02-05 16:56:02 +0000179 size_t i;
Andrew Scullbc7189d2018-08-14 09:35:13 +0100180 hftest_test_fn suite_set_up = NULL;
181 hftest_test_fn suite_tear_down = NULL;
182
Andrew Walbranbc342d42019-02-05 16:56:02 +0000183 for (i = 0; i < hftest_count; ++i) {
184 struct hftest_test *test = &hftest_list[i];
Andrew Walbran320c84e2019-11-12 12:48:24 +0000185
186 /* Check if this test is part of the suite we want. */
187 if (memiter_iseq(&suite_name, test->suite)) {
188 switch (test->kind) {
189 /*
190 * The first entries in the suite are the set up and
191 * tear down functions.
192 */
193 case HFTEST_KIND_SET_UP:
194 suite_set_up = test->fn;
195 break;
196 case HFTEST_KIND_TEAR_DOWN:
197 suite_tear_down = test->fn;
198 break;
199 /* Find the test. */
200 case HFTEST_KIND_TEST:
201 if (memiter_iseq(&test_name, test->name)) {
202 run_test(suite_set_up, test->fn,
203 suite_tear_down, fdt);
204 return;
205 }
206 break;
207 default:
208 /* Ignore other kinds. */
Andrew Scullbc7189d2018-08-14 09:35:13 +0100209 break;
210 }
Andrew Scullbc7189d2018-08-14 09:35:13 +0100211 }
212 }
213
214 HFTEST_LOG("Unable to find requested tests.");
215}
216
Andrew Walbranbc342d42019-02-05 16:56:02 +0000217/**
218 * Writes out usage information.
219 */
220void hftest_help(void)
Andrew Scullbc7189d2018-08-14 09:35:13 +0100221{
222 HFTEST_LOG("usage:");
223 HFTEST_LOG("");
224 HFTEST_LOG(" help");
225 HFTEST_LOG("");
226 HFTEST_LOG(" Show this help.");
227 HFTEST_LOG("");
228 HFTEST_LOG(" json");
229 HFTEST_LOG("");
230 HFTEST_LOG(
231 " Print a directory of test suites and tests in "
232 "JSON "
233 "format.");
234 HFTEST_LOG("");
235 HFTEST_LOG(" run <suite> <test>");
236 HFTEST_LOG("");
237 HFTEST_LOG(" Run the named test from the named test suite.");
238}
Andrew Walbranafabe852019-03-20 17:55:11 +0000239
J-Alves070a40d2021-01-21 14:35:12 +0000240void hftest_command(struct fdt *fdt)
241{
242 struct memiter command_line;
243 struct memiter command;
244
245 if (!hftest_ctrl_start(fdt, &command_line)) {
246 HFTEST_LOG("Unable to read the command line.");
247 return;
248 }
249
250 if (!memiter_parse_str(&command_line, &command)) {
251 HFTEST_LOG("Unable to parse command.");
252 return;
253 }
254
255 if (memiter_iseq(&command, "exit")) {
256 hftest_device_exit_test_environment();
257 return;
258 }
259
260 if (memiter_iseq(&command, "json")) {
261 hftest_json();
262 return;
263 }
264
265 if (memiter_iseq(&command, "run")) {
266 struct memiter suite_name;
267 struct memiter test_name;
268
269 if (!memiter_parse_str(&command_line, &suite_name)) {
270 HFTEST_LOG("Unable to parse test suite.");
271 return;
272 }
273
274 if (!memiter_parse_str(&command_line, &test_name)) {
275 HFTEST_LOG("Unable to parse test.");
276 return;
277 }
278 hftest_run(suite_name, test_name, fdt);
279 return;
280 }
281
282 hftest_help();
283}
284
Andrew Walbranafabe852019-03-20 17:55:11 +0000285static uintptr_t vcpu_index_to_id(size_t index)
286{
287 /* For now we use indices as IDs for vCPUs. */
288 return index;
289}
290
291/**
292 * Get the ID of the CPU with the given index.
293 */
294uintptr_t hftest_get_cpu_id(size_t index)
295{
296 struct boot_params params;
David Brazdilb856be62020-03-25 10:14:55 +0000297 const struct fdt *fdt = hftest_get_context()->fdt;
Andrew Walbranafabe852019-03-20 17:55:11 +0000298
299 if (fdt == NULL) {
300 /*
301 * We must be in a service VM, so apply the mapping that Hafnium
302 * uses for vCPU IDs.
303 */
304 return vcpu_index_to_id(index);
305 }
306
307 /* Find physical CPU ID from FDT. */
David Brazdilb856be62020-03-25 10:14:55 +0000308 fdt_find_cpus(fdt, params.cpu_ids, &params.cpu_count);
Andrew Walbranafabe852019-03-20 17:55:11 +0000309
310 return params.cpu_ids[index];
311}