blob: 214aefde2aa91ccff71229b6cc9ea6407e2d99b0 [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"
15
Raghu Krishnamurthy50af6602021-12-12 15:23:09 -080016#include "vmapi/hf/call.h"
17
J-Alves35e61922021-05-06 10:01:05 +010018#include "test/hftest.h"
19#include "test/hftest_impl.h"
J-Alves4dff3e92022-05-23 11:33:52 +010020#include "test/vmapi/ffa.h"
J-Alves35e61922021-05-06 10:01:05 +010021
22HFTEST_ENABLE();
23
Raghu Krishnamurthy50af6602021-12-12 15:23:09 -080024extern struct hftest_test hftest_begin[];
25extern struct hftest_test hftest_end[];
26
J-Alves35e61922021-05-06 10:01:05 +010027static struct hftest_context global_context;
28
29struct hftest_context *hftest_get_context(void)
30{
31 return &global_context;
32}
33
Kathleen Capellabed1dae2024-01-18 16:20:15 -050034static bool uint32list_has_next(const struct memiter *list)
35{
36 return memiter_size(list) > 0;
37}
38
39static void uint32list_get_next(struct memiter *list, uint32_t *out)
40{
41 uint64_t num;
42
43 CHECK(uint32list_has_next(list));
44 if (!fdt_parse_number(list, sizeof(uint32_t), &num)) {
45 return;
46 }
47
48 *out = (uint32_t)num;
49}
50
J-Alves35e61922021-05-06 10:01:05 +010051noreturn void abort(void)
52{
53 HFTEST_LOG("Service contained failures.");
54 /* Cause a fault, as a secondary/SP can't power down the machine. */
55 *((volatile uint8_t *)1) = 1;
56
57 /* This should never be reached, but to make the compiler happy... */
58 for (;;) {
59 }
60}
Raghu Krishnamurthy50af6602021-12-12 15:23:09 -080061
62/** Find the service with the name passed in the arguments. */
63static hftest_test_fn find_service(struct memiter *args)
64{
65 struct memiter service_name;
66 struct hftest_test *test;
67
68 if (!memiter_parse_str(args, &service_name)) {
69 return NULL;
70 }
71
72 for (test = hftest_begin; test < hftest_end; ++test) {
73 if (test->kind == HFTEST_KIND_SERVICE &&
74 memiter_iseq(&service_name, test->name)) {
75 return test->fn;
76 }
77 }
78
79 return NULL;
80}
81
J-Alvese2354862022-12-08 17:35:51 +000082void hftest_context_init(struct hftest_context *ctx, void *send, void *recv)
83{
84 memset_s(ctx, sizeof(*ctx), 0, sizeof(*ctx));
85 ctx->abort = abort;
86 ctx->send = send;
87 ctx->recv = recv;
88}
89
J-Alves3c282a32023-02-28 18:27:31 +000090/*
91 * Parse the FF-A partition's manifest.
92 * This function assumes the 'fdt' field of the passed 'ctx' has been
93 * initialized.
94 * TODO: Parse other fields as needed.
95 */
96static void hftest_parse_ffa_manifest(struct hftest_context *ctx,
97 struct fdt *fdt)
98{
99 struct fdt_node root;
100 struct fdt_node ffa_node;
101 struct string mem_region_node_name = STRING_INIT("memory-regions");
Madhukar Pappireddy89226712024-01-31 14:34:46 -0600102 struct string dev_region_node_name = STRING_INIT("device-regions");
Kathleen Capellabed1dae2024-01-18 16:20:15 -0500103 struct memiter uuid;
104 uint32_t uuid_word = 0;
105 uint16_t j = 0;
106 uint16_t i = 0;
J-Alves3c282a32023-02-28 18:27:31 +0000107 uint64_t number;
108
109 CHECK(ctx != NULL);
110 CHECK(fdt != NULL);
111
112 ASSERT_TRUE(fdt_find_node(fdt, "/", &root));
113 EXPECT_TRUE(fdt_is_compatible(&root, "arm,ffa-manifest-1.0"));
114 ASSERT_TRUE(fdt_read_number(&root, "load-address",
115 &ctx->partition_manifest.load_addr));
116 EXPECT_TRUE(fdt_read_number(&root, "ffa-version", &number));
117
Kathleen Capellabed1dae2024-01-18 16:20:15 -0500118 EXPECT_TRUE(fdt_read_property(&root, "uuid", &uuid));
119
120 /* Parse UUIDs and populate uuid count.*/
121 while (uint32list_has_next(&uuid) && j < PARTITION_MAX_UUIDS) {
122 while (uint32list_has_next(&uuid) && i < 4) {
123 uint32list_get_next(&uuid, &uuid_word);
124 ctx->partition_manifest.uuids[j].uuid[i] = uuid_word;
125 i++;
126 }
127
128 EXPECT_FALSE(
129 ffa_uuid_is_null(&ctx->partition_manifest.uuids[j]));
130
131 dlog_verbose(" UUID %#x-%x-%x-%x\n",
132 ctx->partition_manifest.uuids[j].uuid[0],
133 ctx->partition_manifest.uuids[j].uuid[1],
134 ctx->partition_manifest.uuids[j].uuid[2],
135 ctx->partition_manifest.uuids[j].uuid[3]);
136 j++;
137 i = 0;
138 }
139
140 ctx->partition_manifest.uuid_count = j;
141
J-Alves3c282a32023-02-28 18:27:31 +0000142 ffa_node = root;
143
144 /* Look for the memory region node. */
145 if (fdt_find_child(&ffa_node, &mem_region_node_name) &&
146 fdt_first_child(&ffa_node)) {
147 uint32_t mem_count = 0;
148
149 do {
150 struct memory_region *cur_region =
151 &ctx->partition_manifest.mem_regions[mem_count];
152 EXPECT_TRUE(fdt_read_number(&ffa_node, "pages-count",
153 &number));
154 cur_region->page_count = (uint32_t)number;
Karl Meakinc2360152023-06-01 14:17:32 +0100155
156 if (!fdt_read_number(&ffa_node, "base-address",
157 &cur_region->base_address)) {
158 EXPECT_TRUE(fdt_read_number(&ffa_node,
159 "relative-address",
160 &number));
161 cur_region->base_address =
162 ctx->partition_manifest.load_addr +
163 number;
164 }
165
J-Alves3c282a32023-02-28 18:27:31 +0000166 EXPECT_TRUE(fdt_read_number(&ffa_node, "attributes",
167 &number));
168 cur_region->attributes = (uint32_t)number;
169 mem_count++;
170 } while (fdt_next_sibling(&ffa_node));
171
172 assert(mem_count < PARTITION_MAX_MEMORY_REGIONS);
173
174 ctx->partition_manifest.mem_region_count = mem_count;
175 }
176
Madhukar Pappireddy89226712024-01-31 14:34:46 -0600177 ffa_node = root;
178
179 /* Look for the device region node. */
180 if (fdt_find_child(&ffa_node, &dev_region_node_name) &&
181 fdt_first_child(&ffa_node)) {
182 uint32_t dev_region_count = 0;
183
184 do {
185 struct device_region *cur_region =
186 &ctx->partition_manifest
187 .dev_regions[dev_region_count];
188 EXPECT_TRUE(fdt_read_number(&ffa_node, "pages-count",
189 &number));
190 cur_region->page_count = (uint32_t)number;
191
192 if (!fdt_read_number(&ffa_node, "base-address",
193 &cur_region->base_address)) {
194 EXPECT_TRUE(fdt_read_number(&ffa_node,
195 "relative-address",
196 &number));
197 cur_region->base_address =
198 ctx->partition_manifest.load_addr +
199 number;
200 }
201
202 EXPECT_TRUE(fdt_read_number(&ffa_node, "attributes",
203 &number));
204 cur_region->attributes = (uint32_t)number;
205 dev_region_count++;
206 } while (fdt_next_sibling(&ffa_node));
207
208 assert(dev_region_count < PARTITION_MAX_DEVICE_REGIONS);
209
210 ctx->partition_manifest.dev_region_count = dev_region_count;
211 }
212
J-Alves3c282a32023-02-28 18:27:31 +0000213 ctx->is_ffa_manifest_parsed = true;
214}
215
Daniel Boulby792b75c2023-08-09 16:53:53 +0100216static void run_service_set_up(struct hftest_context *ctx, struct fdt *fdt)
217{
218 struct fdt_node node;
219 struct hftest_test *hftest_info;
220
221 ASSERT_TRUE(fdt_find_node(fdt, "/", &node));
222
223 if (!fdt_find_child(&node, &(STRING_INIT("hftest-service-setup")))) {
224 return;
225 }
226
227 EXPECT_TRUE(fdt_is_compatible(&node, "arm,hftest"));
228
229 for (hftest_info = hftest_begin; hftest_info < hftest_end;
230 ++hftest_info) {
231 struct memiter data;
232 if (hftest_info->kind != HFTEST_KIND_SERVICE_SET_UP) {
233 continue;
234 }
235 if (fdt_read_property(&node, hftest_info->name, &data)) {
236 HFTEST_LOG("Running service_setup: %s\n",
237 hftest_info->name);
238 hftest_info->fn();
239 if (ctx->failures) {
240 HFTEST_LOG_FAILURE();
241 HFTEST_LOG(HFTEST_LOG_INDENT
242 "%s service_setup failed\n",
243 hftest_info->name);
244 abort();
245 }
246 } else {
247 HFTEST_LOG("Skipping service_setup: %s\n",
248 hftest_info->name);
249 }
250 }
251}
252
Raghu Krishnamurthy50af6602021-12-12 15:23:09 -0800253noreturn void hftest_service_main(const void *fdt_ptr)
254{
255 struct memiter args;
256 hftest_test_fn service;
257 struct hftest_context *ctx;
258 struct ffa_value ret;
259 struct fdt fdt;
J-Alves19e20cf2023-08-02 12:48:55 +0100260 ffa_id_t own_id = hf_vm_get_id();
J-Alves4dff3e92022-05-23 11:33:52 +0100261 struct mailbox_buffers mb = set_up_mailbox();
262 ffa_notifications_bitmap_t bitmap;
263 struct ffa_partition_msg *message = (struct ffa_partition_msg *)mb.recv;
Raghu Krishnamurthy50af6602021-12-12 15:23:09 -0800264
Daniel Boulby792b75c2023-08-09 16:53:53 +0100265 /* Clean the context. */
266 ctx = hftest_get_context();
267 hftest_context_init(ctx, mb.send, mb.recv);
268
269 if (!fdt_struct_from_ptr(fdt_ptr, &fdt)) {
270 HFTEST_LOG(HFTEST_LOG_INDENT "Unable to access the FDT");
271 abort();
272 }
273
274 /*
275 * The memory size argument is to be used only by VMs. It is part of
276 * the dt provided by the Hypervisor. SPs expect to receive their
277 * FF-A manifest which doesn't have a memory size field.
278 */
279 if (ffa_is_vm_id(own_id) &&
280 !fdt_get_memory_size(&fdt, &ctx->memory_size)) {
281 HFTEST_LOG_FAILURE();
282 HFTEST_LOG(HFTEST_LOG_INDENT
283 "No entry in the FDT on memory size details");
284 abort();
285 } else if (!ffa_is_vm_id(own_id)) {
286 /*
287 * It is secure partition. We are currently using the partition
288 * manifest for the SP.
289 */
290 hftest_parse_ffa_manifest(ctx, &fdt);
291
292 /* TODO: Determine memory size referring to the SP Pkg. */
293 ctx->memory_size = 1048576;
294 }
295
296 run_service_set_up(ctx, &fdt);
297
Raghu Krishnamurthy50af6602021-12-12 15:23:09 -0800298 /* Receive the name of the service to run. */
J-Alves8dacd982023-02-08 17:42:25 +0000299 ret = ffa_msg_wait();
300 EXPECT_EQ(ret.func, FFA_RUN_32);
J-Alves4dff3e92022-05-23 11:33:52 +0100301
302 /*
303 * Expect to wake up with indirect message related to the next service
304 * to be executed.
305 */
306 ret = ffa_notification_get(own_id, 0,
307 FFA_NOTIFICATION_FLAG_BITMAP_SPM |
308 FFA_NOTIFICATION_FLAG_BITMAP_HYP);
309 ASSERT_EQ(ret.func, FFA_SUCCESS_32);
310 bitmap = ffa_notification_get_from_framework(ret);
311 ASSERT_TRUE(is_ffa_spm_buffer_full_notification(bitmap) ||
312 is_ffa_hyp_buffer_full_notification(bitmap));
313 ASSERT_EQ(own_id, ffa_rxtx_header_receiver(&message->header));
314 memiter_init(&args, message->payload, message->header.size);
315
316 /* Find service handler. */
Raghu Krishnamurthy50af6602021-12-12 15:23:09 -0800317 service = find_service(&args);
318 EXPECT_EQ(ffa_rx_release().func, FFA_SUCCESS_32);
319
320 /* Check the service was found. */
321 if (service == NULL) {
322 HFTEST_LOG_FAILURE();
323 HFTEST_LOG(HFTEST_LOG_INDENT
324 "Unable to find requested service");
325 abort();
326 }
327
Raghu Krishnamurthy50af6602021-12-12 15:23:09 -0800328 /* Pause so the next time cycles are given the service will be run. */
329 ffa_yield();
330
331 /* Let the service run. */
332 service();
333
334 /* Cleanly handle it if the service returns. */
335 if (ctx->failures) {
336 abort();
337 }
338
339 for (;;) {
340 /* Hang if the service returns. */
341 }
342}
Madhukar Pappireddy29235ec2022-12-22 10:18:41 -0600343
J-Alves19e20cf2023-08-02 12:48:55 +0100344ffa_id_t hftest_get_dir_req_source_id(void)
Madhukar Pappireddy29235ec2022-12-22 10:18:41 -0600345{
346 struct hftest_context *ctx = hftest_get_context();
347 return ctx->dir_req_source_id;
348}
349
J-Alves19e20cf2023-08-02 12:48:55 +0100350void hftest_set_dir_req_source_id(ffa_id_t id)
Madhukar Pappireddy29235ec2022-12-22 10:18:41 -0600351{
352 struct hftest_context *ctx = hftest_get_context();
353 ctx->dir_req_source_id = id;
354}