diff options
author | J-Alves <joao.alves@arm.com> | 2020-11-11 11:38:49 +0000 |
---|---|---|
committer | J-Alves <joao.alves@arm.com> | 2021-01-20 14:44:21 +0000 |
commit | 1d203f17d15f613aac7169399c3fb32667707ea1 (patch) | |
tree | 2b7bb83c4d8786ecd4010906c92b0646e99b2f51 | |
parent | b1e81d83dab05686d0cbb8cec914870a27daebd9 (diff) | |
download | tf-a-tests-1d203f17d15f613aac7169399c3fb32667707ea1.tar.gz |
cactus: testing deadlock by FF-A direct message
Added command CACTUS_DEADLOCK_CMD to file cactus_test_cmds.h to create
a deadlock scenario using FF-A direct message interfaces.
Added command CACTUS_REQ_DEADLOCK_CMD to trigger the sequence
of CACTUS_DEADLOCK_CMD necessary for the deadlock to occur.
Handled both commands in cactus message loop.
The purpose is to verify a deadlock by FF-A direct messaging cannot
happen in Hafnium implementation.
Signed-off-by: J-Alves <joao.alves@arm.com>
Change-Id: Ia5d6e92a955cd73d8997edaeef055f7b8184850e
-rw-r--r-- | spm/cactus/cactus_main.c | 67 | ||||
-rw-r--r-- | spm/cactus/cactus_test_cmds.h | 30 |
2 files changed, 96 insertions, 1 deletions
diff --git a/spm/cactus/cactus_main.c b/spm/cactus/cactus_main.c index 7900e7f39..da7e9139f 100644 --- a/spm/cactus/cactus_main.c +++ b/spm/cactus/cactus_main.c @@ -44,6 +44,8 @@ static void __dead2 message_loop(ffa_vm_id_t vm_id, struct mailbox_buffers *mb) uint32_t sp_response; ffa_vm_id_t source; ffa_vm_id_t destination; + uint64_t cactus_cmd; + /* * This initial wait call is necessary to inform SPMD that @@ -80,7 +82,9 @@ static void __dead2 message_loop(ffa_vm_id_t vm_id, struct mailbox_buffers *mb) PRINT_CMD(ffa_ret); - switch (CACTUS_GET_CMD(ffa_ret)) { + cactus_cmd = CACTUS_GET_CMD(ffa_ret); + + switch (cactus_cmd) { case FFA_MEM_SHARE_SMC32: case FFA_MEM_LEND_SMC32: case FFA_MEM_DONATE_SMC32: @@ -133,6 +137,67 @@ static void __dead2 message_loop(ffa_vm_id_t vm_id, struct mailbox_buffers *mb) CACTUS_ERROR_RESP(vm_id, source); break; } + case CACTUS_DEADLOCK_CMD: + case CACTUS_REQ_DEADLOCK_CMD: + { + ffa_vm_id_t deadlock_dest = + CACTUS_DEADLOCK_GET_NEXT_DEST(ffa_ret); + ffa_vm_id_t deadlock_next_dest = source; + + if (cactus_cmd == CACTUS_DEADLOCK_CMD) { + VERBOSE("%x is creating deadlock. next: %x\n", + source, deadlock_dest); + } else if (cactus_cmd == CACTUS_REQ_DEADLOCK_CMD) { + VERBOSE( + "%x requested deadlock with %x and %x\n", + source, deadlock_dest, deadlock_next_dest); + + deadlock_next_dest = + CACTUS_DEADLOCK_GET_NEXT_DEST2(ffa_ret); + } + + ffa_ret = CACTUS_DEADLOCK_SEND_CMD(vm_id, deadlock_dest, + deadlock_next_dest); + + /* + * Should be true for the last partition to attempt + * an FF-A direct message, to the first partition. + */ + bool is_deadlock_detected = + (ffa_ret.ret0 == FFA_ERROR) && + (ffa_ret.ret2 == FFA_ERROR_BUSY); + + /* + * Should be true after the deadlock has been detected + * and after the first response has been sent down the + * request chain. + */ + bool is_returning_from_deadlock = + (ffa_ret.ret0 == FFA_MSG_SEND_DIRECT_RESP_SMC32) + && (CACTUS_IS_SUCCESS_RESP(ffa_ret)); + + if (is_deadlock_detected) { + NOTICE("Attempting dealock but got error %lx\n", + ffa_ret.ret2); + } + + if (is_deadlock_detected || + is_returning_from_deadlock) { + /* + * This is not the partition, that would have + * created the deadlock. As such, reply back + * to the partitions. + */ + ffa_ret = CACTUS_SUCCESS_RESP(vm_id, source); + break; + } + + /* Shouldn't get to this point */ + ERROR("Deadlock test went wrong!\n"); + ffa_ret = CACTUS_ERROR_RESP(vm_id, source); + + break; + } default: /* * Currently direct message test is handled here. diff --git a/spm/cactus/cactus_test_cmds.h b/spm/cactus/cactus_test_cmds.h index 52aa55bf7..3e16e579b 100644 --- a/spm/cactus/cactus_test_cmds.h +++ b/spm/cactus/cactus_test_cmds.h @@ -64,6 +64,36 @@ #define CACTUS_REQ_ECHO_GET_ECHO_DEST(smc_ret) smc_ret.ret5 /** + * Command to create a cyclic dependency between SPs, which could result in + * a deadlock. This aims at proving such scenario cannot happen. + * If the deadlock happens, the system will just hang. + * If the deadlock is prevented, the last partition to use the command will + * send response CACTUS_SUCCESS. + * + * The id is the hex representation of the string 'dead'. + */ +#define CACTUS_DEADLOCK_CMD U(0x64656164) + +#define CACTUS_DEADLOCK_SEND_CMD(source, dest, next_dest) \ + CACTUS_SEND_CMD(source, dest, CACTUS_DEADLOCK_CMD, next_dest, \ + 0, 0, 0) + +#define CACTUS_DEADLOCK_GET_NEXT_DEST(smc_ret) smc_ret.ret4 + +/** + * Command to request a sequence CACTUS_DEADLOCK_CMD between the partitions + * of specified IDs. + */ +#define CACTUS_REQ_DEADLOCK_CMD (CACTUS_DEADLOCK_CMD + 1) + +#define CACTUS_REQ_DEADLOCK_SEND_CMD(source, dest, next_dest1, next_dest2) \ + CACTUS_SEND_CMD(source, dest, CACTUS_REQ_DEADLOCK_CMD, \ + next_dest1, next_dest2, 0, 0) + +/*To get next_dest1 use CACTUS_DEADLOCK_GET_NEXT_DEST*/ +#define CACTUS_DEADLOCK_GET_NEXT_DEST2(smc_ret) smc_ret.ret5 + +/** * Command to notify cactus of a memory management operation. The cmd value * should be the memory management smc function id. */ |