aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--spm/cactus/cactus_main.c67
-rw-r--r--spm/cactus/cactus_test_cmds.h30
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.
*/