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