blob: f606bf503cc40eb92b894f27fc1ce7fac617dc43 [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
9#include <stdalign.h>
10#include <stdint.h>
11
Raghu Krishnamurthy50af6602021-12-12 15:23:09 -080012#include "hf/fdt_handler.h"
13#include "hf/ffa.h"
14#include "hf/memiter.h"
J-Alves35e61922021-05-06 10:01:05 +010015#include "hf/mm.h"
16#include "hf/std.h"
17
Raghu Krishnamurthy50af6602021-12-12 15:23:09 -080018#include "vmapi/hf/call.h"
19
J-Alves35e61922021-05-06 10:01:05 +010020#include "test/hftest.h"
21#include "test/hftest_impl.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
36noreturn void abort(void)
37{
38 HFTEST_LOG("Service contained failures.");
39 /* Cause a fault, as a secondary/SP can't power down the machine. */
40 *((volatile uint8_t *)1) = 1;
41
42 /* This should never be reached, but to make the compiler happy... */
43 for (;;) {
44 }
45}
Raghu Krishnamurthy50af6602021-12-12 15:23:09 -080046
47/** Find the service with the name passed in the arguments. */
48static hftest_test_fn find_service(struct memiter *args)
49{
50 struct memiter service_name;
51 struct hftest_test *test;
52
53 if (!memiter_parse_str(args, &service_name)) {
54 return NULL;
55 }
56
57 for (test = hftest_begin; test < hftest_end; ++test) {
58 if (test->kind == HFTEST_KIND_SERVICE &&
59 memiter_iseq(&service_name, test->name)) {
60 return test->fn;
61 }
62 }
63
64 return NULL;
65}
66
J-Alvese2354862022-12-08 17:35:51 +000067void hftest_context_init(struct hftest_context *ctx, void *send, void *recv)
68{
69 memset_s(ctx, sizeof(*ctx), 0, sizeof(*ctx));
70 ctx->abort = abort;
71 ctx->send = send;
72 ctx->recv = recv;
73}
74
Raghu Krishnamurthy50af6602021-12-12 15:23:09 -080075noreturn void hftest_service_main(const void *fdt_ptr)
76{
77 struct memiter args;
78 hftest_test_fn service;
79 struct hftest_context *ctx;
80 struct ffa_value ret;
81 struct fdt fdt;
J-Alves4dff3e92022-05-23 11:33:52 +010082 ffa_vm_id_t own_id = hf_vm_get_id();
83 struct mailbox_buffers mb = set_up_mailbox();
84 ffa_notifications_bitmap_t bitmap;
85 struct ffa_partition_msg *message = (struct ffa_partition_msg *)mb.recv;
Raghu Krishnamurthy50af6602021-12-12 15:23:09 -080086
87 /* Receive the name of the service to run. */
J-Alves4dff3e92022-05-23 11:33:52 +010088 ffa_msg_wait();
89
90 /*
91 * Expect to wake up with indirect message related to the next service
92 * to be executed.
93 */
94 ret = ffa_notification_get(own_id, 0,
95 FFA_NOTIFICATION_FLAG_BITMAP_SPM |
96 FFA_NOTIFICATION_FLAG_BITMAP_HYP);
97 ASSERT_EQ(ret.func, FFA_SUCCESS_32);
98 bitmap = ffa_notification_get_from_framework(ret);
99 ASSERT_TRUE(is_ffa_spm_buffer_full_notification(bitmap) ||
100 is_ffa_hyp_buffer_full_notification(bitmap));
101 ASSERT_EQ(own_id, ffa_rxtx_header_receiver(&message->header));
102 memiter_init(&args, message->payload, message->header.size);
103
104 /* Find service handler. */
Raghu Krishnamurthy50af6602021-12-12 15:23:09 -0800105 service = find_service(&args);
106 EXPECT_EQ(ffa_rx_release().func, FFA_SUCCESS_32);
107
108 /* Check the service was found. */
109 if (service == NULL) {
110 HFTEST_LOG_FAILURE();
111 HFTEST_LOG(HFTEST_LOG_INDENT
112 "Unable to find requested service");
113 abort();
114 }
115
116 if (!fdt_struct_from_ptr(fdt_ptr, &fdt)) {
117 HFTEST_LOG(HFTEST_LOG_INDENT "Unable to access the FDT");
118 abort();
119 }
120
121 /* Clean the context. */
122 ctx = hftest_get_context();
J-Alvese2354862022-12-08 17:35:51 +0000123 hftest_context_init(ctx, mb.send, mb.recv);
J-Alves4dff3e92022-05-23 11:33:52 +0100124
125 /*
126 * The memory size argument is to be used only by VMs. It is part of
127 * the dt provided by the Hypervisor. SPs expect to receive their
128 * FF-A manifest which doesn't have a memory size field.
129 */
130 if (!IS_SP_ID(own_id) &&
131 !fdt_get_memory_size(&fdt, &ctx->memory_size)) {
Raghu Krishnamurthy50af6602021-12-12 15:23:09 -0800132 HFTEST_LOG_FAILURE();
133 HFTEST_LOG(HFTEST_LOG_INDENT
134 "No entry in the FDT on memory size details");
135 abort();
136 }
137
138 /* Pause so the next time cycles are given the service will be run. */
139 ffa_yield();
140
141 /* Let the service run. */
142 service();
143
144 /* Cleanly handle it if the service returns. */
145 if (ctx->failures) {
146 abort();
147 }
148
149 for (;;) {
150 /* Hang if the service returns. */
151 }
152}
Madhukar Pappireddy29235ec2022-12-22 10:18:41 -0600153
154ffa_vm_id_t hftest_get_dir_req_source_id()
155{
156 struct hftest_context *ctx = hftest_get_context();
157 return ctx->dir_req_source_id;
158}
159
160void hftest_set_dir_req_source_id(ffa_vm_id_t id)
161{
162 struct hftest_context *ctx = hftest_get_context();
163 ctx->dir_req_source_id = id;
164}