1 /*
2  * Copyright 2022 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 
9 #include <stdint.h>
10 
11 #include "hf/ffa.h"
12 #include "hf/std.h"
13 
14 #include "vmapi/hf/call.h"
15 
16 #include "primary_with_secondary.h"
17 #include "test/hftest.h"
18 #include "test/vmapi/ffa.h"
19 
SET_UP(indirect_messaging)20 SET_UP(indirect_messaging)
21 {
22 	/* Call FFA_VERSION to inform the hypervisor we are v1.1. */
23 	ffa_version(MAKE_FFA_VERSION(1, 1));
24 }
25 
26 /**
27  * Send and receive the same message from the echo VM using
28  * FFA v1.1 FFA_MSG_SEND2 ABI.
29  */
TEST(indirect_messaging,echo)30 TEST(indirect_messaging, echo)
31 {
32 	struct ffa_value ret;
33 	struct mailbox_buffers mb;
34 	const uint32_t payload = 0xAA55AA55;
35 	struct ffa_partition_msg *echo;
36 	const uint32_t *echo_payload;
37 	ffa_vm_id_t own_id = hf_vm_get_id();
38 
39 	mb = set_up_mailbox();
40 	SERVICE_SELECT(SERVICE_VM1, "echo_msg_send2", mb.send);
41 
42 	/* Send the message. */
43 	ret = send_indirect_message(own_id, SERVICE_VM1, mb.send, &payload,
44 				    sizeof(payload), 0);
45 	EXPECT_EQ(ret.func, FFA_SUCCESS_32);
46 
47 	/* Schedule message receiver. */
48 	ret = ffa_run(SERVICE_VM1, 0);
49 	EXPECT_EQ(ret.func, FFA_YIELD_32);
50 
51 	/* Check notification. */
52 	ret = ffa_notification_get(own_id, 0, FFA_NOTIFICATION_FLAG_BITMAP_HYP);
53 	ASSERT_EQ(ret.func, FFA_SUCCESS_32);
54 	ASSERT_TRUE(is_ffa_hyp_buffer_full_notification(
55 		ffa_notification_get_from_framework(ret)));
56 
57 	echo = (struct ffa_partition_msg *)mb.recv;
58 	echo_payload = (const uint32_t *)echo->payload;
59 	HFTEST_LOG("Message echoed back: %#x", *echo_payload);
60 	EXPECT_EQ(*echo_payload, payload);
61 
62 	EXPECT_EQ(ffa_rx_release().func, FFA_SUCCESS_32);
63 }
64 
65 /** Sender haven't mapped TX buffer. */
TEST(indirect_messaging,unmapped_tx)66 TEST(indirect_messaging, unmapped_tx)
67 {
68 	struct ffa_value ret;
69 	struct mailbox_buffers mb;
70 	const uint32_t payload = 0xAA55AA55;
71 	ffa_vm_id_t own_id = hf_vm_get_id();
72 
73 	mb = set_up_mailbox();
74 	SERVICE_SELECT(SERVICE_VM1, "ffa_indirect_msg_error", mb.send);
75 
76 	EXPECT_EQ(ffa_rxtx_unmap().func, FFA_SUCCESS_32);
77 
78 	/* Send the message. */
79 	ret = send_indirect_message(own_id, SERVICE_VM1, mb.send, &payload,
80 				    sizeof(payload), 0);
81 	EXPECT_FFA_ERROR(ret, FFA_DENIED);
82 }
83 
84 /** Receiver haven't mapped RX buffer. */
TEST(indirect_messaging,unmapped_rx)85 TEST(indirect_messaging, unmapped_rx)
86 {
87 	struct ffa_value ret;
88 	struct mailbox_buffers mb;
89 	const uint32_t payload = 0xAA55AA55;
90 	ffa_vm_id_t own_id = hf_vm_get_id();
91 
92 	mb = set_up_mailbox();
93 	SERVICE_SELECT(SERVICE_VM1, "ffa_indirect_msg_error", mb.send);
94 
95 	/* Schedule message receiver. */
96 	ret = ffa_run(SERVICE_VM1, 0);
97 	EXPECT_EQ(ret.func, FFA_MSG_WAIT_32);
98 
99 	/* Send the message. */
100 	ret = send_indirect_message(own_id, SERVICE_VM1, mb.send, &payload,
101 				    sizeof(payload), 0);
102 	EXPECT_FFA_ERROR(ret, FFA_BUSY);
103 }
104 
105 /** Receiver haven't read a previous message. */
TEST(indirect_messaging,unread_message)106 TEST(indirect_messaging, unread_message)
107 {
108 	struct ffa_value ret;
109 	struct mailbox_buffers mb;
110 	const uint32_t payload = 0xAA55AA55;
111 	ffa_vm_id_t own_id = hf_vm_get_id();
112 
113 	mb = set_up_mailbox();
114 	SERVICE_SELECT(SERVICE_VM1, "ffa_indirect_msg_error", mb.send);
115 
116 	/* Send the message. */
117 	ret = send_indirect_message(own_id, SERVICE_VM1, mb.send, &payload,
118 				    sizeof(payload), 0);
119 	EXPECT_EQ(ret.func, FFA_SUCCESS_32);
120 
121 	/* Immediately send another message. */
122 	ret = send_indirect_message(own_id, SERVICE_VM1, mb.send, &payload,
123 				    sizeof(payload), 0);
124 	EXPECT_FFA_ERROR(ret, FFA_BUSY);
125 }
126 
msg_send2_invalid_parameters(ffa_vm_id_t sender,ffa_vm_id_t receiver,uint32_t size)127 static void msg_send2_invalid_parameters(ffa_vm_id_t sender,
128 					 ffa_vm_id_t receiver, uint32_t size)
129 {
130 	struct ffa_value ret;
131 	struct mailbox_buffers mb;
132 	struct ffa_partition_msg *message;
133 
134 	mb = set_up_mailbox();
135 	SERVICE_SELECT(SERVICE_VM1, "ffa_indirect_msg_error", mb.send);
136 
137 	message = (struct ffa_partition_msg *)mb.send;
138 	ffa_rxtx_header_init(sender, receiver, size, &message->header);
139 
140 	/* The header is expected to be invalid, do not set any payload. */
141 
142 	ret = ffa_msg_send2(0);
143 	EXPECT_FFA_ERROR(ret, FFA_INVALID_PARAMETERS);
144 }
145 
146 /** Sender sends message with a non existing VM IDs. */
TEST(indirect_messaging,non_existing_sender)147 TEST(indirect_messaging, non_existing_sender)
148 {
149 	msg_send2_invalid_parameters(SERVICE_VM2, SERVICE_VM1, 0);
150 }
151 
152 /** Sender sends message with another sender VM IDs. */
TEST(indirect_messaging,corrupted_sender)153 TEST(indirect_messaging, corrupted_sender)
154 {
155 	ffa_vm_id_t own_id = hf_vm_get_id();
156 	msg_send2_invalid_parameters(SERVICE_VM1, own_id, 0);
157 }
158 
159 /** Sender sends message to itself. */
TEST(indirect_messaging,self_message)160 TEST(indirect_messaging, self_message)
161 {
162 	ffa_vm_id_t own_id = hf_vm_get_id();
163 	msg_send2_invalid_parameters(own_id, own_id, 0);
164 }
165 
166 /** Sender sends message with invalid size. */
TEST(indirect_messaging,invalid_size)167 TEST(indirect_messaging, invalid_size)
168 {
169 	ffa_vm_id_t own_id = hf_vm_get_id();
170 	msg_send2_invalid_parameters(own_id, SERVICE_VM1, 1024 * 1024);
171 }
172