blob: f03f378f3429cc449d4cc7e936aefdd58733db07 [file] [log] [blame]
Karl Meakin7a664f62024-07-24 17:20:29 +01001/*
2 * Copyright 2024 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
Karl Meakin902af082024-11-28 14:58:38 +00009#include "hf/ffa/notifications.h"
Karl Meakin7a664f62024-07-24 17:20:29 +010010
11#include "hf/arch/other_world.h"
12
13#include "hf/ffa_internal.h"
14#include "hf/std.h"
15#include "hf/vm.h"
16
17#include "hypervisor.h"
18
19/**
20 * Check validity of the calls:
21 * FFA_NOTIFICATION_BITMAP_CREATE/FFA_NOTIFICATION_BITMAP_DESTROY.
22 */
Karl Meakin117c8082024-12-04 16:03:28 +000023struct ffa_value ffa_notifications_is_bitmap_access_valid(struct vcpu *current,
24 ffa_id_t vm_id)
Karl Meakin7a664f62024-07-24 17:20:29 +010025{
26 /*
27 * Call should only be used by the Hypervisor, so any attempt of
28 * invocation from NWd FF-A endpoints should fail.
29 */
30 (void)current;
31 (void)vm_id;
32
33 return ffa_error(FFA_NOT_SUPPORTED);
34}
35
Karl Meakin117c8082024-12-04 16:03:28 +000036bool ffa_notifications_is_bind_valid(struct vcpu *current, ffa_id_t sender_id,
37 ffa_id_t receiver_id)
Karl Meakin7a664f62024-07-24 17:20:29 +010038{
39 ffa_id_t current_vm_id = current->vm->id;
40 /** If Hafnium is hypervisor, receiver needs to be current vm. */
41 return sender_id != receiver_id && current_vm_id == receiver_id;
42}
43
Karl Meakin117c8082024-12-04 16:03:28 +000044bool ffa_notifications_update_bindings_forward(
Karl Meakinf9c73ce2024-07-30 17:37:13 +010045 ffa_id_t receiver_id, ffa_id_t sender_id,
46 ffa_notification_flags_t flags, ffa_notifications_bitmap_t bitmap,
47 bool is_bind, struct ffa_value *ret)
Karl Meakin7a664f62024-07-24 17:20:29 +010048{
49 CHECK(ret != NULL);
50
51 if (vm_id_is_current_world(receiver_id) &&
52 !vm_id_is_current_world(sender_id)) {
53 dlog_verbose(
54 "Forward notifications bind/unbind to other world.\n");
55 *ret = arch_other_world_call((struct ffa_value){
56 .func = is_bind ? FFA_NOTIFICATION_BIND_32
57 : FFA_NOTIFICATION_UNBIND_32,
58 .arg1 = (sender_id << 16) | (receiver_id),
59 .arg2 = is_bind ? flags : 0U,
60 .arg3 = (uint32_t)(bitmap),
61 .arg4 = (uint32_t)(bitmap >> 32),
62 });
63 return true;
64 }
65 return false;
66}
67
Karl Meakin117c8082024-12-04 16:03:28 +000068bool ffa_notifications_is_set_valid(struct vcpu *current, ffa_id_t sender_id,
69 ffa_id_t receiver_id)
Karl Meakin7a664f62024-07-24 17:20:29 +010070{
71 ffa_id_t current_vm_id = current->vm->id;
72
73 /* If Hafnium is hypervisor, sender needs to be current vm. */
74 return sender_id == current_vm_id && sender_id != receiver_id;
75}
76
Karl Meakin117c8082024-12-04 16:03:28 +000077bool ffa_notifications_set_forward(ffa_id_t sender_vm_id,
78 ffa_id_t receiver_vm_id, uint32_t flags,
79 ffa_notifications_bitmap_t bitmap,
80 struct ffa_value *ret)
Karl Meakin7a664f62024-07-24 17:20:29 +010081{
82 /* Forward only if receiver is an SP. */
83 if (vm_id_is_current_world(receiver_vm_id)) {
84 return false;
85 }
86
87 dlog_verbose("Forwarding notification set to SPMC.\n");
88
89 *ret = arch_other_world_call((struct ffa_value){
90 .func = FFA_NOTIFICATION_SET_32,
91 .arg1 = (sender_vm_id << 16) | receiver_vm_id,
92 .arg2 = flags & ~FFA_NOTIFICATIONS_FLAG_DELAY_SRI,
93 .arg3 = (uint32_t)(bitmap),
94 .arg4 = (uint32_t)(bitmap >> 32),
95 });
96
97 if (ret->func == FFA_ERROR_32) {
98 dlog_verbose("Failed to set notifications from SPMC.\n");
99 }
100
101 return true;
102}
103
Karl Meakin117c8082024-12-04 16:03:28 +0000104bool ffa_notifications_is_get_valid(struct vcpu *current, ffa_id_t receiver_id,
105 ffa_notification_flags_t flags)
Karl Meakin7a664f62024-07-24 17:20:29 +0100106{
107 ffa_id_t current_vm_id = current->vm->id;
108
109 (void)flags;
110
111 /* If Hafnium is hypervisor, receiver needs to be current vm. */
112 return (current_vm_id == receiver_id);
113}
114
Karl Meakin117c8082024-12-04 16:03:28 +0000115struct ffa_value ffa_notifications_bitmap_create(ffa_id_t vm_id,
116 ffa_vcpu_count_t vcpu_count)
Karl Meakin7a664f62024-07-24 17:20:29 +0100117{
118 (void)vm_id;
119 (void)vcpu_count;
120
121 return ffa_error(FFA_NOT_SUPPORTED);
122}
123
Karl Meakin117c8082024-12-04 16:03:28 +0000124struct ffa_value ffa_notifications_bitmap_destroy(ffa_id_t vm_id)
Karl Meakin7a664f62024-07-24 17:20:29 +0100125{
126 (void)vm_id;
127
128 return ffa_error(FFA_NOT_SUPPORTED);
129}
130
Karl Meakin117c8082024-12-04 16:03:28 +0000131bool ffa_notifications_bitmap_create_call(ffa_id_t vm_id,
132 ffa_vcpu_count_t vcpu_count)
Karl Meakin7a664f62024-07-24 17:20:29 +0100133{
134 struct ffa_value ret;
135
136 if (plat_ffa_is_tee_enabled()) {
137 ret = arch_other_world_call((struct ffa_value){
138 .func = FFA_NOTIFICATION_BITMAP_CREATE_32,
139 .arg1 = vm_id,
140 .arg2 = vcpu_count,
141 });
142
143 if (ret.func == FFA_ERROR_32) {
144 dlog_error(
145 "Failed to create notifications bitmap "
146 "to VM: %#x; error: %#x.\n",
147 vm_id, ffa_error_code(ret));
148 return false;
149 }
150 }
151
152 return true;
153}
154
Karl Meakin117c8082024-12-04 16:03:28 +0000155void ffa_notifications_info_get_forward(uint16_t *ids, uint32_t *ids_count,
156 uint32_t *lists_sizes,
157 uint32_t *lists_count,
158 const uint32_t ids_count_max)
Karl Meakin7a664f62024-07-24 17:20:29 +0100159{
160 CHECK(ids != NULL);
161 CHECK(ids_count != NULL);
162 CHECK(lists_sizes != NULL);
163 CHECK(lists_count != NULL);
164 CHECK(ids_count_max == FFA_NOTIFICATIONS_INFO_GET_MAX_IDS);
165
166 uint32_t local_lists_sizes[FFA_NOTIFICATIONS_INFO_GET_MAX_IDS];
167 struct ffa_value ret;
168
169 dlog_verbose("Forwarding notification info get to SPMC.\n");
170
171 ret = arch_other_world_call((struct ffa_value){
172 .func = FFA_NOTIFICATION_INFO_GET_64,
173 });
174
175 if (ret.func == FFA_ERROR_32) {
176 dlog_verbose("No notifications returned by SPMC.\n");
177 return;
178 }
179
180 *lists_count = ffa_notification_info_get_lists_count(ret);
181
182 if (*lists_count > ids_count_max) {
183 *lists_count = 0;
184 return;
185 }
186
187 /*
188 * The count of ids should be at least the number of lists, to
189 * encompass for at least the ids of the FF-A endpoints. List
190 * sizes will be between 0 and 3, and relates to the counting of
191 * vCPU of the endpoint that have pending notifications.
192 * If `lists_count` is already ids_count_max, each list size
193 * must be 0.
194 */
195 *ids_count = *lists_count;
196
197 for (uint32_t i = 0; i < *lists_count; i++) {
198 local_lists_sizes[i] =
199 ffa_notification_info_get_list_size(ret, i + 1);
200
201 /*
202 * ... sum the counting of each list size that are part
203 * of the main list.
204 */
205 *ids_count += local_lists_sizes[i];
206 }
207
208 /*
209 * Sanity check returned `lists_count` and determined
210 * `ids_count`. If something wrong, reset arguments to 0 such
211 * that hypervisor's handling of FFA_NOTIFICATION_INFO_GET can
212 * proceed without SPMC's values.
213 */
214 if (*ids_count > ids_count_max) {
215 *ids_count = 0;
216 return;
217 }
218
219 /* Copy now lists sizes, as return sizes have been validated. */
220 memcpy_s(lists_sizes, sizeof(lists_sizes[0]) * ids_count_max,
221 local_lists_sizes, FFA_NOTIFICATIONS_INFO_GET_MAX_IDS);
222
223 /* Unpack the notifications info from the return. */
224 memcpy_s(ids, sizeof(ids[0]) * ids_count_max, &ret.arg3,
225 sizeof(ret.arg3) * FFA_NOTIFICATIONS_INFO_GET_REGS_RET);
226}
227
Karl Meakin117c8082024-12-04 16:03:28 +0000228struct ffa_value ffa_notifications_get_from_sp(
Karl Meakinf9c73ce2024-07-30 17:37:13 +0100229 struct vm_locked receiver_locked, ffa_vcpu_index_t vcpu_id,
230 ffa_notifications_bitmap_t *from_sp)
Karl Meakin7a664f62024-07-24 17:20:29 +0100231{
Karl Meakinf9c73ce2024-07-30 17:37:13 +0100232 struct ffa_value ret = {.func = FFA_SUCCESS_32};
Karl Meakin7a664f62024-07-24 17:20:29 +0100233 ffa_id_t receiver_id = receiver_locked.vm->id;
234
Karl Meakinf9c73ce2024-07-30 17:37:13 +0100235 assert(from_sp != NULL);
Karl Meakin7a664f62024-07-24 17:20:29 +0100236
Karl Meakinf9c73ce2024-07-30 17:37:13 +0100237 ret = arch_other_world_call((struct ffa_value){
Karl Meakin7a664f62024-07-24 17:20:29 +0100238 .func = FFA_NOTIFICATION_GET_32,
239 .arg1 = (vcpu_id << 16) | receiver_id,
240 .arg2 = FFA_NOTIFICATION_FLAG_BITMAP_SP,
241 });
242
Karl Meakinf9c73ce2024-07-30 17:37:13 +0100243 if (ret.func == FFA_ERROR_32) {
244 return ret;
Karl Meakin7a664f62024-07-24 17:20:29 +0100245 }
246
Karl Meakinf9c73ce2024-07-30 17:37:13 +0100247 *from_sp = ffa_notification_get_from_sp(ret);
Karl Meakin7a664f62024-07-24 17:20:29 +0100248
Karl Meakinf9c73ce2024-07-30 17:37:13 +0100249 return ret;
Karl Meakin7a664f62024-07-24 17:20:29 +0100250}
251
Karl Meakin117c8082024-12-04 16:03:28 +0000252struct ffa_value ffa_notifications_get_framework_notifications(
Karl Meakin7a664f62024-07-24 17:20:29 +0100253 struct vm_locked receiver_locked, ffa_notifications_bitmap_t *from_fwk,
Karl Meakinf9c73ce2024-07-30 17:37:13 +0100254 ffa_notification_flags_t flags, ffa_vcpu_index_t vcpu_id)
Karl Meakin7a664f62024-07-24 17:20:29 +0100255{
Karl Meakinf9c73ce2024-07-30 17:37:13 +0100256 struct ffa_value ret = {.func = FFA_SUCCESS_32};
Karl Meakin7a664f62024-07-24 17:20:29 +0100257 ffa_id_t receiver_id = receiver_locked.vm->id;
258 ffa_notifications_bitmap_t spm_notifications = 0;
259
260 (void)flags;
261
262 assert(from_fwk != NULL);
Karl Meakin7a664f62024-07-24 17:20:29 +0100263
264 /* Get SPMC notifications. */
265 if (plat_ffa_is_tee_enabled()) {
Karl Meakinf9c73ce2024-07-30 17:37:13 +0100266 ret = arch_other_world_call((struct ffa_value){
Karl Meakin7a664f62024-07-24 17:20:29 +0100267 .func = FFA_NOTIFICATION_GET_32,
268 .arg1 = (vcpu_id << 16) | receiver_id,
269 .arg2 = FFA_NOTIFICATION_FLAG_BITMAP_SPM,
270 });
271
Karl Meakinf9c73ce2024-07-30 17:37:13 +0100272 if (ffa_func_id(ret) == FFA_ERROR_32) {
273 return ret;
Karl Meakin7a664f62024-07-24 17:20:29 +0100274 }
275
Karl Meakinf9c73ce2024-07-30 17:37:13 +0100276 spm_notifications = ffa_notification_get_from_framework(ret);
Karl Meakin7a664f62024-07-24 17:20:29 +0100277 }
278
279 /* Merge notifications from SPMC and Hypervisor. */
280 *from_fwk = spm_notifications |
281 vm_notifications_framework_get_pending(receiver_locked);
282
Karl Meakinf9c73ce2024-07-30 17:37:13 +0100283 return ret;
Karl Meakin7a664f62024-07-24 17:20:29 +0100284}
285
286/**
287 * A hypervisor should send the SRI to the Primary Endpoint. Not implemented as
288 * the hypervisor is only interesting for us for the sake of having a test
289 * intrastructure that encompasses the NWd, and we are not interested in testing
290 * the flow of notifications between VMs only.
291 */
Karl Meakin117c8082024-12-04 16:03:28 +0000292void ffa_notifications_sri_trigger_if_delayed(struct cpu *cpu)
Karl Meakin7a664f62024-07-24 17:20:29 +0100293{
294 (void)cpu;
295}
296
Karl Meakin117c8082024-12-04 16:03:28 +0000297void ffa_notifications_sri_trigger_not_delayed(struct cpu *cpu)
Karl Meakin7a664f62024-07-24 17:20:29 +0100298{
299 (void)cpu;
300}
301
302/**
303 * Track that in current CPU there was a notification set with delay SRI
304 * flag.
305 */
Karl Meakin117c8082024-12-04 16:03:28 +0000306void ffa_notifications_sri_set_delayed(struct cpu *cpu)
Karl Meakin7a664f62024-07-24 17:20:29 +0100307{
308 (void)cpu;
309}