| J-Alves | bb467d1 | 2021-03-18 11:49:35 +0000 | [diff] [blame] | 1 | /* |
| Daniel Boulby | ce386b1 | 2022-03-29 18:36:36 +0100 | [diff] [blame] | 2 | * Copyright (c) 2021-2022, Arm Limited. All rights reserved. |
| J-Alves | bb467d1 | 2021-03-18 11:49:35 +0000 | [diff] [blame] | 3 | * |
| 4 | * SPDX-License-Identifier: BSD-3-Clause |
| 5 | */ |
| 6 | |
| 7 | #include <debug.h> |
| J-Alves | 269118a | 2021-09-22 09:46:11 +0100 | [diff] [blame] | 8 | #include <irq.h> |
| J-Alves | bb467d1 | 2021-03-18 11:49:35 +0000 | [diff] [blame] | 9 | #include <smccc.h> |
| 10 | |
| 11 | #include <arch_helpers.h> |
| 12 | #include <cactus_test_cmds.h> |
| 13 | #include <ffa_endpoints.h> |
| 14 | #include <ffa_svc.h> |
| 15 | #include <platform.h> |
| 16 | #include <spm_common.h> |
| Daniel Boulby | 82bf339 | 2023-07-28 18:32:27 +0100 | [diff] [blame] | 17 | #include <spm_test_helpers.h> |
| J-Alves | bb467d1 | 2021-03-18 11:49:35 +0000 | [diff] [blame] | 18 | #include <test_helpers.h> |
| 19 | |
| J-Alves | e5f3fe6 | 2021-03-18 11:51:20 +0000 | [diff] [blame] | 20 | static const struct ffa_uuid expected_sp_uuids[] = { |
| 21 | {PRIMARY_UUID}, {SECONDARY_UUID}, {TERTIARY_UUID} |
| 22 | }; |
| 23 | |
| 24 | static ffa_notification_bitmap_t g_notifications = FFA_NOTIFICATION(0) | |
| 25 | FFA_NOTIFICATION(1) | |
| 26 | FFA_NOTIFICATION(30) | |
| 27 | FFA_NOTIFICATION(50) | |
| 28 | FFA_NOTIFICATION(63); |
| 29 | |
| J-Alves | bb467d1 | 2021-03-18 11:49:35 +0000 | [diff] [blame] | 30 | /** |
| J-Alves | 4439ece | 2021-11-05 11:52:54 +0000 | [diff] [blame] | 31 | * Use FFA_FEATURES to retrieve the ID of: |
| 32 | * - Schedule Receiver Interrupt |
| 33 | * - Notification Pending Interrupt |
| 34 | * - Managed Exit Interrupt |
| 35 | * Validate the call works as expected, and they match the used int ID in the |
| 36 | * remainder of the tests. |
| 37 | */ |
| 38 | test_result_t test_notifications_retrieve_int_ids(void) |
| 39 | { |
| Daniel Boulby | ce386b1 | 2022-03-29 18:36:36 +0100 | [diff] [blame] | 40 | struct ffa_value ret; |
| J-Alves | 4439ece | 2021-11-05 11:52:54 +0000 | [diff] [blame] | 41 | |
| 42 | SKIP_TEST_IF_FFA_VERSION_LESS_THAN(1, 1); |
| 43 | |
| 44 | /* Check if SPMC is OP-TEE at S-EL1 */ |
| 45 | if (check_spmc_execution_level()) { |
| 46 | /* FFA_FEATURES is not yet supported in OP-TEE */ |
| 47 | return TEST_RESULT_SUCCESS; |
| 48 | } |
| 49 | |
| 50 | ret = ffa_features(FFA_FEATURE_NPI); |
| Karl Meakin | 0569cc0 | 2024-04-17 17:32:35 +0100 | [diff] [blame] | 51 | if (!is_expected_ffa_error(ret, FFA_ERROR_NOT_SUPPORTED)) |
| J-Alves | 4439ece | 2021-11-05 11:52:54 +0000 | [diff] [blame] | 52 | return TEST_RESULT_FAIL; |
| J-Alves | 4439ece | 2021-11-05 11:52:54 +0000 | [diff] [blame] | 53 | |
| 54 | ret = ffa_features(FFA_FEATURE_SRI); |
| 55 | if (is_ffa_call_error(ret) || |
| 56 | ffa_feature_intid(ret) != FFA_SCHEDULE_RECEIVER_INTERRUPT_ID) { |
| 57 | ERROR("Failed to retrieved SRI (exp: %u, got: %u)\n", |
| 58 | FFA_SCHEDULE_RECEIVER_INTERRUPT_ID, |
| 59 | ffa_feature_intid(ret)); |
| 60 | |
| 61 | return TEST_RESULT_FAIL; |
| 62 | } |
| 63 | |
| 64 | ret = ffa_features(FFA_FEATURE_MEI); |
| Karl Meakin | 0569cc0 | 2024-04-17 17:32:35 +0100 | [diff] [blame] | 65 | if (!is_expected_ffa_error(ret, FFA_ERROR_NOT_SUPPORTED)) |
| J-Alves | 4439ece | 2021-11-05 11:52:54 +0000 | [diff] [blame] | 66 | return TEST_RESULT_FAIL; |
| J-Alves | 4439ece | 2021-11-05 11:52:54 +0000 | [diff] [blame] | 67 | |
| 68 | return TEST_RESULT_SUCCESS; |
| 69 | } |
| 70 | |
| 71 | /** |
| J-Alves | bb467d1 | 2021-03-18 11:49:35 +0000 | [diff] [blame] | 72 | * Helper to create bitmap for NWd VMs. |
| 73 | */ |
| 74 | static bool notifications_bitmap_create(ffa_id_t vm_id, |
| 75 | ffa_vcpu_count_t vcpu_count) |
| 76 | { |
| 77 | VERBOSE("Creating bitmap for VM %x; cpu count: %u.\n", |
| 78 | vm_id, vcpu_count); |
| Daniel Boulby | ce386b1 | 2022-03-29 18:36:36 +0100 | [diff] [blame] | 79 | struct ffa_value ret = ffa_notification_bitmap_create(vm_id, |
| 80 | vcpu_count); |
| J-Alves | bb467d1 | 2021-03-18 11:49:35 +0000 | [diff] [blame] | 81 | |
| 82 | return !is_ffa_call_error(ret); |
| 83 | } |
| 84 | |
| 85 | /** |
| 86 | * Helper to destroy bitmap for NWd VMs. |
| 87 | */ |
| 88 | static bool notifications_bitmap_destroy(ffa_id_t vm_id) |
| 89 | { |
| 90 | VERBOSE("Destroying bitmap of VM %x.\n", vm_id); |
| Daniel Boulby | ce386b1 | 2022-03-29 18:36:36 +0100 | [diff] [blame] | 91 | struct ffa_value ret = ffa_notification_bitmap_destroy(vm_id); |
| J-Alves | bb467d1 | 2021-03-18 11:49:35 +0000 | [diff] [blame] | 92 | |
| 93 | return !is_ffa_call_error(ret); |
| 94 | } |
| 95 | |
| 96 | /** |
| 97 | * Test notifications bitmap create and destroy interfaces. |
| 98 | */ |
| 99 | test_result_t test_ffa_notifications_bitmap_create_destroy(void) |
| 100 | { |
| J-Alves | d5d8715 | 2021-10-29 11:48:37 +0100 | [diff] [blame] | 101 | const ffa_id_t vm_id = VM_ID(1); |
| J-Alves | bb467d1 | 2021-03-18 11:49:35 +0000 | [diff] [blame] | 102 | |
| 103 | SKIP_TEST_IF_FFA_VERSION_LESS_THAN(1, 1); |
| 104 | |
| 105 | if (check_spmc_execution_level()) { |
| 106 | VERBOSE("OPTEE as SPMC at S-EL1. Skipping test!\n"); |
| 107 | return TEST_RESULT_SKIPPED; |
| 108 | } |
| 109 | |
| 110 | if (!notifications_bitmap_create(vm_id, PLATFORM_CORE_COUNT)) { |
| 111 | return TEST_RESULT_FAIL; |
| 112 | } |
| 113 | |
| 114 | if (!notifications_bitmap_destroy(vm_id)) { |
| 115 | return TEST_RESULT_FAIL; |
| 116 | } |
| 117 | |
| 118 | return TEST_RESULT_SUCCESS; |
| 119 | } |
| 120 | |
| 121 | /** |
| 122 | * Test notifications bitmap destroy in a case the bitmap hasn't been created. |
| 123 | */ |
| 124 | test_result_t test_ffa_notifications_destroy_not_created(void) |
| 125 | { |
| 126 | SKIP_TEST_IF_FFA_VERSION_LESS_THAN(1, 1); |
| 127 | |
| 128 | if (check_spmc_execution_level()) { |
| 129 | VERBOSE("OPTEE as SPMC at S-EL1. Skipping test!\n"); |
| 130 | return TEST_RESULT_SKIPPED; |
| 131 | } |
| 132 | |
| Daniel Boulby | ce386b1 | 2022-03-29 18:36:36 +0100 | [diff] [blame] | 133 | struct ffa_value ret = ffa_notification_bitmap_destroy(VM_ID(1)); |
| J-Alves | bb467d1 | 2021-03-18 11:49:35 +0000 | [diff] [blame] | 134 | |
| 135 | if (!is_expected_ffa_error(ret, FFA_ERROR_DENIED)) { |
| 136 | return TEST_RESULT_FAIL; |
| 137 | } |
| 138 | |
| 139 | return TEST_RESULT_SUCCESS; |
| 140 | } |
| 141 | |
| 142 | /** |
| 143 | * Test attempt to create notifications bitmap for NWd VM if it had been |
| 144 | * already created. |
| 145 | */ |
| 146 | test_result_t test_ffa_notifications_create_after_create(void) |
| 147 | { |
| Daniel Boulby | ce386b1 | 2022-03-29 18:36:36 +0100 | [diff] [blame] | 148 | struct ffa_value ret; |
| J-Alves | d5d8715 | 2021-10-29 11:48:37 +0100 | [diff] [blame] | 149 | const ffa_id_t vm_id = VM_ID(2); |
| J-Alves | bb467d1 | 2021-03-18 11:49:35 +0000 | [diff] [blame] | 150 | |
| 151 | SKIP_TEST_IF_FFA_VERSION_LESS_THAN(1, 1); |
| 152 | |
| 153 | if (check_spmc_execution_level()) { |
| 154 | VERBOSE("OPTEE as SPMC at S-EL1. Skipping test!\n"); |
| 155 | return TEST_RESULT_SKIPPED; |
| 156 | } |
| 157 | |
| 158 | /* First successfully create a notifications bitmap */ |
| 159 | if (!notifications_bitmap_create(vm_id, 1)) { |
| 160 | return TEST_RESULT_FAIL; |
| 161 | } |
| 162 | |
| 163 | /* Attempt to do the same to the same VM. */ |
| 164 | ret = ffa_notification_bitmap_create(vm_id, 1); |
| 165 | |
| 166 | if (!is_expected_ffa_error(ret, FFA_ERROR_DENIED)) { |
| 167 | return TEST_RESULT_FAIL; |
| 168 | } |
| 169 | |
| 170 | /* Destroy to not affect other tests */ |
| 171 | if (!notifications_bitmap_destroy(vm_id)) { |
| 172 | return TEST_RESULT_FAIL; |
| 173 | } |
| 174 | |
| 175 | return TEST_RESULT_SUCCESS; |
| 176 | } |
| J-Alves | e5f3fe6 | 2021-03-18 11:51:20 +0000 | [diff] [blame] | 177 | |
| 178 | /** |
| 179 | * Helper function to test FFA_NOTIFICATION_BIND interface. |
| 180 | * Receives all arguments to use 'cactus_notification_bind_send_cmd', and |
| 181 | * expected response for the test command. |
| 182 | * |
| 183 | * Returns: |
| 184 | * - 'true' if response was obtained and it was as expected; |
| 185 | * - 'false' if there was an error with use of FFA_MSG_SEND_DIRECT_REQ, or |
| 186 | * the obtained response was not as expected. |
| 187 | */ |
| 188 | static bool request_notification_bind( |
| 189 | ffa_id_t cmd_dest, ffa_id_t receiver, ffa_id_t sender, |
| 190 | ffa_notification_bitmap_t notifications, uint32_t flags, |
| 191 | uint32_t expected_resp, uint32_t error_code) |
| 192 | { |
| Daniel Boulby | ce386b1 | 2022-03-29 18:36:36 +0100 | [diff] [blame] | 193 | struct ffa_value ret; |
| J-Alves | e5f3fe6 | 2021-03-18 11:51:20 +0000 | [diff] [blame] | 194 | |
| 195 | VERBOSE("TFTF requesting SP to bind notifications!\n"); |
| 196 | |
| 197 | ret = cactus_notification_bind_send_cmd(HYP_ID, cmd_dest, receiver, |
| 198 | sender, notifications, flags); |
| 199 | |
| J-Alves | e555433 | 2021-11-04 17:24:57 +0000 | [diff] [blame] | 200 | if (!is_expected_cactus_response(ret, expected_resp, error_code)) { |
| 201 | ERROR("Failed notifications bind. receiver: %x; sender: %x\n", |
| 202 | receiver, sender); |
| 203 | return false; |
| 204 | } |
| 205 | |
| 206 | return true; |
| J-Alves | e5f3fe6 | 2021-03-18 11:51:20 +0000 | [diff] [blame] | 207 | } |
| 208 | |
| 209 | /** |
| 210 | * Helper function to test FFA_NOTIFICATION_UNBIND interface. |
| 211 | * Receives all arguments to use 'cactus_notification_unbind_send_cmd', and |
| 212 | * expected response for the test command. |
| 213 | * |
| 214 | * Returns: |
| 215 | * - 'true' if response was obtained and it was as expected; |
| 216 | * - 'false' if there was an error with use of FFA_MSG_SEND_DIRECT_REQ, or |
| 217 | * the obtained response was not as expected. |
| 218 | */ |
| 219 | static bool request_notification_unbind( |
| 220 | ffa_id_t cmd_dest, ffa_id_t receiver, ffa_id_t sender, |
| 221 | ffa_notification_bitmap_t notifications, uint32_t expected_resp, |
| 222 | uint32_t error_code) |
| 223 | { |
| Daniel Boulby | ce386b1 | 2022-03-29 18:36:36 +0100 | [diff] [blame] | 224 | struct ffa_value ret; |
| J-Alves | e5f3fe6 | 2021-03-18 11:51:20 +0000 | [diff] [blame] | 225 | |
| 226 | VERBOSE("TFTF requesting SP to unbind notifications!\n"); |
| 227 | |
| 228 | ret = cactus_notification_unbind_send_cmd(HYP_ID, cmd_dest, receiver, |
| 229 | sender, notifications); |
| 230 | |
| J-Alves | e555433 | 2021-11-04 17:24:57 +0000 | [diff] [blame] | 231 | if (!is_expected_cactus_response(ret, expected_resp, error_code)) { |
| 232 | ERROR("Failed notifications unbind. receiver: %x; sender: %x\n", |
| 233 | receiver, sender); |
| 234 | return false; |
| 235 | } |
| 236 | |
| 237 | return true; |
| J-Alves | e5f3fe6 | 2021-03-18 11:51:20 +0000 | [diff] [blame] | 238 | } |
| 239 | |
| 240 | /** |
| 241 | * Test calls from SPs to the bind and unbind interfaces, expecting success |
| 242 | * returns. |
| 243 | * This test issues a request via direct messaging to the SP, which executes |
| 244 | * the test and responds with the result of the call. |
| 245 | */ |
| 246 | test_result_t test_ffa_notifications_sp_bind_unbind(void) |
| 247 | { |
| 248 | CHECK_SPMC_TESTING_SETUP(1, 1, expected_sp_uuids); |
| 249 | |
| 250 | /** First bind... */ |
| 251 | if (!request_notification_bind(SP_ID(1), SP_ID(1), SP_ID(2), |
| 252 | g_notifications, 0, CACTUS_SUCCESS, 0)) { |
| 253 | return TEST_RESULT_FAIL; |
| 254 | } |
| 255 | |
| 256 | if (!request_notification_bind(SP_ID(1), SP_ID(1), 1, |
| 257 | g_notifications, 0, CACTUS_SUCCESS, 0)) { |
| 258 | return TEST_RESULT_FAIL; |
| 259 | } |
| 260 | |
| 261 | /** ... then unbind using the same arguments. */ |
| 262 | if (!request_notification_unbind(SP_ID(1), SP_ID(1), SP_ID(2), |
| 263 | g_notifications, CACTUS_SUCCESS, 0)) { |
| 264 | return TEST_RESULT_FAIL; |
| 265 | } |
| 266 | |
| 267 | if (!request_notification_unbind(SP_ID(1), SP_ID(1), 1, |
| 268 | g_notifications, CACTUS_SUCCESS, 0)) { |
| 269 | return TEST_RESULT_FAIL; |
| 270 | } |
| 271 | |
| 272 | return TEST_RESULT_SUCCESS; |
| 273 | } |
| 274 | |
| 275 | /** |
| 276 | * Test successful attempt of doing bind and unbind of the same set of |
| 277 | * notifications. |
| 278 | */ |
| 279 | test_result_t test_ffa_notifications_vm_bind_unbind(void) |
| 280 | { |
| 281 | CHECK_SPMC_TESTING_SETUP(1, 1, expected_sp_uuids); |
| J-Alves | d5d8715 | 2021-10-29 11:48:37 +0100 | [diff] [blame] | 282 | const ffa_id_t vm_id = VM_ID(1); |
| Daniel Boulby | ce386b1 | 2022-03-29 18:36:36 +0100 | [diff] [blame] | 283 | struct ffa_value ret; |
| J-Alves | e5f3fe6 | 2021-03-18 11:51:20 +0000 | [diff] [blame] | 284 | |
| 285 | if (!notifications_bitmap_create(vm_id, 1)) { |
| 286 | return TEST_RESULT_FAIL; |
| 287 | } |
| 288 | |
| 289 | ret = ffa_notification_bind(SP_ID(2), vm_id, 0, g_notifications); |
| 290 | |
| 291 | if (!is_expected_ffa_return(ret, FFA_SUCCESS_SMC32)) { |
| 292 | return TEST_RESULT_FAIL; |
| 293 | } |
| 294 | |
| 295 | ret = ffa_notification_unbind(SP_ID(2), vm_id, g_notifications); |
| 296 | |
| 297 | if (!is_expected_ffa_return(ret, FFA_SUCCESS_SMC32)) { |
| 298 | return TEST_RESULT_FAIL; |
| 299 | } |
| 300 | |
| 301 | if (!notifications_bitmap_destroy(vm_id)) { |
| 302 | return TEST_RESULT_FAIL; |
| 303 | } |
| 304 | |
| 305 | return TEST_RESULT_SUCCESS; |
| 306 | } |
| 307 | |
| 308 | /** |
| 309 | * Test expected failure of using a NS FF-A ID for the sender. |
| 310 | */ |
| 311 | test_result_t test_ffa_notifications_vm_bind_vm(void) |
| 312 | { |
| 313 | CHECK_SPMC_TESTING_SETUP(1, 1, expected_sp_uuids); |
| J-Alves | d5d8715 | 2021-10-29 11:48:37 +0100 | [diff] [blame] | 314 | const ffa_id_t vm_id = VM_ID(1); |
| 315 | const ffa_id_t sender_id = VM_ID(2); |
| Daniel Boulby | ce386b1 | 2022-03-29 18:36:36 +0100 | [diff] [blame] | 316 | struct ffa_value ret; |
| J-Alves | e5f3fe6 | 2021-03-18 11:51:20 +0000 | [diff] [blame] | 317 | |
| 318 | if (!notifications_bitmap_create(vm_id, 1)) { |
| 319 | return TEST_RESULT_FAIL; |
| 320 | } |
| 321 | |
| 322 | ret = ffa_notification_bind(sender_id, vm_id, 0, g_notifications); |
| 323 | |
| 324 | if (!is_expected_ffa_error(ret, FFA_ERROR_INVALID_PARAMETER)) { |
| 325 | return TEST_RESULT_FAIL; |
| 326 | } |
| 327 | |
| 328 | if (!notifications_bitmap_destroy(vm_id)) { |
| 329 | return TEST_RESULT_FAIL; |
| 330 | } |
| 331 | |
| 332 | return TEST_RESULT_SUCCESS; |
| 333 | } |
| 334 | |
| 335 | /** |
| 336 | * Test failure of both bind and unbind in case at least one notification is |
| 337 | * already bound to another FF-A endpoint. |
| 338 | * Expect error code FFA_ERROR_DENIED. |
| 339 | */ |
| 340 | test_result_t test_ffa_notifications_already_bound(void) |
| 341 | { |
| 342 | CHECK_SPMC_TESTING_SETUP(1, 1, expected_sp_uuids); |
| 343 | |
| 344 | /** Bind first to test */ |
| 345 | if (!request_notification_bind(SP_ID(1), SP_ID(1), SP_ID(2), |
| 346 | g_notifications, 0, CACTUS_SUCCESS, 0)) { |
| 347 | return TEST_RESULT_FAIL; |
| 348 | } |
| 349 | |
| 350 | /** Attempt to bind notifications bound in above request. */ |
| 351 | if (!request_notification_bind(SP_ID(1), SP_ID(1), SP_ID(3), |
| 352 | g_notifications, 0, CACTUS_ERROR, |
| 353 | FFA_ERROR_DENIED)) { |
| 354 | return TEST_RESULT_FAIL; |
| 355 | } |
| 356 | |
| 357 | /** Attempt to unbind notifications bound in initial request. */ |
| 358 | if (!request_notification_unbind(SP_ID(1), SP_ID(1), SP_ID(3), |
| 359 | g_notifications, CACTUS_ERROR, |
| 360 | FFA_ERROR_DENIED)) { |
| 361 | return TEST_RESULT_FAIL; |
| 362 | } |
| 363 | |
| 364 | /** Reset the state the SP's notifications state. */ |
| 365 | if (!request_notification_unbind(SP_ID(1), SP_ID(1), SP_ID(2), |
| 366 | g_notifications, CACTUS_SUCCESS, 0)) { |
| 367 | return TEST_RESULT_FAIL; |
| 368 | } |
| 369 | |
| 370 | return TEST_RESULT_SUCCESS; |
| 371 | } |
| 372 | |
| 373 | /** |
| 374 | * Try to bind/unbind notifications spoofing the identity of the receiver. |
| 375 | * Commands will be sent to SP_ID(1), which will use SP_ID(3) as the receiver. |
| 376 | * Expect error code FFA_ERROR_INVALID_PARAMETER. |
| 377 | */ |
| 378 | test_result_t test_ffa_notifications_bind_unbind_spoofing(void) |
| 379 | { |
| 380 | ffa_notification_bitmap_t notifications = FFA_NOTIFICATION(8); |
| 381 | |
| 382 | CHECK_SPMC_TESTING_SETUP(1, 1, expected_sp_uuids); |
| 383 | |
| 384 | if (!request_notification_bind(SP_ID(1), SP_ID(3), SP_ID(2), |
| 385 | notifications, 0, CACTUS_ERROR, |
| 386 | FFA_ERROR_INVALID_PARAMETER)) { |
| 387 | return TEST_RESULT_FAIL; |
| 388 | } |
| 389 | |
| 390 | if (!request_notification_unbind(SP_ID(1), SP_ID(3), SP_ID(2), |
| 391 | notifications, CACTUS_ERROR, |
| 392 | FFA_ERROR_INVALID_PARAMETER)) { |
| 393 | return TEST_RESULT_FAIL; |
| 394 | } |
| 395 | |
| 396 | return TEST_RESULT_SUCCESS; |
| 397 | } |
| 398 | |
| 399 | /** |
| 400 | * Call FFA_NOTIFICATION_BIND with notifications bitmap zeroed. |
| 401 | * Expecting error code FFA_ERROR_INVALID_PARAMETER. |
| 402 | */ |
| 403 | test_result_t test_ffa_notifications_bind_unbind_zeroed(void) |
| 404 | { |
| 405 | CHECK_SPMC_TESTING_SETUP(1, 1, expected_sp_uuids); |
| 406 | |
| 407 | if (!request_notification_bind(SP_ID(1), SP_ID(1), SP_ID(2), |
| 408 | 0, 0, CACTUS_ERROR, |
| 409 | FFA_ERROR_INVALID_PARAMETER)) { |
| 410 | return TEST_RESULT_FAIL; |
| 411 | } |
| 412 | |
| 413 | if (!request_notification_unbind(SP_ID(1), SP_ID(1), SP_ID(2), |
| 414 | 0, CACTUS_ERROR, |
| 415 | FFA_ERROR_INVALID_PARAMETER)) { |
| 416 | return TEST_RESULT_FAIL; |
| 417 | } |
| 418 | |
| 419 | return TEST_RESULT_SUCCESS; |
| 420 | } |
| J-Alves | d63ae4b | 2021-03-29 15:25:19 +0100 | [diff] [blame] | 421 | |
| 422 | /** |
| 423 | * Helper function to test FFA_NOTIFICATION_GET interface. |
| 424 | * Receives all arguments to use 'cactus_notification_get_send_cmd', and returns |
| 425 | * the received response. Depending on the testing scenario, this will allow |
| 426 | * to validate if the returned bitmaps are as expected. |
| 427 | * |
| 428 | * Returns: |
| 429 | * - 'true' if response was obtained. |
| 430 | * - 'false' if there was an error sending the request. |
| 431 | */ |
| 432 | static bool request_notification_get( |
| J-Alves | c08db42 | 2021-10-19 16:15:06 +0100 | [diff] [blame] | 433 | ffa_id_t cmd_dest, ffa_id_t receiver, uint32_t vcpu_id, uint32_t flags, |
| Daniel Boulby | ce386b1 | 2022-03-29 18:36:36 +0100 | [diff] [blame] | 434 | bool check_npi_handled, struct ffa_value *response) |
| J-Alves | d63ae4b | 2021-03-29 15:25:19 +0100 | [diff] [blame] | 435 | { |
| 436 | VERBOSE("TFTF requesting SP to get notifications!\n"); |
| 437 | |
| 438 | *response = cactus_notification_get_send_cmd(HYP_ID, cmd_dest, |
| 439 | receiver, vcpu_id, |
| J-Alves | c08db42 | 2021-10-19 16:15:06 +0100 | [diff] [blame] | 440 | flags, check_npi_handled); |
| J-Alves | d63ae4b | 2021-03-29 15:25:19 +0100 | [diff] [blame] | 441 | |
| 442 | return is_ffa_direct_response(*response); |
| 443 | } |
| 444 | |
| 445 | static bool request_notification_set( |
| 446 | ffa_id_t cmd_dest, ffa_id_t receiver, ffa_id_t sender, uint32_t flags, |
| J-Alves | f032847 | 2021-09-21 18:32:02 +0100 | [diff] [blame] | 447 | ffa_notification_bitmap_t notifications, ffa_id_t echo_dest, |
| 448 | uint32_t exp_resp, int32_t exp_error) |
| J-Alves | d63ae4b | 2021-03-29 15:25:19 +0100 | [diff] [blame] | 449 | { |
| Daniel Boulby | ce386b1 | 2022-03-29 18:36:36 +0100 | [diff] [blame] | 450 | struct ffa_value ret; |
| J-Alves | d63ae4b | 2021-03-29 15:25:19 +0100 | [diff] [blame] | 451 | |
| 452 | VERBOSE("TFTF requesting SP %x (as %x) to set notifications to %x\n", |
| 453 | cmd_dest, sender, receiver); |
| 454 | |
| 455 | ret = cactus_notifications_set_send_cmd(HYP_ID, cmd_dest, receiver, |
| J-Alves | f032847 | 2021-09-21 18:32:02 +0100 | [diff] [blame] | 456 | sender, flags, notifications, |
| 457 | echo_dest); |
| J-Alves | d63ae4b | 2021-03-29 15:25:19 +0100 | [diff] [blame] | 458 | |
| J-Alves | e555433 | 2021-11-04 17:24:57 +0000 | [diff] [blame] | 459 | if (!is_expected_cactus_response(ret, exp_resp, exp_error)) { |
| 460 | ERROR("Failed notifications set. receiver: %x; sender: %x\n", |
| 461 | receiver, sender); |
| 462 | return false; |
| 463 | } |
| 464 | |
| 465 | return true; |
| J-Alves | d63ae4b | 2021-03-29 15:25:19 +0100 | [diff] [blame] | 466 | } |
| 467 | |
| 468 | /** |
| J-Alves | 4849c8c | 2021-10-27 18:49:54 +0100 | [diff] [blame] | 469 | * Helper to set notification. If sender is VM, the function will call directly |
| 470 | * FFA_NOTIFICATION_SET, if it is an SP it will request the SP to set |
| 471 | * notifications. In both cases it is expected a successful outcome. |
| 472 | */ |
| 473 | static bool notification_set(ffa_id_t receiver, ffa_id_t sender, |
| 474 | uint32_t flags, |
| 475 | ffa_notification_bitmap_t notifications) |
| 476 | { |
| Daniel Boulby | ce386b1 | 2022-03-29 18:36:36 +0100 | [diff] [blame] | 477 | struct ffa_value ret; |
| J-Alves | 4849c8c | 2021-10-27 18:49:54 +0100 | [diff] [blame] | 478 | |
| 479 | /* Sender sets notifications to receiver. */ |
| 480 | if (!IS_SP_ID(sender)) { |
| 481 | VERBOSE("VM %x Setting notifications %llx to receiver %x\n", |
| 482 | sender, notifications, receiver); |
| 483 | ret = ffa_notification_set(sender, receiver, flags, notifications); |
| 484 | |
| 485 | if (!is_expected_ffa_return(ret, FFA_SUCCESS_SMC32)) { |
| 486 | ERROR("Failed notifications set. receiver: %x; sender: %x\n", |
| 487 | receiver, sender); |
| 488 | return false; |
| 489 | } |
| 490 | return true; |
| 491 | } |
| 492 | |
| 493 | return request_notification_set(sender, receiver, sender, flags, |
| 494 | notifications, 0, CACTUS_SUCCESS, 0); |
| 495 | } |
| 496 | |
| 497 | /** |
| J-Alves | d63ae4b | 2021-03-29 15:25:19 +0100 | [diff] [blame] | 498 | * Check that SP's response to CACTUS_NOTIFICATION_GET_CMD is as expected. |
| 499 | */ |
| 500 | static bool is_notifications_get_as_expected( |
| Daniel Boulby | ce386b1 | 2022-03-29 18:36:36 +0100 | [diff] [blame] | 501 | struct ffa_value *ret, uint64_t exp_from_sp, uint64_t exp_from_vm, |
| J-Alves | d63ae4b | 2021-03-29 15:25:19 +0100 | [diff] [blame] | 502 | ffa_id_t receiver) |
| 503 | { |
| 504 | uint64_t from_sp; |
| 505 | uint64_t from_vm; |
| 506 | bool success_ret; |
| 507 | |
| 508 | /** |
| 509 | * If receiver ID is SP, this is to evaluate the response to test |
| 510 | * command 'CACTUS_NOTIFICATION_GET_CMD'. |
| 511 | */ |
| 512 | if (IS_SP_ID(receiver)) { |
| 513 | success_ret = (cactus_get_response(*ret) == CACTUS_SUCCESS); |
| 514 | from_sp = cactus_notifications_get_from_sp(*ret); |
| 515 | from_vm = cactus_notifications_get_from_vm(*ret); |
| 516 | } else { |
| 517 | /** |
| 518 | * Else, this is to evaluate the return of FF-A call: |
| 519 | * ffa_notification_get. |
| 520 | */ |
| 521 | success_ret = (ffa_func_id(*ret) == FFA_SUCCESS_SMC32); |
| J-Alves | c6b92d5 | 2024-04-05 14:16:00 +0100 | [diff] [blame] | 522 | from_sp = ffa_notification_get_from_sp(*ret); |
| 523 | from_vm = ffa_notification_get_from_vm(*ret); |
| J-Alves | d63ae4b | 2021-03-29 15:25:19 +0100 | [diff] [blame] | 524 | } |
| 525 | |
| 526 | if (success_ret != true || |
| 527 | exp_from_sp != from_sp || |
| 528 | exp_from_vm != from_vm) { |
| 529 | VERBOSE("Notifications not as expected:\n" |
| 530 | " from sp: %llx exp: %llx\n" |
| 531 | " from vm: %llx exp: %llx\n", |
| 532 | from_sp, exp_from_sp, from_vm, exp_from_vm); |
| 533 | return false; |
| 534 | } |
| 535 | |
| 536 | return true; |
| 537 | } |
| 538 | |
| J-Alves | 16d52d5 | 2021-06-14 14:29:37 +0100 | [diff] [blame] | 539 | static bool is_notifications_info_get_as_expected( |
| Daniel Boulby | ce386b1 | 2022-03-29 18:36:36 +0100 | [diff] [blame] | 540 | struct ffa_value *ret, uint16_t *ids, uint32_t *lists_sizes, |
| J-Alves | 16d52d5 | 2021-06-14 14:29:37 +0100 | [diff] [blame] | 541 | const uint32_t max_ids_count, uint32_t lists_count, bool more_pending) |
| 542 | { |
| J-Alves | c6b92d5 | 2024-04-05 14:16:00 +0100 | [diff] [blame] | 543 | if (lists_count != ffa_notification_info_get_lists_count(*ret) || |
| 544 | more_pending != ffa_notification_info_get_more_pending(*ret)) { |
| J-Alves | 16d52d5 | 2021-06-14 14:29:37 +0100 | [diff] [blame] | 545 | ERROR("Notification info get not as expected.\n" |
| 546 | " Lists counts: %u; more pending %u\n", |
| J-Alves | c6b92d5 | 2024-04-05 14:16:00 +0100 | [diff] [blame] | 547 | ffa_notification_info_get_lists_count(*ret), |
| 548 | ffa_notification_info_get_more_pending(*ret)); |
| Daniel Boulby | ce386b1 | 2022-03-29 18:36:36 +0100 | [diff] [blame] | 549 | dump_ffa_value(*ret); |
| J-Alves | 16d52d5 | 2021-06-14 14:29:37 +0100 | [diff] [blame] | 550 | return false; |
| 551 | } |
| 552 | |
| 553 | for (uint32_t i = 0; i < lists_count; i++) { |
| 554 | uint32_t cur_size = |
| J-Alves | c6b92d5 | 2024-04-05 14:16:00 +0100 | [diff] [blame] | 555 | ffa_notification_info_get_list_size(*ret, |
| J-Alves | 16d52d5 | 2021-06-14 14:29:37 +0100 | [diff] [blame] | 556 | i + 1); |
| 557 | |
| 558 | if (lists_sizes[i] != cur_size) { |
| 559 | ERROR("Expected list size[%u] %u != %u\n", i, |
| 560 | lists_sizes[i], cur_size); |
| 561 | return false; |
| 562 | } |
| 563 | } |
| 564 | |
| 565 | /* Compare the IDs list */ |
| Daniel Boulby | ce386b1 | 2022-03-29 18:36:36 +0100 | [diff] [blame] | 566 | if (memcmp(&ret->arg3, ids, sizeof(ids[0]) * max_ids_count) != 0) { |
| J-Alves | 16d52d5 | 2021-06-14 14:29:37 +0100 | [diff] [blame] | 567 | ERROR("List of IDs not as expected\n"); |
| 568 | return false; |
| 569 | } |
| 570 | |
| 571 | return true; |
| 572 | } |
| 573 | |
| J-Alves | d63ae4b | 2021-03-29 15:25:19 +0100 | [diff] [blame] | 574 | /** |
| 575 | * Helper to bind notification and set it. |
| 576 | * If receiver is SP it will request SP to perform the bind, else invokes |
| 577 | * FFA_NOTIFICATION_BIND. |
| 578 | * If Sender is SP it will request it to perform the set, else invokes |
| 579 | * FFA_NOTIFICATION_SET. |
| 580 | */ |
| 581 | static bool notification_bind_and_set(ffa_id_t sender, |
| 582 | ffa_id_t receiver, ffa_notification_bitmap_t notifications, uint32_t flags) |
| 583 | { |
| Daniel Boulby | ce386b1 | 2022-03-29 18:36:36 +0100 | [diff] [blame] | 584 | struct ffa_value ret; |
| J-Alves | d63ae4b | 2021-03-29 15:25:19 +0100 | [diff] [blame] | 585 | uint32_t flags_bind = flags & FFA_NOTIFICATIONS_FLAG_PER_VCPU; |
| 586 | |
| 587 | /* Receiver binds notifications to sender. */ |
| 588 | if (!IS_SP_ID(receiver)) { |
| 589 | ret = ffa_notification_bind(sender, receiver, |
| 590 | flags_bind, notifications); |
| 591 | |
| 592 | if (is_ffa_call_error(ret)) { |
| 593 | return false; |
| 594 | } |
| 595 | } else { |
| 596 | if (!request_notification_bind(receiver, receiver, sender, |
| 597 | notifications, flags_bind, |
| 598 | CACTUS_SUCCESS, |
| 599 | 0)) { |
| 600 | return false; |
| 601 | } |
| 602 | } |
| 603 | |
| J-Alves | 4849c8c | 2021-10-27 18:49:54 +0100 | [diff] [blame] | 604 | return notification_set(receiver, sender, flags, notifications); |
| J-Alves | d63ae4b | 2021-03-29 15:25:19 +0100 | [diff] [blame] | 605 | } |
| 606 | |
| 607 | /** |
| 608 | * Helper to request SP to get the notifications and validate the return. |
| 609 | */ |
| 610 | static bool notification_get_and_validate( |
| 611 | ffa_id_t receiver, ffa_notification_bitmap_t exp_from_sp, |
| 612 | ffa_notification_bitmap_t exp_from_vm, uint32_t vcpu_id, |
| J-Alves | c08db42 | 2021-10-19 16:15:06 +0100 | [diff] [blame] | 613 | uint32_t flags, bool check_npi_handled) |
| J-Alves | d63ae4b | 2021-03-29 15:25:19 +0100 | [diff] [blame] | 614 | { |
| Daniel Boulby | ce386b1 | 2022-03-29 18:36:36 +0100 | [diff] [blame] | 615 | struct ffa_value ret; |
| J-Alves | d63ae4b | 2021-03-29 15:25:19 +0100 | [diff] [blame] | 616 | |
| 617 | /* Receiver gets pending notifications. */ |
| 618 | if (IS_SP_ID(receiver)) { |
| 619 | request_notification_get(receiver, receiver, vcpu_id, flags, |
| J-Alves | c08db42 | 2021-10-19 16:15:06 +0100 | [diff] [blame] | 620 | check_npi_handled, &ret); |
| J-Alves | d63ae4b | 2021-03-29 15:25:19 +0100 | [diff] [blame] | 621 | } else { |
| 622 | ret = ffa_notification_get(receiver, vcpu_id, flags); |
| 623 | } |
| 624 | |
| 625 | return is_notifications_get_as_expected(&ret, exp_from_sp, exp_from_vm, |
| 626 | receiver); |
| 627 | } |
| 628 | |
| J-Alves | 16d52d5 | 2021-06-14 14:29:37 +0100 | [diff] [blame] | 629 | static bool notifications_info_get( |
| 630 | uint16_t *expected_ids, uint32_t expected_lists_count, |
| 631 | uint32_t *expected_lists_sizes, const uint32_t max_ids_count, |
| 632 | bool expected_more_pending) |
| 633 | { |
| Daniel Boulby | ce386b1 | 2022-03-29 18:36:36 +0100 | [diff] [blame] | 634 | struct ffa_value ret; |
| J-Alves | 16d52d5 | 2021-06-14 14:29:37 +0100 | [diff] [blame] | 635 | |
| 636 | VERBOSE("Getting pending notification's info.\n"); |
| 637 | |
| 638 | ret = ffa_notification_info_get(); |
| 639 | |
| 640 | return !is_ffa_call_error(ret) && |
| 641 | is_notifications_info_get_as_expected(&ret, expected_ids, |
| 642 | expected_lists_sizes, |
| 643 | max_ids_count, |
| 644 | expected_lists_count, |
| 645 | expected_more_pending); |
| 646 | } |
| 647 | |
| J-Alves | 269118a | 2021-09-22 09:46:11 +0100 | [diff] [blame] | 648 | static volatile int schedule_receiver_interrupt_received; |
| 649 | |
| 650 | static int schedule_receiver_interrupt_handler(void *data) |
| 651 | { |
| 652 | assert(schedule_receiver_interrupt_received == 0); |
| 653 | schedule_receiver_interrupt_received = 1; |
| 654 | return 0; |
| 655 | } |
| 656 | |
| 657 | /** |
| 658 | * Enable the Schedule Receiver Interrupt and register the respective |
| 659 | * handler. |
| 660 | */ |
| 661 | static void schedule_receiver_interrupt_init(void) |
| 662 | { |
| 663 | tftf_irq_register_handler(FFA_SCHEDULE_RECEIVER_INTERRUPT_ID, |
| 664 | schedule_receiver_interrupt_handler); |
| J-Alves | 269118a | 2021-09-22 09:46:11 +0100 | [diff] [blame] | 665 | } |
| 666 | |
| 667 | /** |
| 668 | * Disable the Schedule Receiver Interrupt and unregister the respective |
| 669 | * handler. |
| 670 | */ |
| 671 | static void schedule_receiver_interrupt_deinit(void) |
| 672 | { |
| J-Alves | 269118a | 2021-09-22 09:46:11 +0100 | [diff] [blame] | 673 | tftf_irq_unregister_handler(FFA_SCHEDULE_RECEIVER_INTERRUPT_ID); |
| 674 | schedule_receiver_interrupt_received = 0; |
| 675 | } |
| 676 | |
| 677 | bool check_schedule_receiver_interrupt_handled(void) |
| 678 | { |
| 679 | if (schedule_receiver_interrupt_received == 1) { |
| 680 | VERBOSE("Schedule Receiver Interrupt handled!\n"); |
| 681 | schedule_receiver_interrupt_received = 0; |
| 682 | return true; |
| 683 | } |
| 684 | VERBOSE("Schedule Receiver Interrupt NOT handled!\n"); |
| 685 | return false; |
| 686 | } |
| 687 | |
| J-Alves | d63ae4b | 2021-03-29 15:25:19 +0100 | [diff] [blame] | 688 | /** |
| J-Alves | bd909ac | 2021-10-19 16:37:02 +0100 | [diff] [blame] | 689 | * Base function to test notifications signaling with an SP as a receiver. |
| J-Alves | d63ae4b | 2021-03-29 15:25:19 +0100 | [diff] [blame] | 690 | */ |
| J-Alves | bd909ac | 2021-10-19 16:37:02 +0100 | [diff] [blame] | 691 | static test_result_t base_test_global_notifications_signal_sp( |
| 692 | const ffa_id_t sender, const ffa_id_t receiver, |
| J-Alves | eb37879 | 2024-06-19 13:17:44 +0100 | [diff] [blame] | 693 | const ffa_notification_bitmap_t notifications, const uint32_t flags_get, |
| 694 | const uint32_t flags_set) |
| J-Alves | d63ae4b | 2021-03-29 15:25:19 +0100 | [diff] [blame] | 695 | { |
| J-Alves | 16d52d5 | 2021-06-14 14:29:37 +0100 | [diff] [blame] | 696 | /* Variables to validate calls to FFA_NOTIFICATION_INFO_GET. */ |
| 697 | uint16_t ids[FFA_NOTIFICATIONS_INFO_GET_MAX_IDS] = {0}; |
| 698 | uint32_t lists_count; |
| 699 | uint32_t lists_sizes[FFA_NOTIFICATIONS_INFO_GET_MAX_IDS] = {0}; |
| 700 | |
| 701 | CHECK_SPMC_TESTING_SETUP(1, 1, expected_sp_uuids); |
| 702 | |
| J-Alves | eb37879 | 2024-06-19 13:17:44 +0100 | [diff] [blame] | 703 | if (!IS_SP_ID(receiver)) { |
| 704 | ERROR("Receiver is expected to be an SP ID!\n"); |
| 705 | return TEST_RESULT_FAIL; |
| 706 | } |
| 707 | |
| J-Alves | 269118a | 2021-09-22 09:46:11 +0100 | [diff] [blame] | 708 | schedule_receiver_interrupt_init(); |
| 709 | |
| J-Alves | bd909ac | 2021-10-19 16:37:02 +0100 | [diff] [blame] | 710 | if (!notification_bind_and_set(sender, receiver, notifications, |
| J-Alves | eb37879 | 2024-06-19 13:17:44 +0100 | [diff] [blame] | 711 | flags_set)) { |
| J-Alves | d63ae4b | 2021-03-29 15:25:19 +0100 | [diff] [blame] | 712 | return TEST_RESULT_FAIL; |
| 713 | } |
| 714 | |
| J-Alves | 5fb1421 | 2021-09-21 13:04:48 +0100 | [diff] [blame] | 715 | if (!check_schedule_receiver_interrupt_handled()) { |
| 716 | return TEST_RESULT_FAIL; |
| 717 | } |
| J-Alves | 269118a | 2021-09-22 09:46:11 +0100 | [diff] [blame] | 718 | |
| J-Alves | 16d52d5 | 2021-06-14 14:29:37 +0100 | [diff] [blame] | 719 | /** |
| 720 | * Simple list of IDs expected on return from FFA_NOTIFICATION_INFO_GET. |
| 721 | */ |
| 722 | ids[0] = receiver; |
| 723 | lists_count = 1; |
| 724 | |
| 725 | if (!notifications_info_get(ids, lists_count, lists_sizes, |
| 726 | FFA_NOTIFICATIONS_INFO_GET_MAX_IDS, |
| J-Alves | bd909ac | 2021-10-19 16:37:02 +0100 | [diff] [blame] | 727 | false)) { |
| J-Alves | 16d52d5 | 2021-06-14 14:29:37 +0100 | [diff] [blame] | 728 | return TEST_RESULT_FAIL; |
| 729 | } |
| 730 | |
| J-Alves | bd909ac | 2021-10-19 16:37:02 +0100 | [diff] [blame] | 731 | if (!notification_get_and_validate( |
| 732 | receiver, IS_SP_ID(sender) ? notifications : 0, |
| 733 | !IS_SP_ID(sender) ? notifications : 0, 0, flags_get, true)) { |
| J-Alves | d63ae4b | 2021-03-29 15:25:19 +0100 | [diff] [blame] | 734 | return TEST_RESULT_FAIL; |
| 735 | } |
| 736 | |
| 737 | if (!request_notification_unbind(receiver, receiver, sender, |
| 738 | notifications, CACTUS_SUCCESS, 0)) { |
| 739 | return TEST_RESULT_FAIL; |
| 740 | } |
| 741 | |
| J-Alves | 269118a | 2021-09-22 09:46:11 +0100 | [diff] [blame] | 742 | schedule_receiver_interrupt_deinit(); |
| 743 | |
| J-Alves | d63ae4b | 2021-03-29 15:25:19 +0100 | [diff] [blame] | 744 | return TEST_RESULT_SUCCESS; |
| 745 | } |
| 746 | |
| 747 | /** |
| J-Alves | bd909ac | 2021-10-19 16:37:02 +0100 | [diff] [blame] | 748 | * Test to validate a VM can signal an SP. |
| 749 | */ |
| 750 | test_result_t test_ffa_notifications_vm_signals_sp(void) |
| 751 | { |
| 752 | return base_test_global_notifications_signal_sp( |
| 753 | 1, SP_ID(1), FFA_NOTIFICATION(1) | FFA_NOTIFICATION(60), |
| J-Alves | eb37879 | 2024-06-19 13:17:44 +0100 | [diff] [blame] | 754 | FFA_NOTIFICATIONS_FLAG_BITMAP_VM, 0); |
| 755 | } |
| 756 | |
| 757 | test_result_t test_ffa_notifications_vm_signals_sp_delay_sri_fail(void) |
| 758 | { |
| 759 | const ffa_id_t sender = 1; |
| 760 | const ffa_id_t receiver = SP_ID(1); |
| 761 | const ffa_notification_bitmap_t notif = (1LU << 34); |
| 762 | struct ffa_value ret; |
| 763 | |
| 764 | CHECK_SPMC_TESTING_SETUP(1, 1, expected_sp_uuids); |
| 765 | |
| 766 | if (!request_notification_bind(receiver, receiver, |
| 767 | sender, notif, 0, |
| 768 | CACTUS_SUCCESS, 0)) { |
| 769 | return TEST_RESULT_FAIL; |
| 770 | } |
| 771 | |
| 772 | ret = ffa_notification_set(sender, receiver, |
| 773 | FFA_NOTIFICATIONS_FLAG_DELAY_SRI, notif); |
| 774 | |
| 775 | if (!is_expected_ffa_error(ret, FFA_ERROR_INVALID_PARAMETER)) { |
| 776 | return TEST_RESULT_FAIL; |
| 777 | } |
| 778 | |
| 779 | if (!request_notification_unbind(receiver, receiver, sender, |
| 780 | notif, CACTUS_SUCCESS, 0)) { |
| 781 | return TEST_RESULT_FAIL; |
| 782 | } |
| 783 | |
| 784 | return TEST_RESULT_SUCCESS; |
| J-Alves | bd909ac | 2021-10-19 16:37:02 +0100 | [diff] [blame] | 785 | } |
| 786 | |
| 787 | /** |
| J-Alves | d63ae4b | 2021-03-29 15:25:19 +0100 | [diff] [blame] | 788 | * Test to validate an SP can signal an SP. |
| 789 | */ |
| 790 | test_result_t test_ffa_notifications_sp_signals_sp(void) |
| 791 | { |
| J-Alves | bd909ac | 2021-10-19 16:37:02 +0100 | [diff] [blame] | 792 | return base_test_global_notifications_signal_sp( |
| 793 | SP_ID(1), SP_ID(2), g_notifications, |
| J-Alves | eb37879 | 2024-06-19 13:17:44 +0100 | [diff] [blame] | 794 | FFA_NOTIFICATIONS_FLAG_BITMAP_SP, |
| 795 | FFA_NOTIFICATIONS_FLAG_DELAY_SRI); |
| J-Alves | d63ae4b | 2021-03-29 15:25:19 +0100 | [diff] [blame] | 796 | } |
| 797 | |
| 798 | /** |
| 799 | * Test to validate an SP can signal a VM. |
| 800 | */ |
| 801 | test_result_t test_ffa_notifications_sp_signals_vm(void) |
| 802 | { |
| 803 | CHECK_SPMC_TESTING_SETUP(1, 1, expected_sp_uuids); |
| 804 | const ffa_id_t sender = SP_ID(1); |
| J-Alves | d5d8715 | 2021-10-29 11:48:37 +0100 | [diff] [blame] | 805 | const ffa_id_t receiver = VM_ID(1); |
| J-Alves | d63ae4b | 2021-03-29 15:25:19 +0100 | [diff] [blame] | 806 | uint32_t get_flags = FFA_NOTIFICATIONS_FLAG_BITMAP_SP; |
| Daniel Boulby | ce386b1 | 2022-03-29 18:36:36 +0100 | [diff] [blame] | 807 | struct ffa_value ret; |
| J-Alves | 269118a | 2021-09-22 09:46:11 +0100 | [diff] [blame] | 808 | test_result_t result = TEST_RESULT_SUCCESS; |
| J-Alves | d63ae4b | 2021-03-29 15:25:19 +0100 | [diff] [blame] | 809 | |
| J-Alves | 16d52d5 | 2021-06-14 14:29:37 +0100 | [diff] [blame] | 810 | /* Variables to validate calls to FFA_NOTIFICATION_INFO_GET. */ |
| 811 | uint16_t ids[FFA_NOTIFICATIONS_INFO_GET_MAX_IDS] = {0}; |
| 812 | uint32_t lists_count; |
| 813 | uint32_t lists_sizes[FFA_NOTIFICATIONS_INFO_GET_MAX_IDS] = {0}; |
| 814 | |
| J-Alves | d63ae4b | 2021-03-29 15:25:19 +0100 | [diff] [blame] | 815 | /* Ask SPMC to allocate notifications bitmap. */ |
| 816 | if (!notifications_bitmap_create(receiver, 1)) { |
| J-Alves | 269118a | 2021-09-22 09:46:11 +0100 | [diff] [blame] | 817 | result = TEST_RESULT_FAIL; |
| J-Alves | d63ae4b | 2021-03-29 15:25:19 +0100 | [diff] [blame] | 818 | } |
| 819 | |
| J-Alves | 269118a | 2021-09-22 09:46:11 +0100 | [diff] [blame] | 820 | schedule_receiver_interrupt_init(); |
| 821 | |
| J-Alves | d63ae4b | 2021-03-29 15:25:19 +0100 | [diff] [blame] | 822 | /* Request receiver to bind a set of notifications to the sender. */ |
| J-Alves | fbbbf62 | 2021-07-30 16:43:36 +0100 | [diff] [blame] | 823 | if (!notification_bind_and_set(sender, receiver, g_notifications, |
| 824 | FFA_NOTIFICATIONS_FLAG_DELAY_SRI)) { |
| J-Alves | 5fb1421 | 2021-09-21 13:04:48 +0100 | [diff] [blame] | 825 | result = TEST_RESULT_FAIL; |
| J-Alves | d63ae4b | 2021-03-29 15:25:19 +0100 | [diff] [blame] | 826 | } |
| 827 | |
| J-Alves | 5fb1421 | 2021-09-21 13:04:48 +0100 | [diff] [blame] | 828 | if (!check_schedule_receiver_interrupt_handled()) { |
| 829 | result = TEST_RESULT_FAIL; |
| 830 | } |
| J-Alves | 269118a | 2021-09-22 09:46:11 +0100 | [diff] [blame] | 831 | |
| J-Alves | 16d52d5 | 2021-06-14 14:29:37 +0100 | [diff] [blame] | 832 | /* |
| 833 | * FFA_NOTIFICATION_INFO_GET return list should be simple, containing |
| 834 | * only the receiver's ID. |
| 835 | */ |
| 836 | ids[0] = receiver; |
| 837 | lists_count = 1; |
| 838 | |
| 839 | if (!notifications_info_get(ids, lists_count, lists_sizes, |
| 840 | FFA_NOTIFICATIONS_INFO_GET_MAX_IDS, |
| 841 | false)) { |
| J-Alves | 269118a | 2021-09-22 09:46:11 +0100 | [diff] [blame] | 842 | result = TEST_RESULT_FAIL; |
| J-Alves | 16d52d5 | 2021-06-14 14:29:37 +0100 | [diff] [blame] | 843 | } |
| 844 | |
| J-Alves | d63ae4b | 2021-03-29 15:25:19 +0100 | [diff] [blame] | 845 | /* Get pending notifications, and retrieve response. */ |
| 846 | if (!notification_get_and_validate(receiver, g_notifications, 0, 0, |
| J-Alves | c08db42 | 2021-10-19 16:15:06 +0100 | [diff] [blame] | 847 | get_flags, false)) { |
| J-Alves | 5fb1421 | 2021-09-21 13:04:48 +0100 | [diff] [blame] | 848 | result = TEST_RESULT_FAIL; |
| J-Alves | d63ae4b | 2021-03-29 15:25:19 +0100 | [diff] [blame] | 849 | } |
| 850 | |
| 851 | ret = ffa_notification_unbind(sender, receiver, g_notifications); |
| 852 | |
| 853 | if (!is_expected_ffa_return(ret, FFA_SUCCESS_SMC32)) { |
| J-Alves | 269118a | 2021-09-22 09:46:11 +0100 | [diff] [blame] | 854 | result = TEST_RESULT_FAIL; |
| J-Alves | d63ae4b | 2021-03-29 15:25:19 +0100 | [diff] [blame] | 855 | } |
| 856 | |
| 857 | if (!notifications_bitmap_destroy(receiver)) { |
| J-Alves | 269118a | 2021-09-22 09:46:11 +0100 | [diff] [blame] | 858 | result = TEST_RESULT_FAIL; |
| J-Alves | d63ae4b | 2021-03-29 15:25:19 +0100 | [diff] [blame] | 859 | } |
| 860 | |
| J-Alves | 269118a | 2021-09-22 09:46:11 +0100 | [diff] [blame] | 861 | schedule_receiver_interrupt_deinit(); |
| 862 | |
| 863 | return result; |
| J-Alves | d63ae4b | 2021-03-29 15:25:19 +0100 | [diff] [blame] | 864 | } |
| 865 | |
| 866 | /** |
| 867 | * Test to validate it is not possible to unbind a pending notification. |
| 868 | */ |
| 869 | test_result_t test_ffa_notifications_unbind_pending(void) |
| 870 | { |
| 871 | CHECK_SPMC_TESTING_SETUP(1, 1, expected_sp_uuids); |
| 872 | const ffa_id_t receiver = SP_ID(1); |
| J-Alves | d5d8715 | 2021-10-29 11:48:37 +0100 | [diff] [blame] | 873 | const ffa_id_t sender = VM_ID(1); |
| J-Alves | d63ae4b | 2021-03-29 15:25:19 +0100 | [diff] [blame] | 874 | const ffa_notification_bitmap_t notifications = FFA_NOTIFICATION(30) | |
| 875 | FFA_NOTIFICATION(35); |
| 876 | uint32_t get_flags = FFA_NOTIFICATIONS_FLAG_BITMAP_VM; |
| 877 | |
| J-Alves | 269118a | 2021-09-22 09:46:11 +0100 | [diff] [blame] | 878 | schedule_receiver_interrupt_init(); |
| 879 | |
| J-Alves | d63ae4b | 2021-03-29 15:25:19 +0100 | [diff] [blame] | 880 | /* Request receiver to bind a set of notifications to the sender. */ |
| 881 | if (!notification_bind_and_set(sender, receiver, notifications, 0)) { |
| 882 | return TEST_RESULT_FAIL; |
| 883 | } |
| 884 | |
| 885 | /* |
| 886 | * Attempt to unbind the pending notification, but expect error return |
| 887 | * given the notification is pending. |
| 888 | */ |
| 889 | if (!request_notification_unbind(receiver, receiver, sender, |
| 890 | FFA_NOTIFICATION(30), |
| 891 | CACTUS_ERROR, FFA_ERROR_DENIED)) { |
| 892 | return TEST_RESULT_FAIL; |
| 893 | } |
| 894 | |
| J-Alves | 269118a | 2021-09-22 09:46:11 +0100 | [diff] [blame] | 895 | if (!check_schedule_receiver_interrupt_handled()) { |
| 896 | return TEST_RESULT_FAIL; |
| 897 | } |
| 898 | |
| J-Alves | d63ae4b | 2021-03-29 15:25:19 +0100 | [diff] [blame] | 899 | /* |
| 900 | * Request receiver partition to get pending notifications from VMs. |
| 901 | * Only notification 30 is expected. |
| 902 | */ |
| 903 | if (!notification_get_and_validate(receiver, 0, notifications, 0, |
| J-Alves | c08db42 | 2021-10-19 16:15:06 +0100 | [diff] [blame] | 904 | get_flags, false)) { |
| J-Alves | d63ae4b | 2021-03-29 15:25:19 +0100 | [diff] [blame] | 905 | return TEST_RESULT_FAIL; |
| 906 | } |
| 907 | |
| 908 | /* Unbind all notifications, to not interfere with other tests. */ |
| 909 | if (!request_notification_unbind(receiver, receiver, sender, |
| 910 | notifications, CACTUS_SUCCESS, 0)) { |
| 911 | return TEST_RESULT_FAIL; |
| 912 | } |
| 913 | |
| J-Alves | 269118a | 2021-09-22 09:46:11 +0100 | [diff] [blame] | 914 | schedule_receiver_interrupt_deinit(); |
| 915 | |
| J-Alves | d63ae4b | 2021-03-29 15:25:19 +0100 | [diff] [blame] | 916 | return TEST_RESULT_SUCCESS; |
| 917 | } |
| J-Alves | 16d52d5 | 2021-06-14 14:29:37 +0100 | [diff] [blame] | 918 | |
| 919 | /** |
| 920 | * Test the result of a call to FFA_NOTIFICATION_INFO_GET if no pending |
| 921 | * notifications. |
| 922 | */ |
| 923 | test_result_t test_ffa_notifications_info_get_none(void) |
| 924 | { |
| 925 | SKIP_TEST_IF_FFA_VERSION_LESS_THAN(1, 1); |
| 926 | |
| 927 | if (check_spmc_execution_level()) { |
| 928 | VERBOSE("OPTEE as SPMC at S-EL1. Skipping test!\n"); |
| 929 | return TEST_RESULT_SKIPPED; |
| 930 | } |
| 931 | |
| Daniel Boulby | ce386b1 | 2022-03-29 18:36:36 +0100 | [diff] [blame] | 932 | struct ffa_value ret; |
| J-Alves | 16d52d5 | 2021-06-14 14:29:37 +0100 | [diff] [blame] | 933 | |
| 934 | ret = ffa_notification_info_get(); |
| 935 | |
| 936 | if (!is_expected_ffa_error(ret, FFA_ERROR_NO_DATA)) { |
| 937 | return TEST_RESULT_FAIL; |
| 938 | } |
| 939 | |
| 940 | return TEST_RESULT_SUCCESS; |
| 941 | } |
| J-Alves | 44ec4f7 | 2021-07-27 12:07:14 +0100 | [diff] [blame] | 942 | |
| 943 | /** |
| J-Alves | 5fb1421 | 2021-09-21 13:04:48 +0100 | [diff] [blame] | 944 | * Test to validate behavior in SWd if the SRI is not delayed. If the |
| 945 | * notification setter handled a managed exit it is indicative the SRI was |
| 946 | * sent immediately. |
| 947 | */ |
| 948 | test_result_t test_ffa_notifications_sp_signals_sp_immediate_sri(void) |
| 949 | { |
| 950 | CHECK_SPMC_TESTING_SETUP(1, 1, expected_sp_uuids); |
| 951 | const ffa_id_t sender = SP_ID(1); |
| 952 | const ffa_id_t receiver = SP_ID(2); |
| 953 | uint32_t get_flags = FFA_NOTIFICATIONS_FLAG_BITMAP_SP; |
| Daniel Boulby | ce386b1 | 2022-03-29 18:36:36 +0100 | [diff] [blame] | 954 | struct ffa_value ret; |
| J-Alves | 5fb1421 | 2021-09-21 13:04:48 +0100 | [diff] [blame] | 955 | test_result_t result = TEST_RESULT_SUCCESS; |
| 956 | |
| 957 | /** Variables to validate calls to FFA_NOTIFICATION_INFO_GET. */ |
| 958 | uint16_t ids[FFA_NOTIFICATIONS_INFO_GET_MAX_IDS] = {0}; |
| 959 | uint32_t lists_count; |
| 960 | uint32_t lists_sizes[FFA_NOTIFICATIONS_INFO_GET_MAX_IDS] = {0}; |
| 961 | |
| 962 | ids[0] = receiver; |
| 963 | lists_count = 1; |
| 964 | |
| J-Alves | 5fb1421 | 2021-09-21 13:04:48 +0100 | [diff] [blame] | 965 | schedule_receiver_interrupt_init(); |
| 966 | |
| 967 | /* Request receiver to bind a set of notifications to the sender. */ |
| 968 | if (!request_notification_bind(receiver, receiver, sender, |
| 969 | g_notifications, 0, CACTUS_SUCCESS, 0)) { |
| 970 | result = TEST_RESULT_FAIL; |
| 971 | } |
| 972 | |
| 973 | /* |
| 974 | * Request sender to set notification, and expect the response is |
| 975 | * MANAGED_EXIT_INTERRUPT_ID. |
| 976 | */ |
| 977 | if (!request_notification_set(sender, receiver, sender, 0, |
| J-Alves | f032847 | 2021-09-21 18:32:02 +0100 | [diff] [blame] | 978 | g_notifications, 0, |
| 979 | MANAGED_EXIT_INTERRUPT_ID, 0)) { |
| J-Alves | 5fb1421 | 2021-09-21 13:04:48 +0100 | [diff] [blame] | 980 | ERROR("SRI not handled immediately!\n"); |
| 981 | result = TEST_RESULT_FAIL; |
| 982 | } else { |
| 983 | VERBOSE("SP %x did a managed exit.\n", sender); |
| 984 | } |
| 985 | |
| 986 | if (!check_schedule_receiver_interrupt_handled()) { |
| 987 | result = TEST_RESULT_FAIL; |
| 988 | } |
| 989 | |
| 990 | /* Call FFA_NOTIFICATION_INFO_GET and validate return. */ |
| 991 | if (!notifications_info_get(ids, lists_count, lists_sizes, |
| 992 | FFA_NOTIFICATIONS_INFO_GET_MAX_IDS, |
| 993 | false)) { |
| 994 | result = TEST_RESULT_FAIL; |
| 995 | } |
| 996 | |
| 997 | /* Validate notification get. */ |
| J-Alves | c08db42 | 2021-10-19 16:15:06 +0100 | [diff] [blame] | 998 | if (!request_notification_get(receiver, receiver, 0, get_flags, false, &ret) || |
| J-Alves | 5fb1421 | 2021-09-21 13:04:48 +0100 | [diff] [blame] | 999 | !is_notifications_get_as_expected(&ret, g_notifications, 0, |
| 1000 | receiver)) { |
| 1001 | result = TEST_RESULT_FAIL; |
| 1002 | } |
| 1003 | |
| 1004 | /* |
| 1005 | * Resume setter Cactus in the handling of CACTUS_NOTIFICATIONS_SET_CMD. |
| 1006 | */ |
| Madhukar Pappireddy | 92d2e81 | 2022-09-19 13:48:13 -0500 | [diff] [blame] | 1007 | ret = cactus_resume_after_managed_exit(HYP_ID, sender); |
| J-Alves | 5fb1421 | 2021-09-21 13:04:48 +0100 | [diff] [blame] | 1008 | |
| 1009 | /* Expected result to CACTUS_NOTIFICATIONS_SET_CMD. */ |
| 1010 | if (!is_expected_cactus_response(ret, CACTUS_SUCCESS, 0)) { |
| 1011 | result = TEST_RESULT_FAIL; |
| 1012 | } |
| 1013 | |
| 1014 | /* Unbind for clean-up. */ |
| 1015 | if (!request_notification_unbind(receiver, receiver, sender, |
| 1016 | g_notifications, CACTUS_SUCCESS, 0)) { |
| 1017 | result = TEST_RESULT_FAIL; |
| 1018 | } |
| 1019 | |
| 1020 | schedule_receiver_interrupt_deinit(); |
| 1021 | |
| J-Alves | 5fb1421 | 2021-09-21 13:04:48 +0100 | [diff] [blame] | 1022 | return result; |
| 1023 | } |
| J-Alves | f032847 | 2021-09-21 18:32:02 +0100 | [diff] [blame] | 1024 | |
| 1025 | /** |
| 1026 | * Test to validate behavior in SWd if the SRI is delayed. |
| 1027 | */ |
| 1028 | test_result_t test_ffa_notifications_sp_signals_sp_delayed_sri(void) |
| 1029 | { |
| 1030 | CHECK_SPMC_TESTING_SETUP(1, 1, expected_sp_uuids); |
| 1031 | const ffa_id_t sender = SP_ID(3); |
| 1032 | const ffa_id_t receiver = SP_ID(2); |
| 1033 | const ffa_id_t echo_dest = SP_ID(1); |
| 1034 | uint32_t echo_dest_cmd_count = 0; |
| 1035 | uint32_t get_flags = FFA_NOTIFICATIONS_FLAG_BITMAP_SP; |
| Daniel Boulby | ce386b1 | 2022-03-29 18:36:36 +0100 | [diff] [blame] | 1036 | struct ffa_value ret; |
| J-Alves | f032847 | 2021-09-21 18:32:02 +0100 | [diff] [blame] | 1037 | test_result_t result = TEST_RESULT_SUCCESS; |
| 1038 | |
| 1039 | /** Variables to validate calls to FFA_NOTIFICATION_INFO_GET. */ |
| 1040 | uint16_t ids[FFA_NOTIFICATIONS_INFO_GET_MAX_IDS] = {0}; |
| 1041 | uint32_t lists_count; |
| 1042 | uint32_t lists_sizes[FFA_NOTIFICATIONS_INFO_GET_MAX_IDS] = {0}; |
| 1043 | |
| 1044 | ids[0] = receiver; |
| 1045 | lists_count = 1; |
| 1046 | |
| J-Alves | f032847 | 2021-09-21 18:32:02 +0100 | [diff] [blame] | 1047 | schedule_receiver_interrupt_init(); |
| 1048 | |
| 1049 | /* Request receiver to bind a set of notifications to the sender. */ |
| 1050 | if (!request_notification_bind(receiver, receiver, sender, |
| 1051 | g_notifications, 0, CACTUS_SUCCESS, 0)) { |
| 1052 | result = TEST_RESULT_FAIL; |
| 1053 | } |
| 1054 | |
| 1055 | ret = cactus_get_req_count_send_cmd(HYP_ID, echo_dest); |
| 1056 | |
| 1057 | if (cactus_get_response(ret) == CACTUS_SUCCESS) { |
| 1058 | /* |
| 1059 | * Save the command count from the echo_dest, to validate it |
| 1060 | * has been incremented after the request to set notifications. |
| 1061 | */ |
| 1062 | echo_dest_cmd_count = cactus_get_req_count(ret); |
| 1063 | VERBOSE("Partition %x command count %u.\n", echo_dest, |
| 1064 | echo_dest_cmd_count); |
| 1065 | } else { |
| 1066 | VERBOSE("Failed to get cmds count from %u\n", echo_dest); |
| 1067 | result = TEST_RESULT_FAIL; |
| 1068 | } |
| 1069 | |
| 1070 | /* |
| 1071 | * Request sender to set notification with Delay SRI flag, and specify |
| 1072 | * echo destination. |
| 1073 | */ |
| 1074 | if (!request_notification_set(sender, receiver, sender, |
| 1075 | FFA_NOTIFICATIONS_FLAG_DELAY_SRI, |
| 1076 | g_notifications, echo_dest, |
| 1077 | CACTUS_SUCCESS, 0)) { |
| 1078 | VERBOSE("Failed to set notifications!\n"); |
| 1079 | result = TEST_RESULT_FAIL; |
| 1080 | } |
| 1081 | |
| 1082 | if (!check_schedule_receiver_interrupt_handled()) { |
| 1083 | result = TEST_RESULT_FAIL; |
| 1084 | } |
| 1085 | |
| 1086 | /* |
| 1087 | * Get command count again from echo_dest, to validate that it has been |
| 1088 | * incremented by one. This should indicate the notification setter has |
| 1089 | * issued a request to echo_dest right after the notification set, thus |
| 1090 | * proving the SRI hasn't been sent right after FFA_NOTIFICATION_SET. |
| 1091 | */ |
| 1092 | ret = cactus_get_req_count_send_cmd(HYP_ID, echo_dest); |
| 1093 | if (cactus_get_response(ret) == CACTUS_SUCCESS) { |
| 1094 | if (cactus_get_req_count(ret) == echo_dest_cmd_count + 1) { |
| 1095 | VERBOSE("SRI successfully delayed.\n"); |
| 1096 | } else { |
| 1097 | VERBOSE("Failed to get cmds count from %u.\n", |
| 1098 | echo_dest); |
| 1099 | result = TEST_RESULT_FAIL; |
| 1100 | } |
| 1101 | } else { |
| 1102 | VERBOSE("Failed to get cmds count from %x\n", echo_dest); |
| 1103 | result = TEST_RESULT_FAIL; |
| 1104 | } |
| 1105 | |
| 1106 | /* Call FFA_NOTIFICATION_INFO_GET and validate return. */ |
| 1107 | if (!notifications_info_get(ids, lists_count, lists_sizes, |
| 1108 | FFA_NOTIFICATIONS_INFO_GET_MAX_IDS, |
| 1109 | false)) { |
| 1110 | result = TEST_RESULT_FAIL; |
| 1111 | } |
| 1112 | |
| 1113 | /* Validate notification get. */ |
| J-Alves | c08db42 | 2021-10-19 16:15:06 +0100 | [diff] [blame] | 1114 | if (!request_notification_get(receiver, receiver, 0, get_flags, false, &ret) || |
| J-Alves | f032847 | 2021-09-21 18:32:02 +0100 | [diff] [blame] | 1115 | !is_notifications_get_as_expected(&ret, g_notifications, 0, |
| 1116 | receiver)) { |
| 1117 | result = TEST_RESULT_FAIL; |
| 1118 | } |
| 1119 | |
| 1120 | /* Unbind for clean-up. */ |
| 1121 | if (!request_notification_unbind(receiver, receiver, sender, |
| 1122 | g_notifications, CACTUS_SUCCESS, 0)) { |
| 1123 | result = TEST_RESULT_FAIL; |
| 1124 | } |
| 1125 | |
| 1126 | schedule_receiver_interrupt_deinit(); |
| 1127 | |
| J-Alves | f032847 | 2021-09-21 18:32:02 +0100 | [diff] [blame] | 1128 | return result; |
| 1129 | } |