blob: d9b91d2e0f86ba5d6d936ed48b5d66df8db0cb5e [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-Alves0c029c22023-06-21 10:32:57 +010018#include "../msr.h"
J-Alves35e61922021-05-06 10:01:05 +010019#include "test/hftest.h"
20#include "test/hftest_impl.h"
J-Alves0c029c22023-06-21 10:32:57 +010021#include "test/vmapi/arch/exception_handler.h"
J-Alves4dff3e92022-05-23 11:33:52 +010022#include "test/vmapi/ffa.h"
J-Alves35e61922021-05-06 10:01:05 +010023
24HFTEST_ENABLE();
25
Raghu Krishnamurthy50af6602021-12-12 15:23:09 -080026extern struct hftest_test hftest_begin[];
27extern struct hftest_test hftest_end[];
28
J-Alves35e61922021-05-06 10:01:05 +010029static struct hftest_context global_context;
30
31struct hftest_context *hftest_get_context(void)
32{
33 return &global_context;
34}
35
Kathleen Capellabed1dae2024-01-18 16:20:15 -050036static bool uint32list_has_next(const struct memiter *list)
37{
38 return memiter_size(list) > 0;
39}
40
41static void uint32list_get_next(struct memiter *list, uint32_t *out)
42{
43 uint64_t num;
44
45 CHECK(uint32list_has_next(list));
46 if (!fdt_parse_number(list, sizeof(uint32_t), &num)) {
47 return;
48 }
49
50 *out = (uint32_t)num;
51}
52
J-Alves35e61922021-05-06 10:01:05 +010053noreturn void abort(void)
54{
55 HFTEST_LOG("Service contained failures.");
56 /* Cause a fault, as a secondary/SP can't power down the machine. */
57 *((volatile uint8_t *)1) = 1;
58
59 /* This should never be reached, but to make the compiler happy... */
60 for (;;) {
61 }
62}
Raghu Krishnamurthy50af6602021-12-12 15:23:09 -080063
64/** Find the service with the name passed in the arguments. */
65static hftest_test_fn find_service(struct memiter *args)
66{
67 struct memiter service_name;
68 struct hftest_test *test;
69
70 if (!memiter_parse_str(args, &service_name)) {
71 return NULL;
72 }
73
74 for (test = hftest_begin; test < hftest_end; ++test) {
75 if (test->kind == HFTEST_KIND_SERVICE &&
76 memiter_iseq(&service_name, test->name)) {
77 return test->fn;
78 }
79 }
80
81 return NULL;
82}
83
J-Alvese2354862022-12-08 17:35:51 +000084void hftest_context_init(struct hftest_context *ctx, void *send, void *recv)
85{
86 memset_s(ctx, sizeof(*ctx), 0, sizeof(*ctx));
87 ctx->abort = abort;
88 ctx->send = send;
89 ctx->recv = recv;
90}
91
J-Alves3c282a32023-02-28 18:27:31 +000092/*
93 * Parse the FF-A partition's manifest.
94 * This function assumes the 'fdt' field of the passed 'ctx' has been
95 * initialized.
96 * TODO: Parse other fields as needed.
97 */
98static void hftest_parse_ffa_manifest(struct hftest_context *ctx,
99 struct fdt *fdt)
100{
101 struct fdt_node root;
102 struct fdt_node ffa_node;
103 struct string mem_region_node_name = STRING_INIT("memory-regions");
Madhukar Pappireddy89226712024-01-31 14:34:46 -0600104 struct string dev_region_node_name = STRING_INIT("device-regions");
Kathleen Capellabed1dae2024-01-18 16:20:15 -0500105 struct memiter uuid;
106 uint32_t uuid_word = 0;
107 uint16_t j = 0;
108 uint16_t i = 0;
J-Alves3c282a32023-02-28 18:27:31 +0000109 uint64_t number;
110
111 CHECK(ctx != NULL);
112 CHECK(fdt != NULL);
113
114 ASSERT_TRUE(fdt_find_node(fdt, "/", &root));
115 EXPECT_TRUE(fdt_is_compatible(&root, "arm,ffa-manifest-1.0"));
116 ASSERT_TRUE(fdt_read_number(&root, "load-address",
117 &ctx->partition_manifest.load_addr));
118 EXPECT_TRUE(fdt_read_number(&root, "ffa-version", &number));
119
Kathleen Capellabed1dae2024-01-18 16:20:15 -0500120 EXPECT_TRUE(fdt_read_property(&root, "uuid", &uuid));
121
122 /* Parse UUIDs and populate uuid count.*/
123 while (uint32list_has_next(&uuid) && j < PARTITION_MAX_UUIDS) {
124 while (uint32list_has_next(&uuid) && i < 4) {
125 uint32list_get_next(&uuid, &uuid_word);
126 ctx->partition_manifest.uuids[j].uuid[i] = uuid_word;
127 i++;
128 }
129
130 EXPECT_FALSE(
131 ffa_uuid_is_null(&ctx->partition_manifest.uuids[j]));
132
133 dlog_verbose(" UUID %#x-%x-%x-%x\n",
134 ctx->partition_manifest.uuids[j].uuid[0],
135 ctx->partition_manifest.uuids[j].uuid[1],
136 ctx->partition_manifest.uuids[j].uuid[2],
137 ctx->partition_manifest.uuids[j].uuid[3]);
138 j++;
139 i = 0;
140 }
141
142 ctx->partition_manifest.uuid_count = j;
143
J-Alves3c282a32023-02-28 18:27:31 +0000144 ffa_node = root;
145
146 /* Look for the memory region node. */
147 if (fdt_find_child(&ffa_node, &mem_region_node_name) &&
148 fdt_first_child(&ffa_node)) {
149 uint32_t mem_count = 0;
150
151 do {
152 struct memory_region *cur_region =
153 &ctx->partition_manifest.mem_regions[mem_count];
154 EXPECT_TRUE(fdt_read_number(&ffa_node, "pages-count",
155 &number));
156 cur_region->page_count = (uint32_t)number;
Karl Meakinc2360152023-06-01 14:17:32 +0100157
158 if (!fdt_read_number(&ffa_node, "base-address",
159 &cur_region->base_address)) {
160 EXPECT_TRUE(fdt_read_number(&ffa_node,
161 "relative-address",
162 &number));
163 cur_region->base_address =
164 ctx->partition_manifest.load_addr +
165 number;
166 }
167
J-Alves3c282a32023-02-28 18:27:31 +0000168 EXPECT_TRUE(fdt_read_number(&ffa_node, "attributes",
169 &number));
170 cur_region->attributes = (uint32_t)number;
171 mem_count++;
172 } while (fdt_next_sibling(&ffa_node));
173
174 assert(mem_count < PARTITION_MAX_MEMORY_REGIONS);
175
176 ctx->partition_manifest.mem_region_count = mem_count;
177 }
178
Madhukar Pappireddy89226712024-01-31 14:34:46 -0600179 ffa_node = root;
180
181 /* Look for the device region node. */
182 if (fdt_find_child(&ffa_node, &dev_region_node_name) &&
183 fdt_first_child(&ffa_node)) {
184 uint32_t dev_region_count = 0;
185
186 do {
187 struct device_region *cur_region =
188 &ctx->partition_manifest
189 .dev_regions[dev_region_count];
190 EXPECT_TRUE(fdt_read_number(&ffa_node, "pages-count",
191 &number));
192 cur_region->page_count = (uint32_t)number;
193
194 if (!fdt_read_number(&ffa_node, "base-address",
195 &cur_region->base_address)) {
196 EXPECT_TRUE(fdt_read_number(&ffa_node,
197 "relative-address",
198 &number));
199 cur_region->base_address =
200 ctx->partition_manifest.load_addr +
201 number;
202 }
203
204 EXPECT_TRUE(fdt_read_number(&ffa_node, "attributes",
205 &number));
206 cur_region->attributes = (uint32_t)number;
207 dev_region_count++;
208 } while (fdt_next_sibling(&ffa_node));
209
210 assert(dev_region_count < PARTITION_MAX_DEVICE_REGIONS);
211
212 ctx->partition_manifest.dev_region_count = dev_region_count;
213 }
214
J-Alves3c282a32023-02-28 18:27:31 +0000215 ctx->is_ffa_manifest_parsed = true;
216}
217
Daniel Boulby792b75c2023-08-09 16:53:53 +0100218static void run_service_set_up(struct hftest_context *ctx, struct fdt *fdt)
219{
220 struct fdt_node node;
221 struct hftest_test *hftest_info;
222
223 ASSERT_TRUE(fdt_find_node(fdt, "/", &node));
224
225 if (!fdt_find_child(&node, &(STRING_INIT("hftest-service-setup")))) {
226 return;
227 }
228
229 EXPECT_TRUE(fdt_is_compatible(&node, "arm,hftest"));
230
231 for (hftest_info = hftest_begin; hftest_info < hftest_end;
232 ++hftest_info) {
233 struct memiter data;
234 if (hftest_info->kind != HFTEST_KIND_SERVICE_SET_UP) {
235 continue;
236 }
237 if (fdt_read_property(&node, hftest_info->name, &data)) {
238 HFTEST_LOG("Running service_setup: %s\n",
239 hftest_info->name);
240 hftest_info->fn();
241 if (ctx->failures) {
242 HFTEST_LOG_FAILURE();
243 HFTEST_LOG(HFTEST_LOG_INDENT
244 "%s service_setup failed\n",
245 hftest_info->name);
246 abort();
247 }
248 } else {
249 HFTEST_LOG("Skipping service_setup: %s\n",
250 hftest_info->name);
251 }
252 }
253}
254
Raghu Krishnamurthy50af6602021-12-12 15:23:09 -0800255noreturn void hftest_service_main(const void *fdt_ptr)
256{
J-Alves0c029c22023-06-21 10:32:57 +0100257 struct hftest_context *ctx;
Raghu Krishnamurthy50af6602021-12-12 15:23:09 -0800258 struct memiter args;
259 hftest_test_fn service;
Raghu Krishnamurthy50af6602021-12-12 15:23:09 -0800260 struct ffa_value ret;
261 struct fdt fdt;
J-Alves0c029c22023-06-21 10:32:57 +0100262 const ffa_id_t own_id = hf_vm_get_id();
J-Alves4dff3e92022-05-23 11:33:52 +0100263 ffa_notifications_bitmap_t bitmap;
J-Alves0c029c22023-06-21 10:32:57 +0100264 struct ffa_partition_msg *message;
265 uint32_t vcpu = get_current_vcpu_index();
Raghu Krishnamurthy50af6602021-12-12 15:23:09 -0800266
Daniel Boulby792b75c2023-08-09 16:53:53 +0100267 ctx = hftest_get_context();
J-Alves0c029c22023-06-21 10:32:57 +0100268
269 /* If boot vcpu, set up mailbox and intialize context abort function. */
270 if (vcpu == 0) {
271 struct mailbox_buffers mb;
272 mb = set_up_mailbox();
273 hftest_context_init(ctx, mb.send, mb.recv);
274 }
Daniel Boulby792b75c2023-08-09 16:53:53 +0100275
276 if (!fdt_struct_from_ptr(fdt_ptr, &fdt)) {
277 HFTEST_LOG(HFTEST_LOG_INDENT "Unable to access the FDT");
278 abort();
279 }
280
281 /*
282 * The memory size argument is to be used only by VMs. It is part of
283 * the dt provided by the Hypervisor. SPs expect to receive their
284 * FF-A manifest which doesn't have a memory size field.
285 */
286 if (ffa_is_vm_id(own_id) &&
287 !fdt_get_memory_size(&fdt, &ctx->memory_size)) {
288 HFTEST_LOG_FAILURE();
289 HFTEST_LOG(HFTEST_LOG_INDENT
290 "No entry in the FDT on memory size details");
291 abort();
292 } else if (!ffa_is_vm_id(own_id)) {
293 /*
294 * It is secure partition. We are currently using the partition
295 * manifest for the SP.
296 */
297 hftest_parse_ffa_manifest(ctx, &fdt);
298
299 /* TODO: Determine memory size referring to the SP Pkg. */
300 ctx->memory_size = 1048576;
301 }
302
303 run_service_set_up(ctx, &fdt);
304
Raghu Krishnamurthy50af6602021-12-12 15:23:09 -0800305 /* Receive the name of the service to run. */
J-Alves8dacd982023-02-08 17:42:25 +0000306 ret = ffa_msg_wait();
307 EXPECT_EQ(ret.func, FFA_RUN_32);
J-Alves4dff3e92022-05-23 11:33:52 +0100308
J-Alves0c029c22023-06-21 10:32:57 +0100309 message = (struct ffa_partition_msg *)SERVICE_RECV_BUFFER();
310
J-Alves4dff3e92022-05-23 11:33:52 +0100311 /*
312 * Expect to wake up with indirect message related to the next service
313 * to be executed.
314 */
J-Alves0c029c22023-06-21 10:32:57 +0100315 ret = ffa_notification_get(own_id, vcpu,
J-Alves4dff3e92022-05-23 11:33:52 +0100316 FFA_NOTIFICATION_FLAG_BITMAP_SPM |
317 FFA_NOTIFICATION_FLAG_BITMAP_HYP);
318 ASSERT_EQ(ret.func, FFA_SUCCESS_32);
319 bitmap = ffa_notification_get_from_framework(ret);
320 ASSERT_TRUE(is_ffa_spm_buffer_full_notification(bitmap) ||
321 is_ffa_hyp_buffer_full_notification(bitmap));
322 ASSERT_EQ(own_id, ffa_rxtx_header_receiver(&message->header));
323 memiter_init(&args, message->payload, message->header.size);
324
325 /* Find service handler. */
Raghu Krishnamurthy50af6602021-12-12 15:23:09 -0800326 service = find_service(&args);
327 EXPECT_EQ(ffa_rx_release().func, FFA_SUCCESS_32);
328
329 /* Check the service was found. */
330 if (service == NULL) {
331 HFTEST_LOG_FAILURE();
332 HFTEST_LOG(HFTEST_LOG_INDENT
333 "Unable to find requested service");
334 abort();
335 }
336
Raghu Krishnamurthy50af6602021-12-12 15:23:09 -0800337 /* Pause so the next time cycles are given the service will be run. */
338 ffa_yield();
339
340 /* Let the service run. */
341 service();
342
343 /* Cleanly handle it if the service returns. */
344 if (ctx->failures) {
345 abort();
346 }
347
348 for (;;) {
349 /* Hang if the service returns. */
350 }
351}
Madhukar Pappireddy29235ec2022-12-22 10:18:41 -0600352
J-Alves19e20cf2023-08-02 12:48:55 +0100353ffa_id_t hftest_get_dir_req_source_id(void)
Madhukar Pappireddy29235ec2022-12-22 10:18:41 -0600354{
355 struct hftest_context *ctx = hftest_get_context();
356 return ctx->dir_req_source_id;
357}
358
J-Alves19e20cf2023-08-02 12:48:55 +0100359void hftest_set_dir_req_source_id(ffa_id_t id)
Madhukar Pappireddy29235ec2022-12-22 10:18:41 -0600360{
361 struct hftest_context *ctx = hftest_get_context();
362 ctx->dir_req_source_id = id;
363}