blob: 510fc773c537df098d3e0b724df6ee6bcfcf853d [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
34noreturn void abort(void)
35{
36 HFTEST_LOG("Service contained failures.");
37 /* Cause a fault, as a secondary/SP can't power down the machine. */
38 *((volatile uint8_t *)1) = 1;
39
40 /* This should never be reached, but to make the compiler happy... */
41 for (;;) {
42 }
43}
Raghu Krishnamurthy50af6602021-12-12 15:23:09 -080044
45/** Find the service with the name passed in the arguments. */
46static hftest_test_fn find_service(struct memiter *args)
47{
48 struct memiter service_name;
49 struct hftest_test *test;
50
51 if (!memiter_parse_str(args, &service_name)) {
52 return NULL;
53 }
54
55 for (test = hftest_begin; test < hftest_end; ++test) {
56 if (test->kind == HFTEST_KIND_SERVICE &&
57 memiter_iseq(&service_name, test->name)) {
58 return test->fn;
59 }
60 }
61
62 return NULL;
63}
64
J-Alvese2354862022-12-08 17:35:51 +000065void hftest_context_init(struct hftest_context *ctx, void *send, void *recv)
66{
67 memset_s(ctx, sizeof(*ctx), 0, sizeof(*ctx));
68 ctx->abort = abort;
69 ctx->send = send;
70 ctx->recv = recv;
71}
72
J-Alves3c282a32023-02-28 18:27:31 +000073/*
74 * Parse the FF-A partition's manifest.
75 * This function assumes the 'fdt' field of the passed 'ctx' has been
76 * initialized.
77 * TODO: Parse other fields as needed.
78 */
79static void hftest_parse_ffa_manifest(struct hftest_context *ctx,
80 struct fdt *fdt)
81{
82 struct fdt_node root;
83 struct fdt_node ffa_node;
84 struct string mem_region_node_name = STRING_INIT("memory-regions");
Madhukar Pappireddy89226712024-01-31 14:34:46 -060085 struct string dev_region_node_name = STRING_INIT("device-regions");
J-Alves3c282a32023-02-28 18:27:31 +000086 uint64_t number;
87
88 CHECK(ctx != NULL);
89 CHECK(fdt != NULL);
90
91 ASSERT_TRUE(fdt_find_node(fdt, "/", &root));
92 EXPECT_TRUE(fdt_is_compatible(&root, "arm,ffa-manifest-1.0"));
93 ASSERT_TRUE(fdt_read_number(&root, "load-address",
94 &ctx->partition_manifest.load_addr));
95 EXPECT_TRUE(fdt_read_number(&root, "ffa-version", &number));
96
97 ffa_node = root;
98
99 /* Look for the memory region node. */
100 if (fdt_find_child(&ffa_node, &mem_region_node_name) &&
101 fdt_first_child(&ffa_node)) {
102 uint32_t mem_count = 0;
103
104 do {
105 struct memory_region *cur_region =
106 &ctx->partition_manifest.mem_regions[mem_count];
107 EXPECT_TRUE(fdt_read_number(&ffa_node, "pages-count",
108 &number));
109 cur_region->page_count = (uint32_t)number;
Karl Meakinc2360152023-06-01 14:17:32 +0100110
111 if (!fdt_read_number(&ffa_node, "base-address",
112 &cur_region->base_address)) {
113 EXPECT_TRUE(fdt_read_number(&ffa_node,
114 "relative-address",
115 &number));
116 cur_region->base_address =
117 ctx->partition_manifest.load_addr +
118 number;
119 }
120
J-Alves3c282a32023-02-28 18:27:31 +0000121 EXPECT_TRUE(fdt_read_number(&ffa_node, "attributes",
122 &number));
123 cur_region->attributes = (uint32_t)number;
124 mem_count++;
125 } while (fdt_next_sibling(&ffa_node));
126
127 assert(mem_count < PARTITION_MAX_MEMORY_REGIONS);
128
129 ctx->partition_manifest.mem_region_count = mem_count;
130 }
131
Madhukar Pappireddy89226712024-01-31 14:34:46 -0600132 ffa_node = root;
133
134 /* Look for the device region node. */
135 if (fdt_find_child(&ffa_node, &dev_region_node_name) &&
136 fdt_first_child(&ffa_node)) {
137 uint32_t dev_region_count = 0;
138
139 do {
140 struct device_region *cur_region =
141 &ctx->partition_manifest
142 .dev_regions[dev_region_count];
143 EXPECT_TRUE(fdt_read_number(&ffa_node, "pages-count",
144 &number));
145 cur_region->page_count = (uint32_t)number;
146
147 if (!fdt_read_number(&ffa_node, "base-address",
148 &cur_region->base_address)) {
149 EXPECT_TRUE(fdt_read_number(&ffa_node,
150 "relative-address",
151 &number));
152 cur_region->base_address =
153 ctx->partition_manifest.load_addr +
154 number;
155 }
156
157 EXPECT_TRUE(fdt_read_number(&ffa_node, "attributes",
158 &number));
159 cur_region->attributes = (uint32_t)number;
160 dev_region_count++;
161 } while (fdt_next_sibling(&ffa_node));
162
163 assert(dev_region_count < PARTITION_MAX_DEVICE_REGIONS);
164
165 ctx->partition_manifest.dev_region_count = dev_region_count;
166 }
167
J-Alves3c282a32023-02-28 18:27:31 +0000168 ctx->is_ffa_manifest_parsed = true;
169}
170
Daniel Boulby792b75c2023-08-09 16:53:53 +0100171static void run_service_set_up(struct hftest_context *ctx, struct fdt *fdt)
172{
173 struct fdt_node node;
174 struct hftest_test *hftest_info;
175
176 ASSERT_TRUE(fdt_find_node(fdt, "/", &node));
177
178 if (!fdt_find_child(&node, &(STRING_INIT("hftest-service-setup")))) {
179 return;
180 }
181
182 EXPECT_TRUE(fdt_is_compatible(&node, "arm,hftest"));
183
184 for (hftest_info = hftest_begin; hftest_info < hftest_end;
185 ++hftest_info) {
186 struct memiter data;
187 if (hftest_info->kind != HFTEST_KIND_SERVICE_SET_UP) {
188 continue;
189 }
190 if (fdt_read_property(&node, hftest_info->name, &data)) {
191 HFTEST_LOG("Running service_setup: %s\n",
192 hftest_info->name);
193 hftest_info->fn();
194 if (ctx->failures) {
195 HFTEST_LOG_FAILURE();
196 HFTEST_LOG(HFTEST_LOG_INDENT
197 "%s service_setup failed\n",
198 hftest_info->name);
199 abort();
200 }
201 } else {
202 HFTEST_LOG("Skipping service_setup: %s\n",
203 hftest_info->name);
204 }
205 }
206}
207
Raghu Krishnamurthy50af6602021-12-12 15:23:09 -0800208noreturn void hftest_service_main(const void *fdt_ptr)
209{
210 struct memiter args;
211 hftest_test_fn service;
212 struct hftest_context *ctx;
213 struct ffa_value ret;
214 struct fdt fdt;
J-Alves19e20cf2023-08-02 12:48:55 +0100215 ffa_id_t own_id = hf_vm_get_id();
J-Alves4dff3e92022-05-23 11:33:52 +0100216 struct mailbox_buffers mb = set_up_mailbox();
217 ffa_notifications_bitmap_t bitmap;
218 struct ffa_partition_msg *message = (struct ffa_partition_msg *)mb.recv;
Raghu Krishnamurthy50af6602021-12-12 15:23:09 -0800219
Daniel Boulby792b75c2023-08-09 16:53:53 +0100220 /* Clean the context. */
221 ctx = hftest_get_context();
222 hftest_context_init(ctx, mb.send, mb.recv);
223
224 if (!fdt_struct_from_ptr(fdt_ptr, &fdt)) {
225 HFTEST_LOG(HFTEST_LOG_INDENT "Unable to access the FDT");
226 abort();
227 }
228
229 /*
230 * The memory size argument is to be used only by VMs. It is part of
231 * the dt provided by the Hypervisor. SPs expect to receive their
232 * FF-A manifest which doesn't have a memory size field.
233 */
234 if (ffa_is_vm_id(own_id) &&
235 !fdt_get_memory_size(&fdt, &ctx->memory_size)) {
236 HFTEST_LOG_FAILURE();
237 HFTEST_LOG(HFTEST_LOG_INDENT
238 "No entry in the FDT on memory size details");
239 abort();
240 } else if (!ffa_is_vm_id(own_id)) {
241 /*
242 * It is secure partition. We are currently using the partition
243 * manifest for the SP.
244 */
245 hftest_parse_ffa_manifest(ctx, &fdt);
246
247 /* TODO: Determine memory size referring to the SP Pkg. */
248 ctx->memory_size = 1048576;
249 }
250
251 run_service_set_up(ctx, &fdt);
252
Raghu Krishnamurthy50af6602021-12-12 15:23:09 -0800253 /* Receive the name of the service to run. */
J-Alves8dacd982023-02-08 17:42:25 +0000254 ret = ffa_msg_wait();
255 EXPECT_EQ(ret.func, FFA_RUN_32);
J-Alves4dff3e92022-05-23 11:33:52 +0100256
257 /*
258 * Expect to wake up with indirect message related to the next service
259 * to be executed.
260 */
261 ret = ffa_notification_get(own_id, 0,
262 FFA_NOTIFICATION_FLAG_BITMAP_SPM |
263 FFA_NOTIFICATION_FLAG_BITMAP_HYP);
264 ASSERT_EQ(ret.func, FFA_SUCCESS_32);
265 bitmap = ffa_notification_get_from_framework(ret);
266 ASSERT_TRUE(is_ffa_spm_buffer_full_notification(bitmap) ||
267 is_ffa_hyp_buffer_full_notification(bitmap));
268 ASSERT_EQ(own_id, ffa_rxtx_header_receiver(&message->header));
269 memiter_init(&args, message->payload, message->header.size);
270
271 /* Find service handler. */
Raghu Krishnamurthy50af6602021-12-12 15:23:09 -0800272 service = find_service(&args);
273 EXPECT_EQ(ffa_rx_release().func, FFA_SUCCESS_32);
274
275 /* Check the service was found. */
276 if (service == NULL) {
277 HFTEST_LOG_FAILURE();
278 HFTEST_LOG(HFTEST_LOG_INDENT
279 "Unable to find requested service");
280 abort();
281 }
282
Raghu Krishnamurthy50af6602021-12-12 15:23:09 -0800283 /* Pause so the next time cycles are given the service will be run. */
284 ffa_yield();
285
286 /* Let the service run. */
287 service();
288
289 /* Cleanly handle it if the service returns. */
290 if (ctx->failures) {
291 abort();
292 }
293
294 for (;;) {
295 /* Hang if the service returns. */
296 }
297}
Madhukar Pappireddy29235ec2022-12-22 10:18:41 -0600298
J-Alves19e20cf2023-08-02 12:48:55 +0100299ffa_id_t hftest_get_dir_req_source_id(void)
Madhukar Pappireddy29235ec2022-12-22 10:18:41 -0600300{
301 struct hftest_context *ctx = hftest_get_context();
302 return ctx->dir_req_source_id;
303}
304
J-Alves19e20cf2023-08-02 12:48:55 +0100305void hftest_set_dir_req_source_id(ffa_id_t id)
Madhukar Pappireddy29235ec2022-12-22 10:18:41 -0600306{
307 struct hftest_context *ctx = hftest_get_context();
308 ctx->dir_req_source_id = id;
309}