blob: 2ec6e1695a15305d5a649bfc5e3473dd075600e9 [file] [log] [blame]
J-Alves35e61922021-05-06 10:01:05 +01001/*
2 * Copyright 2021 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
J-Alves3c282a32023-02-28 18:27:31 +00009#include "hf/check.h"
Raghu Krishnamurthy50af6602021-12-12 15:23:09 -080010#include "hf/fdt_handler.h"
11#include "hf/ffa.h"
12#include "hf/memiter.h"
J-Alves35e61922021-05-06 10:01:05 +010013#include "hf/mm.h"
14#include "hf/std.h"
Karl Meakin133ae6e2024-04-10 12:05:36 +010015#include "hf/stdout.h"
J-Alves35e61922021-05-06 10:01:05 +010016
Raghu Krishnamurthy50af6602021-12-12 15:23:09 -080017#include "vmapi/hf/call.h"
18
J-Alves0c029c22023-06-21 10:32:57 +010019#include "../msr.h"
J-Alves35e61922021-05-06 10:01:05 +010020#include "test/hftest.h"
21#include "test/hftest_impl.h"
J-Alves0c029c22023-06-21 10:32:57 +010022#include "test/vmapi/arch/exception_handler.h"
J-Alves4dff3e92022-05-23 11:33:52 +010023#include "test/vmapi/ffa.h"
J-Alves35e61922021-05-06 10:01:05 +010024
Raghu Krishnamurthy50af6602021-12-12 15:23:09 -080025extern struct hftest_test hftest_begin[];
26extern struct hftest_test hftest_end[];
27
J-Alves35e61922021-05-06 10:01:05 +010028static struct hftest_context global_context;
29
J-Alves31e5c952024-07-12 09:45:05 +010030static alignas(PAGE_SIZE) uint8_t secondary_ec_stack[MAX_CPUS][PAGE_SIZE];
31
32uint8_t *hftest_get_secondary_ec_stack(size_t id)
33{
34 assert(id < MAX_CPUS);
35 return secondary_ec_stack[id];
36}
37
J-Alves35e61922021-05-06 10:01:05 +010038struct hftest_context *hftest_get_context(void)
39{
40 return &global_context;
41}
42
Kathleen Capellabed1dae2024-01-18 16:20:15 -050043static bool uint32list_has_next(const struct memiter *list)
44{
45 return memiter_size(list) > 0;
46}
47
48static void uint32list_get_next(struct memiter *list, uint32_t *out)
49{
50 uint64_t num;
51
52 CHECK(uint32list_has_next(list));
53 if (!fdt_parse_number(list, sizeof(uint32_t), &num)) {
54 return;
55 }
56
57 *out = (uint32_t)num;
58}
59
J-Alves35e61922021-05-06 10:01:05 +010060noreturn void abort(void)
61{
62 HFTEST_LOG("Service contained failures.");
63 /* Cause a fault, as a secondary/SP can't power down the machine. */
64 *((volatile uint8_t *)1) = 1;
65
66 /* This should never be reached, but to make the compiler happy... */
67 for (;;) {
68 }
69}
Raghu Krishnamurthy50af6602021-12-12 15:23:09 -080070
71/** Find the service with the name passed in the arguments. */
72static hftest_test_fn find_service(struct memiter *args)
73{
74 struct memiter service_name;
75 struct hftest_test *test;
76
77 if (!memiter_parse_str(args, &service_name)) {
78 return NULL;
79 }
80
81 for (test = hftest_begin; test < hftest_end; ++test) {
82 if (test->kind == HFTEST_KIND_SERVICE &&
83 memiter_iseq(&service_name, test->name)) {
84 return test->fn;
85 }
86 }
87
88 return NULL;
89}
90
J-Alvese2354862022-12-08 17:35:51 +000091void hftest_context_init(struct hftest_context *ctx, void *send, void *recv)
92{
93 memset_s(ctx, sizeof(*ctx), 0, sizeof(*ctx));
94 ctx->abort = abort;
95 ctx->send = send;
96 ctx->recv = recv;
97}
98
J-Alves3c282a32023-02-28 18:27:31 +000099/*
100 * Parse the FF-A partition's manifest.
101 * This function assumes the 'fdt' field of the passed 'ctx' has been
102 * initialized.
103 * TODO: Parse other fields as needed.
104 */
Madhukar Pappireddyae519e12024-08-20 16:16:23 -0500105void hftest_parse_ffa_manifest(struct hftest_context *ctx, struct fdt *fdt)
J-Alves3c282a32023-02-28 18:27:31 +0000106{
107 struct fdt_node root;
108 struct fdt_node ffa_node;
109 struct string mem_region_node_name = STRING_INIT("memory-regions");
Madhukar Pappireddy89226712024-01-31 14:34:46 -0600110 struct string dev_region_node_name = STRING_INIT("device-regions");
Kathleen Capellabed1dae2024-01-18 16:20:15 -0500111 struct memiter uuid;
112 uint32_t uuid_word = 0;
113 uint16_t j = 0;
114 uint16_t i = 0;
J-Alves3c282a32023-02-28 18:27:31 +0000115 uint64_t number;
116
117 CHECK(ctx != NULL);
118 CHECK(fdt != NULL);
119
120 ASSERT_TRUE(fdt_find_node(fdt, "/", &root));
121 EXPECT_TRUE(fdt_is_compatible(&root, "arm,ffa-manifest-1.0"));
122 ASSERT_TRUE(fdt_read_number(&root, "load-address",
123 &ctx->partition_manifest.load_addr));
124 EXPECT_TRUE(fdt_read_number(&root, "ffa-version", &number));
Karl Meakin133ae6e2024-04-10 12:05:36 +0100125 ctx->partition_manifest.ffa_version = number;
J-Alves3c282a32023-02-28 18:27:31 +0000126
Madhukar Pappireddy538b6882024-08-20 16:50:52 -0500127 EXPECT_TRUE(fdt_read_number(&root, "execution-ctx-count", &number));
128 ctx->partition_manifest.execution_ctx_count = (uint16_t)number;
J-Alves77b4eef2024-09-11 13:34:26 +0100129
130 EXPECT_TRUE(fdt_read_number(&root, "exception-level", &number));
131 ctx->partition_manifest.run_time_el = (uint16_t)number;
132
Kathleen Capellabed1dae2024-01-18 16:20:15 -0500133 EXPECT_TRUE(fdt_read_property(&root, "uuid", &uuid));
134
135 /* Parse UUIDs and populate uuid count.*/
136 while (uint32list_has_next(&uuid) && j < PARTITION_MAX_UUIDS) {
137 while (uint32list_has_next(&uuid) && i < 4) {
138 uint32list_get_next(&uuid, &uuid_word);
139 ctx->partition_manifest.uuids[j].uuid[i] = uuid_word;
140 i++;
141 }
142
143 EXPECT_FALSE(
144 ffa_uuid_is_null(&ctx->partition_manifest.uuids[j]));
145
146 dlog_verbose(" UUID %#x-%x-%x-%x\n",
147 ctx->partition_manifest.uuids[j].uuid[0],
148 ctx->partition_manifest.uuids[j].uuid[1],
149 ctx->partition_manifest.uuids[j].uuid[2],
150 ctx->partition_manifest.uuids[j].uuid[3]);
151 j++;
152 i = 0;
153 }
154
155 ctx->partition_manifest.uuid_count = j;
156
J-Alves3c282a32023-02-28 18:27:31 +0000157 ffa_node = root;
158
159 /* Look for the memory region node. */
160 if (fdt_find_child(&ffa_node, &mem_region_node_name) &&
161 fdt_first_child(&ffa_node)) {
162 uint32_t mem_count = 0;
163
164 do {
165 struct memory_region *cur_region =
166 &ctx->partition_manifest.mem_regions[mem_count];
167 EXPECT_TRUE(fdt_read_number(&ffa_node, "pages-count",
168 &number));
169 cur_region->page_count = (uint32_t)number;
Karl Meakinc2360152023-06-01 14:17:32 +0100170
171 if (!fdt_read_number(&ffa_node, "base-address",
172 &cur_region->base_address)) {
Davidson K8ccd2d02024-09-03 16:10:54 +0530173 EXPECT_TRUE(fdt_read_number(
174 &ffa_node,
175 "load-address-relative-offset",
176 &number));
Karl Meakinc2360152023-06-01 14:17:32 +0100177 cur_region->base_address =
178 ctx->partition_manifest.load_addr +
179 number;
180 }
181
J-Alves3c282a32023-02-28 18:27:31 +0000182 EXPECT_TRUE(fdt_read_number(&ffa_node, "attributes",
183 &number));
184 cur_region->attributes = (uint32_t)number;
185 mem_count++;
186 } while (fdt_next_sibling(&ffa_node));
187
188 assert(mem_count < PARTITION_MAX_MEMORY_REGIONS);
189
190 ctx->partition_manifest.mem_region_count = mem_count;
191 }
192
Madhukar Pappireddy89226712024-01-31 14:34:46 -0600193 ffa_node = root;
194
195 /* Look for the device region node. */
196 if (fdt_find_child(&ffa_node, &dev_region_node_name) &&
197 fdt_first_child(&ffa_node)) {
198 uint32_t dev_region_count = 0;
199
200 do {
201 struct device_region *cur_region =
202 &ctx->partition_manifest
203 .dev_regions[dev_region_count];
204 EXPECT_TRUE(fdt_read_number(&ffa_node, "pages-count",
205 &number));
206 cur_region->page_count = (uint32_t)number;
207
208 if (!fdt_read_number(&ffa_node, "base-address",
209 &cur_region->base_address)) {
Davidson K8ccd2d02024-09-03 16:10:54 +0530210 EXPECT_TRUE(fdt_read_number(
211 &ffa_node,
212 "load-address-relative-offset",
213 &number));
Madhukar Pappireddy89226712024-01-31 14:34:46 -0600214 cur_region->base_address =
215 ctx->partition_manifest.load_addr +
216 number;
217 }
218
219 EXPECT_TRUE(fdt_read_number(&ffa_node, "attributes",
220 &number));
221 cur_region->attributes = (uint32_t)number;
222 dev_region_count++;
223 } while (fdt_next_sibling(&ffa_node));
224
225 assert(dev_region_count < PARTITION_MAX_DEVICE_REGIONS);
226
227 ctx->partition_manifest.dev_region_count = dev_region_count;
228 }
229
J-Alves3c282a32023-02-28 18:27:31 +0000230 ctx->is_ffa_manifest_parsed = true;
231}
232
Madhukar Pappireddy538b6882024-08-20 16:50:52 -0500233void hftest_service_set_up(struct hftest_context *ctx, struct fdt *fdt)
Daniel Boulby792b75c2023-08-09 16:53:53 +0100234{
235 struct fdt_node node;
236 struct hftest_test *hftest_info;
237
238 ASSERT_TRUE(fdt_find_node(fdt, "/", &node));
239
240 if (!fdt_find_child(&node, &(STRING_INIT("hftest-service-setup")))) {
241 return;
242 }
243
244 EXPECT_TRUE(fdt_is_compatible(&node, "arm,hftest"));
245
246 for (hftest_info = hftest_begin; hftest_info < hftest_end;
247 ++hftest_info) {
248 struct memiter data;
249 if (hftest_info->kind != HFTEST_KIND_SERVICE_SET_UP) {
250 continue;
251 }
252 if (fdt_read_property(&node, hftest_info->name, &data)) {
253 HFTEST_LOG("Running service_setup: %s\n",
254 hftest_info->name);
255 hftest_info->fn();
256 if (ctx->failures) {
257 HFTEST_LOG_FAILURE();
258 HFTEST_LOG(HFTEST_LOG_INDENT
259 "%s service_setup failed\n",
260 hftest_info->name);
261 abort();
262 }
263 } else {
264 HFTEST_LOG("Skipping service_setup: %s\n",
265 hftest_info->name);
266 }
267 }
268}
269
Raghu Krishnamurthy50af6602021-12-12 15:23:09 -0800270noreturn void hftest_service_main(const void *fdt_ptr)
271{
J-Alves0c029c22023-06-21 10:32:57 +0100272 struct hftest_context *ctx;
Raghu Krishnamurthy50af6602021-12-12 15:23:09 -0800273 struct memiter args;
274 hftest_test_fn service;
Raghu Krishnamurthy50af6602021-12-12 15:23:09 -0800275 struct ffa_value ret;
276 struct fdt fdt;
J-Alves0c029c22023-06-21 10:32:57 +0100277 const ffa_id_t own_id = hf_vm_get_id();
J-Alves4dff3e92022-05-23 11:33:52 +0100278 ffa_notifications_bitmap_t bitmap;
J-Alves0c029c22023-06-21 10:32:57 +0100279 struct ffa_partition_msg *message;
280 uint32_t vcpu = get_current_vcpu_index();
Raghu Krishnamurthy50af6602021-12-12 15:23:09 -0800281
Daniel Boulby792b75c2023-08-09 16:53:53 +0100282 ctx = hftest_get_context();
J-Alves0c029c22023-06-21 10:32:57 +0100283
284 /* If boot vcpu, set up mailbox and intialize context abort function. */
285 if (vcpu == 0) {
286 struct mailbox_buffers mb;
287 mb = set_up_mailbox();
288 hftest_context_init(ctx, mb.send, mb.recv);
289 }
Daniel Boulby792b75c2023-08-09 16:53:53 +0100290
291 if (!fdt_struct_from_ptr(fdt_ptr, &fdt)) {
292 HFTEST_LOG(HFTEST_LOG_INDENT "Unable to access the FDT");
293 abort();
294 }
295
296 /*
297 * The memory size argument is to be used only by VMs. It is part of
298 * the dt provided by the Hypervisor. SPs expect to receive their
299 * FF-A manifest which doesn't have a memory size field.
300 */
301 if (ffa_is_vm_id(own_id) &&
302 !fdt_get_memory_size(&fdt, &ctx->memory_size)) {
303 HFTEST_LOG_FAILURE();
304 HFTEST_LOG(HFTEST_LOG_INDENT
305 "No entry in the FDT on memory size details");
306 abort();
307 } else if (!ffa_is_vm_id(own_id)) {
308 /*
309 * It is secure partition. We are currently using the partition
310 * manifest for the SP.
311 */
312 hftest_parse_ffa_manifest(ctx, &fdt);
Karl Meakin133ae6e2024-04-10 12:05:36 +0100313 stdout_init(ctx->partition_manifest.ffa_version);
Daniel Boulby792b75c2023-08-09 16:53:53 +0100314
315 /* TODO: Determine memory size referring to the SP Pkg. */
316 ctx->memory_size = 1048576;
317 }
318
J-Alves1c56a252024-08-27 17:32:58 +0100319 /* If boot vcpu, it means it is running in RTM_INIT. */
320 if (vcpu == 0) {
321 run_service_set_up(ctx, &fdt);
322 }
Daniel Boulby792b75c2023-08-09 16:53:53 +0100323
Raghu Krishnamurthy50af6602021-12-12 15:23:09 -0800324 /* Receive the name of the service to run. */
J-Alves8dacd982023-02-08 17:42:25 +0000325 ret = ffa_msg_wait();
326 EXPECT_EQ(ret.func, FFA_RUN_32);
J-Alves4dff3e92022-05-23 11:33:52 +0100327
J-Alves0c029c22023-06-21 10:32:57 +0100328 message = (struct ffa_partition_msg *)SERVICE_RECV_BUFFER();
329
J-Alves4dff3e92022-05-23 11:33:52 +0100330 /*
331 * Expect to wake up with indirect message related to the next service
332 * to be executed.
333 */
J-Alves0c029c22023-06-21 10:32:57 +0100334 ret = ffa_notification_get(own_id, vcpu,
J-Alves4dff3e92022-05-23 11:33:52 +0100335 FFA_NOTIFICATION_FLAG_BITMAP_SPM |
336 FFA_NOTIFICATION_FLAG_BITMAP_HYP);
337 ASSERT_EQ(ret.func, FFA_SUCCESS_32);
338 bitmap = ffa_notification_get_from_framework(ret);
339 ASSERT_TRUE(is_ffa_spm_buffer_full_notification(bitmap) ||
340 is_ffa_hyp_buffer_full_notification(bitmap));
341 ASSERT_EQ(own_id, ffa_rxtx_header_receiver(&message->header));
J-Alves77b4eef2024-09-11 13:34:26 +0100342
343 if (ctx->is_ffa_manifest_parsed &&
344 ctx->partition_manifest.run_time_el == S_EL1) {
345 ASSERT_EQ(hf_interrupt_get(), HF_NOTIFICATION_PENDING_INTID);
346 }
347
J-Alves4dff3e92022-05-23 11:33:52 +0100348 memiter_init(&args, message->payload, message->header.size);
349
350 /* Find service handler. */
Raghu Krishnamurthy50af6602021-12-12 15:23:09 -0800351 service = find_service(&args);
352 EXPECT_EQ(ffa_rx_release().func, FFA_SUCCESS_32);
353
354 /* Check the service was found. */
355 if (service == NULL) {
356 HFTEST_LOG_FAILURE();
357 HFTEST_LOG(HFTEST_LOG_INDENT
358 "Unable to find requested service");
359 abort();
360 }
361
Raghu Krishnamurthy50af6602021-12-12 15:23:09 -0800362 /* Pause so the next time cycles are given the service will be run. */
363 ffa_yield();
364
365 /* Let the service run. */
366 service();
367
368 /* Cleanly handle it if the service returns. */
369 if (ctx->failures) {
370 abort();
371 }
372
373 for (;;) {
374 /* Hang if the service returns. */
375 }
376}
Madhukar Pappireddy29235ec2022-12-22 10:18:41 -0600377
J-Alves19e20cf2023-08-02 12:48:55 +0100378ffa_id_t hftest_get_dir_req_source_id(void)
Madhukar Pappireddy29235ec2022-12-22 10:18:41 -0600379{
380 struct hftest_context *ctx = hftest_get_context();
381 return ctx->dir_req_source_id;
382}
383
J-Alves19e20cf2023-08-02 12:48:55 +0100384void hftest_set_dir_req_source_id(ffa_id_t id)
Madhukar Pappireddy29235ec2022-12-22 10:18:41 -0600385{
386 struct hftest_context *ctx = hftest_get_context();
387 ctx->dir_req_source_id = id;
388}
Madhukar Pappireddyae519e12024-08-20 16:16:23 -0500389
390void hftest_map_device_regions(struct hftest_context *ctx)
391{
392 struct device_region *dev_region;
393 uint32_t dev_region_count;
394
395 /*
396 * The running partition must have received and parsed its own
397 * partition manifest by now.
398 */
399 if (!ctx || !ctx->is_ffa_manifest_parsed) {
400 panic("Partition manifest not parsed.\n");
401 }
402
403 dev_region_count = ctx->partition_manifest.dev_region_count;
404
405 /* Map the MMIO address space of the devices. */
406 for (uint32_t i = 0; i < dev_region_count; i++) {
407 dev_region = &ctx->partition_manifest.dev_regions[i];
408
409 hftest_mm_identity_map(
410 // NOLINTNEXTLINE(performance-no-int-to-ptr)
411 (const void *)dev_region->base_address,
412 dev_region->page_count * PAGE_SIZE,
413 dev_region->attributes);
414 }
415}