blob: b277b383a7fd90fa7d3cfff39e0104258ebfcf48 [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
25HFTEST_ENABLE();
26
Raghu Krishnamurthy50af6602021-12-12 15:23:09 -080027extern struct hftest_test hftest_begin[];
28extern struct hftest_test hftest_end[];
29
J-Alves35e61922021-05-06 10:01:05 +010030static struct hftest_context global_context;
31
32struct hftest_context *hftest_get_context(void)
33{
34 return &global_context;
35}
36
Kathleen Capellabed1dae2024-01-18 16:20:15 -050037static bool uint32list_has_next(const struct memiter *list)
38{
39 return memiter_size(list) > 0;
40}
41
42static void uint32list_get_next(struct memiter *list, uint32_t *out)
43{
44 uint64_t num;
45
46 CHECK(uint32list_has_next(list));
47 if (!fdt_parse_number(list, sizeof(uint32_t), &num)) {
48 return;
49 }
50
51 *out = (uint32_t)num;
52}
53
J-Alves35e61922021-05-06 10:01:05 +010054noreturn void abort(void)
55{
56 HFTEST_LOG("Service contained failures.");
57 /* Cause a fault, as a secondary/SP can't power down the machine. */
58 *((volatile uint8_t *)1) = 1;
59
60 /* This should never be reached, but to make the compiler happy... */
61 for (;;) {
62 }
63}
Raghu Krishnamurthy50af6602021-12-12 15:23:09 -080064
65/** Find the service with the name passed in the arguments. */
66static hftest_test_fn find_service(struct memiter *args)
67{
68 struct memiter service_name;
69 struct hftest_test *test;
70
71 if (!memiter_parse_str(args, &service_name)) {
72 return NULL;
73 }
74
75 for (test = hftest_begin; test < hftest_end; ++test) {
76 if (test->kind == HFTEST_KIND_SERVICE &&
77 memiter_iseq(&service_name, test->name)) {
78 return test->fn;
79 }
80 }
81
82 return NULL;
83}
84
J-Alvese2354862022-12-08 17:35:51 +000085void hftest_context_init(struct hftest_context *ctx, void *send, void *recv)
86{
87 memset_s(ctx, sizeof(*ctx), 0, sizeof(*ctx));
88 ctx->abort = abort;
89 ctx->send = send;
90 ctx->recv = recv;
91}
92
J-Alves3c282a32023-02-28 18:27:31 +000093/*
94 * Parse the FF-A partition's manifest.
95 * This function assumes the 'fdt' field of the passed 'ctx' has been
96 * initialized.
97 * TODO: Parse other fields as needed.
98 */
99static void hftest_parse_ffa_manifest(struct hftest_context *ctx,
100 struct fdt *fdt)
101{
102 struct fdt_node root;
103 struct fdt_node ffa_node;
104 struct string mem_region_node_name = STRING_INIT("memory-regions");
Madhukar Pappireddy89226712024-01-31 14:34:46 -0600105 struct string dev_region_node_name = STRING_INIT("device-regions");
Kathleen Capellabed1dae2024-01-18 16:20:15 -0500106 struct memiter uuid;
107 uint32_t uuid_word = 0;
108 uint16_t j = 0;
109 uint16_t i = 0;
J-Alves3c282a32023-02-28 18:27:31 +0000110 uint64_t number;
111
112 CHECK(ctx != NULL);
113 CHECK(fdt != NULL);
114
115 ASSERT_TRUE(fdt_find_node(fdt, "/", &root));
116 EXPECT_TRUE(fdt_is_compatible(&root, "arm,ffa-manifest-1.0"));
117 ASSERT_TRUE(fdt_read_number(&root, "load-address",
118 &ctx->partition_manifest.load_addr));
119 EXPECT_TRUE(fdt_read_number(&root, "ffa-version", &number));
Karl Meakin133ae6e2024-04-10 12:05:36 +0100120 ctx->partition_manifest.ffa_version = number;
J-Alves3c282a32023-02-28 18:27:31 +0000121
Kathleen Capellabed1dae2024-01-18 16:20:15 -0500122 EXPECT_TRUE(fdt_read_property(&root, "uuid", &uuid));
123
124 /* Parse UUIDs and populate uuid count.*/
125 while (uint32list_has_next(&uuid) && j < PARTITION_MAX_UUIDS) {
126 while (uint32list_has_next(&uuid) && i < 4) {
127 uint32list_get_next(&uuid, &uuid_word);
128 ctx->partition_manifest.uuids[j].uuid[i] = uuid_word;
129 i++;
130 }
131
132 EXPECT_FALSE(
133 ffa_uuid_is_null(&ctx->partition_manifest.uuids[j]));
134
135 dlog_verbose(" UUID %#x-%x-%x-%x\n",
136 ctx->partition_manifest.uuids[j].uuid[0],
137 ctx->partition_manifest.uuids[j].uuid[1],
138 ctx->partition_manifest.uuids[j].uuid[2],
139 ctx->partition_manifest.uuids[j].uuid[3]);
140 j++;
141 i = 0;
142 }
143
144 ctx->partition_manifest.uuid_count = j;
145
J-Alves3c282a32023-02-28 18:27:31 +0000146 ffa_node = root;
147
148 /* Look for the memory region node. */
149 if (fdt_find_child(&ffa_node, &mem_region_node_name) &&
150 fdt_first_child(&ffa_node)) {
151 uint32_t mem_count = 0;
152
153 do {
154 struct memory_region *cur_region =
155 &ctx->partition_manifest.mem_regions[mem_count];
156 EXPECT_TRUE(fdt_read_number(&ffa_node, "pages-count",
157 &number));
158 cur_region->page_count = (uint32_t)number;
Karl Meakinc2360152023-06-01 14:17:32 +0100159
160 if (!fdt_read_number(&ffa_node, "base-address",
161 &cur_region->base_address)) {
162 EXPECT_TRUE(fdt_read_number(&ffa_node,
163 "relative-address",
164 &number));
165 cur_region->base_address =
166 ctx->partition_manifest.load_addr +
167 number;
168 }
169
J-Alves3c282a32023-02-28 18:27:31 +0000170 EXPECT_TRUE(fdt_read_number(&ffa_node, "attributes",
171 &number));
172 cur_region->attributes = (uint32_t)number;
173 mem_count++;
174 } while (fdt_next_sibling(&ffa_node));
175
176 assert(mem_count < PARTITION_MAX_MEMORY_REGIONS);
177
178 ctx->partition_manifest.mem_region_count = mem_count;
179 }
180
Madhukar Pappireddy89226712024-01-31 14:34:46 -0600181 ffa_node = root;
182
183 /* Look for the device region node. */
184 if (fdt_find_child(&ffa_node, &dev_region_node_name) &&
185 fdt_first_child(&ffa_node)) {
186 uint32_t dev_region_count = 0;
187
188 do {
189 struct device_region *cur_region =
190 &ctx->partition_manifest
191 .dev_regions[dev_region_count];
192 EXPECT_TRUE(fdt_read_number(&ffa_node, "pages-count",
193 &number));
194 cur_region->page_count = (uint32_t)number;
195
196 if (!fdt_read_number(&ffa_node, "base-address",
197 &cur_region->base_address)) {
198 EXPECT_TRUE(fdt_read_number(&ffa_node,
199 "relative-address",
200 &number));
201 cur_region->base_address =
202 ctx->partition_manifest.load_addr +
203 number;
204 }
205
206 EXPECT_TRUE(fdt_read_number(&ffa_node, "attributes",
207 &number));
208 cur_region->attributes = (uint32_t)number;
209 dev_region_count++;
210 } while (fdt_next_sibling(&ffa_node));
211
212 assert(dev_region_count < PARTITION_MAX_DEVICE_REGIONS);
213
214 ctx->partition_manifest.dev_region_count = dev_region_count;
215 }
216
J-Alves3c282a32023-02-28 18:27:31 +0000217 ctx->is_ffa_manifest_parsed = true;
218}
219
Daniel Boulby792b75c2023-08-09 16:53:53 +0100220static void run_service_set_up(struct hftest_context *ctx, struct fdt *fdt)
221{
222 struct fdt_node node;
223 struct hftest_test *hftest_info;
224
225 ASSERT_TRUE(fdt_find_node(fdt, "/", &node));
226
227 if (!fdt_find_child(&node, &(STRING_INIT("hftest-service-setup")))) {
228 return;
229 }
230
231 EXPECT_TRUE(fdt_is_compatible(&node, "arm,hftest"));
232
233 for (hftest_info = hftest_begin; hftest_info < hftest_end;
234 ++hftest_info) {
235 struct memiter data;
236 if (hftest_info->kind != HFTEST_KIND_SERVICE_SET_UP) {
237 continue;
238 }
239 if (fdt_read_property(&node, hftest_info->name, &data)) {
240 HFTEST_LOG("Running service_setup: %s\n",
241 hftest_info->name);
242 hftest_info->fn();
243 if (ctx->failures) {
244 HFTEST_LOG_FAILURE();
245 HFTEST_LOG(HFTEST_LOG_INDENT
246 "%s service_setup failed\n",
247 hftest_info->name);
248 abort();
249 }
250 } else {
251 HFTEST_LOG("Skipping service_setup: %s\n",
252 hftest_info->name);
253 }
254 }
255}
256
Raghu Krishnamurthy50af6602021-12-12 15:23:09 -0800257noreturn void hftest_service_main(const void *fdt_ptr)
258{
J-Alves0c029c22023-06-21 10:32:57 +0100259 struct hftest_context *ctx;
Raghu Krishnamurthy50af6602021-12-12 15:23:09 -0800260 struct memiter args;
261 hftest_test_fn service;
Raghu Krishnamurthy50af6602021-12-12 15:23:09 -0800262 struct ffa_value ret;
263 struct fdt fdt;
J-Alves0c029c22023-06-21 10:32:57 +0100264 const ffa_id_t own_id = hf_vm_get_id();
J-Alves4dff3e92022-05-23 11:33:52 +0100265 ffa_notifications_bitmap_t bitmap;
J-Alves0c029c22023-06-21 10:32:57 +0100266 struct ffa_partition_msg *message;
267 uint32_t vcpu = get_current_vcpu_index();
Raghu Krishnamurthy50af6602021-12-12 15:23:09 -0800268
Daniel Boulby792b75c2023-08-09 16:53:53 +0100269 ctx = hftest_get_context();
J-Alves0c029c22023-06-21 10:32:57 +0100270
271 /* If boot vcpu, set up mailbox and intialize context abort function. */
272 if (vcpu == 0) {
273 struct mailbox_buffers mb;
274 mb = set_up_mailbox();
275 hftest_context_init(ctx, mb.send, mb.recv);
276 }
Daniel Boulby792b75c2023-08-09 16:53:53 +0100277
278 if (!fdt_struct_from_ptr(fdt_ptr, &fdt)) {
279 HFTEST_LOG(HFTEST_LOG_INDENT "Unable to access the FDT");
280 abort();
281 }
282
283 /*
284 * The memory size argument is to be used only by VMs. It is part of
285 * the dt provided by the Hypervisor. SPs expect to receive their
286 * FF-A manifest which doesn't have a memory size field.
287 */
288 if (ffa_is_vm_id(own_id) &&
289 !fdt_get_memory_size(&fdt, &ctx->memory_size)) {
290 HFTEST_LOG_FAILURE();
291 HFTEST_LOG(HFTEST_LOG_INDENT
292 "No entry in the FDT on memory size details");
293 abort();
294 } else if (!ffa_is_vm_id(own_id)) {
295 /*
296 * It is secure partition. We are currently using the partition
297 * manifest for the SP.
298 */
299 hftest_parse_ffa_manifest(ctx, &fdt);
Karl Meakin133ae6e2024-04-10 12:05:36 +0100300 stdout_init(ctx->partition_manifest.ffa_version);
Daniel Boulby792b75c2023-08-09 16:53:53 +0100301
302 /* TODO: Determine memory size referring to the SP Pkg. */
303 ctx->memory_size = 1048576;
304 }
305
306 run_service_set_up(ctx, &fdt);
307
Raghu Krishnamurthy50af6602021-12-12 15:23:09 -0800308 /* Receive the name of the service to run. */
J-Alves8dacd982023-02-08 17:42:25 +0000309 ret = ffa_msg_wait();
310 EXPECT_EQ(ret.func, FFA_RUN_32);
J-Alves4dff3e92022-05-23 11:33:52 +0100311
J-Alves0c029c22023-06-21 10:32:57 +0100312 message = (struct ffa_partition_msg *)SERVICE_RECV_BUFFER();
313
J-Alves4dff3e92022-05-23 11:33:52 +0100314 /*
315 * Expect to wake up with indirect message related to the next service
316 * to be executed.
317 */
J-Alves0c029c22023-06-21 10:32:57 +0100318 ret = ffa_notification_get(own_id, vcpu,
J-Alves4dff3e92022-05-23 11:33:52 +0100319 FFA_NOTIFICATION_FLAG_BITMAP_SPM |
320 FFA_NOTIFICATION_FLAG_BITMAP_HYP);
321 ASSERT_EQ(ret.func, FFA_SUCCESS_32);
322 bitmap = ffa_notification_get_from_framework(ret);
323 ASSERT_TRUE(is_ffa_spm_buffer_full_notification(bitmap) ||
324 is_ffa_hyp_buffer_full_notification(bitmap));
325 ASSERT_EQ(own_id, ffa_rxtx_header_receiver(&message->header));
326 memiter_init(&args, message->payload, message->header.size);
327
328 /* Find service handler. */
Raghu Krishnamurthy50af6602021-12-12 15:23:09 -0800329 service = find_service(&args);
330 EXPECT_EQ(ffa_rx_release().func, FFA_SUCCESS_32);
331
332 /* Check the service was found. */
333 if (service == NULL) {
334 HFTEST_LOG_FAILURE();
335 HFTEST_LOG(HFTEST_LOG_INDENT
336 "Unable to find requested service");
337 abort();
338 }
339
Raghu Krishnamurthy50af6602021-12-12 15:23:09 -0800340 /* Pause so the next time cycles are given the service will be run. */
341 ffa_yield();
342
343 /* Let the service run. */
344 service();
345
346 /* Cleanly handle it if the service returns. */
347 if (ctx->failures) {
348 abort();
349 }
350
351 for (;;) {
352 /* Hang if the service returns. */
353 }
354}
Madhukar Pappireddy29235ec2022-12-22 10:18:41 -0600355
J-Alves19e20cf2023-08-02 12:48:55 +0100356ffa_id_t hftest_get_dir_req_source_id(void)
Madhukar Pappireddy29235ec2022-12-22 10:18:41 -0600357{
358 struct hftest_context *ctx = hftest_get_context();
359 return ctx->dir_req_source_id;
360}
361
J-Alves19e20cf2023-08-02 12:48:55 +0100362void hftest_set_dir_req_source_id(ffa_id_t id)
Madhukar Pappireddy29235ec2022-12-22 10:18:41 -0600363{
364 struct hftest_context *ctx = hftest_get_context();
365 ctx->dir_req_source_id = id;
366}