blob: 30550874f4d07e0bcfd9858e5e6b6c0cb1bd10c7 [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
Daniel Boulby61049dc2023-06-16 14:15:21 +010019#define HFTEST_CTRL_JSON_START "[hftest_ctrl:json_start]"
20#define HFTEST_CTRL_JSON_END "[hftest_ctrl:json_end]"
21
Andrew Scullbc7189d2018-08-14 09:35:13 +010022HFTEST_ENABLE();
23
Andrew Walbranbc342d42019-02-05 16:56:02 +000024static struct hftest_test hftest_constructed[HFTEST_MAX_TESTS];
25static size_t hftest_count;
26static struct hftest_test *hftest_list;
Andrew Scullbc7189d2018-08-14 09:35:13 +010027
Andrew Scullf0551c82018-12-15 20:38:47 +000028static struct hftest_context global_context;
29
30struct hftest_context *hftest_get_context(void)
31{
32 return &global_context;
33}
34
Andrew Walbranbc342d42019-02-05 16:56:02 +000035/**
36 * Adds the given test information to the global list, to be used by
37 * `hftest_use_registered_list`.
38 */
39void hftest_register(struct hftest_test test)
Andrew Scullbc7189d2018-08-14 09:35:13 +010040{
Andrew Walbranbc342d42019-02-05 16:56:02 +000041 if (hftest_count < HFTEST_MAX_TESTS) {
42 hftest_constructed[hftest_count++] = test;
43 } else {
Andrew Walbran78a63b72019-03-18 17:28:22 +000044 HFTEST_FAIL(true, "Too many tests");
Andrew Walbranbc342d42019-02-05 16:56:02 +000045 }
46}
47
48/**
49 * Uses the list of tests registered by `hftest_register(...)` as the ones to
50 * run.
51 */
52void hftest_use_registered_list(void)
53{
54 hftest_list = hftest_constructed;
55}
56
57/**
58 * Uses the given list of tests as the ones to run.
59 */
60void hftest_use_list(struct hftest_test list[], size_t count)
61{
62 hftest_list = list;
63 hftest_count = count;
64}
65
66/**
67 * Writes out a JSON structure describing the available tests.
68 */
69void hftest_json(void)
70{
Andrew Scullbc7189d2018-08-14 09:35:13 +010071 const char *suite = NULL;
Andrew Walbranbc342d42019-02-05 16:56:02 +000072 size_t i;
Andrew Scullbc7189d2018-08-14 09:35:13 +010073 size_t tests_in_suite = 0;
74
Daniel Boulby61049dc2023-06-16 14:15:21 +010075 /* Wrap the JSON in tags for the hftest script to use. */
76 HFTEST_LOG(HFTEST_CTRL_JSON_START);
77
Andrew Scullbc7189d2018-08-14 09:35:13 +010078 HFTEST_LOG("{");
79 HFTEST_LOG(" \"suites\": [");
Andrew Walbranbc342d42019-02-05 16:56:02 +000080 for (i = 0; i < hftest_count; ++i) {
81 struct hftest_test *test = &hftest_list[i];
Andrew Scullbc7189d2018-08-14 09:35:13 +010082 if (test->suite != suite) {
83 /* Close out previously open suite. */
84 if (tests_in_suite) {
85 HFTEST_LOG(" ]");
86 HFTEST_LOG(" },");
87 }
88 /* Move onto new suite. */
Andrew Scullbc7189d2018-08-14 09:35:13 +010089 suite = test->suite;
90 tests_in_suite = 0;
91 HFTEST_LOG(" {");
92 HFTEST_LOG(" \"name\": \"%s\",", test->suite);
93 }
94 if (test->kind == HFTEST_KIND_SET_UP) {
95 HFTEST_LOG(" \"setup\": true,");
96 }
97 if (test->kind == HFTEST_KIND_TEAR_DOWN) {
98 HFTEST_LOG(" \"teardown\": true,");
99 }
100 if (test->kind == HFTEST_KIND_TEST) {
J-Alvesd459b562022-12-05 14:56:33 +0000101 /*
102 * If test has a precondition, run respective function.
103 * If it returns false, then the current setup is not
104 * meant to run the test. Hence, we must skip it.
105 */
106 bool skip_test = test->precondition != NULL &&
107 !test->precondition();
108
Andrew Scullbc7189d2018-08-14 09:35:13 +0100109 if (!tests_in_suite) {
110 HFTEST_LOG(" \"tests\": [");
111 }
Andrew Scullf0551c82018-12-15 20:38:47 +0000112 /*
113 * It's easier to put the comma at the start of the line
Andrew Scull2b5fbad2019-04-05 13:55:56 +0100114 * than the end even though the JSON looks a bit funky.
Andrew Scullf0551c82018-12-15 20:38:47 +0000115 */
David Brazdil3cc24aa2019-09-27 10:24:41 +0100116 HFTEST_LOG(" %c{", tests_in_suite ? ',' : ' ');
117 HFTEST_LOG(" \"name\": \"%s\",", test->name);
J-Alvesd459b562022-12-05 14:56:33 +0000118 HFTEST_LOG(" \"is_long_running\": %s,",
David Brazdil3cc24aa2019-09-27 10:24:41 +0100119 test->is_long_running ? "true" : "false");
J-Alvesd459b562022-12-05 14:56:33 +0000120 HFTEST_LOG(" \"skip_test\": %s",
121 skip_test ? "true" : "false");
David Brazdil3cc24aa2019-09-27 10:24:41 +0100122 HFTEST_LOG(" }");
Andrew Scullbc7189d2018-08-14 09:35:13 +0100123 ++tests_in_suite;
124 }
125 }
126 if (tests_in_suite) {
127 HFTEST_LOG(" ]");
128 HFTEST_LOG(" }");
129 }
130 HFTEST_LOG(" ]");
131 HFTEST_LOG("}");
Daniel Boulby61049dc2023-06-16 14:15:21 +0100132
133 /* Wrap the JSON in tags for the hftest script to use. */
134 HFTEST_LOG(HFTEST_CTRL_JSON_END);
Andrew Scullbc7189d2018-08-14 09:35:13 +0100135}
136
Andrew Walbranbc342d42019-02-05 16:56:02 +0000137/**
138 * Logs a failure message and shut down.
139 */
Andrew Sculla59f9bc2019-04-03 15:24:35 +0100140noreturn void abort(void)
Andrew Scullf0551c82018-12-15 20:38:47 +0000141{
142 HFTEST_LOG("FAIL");
Andrew Walbranc6903d12019-03-05 18:28:20 +0000143 arch_power_off();
Andrew Scullf0551c82018-12-15 20:38:47 +0000144}
145
Andrew Scullbc7189d2018-08-14 09:35:13 +0100146static void run_test(hftest_test_fn set_up, hftest_test_fn test,
David Brazdilb856be62020-03-25 10:14:55 +0000147 hftest_test_fn tear_down, const struct fdt *fdt)
Andrew Scullbc7189d2018-08-14 09:35:13 +0100148{
Andrew Scullf0551c82018-12-15 20:38:47 +0000149 /* Prepare the context. */
150 struct hftest_context *ctx = hftest_get_context();
Andrew Scull2b5fbad2019-04-05 13:55:56 +0100151 memset_s(ctx, sizeof(*ctx), 0, sizeof(*ctx));
Andrew Scullf0551c82018-12-15 20:38:47 +0000152 ctx->abort = abort;
Andrew Walbranafabe852019-03-20 17:55:11 +0000153 ctx->fdt = fdt;
Andrew Scullbc7189d2018-08-14 09:35:13 +0100154
Andrew Scullf0551c82018-12-15 20:38:47 +0000155 /* Run any set up functions. */
Andrew Scullbc7189d2018-08-14 09:35:13 +0100156 if (set_up) {
Andrew Scullf0551c82018-12-15 20:38:47 +0000157 set_up();
158 if (ctx->failures) {
159 abort();
Andrew Scullbc7189d2018-08-14 09:35:13 +0100160 }
161 }
162
Andrew Scullf0551c82018-12-15 20:38:47 +0000163 /* Run the test. */
164 test();
165 if (ctx->failures) {
166 abort();
Andrew Scullbc7189d2018-08-14 09:35:13 +0100167 }
168
Andrew Scullf0551c82018-12-15 20:38:47 +0000169 /* Run any tear down functions. */
Andrew Scullbc7189d2018-08-14 09:35:13 +0100170 if (tear_down) {
Andrew Scullf0551c82018-12-15 20:38:47 +0000171 tear_down();
172 if (ctx->failures) {
173 abort();
Andrew Scullbc7189d2018-08-14 09:35:13 +0100174 }
175 }
176
Andrew Scullf0551c82018-12-15 20:38:47 +0000177 HFTEST_LOG("FINISHED");
Andrew Scullbc7189d2018-08-14 09:35:13 +0100178}
179
Andrew Walbranbc342d42019-02-05 16:56:02 +0000180/**
181 * Runs the given test case.
182 */
Andrew Walbranafabe852019-03-20 17:55:11 +0000183void hftest_run(struct memiter suite_name, struct memiter test_name,
David Brazdilb856be62020-03-25 10:14:55 +0000184 const struct fdt *fdt)
Andrew Scullbc7189d2018-08-14 09:35:13 +0100185{
Andrew Walbranbc342d42019-02-05 16:56:02 +0000186 size_t i;
Andrew Scullbc7189d2018-08-14 09:35:13 +0100187 hftest_test_fn suite_set_up = NULL;
188 hftest_test_fn suite_tear_down = NULL;
189
Andrew Walbranbc342d42019-02-05 16:56:02 +0000190 for (i = 0; i < hftest_count; ++i) {
191 struct hftest_test *test = &hftest_list[i];
Andrew Walbran320c84e2019-11-12 12:48:24 +0000192
193 /* Check if this test is part of the suite we want. */
194 if (memiter_iseq(&suite_name, test->suite)) {
195 switch (test->kind) {
196 /*
197 * The first entries in the suite are the set up and
198 * tear down functions.
199 */
200 case HFTEST_KIND_SET_UP:
201 suite_set_up = test->fn;
202 break;
203 case HFTEST_KIND_TEAR_DOWN:
204 suite_tear_down = test->fn;
205 break;
206 /* Find the test. */
207 case HFTEST_KIND_TEST:
208 if (memiter_iseq(&test_name, test->name)) {
209 run_test(suite_set_up, test->fn,
210 suite_tear_down, fdt);
211 return;
212 }
213 break;
214 default:
215 /* Ignore other kinds. */
Andrew Scullbc7189d2018-08-14 09:35:13 +0100216 break;
217 }
Andrew Scullbc7189d2018-08-14 09:35:13 +0100218 }
219 }
220
221 HFTEST_LOG("Unable to find requested tests.");
222}
223
Andrew Walbranbc342d42019-02-05 16:56:02 +0000224/**
225 * Writes out usage information.
226 */
227void hftest_help(void)
Andrew Scullbc7189d2018-08-14 09:35:13 +0100228{
229 HFTEST_LOG("usage:");
230 HFTEST_LOG("");
231 HFTEST_LOG(" help");
232 HFTEST_LOG("");
233 HFTEST_LOG(" Show this help.");
234 HFTEST_LOG("");
235 HFTEST_LOG(" json");
236 HFTEST_LOG("");
237 HFTEST_LOG(
238 " Print a directory of test suites and tests in "
239 "JSON "
240 "format.");
241 HFTEST_LOG("");
242 HFTEST_LOG(" run <suite> <test>");
243 HFTEST_LOG("");
244 HFTEST_LOG(" Run the named test from the named test suite.");
245}
Andrew Walbranafabe852019-03-20 17:55:11 +0000246
J-Alves070a40d2021-01-21 14:35:12 +0000247void hftest_command(struct fdt *fdt)
248{
249 struct memiter command_line;
250 struct memiter command;
251
252 if (!hftest_ctrl_start(fdt, &command_line)) {
253 HFTEST_LOG("Unable to read the command line.");
254 return;
255 }
256
257 if (!memiter_parse_str(&command_line, &command)) {
258 HFTEST_LOG("Unable to parse command.");
259 return;
260 }
261
262 if (memiter_iseq(&command, "exit")) {
263 hftest_device_exit_test_environment();
264 return;
265 }
266
267 if (memiter_iseq(&command, "json")) {
268 hftest_json();
269 return;
270 }
271
272 if (memiter_iseq(&command, "run")) {
273 struct memiter suite_name;
274 struct memiter test_name;
275
276 if (!memiter_parse_str(&command_line, &suite_name)) {
277 HFTEST_LOG("Unable to parse test suite.");
278 return;
279 }
280
281 if (!memiter_parse_str(&command_line, &test_name)) {
282 HFTEST_LOG("Unable to parse test.");
283 return;
284 }
285 hftest_run(suite_name, test_name, fdt);
286 return;
287 }
288
289 hftest_help();
290}
291
Andrew Walbranafabe852019-03-20 17:55:11 +0000292static uintptr_t vcpu_index_to_id(size_t index)
293{
294 /* For now we use indices as IDs for vCPUs. */
295 return index;
296}
297
298/**
299 * Get the ID of the CPU with the given index.
300 */
301uintptr_t hftest_get_cpu_id(size_t index)
302{
303 struct boot_params params;
David Brazdilb856be62020-03-25 10:14:55 +0000304 const struct fdt *fdt = hftest_get_context()->fdt;
Andrew Walbranafabe852019-03-20 17:55:11 +0000305
306 if (fdt == NULL) {
307 /*
308 * We must be in a service VM, so apply the mapping that Hafnium
309 * uses for vCPU IDs.
310 */
311 return vcpu_index_to_id(index);
312 }
313
J-Alves0c029c22023-06-21 10:32:57 +0100314 /*
315 * VM is primary VM. Convert vCPU ids to the linear cpu id as passed to
316 * the primary VM in the FDT structure.
317 */
318 index = MAX_CPUS - index;
319
Andrew Walbranafabe852019-03-20 17:55:11 +0000320 /* Find physical CPU ID from FDT. */
David Brazdilb856be62020-03-25 10:14:55 +0000321 fdt_find_cpus(fdt, params.cpu_ids, &params.cpu_count);
Andrew Walbranafabe852019-03-20 17:55:11 +0000322
323 return params.cpu_ids[index];
324}