aboutsummaryrefslogtreecommitdiff
path: root/spm/cactus/cactus_tests/cactus_test_direct_messaging.c
blob: 93bcba170400b876615e8b1882595250ee729983 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
/*
 * Copyright (c) 2021-2022, Arm Limited. All rights reserved.
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */

#include "cactus_message_loop.h"
#include "cactus_test_cmds.h"
#include <debug.h>
#include <ffa_helpers.h>

CACTUS_CMD_HANDLER(echo_cmd, CACTUS_ECHO_CMD)
{
	uint64_t echo_val = cactus_echo_get_val(*args);

	VERBOSE("Received echo at %x, value %llx.\n", ffa_dir_msg_dest(*args),
						      echo_val);

	return cactus_success_resp(ffa_dir_msg_dest(*args),
				   ffa_dir_msg_source(*args),
				   echo_val);
}

CACTUS_CMD_HANDLER(req_echo_cmd, CACTUS_REQ_ECHO_CMD)
{
	struct ffa_value ffa_ret;
	ffa_id_t vm_id = ffa_dir_msg_dest(*args);
	ffa_id_t echo_dest = cactus_req_echo_get_echo_dest(*args);
	uint64_t echo_val = cactus_echo_get_val(*args);

	VERBOSE("%x requested to send echo to %x, value %llx\n",
		ffa_dir_msg_source(*args), echo_dest, echo_val);

	ffa_ret = cactus_echo_send_cmd(vm_id, echo_dest, echo_val);

	if (!is_ffa_direct_response(ffa_ret)) {
		return cactus_error_resp(vm_id, ffa_dir_msg_source(*args),
					 CACTUS_ERROR_FFA_CALL);
	}

	if (cactus_get_response(ffa_ret) != CACTUS_SUCCESS ||
	    cactus_echo_get_val(ffa_ret) != echo_val) {
		ERROR("Echo Failed!\n");
		return cactus_error_resp(vm_id, ffa_dir_msg_source(*args),
					 CACTUS_ERROR_TEST);
	}

	return cactus_success_resp(vm_id, ffa_dir_msg_source(*args), 0);
}

static struct ffa_value base_deadlock_handler(ffa_id_t vm_id,
					      ffa_id_t source,
					      ffa_id_t deadlock_dest,
					      ffa_id_t deadlock_next_dest)
{
	struct ffa_value 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_func_id(ffa_ret) == FFA_ERROR) &&
				    (ffa_error_code(ffa_ret) == 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 =
		(is_ffa_direct_response(ffa_ret)) &&
		(cactus_get_response(ffa_ret) == CACTUS_SUCCESS);

	if (is_deadlock_detected) {
		VERBOSE("Attempt to create deadlock failed\n");
	}

	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.
		 */
		return cactus_success_resp(vm_id, source, 0);
	}

	/* Shouldn't get to this point */
	ERROR("Deadlock test went wrong!\n");
	return cactus_error_resp(vm_id, source, CACTUS_ERROR_TEST);
}

CACTUS_CMD_HANDLER(deadlock_cmd, CACTUS_DEADLOCK_CMD)
{
	ffa_id_t source = ffa_dir_msg_source(*args);
	ffa_id_t deadlock_dest = cactus_deadlock_get_next_dest(*args);
	ffa_id_t deadlock_next_dest = source;

	VERBOSE("%x is creating deadlock. next: %x\n", source, deadlock_dest);

	return base_deadlock_handler(ffa_dir_msg_dest(*args), source,
				      deadlock_dest, deadlock_next_dest);
}

CACTUS_CMD_HANDLER(req_deadlock_cmd, CACTUS_REQ_DEADLOCK_CMD)
{
	ffa_id_t vm_id = ffa_dir_msg_dest(*args);
	ffa_id_t source = ffa_dir_msg_source(*args);
	ffa_id_t deadlock_dest = cactus_deadlock_get_next_dest(*args);
	ffa_id_t deadlock_next_dest = cactus_deadlock_get_next_dest2(*args);

	VERBOSE("%x requested deadlock with %x and %x\n",
		ffa_dir_msg_source(*args), deadlock_dest, deadlock_next_dest);

	return base_deadlock_handler(vm_id, source, deadlock_dest, deadlock_next_dest);
}