1 /*
2  * Copyright 2021 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 "hf/dlog.h"
10 #include "hf/ffa.h"
11 #include "hf/ffa_v1_0.h"
12 
13 #include "vmapi/hf/call.h"
14 
15 #include "ffa_secure_partitions.h"
16 #include "partition_services.h"
17 #include "test/hftest.h"
18 #include "test/vmapi/ffa.h"
19 
TEAR_DOWN(ffa)20 TEAR_DOWN(ffa)
21 {
22 	EXPECT_FFA_ERROR(ffa_rx_release(), FFA_DENIED);
23 }
24 
check_v1_1_partition_info_descriptors(const struct ffa_partition_info * partitions)25 static void check_v1_1_partition_info_descriptors(
26 	const struct ffa_partition_info *partitions)
27 {
28 	struct ffa_uuid uuid;
29 
30 	/* Expect the PVM as first partition. */
31 	EXPECT_EQ(partitions[0].vm_id, hf_vm_get_id());
32 	EXPECT_EQ(partitions[0].vcpu_count, 8);
33 	ffa_uuid_init(0xb4b5671e, 0x4a904fe1, 0xb81ffb13, 0xdae1dacb, &uuid);
34 	EXPECT_TRUE(ffa_uuid_equal(&partitions[0].uuid, &uuid));
35 	EXPECT_EQ(partitions[0].properties,
36 		  FFA_PARTITION_AARCH64_EXEC | FFA_PARTITION_NOTIFICATION |
37 			  FFA_PARTITION_INDIRECT_MSG |
38 			  FFA_PARTITION_DIRECT_REQ_SEND);
39 
40 	/* Expect a primary SP as second partition. */
41 	EXPECT_EQ(partitions[1].vm_id, SP_ID(1));
42 	EXPECT_TRUE(partitions[1].vcpu_count == 8 ||
43 		    partitions[1].vcpu_count == 1);
44 	ffa_uuid_init(0x9458bb2d, 0x353b4ee2, 0xaa25710c, 0x99b73ddc, &uuid);
45 	EXPECT_TRUE(ffa_uuid_equal(&partitions[1].uuid, &uuid));
46 	EXPECT_EQ(partitions[1].properties,
47 		  FFA_PARTITION_AARCH64_EXEC | FFA_PARTITION_NOTIFICATION |
48 			  FFA_PARTITION_DIRECT_REQ_RECV);
49 
50 	/* Expect a secondary SP as third partition. */
51 	EXPECT_EQ(partitions[2].vm_id, SP_ID(2));
52 	EXPECT_TRUE(partitions[1].vcpu_count == 8 ||
53 		    partitions[1].vcpu_count == 1);
54 	ffa_uuid_init(0xa609f132, 0x6b4f, 0x4c14, 0x9489, &uuid);
55 	EXPECT_TRUE(ffa_uuid_equal(&partitions[2].uuid, &uuid));
56 	EXPECT_EQ(partitions[2].properties,
57 		  FFA_PARTITION_AARCH64_EXEC | FFA_PARTITION_NOTIFICATION |
58 			  FFA_PARTITION_DIRECT_REQ_RECV);
59 
60 	/* Expect a tertiary SP as fourth partition. */
61 	EXPECT_EQ(partitions[3].vm_id, SP_ID(3));
62 	EXPECT_TRUE(partitions[3].vcpu_count == 8);
63 	ffa_uuid_init(0x1df938ef, 0xe8b94490, 0x84967204, 0xab77f4a5, &uuid);
64 	EXPECT_TRUE(ffa_uuid_equal(&partitions[3].uuid, &uuid));
65 	EXPECT_EQ(partitions[3].properties,
66 		  FFA_PARTITION_AARCH64_EXEC | FFA_PARTITION_NOTIFICATION |
67 			  FFA_PARTITION_DIRECT_REQ_RECV);
68 }
69 
TEST(ffa,ffa_partition_info_get_regs_sp_test)70 TEST(ffa, ffa_partition_info_get_regs_sp_test)
71 {
72 	const ffa_id_t receiver_id = SP_ID(1);
73 	struct ffa_value res;
74 	ffa_id_t own_id = hf_vm_get_id();
75 
76 	res = sp_check_partition_info_get_regs_cmd_send(own_id, receiver_id);
77 
78 	EXPECT_EQ(res.func, FFA_MSG_SEND_DIRECT_RESP_32);
79 	EXPECT_EQ(sp_resp(res), SP_SUCCESS);
80 }
81 
TEST(ffa,ffa_partition_info_get_regs_uuid_null)82 TEST(ffa, ffa_partition_info_get_regs_uuid_null)
83 {
84 	struct ffa_value ret;
85 	uint16_t start_index = 0;
86 	struct ffa_uuid uuid;
87 	struct ffa_partition_info partition_info[4];
88 	uint16_t last_index;
89 	uint16_t curr_index;
90 	uint16_t tag;
91 	uint16_t desc_size;
92 
93 	/*
94 	 * A Null UUID requests information for all partitions
95 	 * including VMs and SPs.
96 	 */
97 	ffa_uuid_init(0, 0, 0, 0, &uuid);
98 
99 	/* Check that expected partition information is returned. */
100 	ret = ffa_partition_info_get_regs(&uuid, start_index, 0);
101 	EXPECT_EQ(ret.func, FFA_SUCCESS_64);
102 
103 	last_index = ffa_partition_info_regs_get_last_idx(ret);
104 	curr_index = ffa_partition_info_regs_get_curr_idx(ret);
105 	tag = ffa_partition_info_regs_get_tag(ret);
106 	desc_size = ffa_partition_info_regs_get_desc_size(ret);
107 
108 	/* Expect four partitions, one VM (primary), three SPs) */
109 	EXPECT_EQ(last_index, 3);
110 	EXPECT_EQ(curr_index, 3);
111 	EXPECT_EQ(tag, 0);
112 	EXPECT_EQ(desc_size, sizeof(struct ffa_partition_info));
113 
114 	ffa_partition_info_regs_get_part_info(ret, 0, &partition_info[0]);
115 	ffa_partition_info_regs_get_part_info(ret, 1, &partition_info[1]);
116 	ffa_partition_info_regs_get_part_info(ret, 2, &partition_info[2]);
117 	ffa_partition_info_regs_get_part_info(ret, 3, &partition_info[3]);
118 
119 	check_v1_1_partition_info_descriptors(partition_info);
120 }
121 
TEST(ffa,ffa_partition_info_get_uuid_null)122 TEST(ffa, ffa_partition_info_get_uuid_null)
123 {
124 	struct mailbox_buffers mb;
125 	struct ffa_value ret;
126 	const struct ffa_partition_info *partitions;
127 	struct ffa_uuid uuid;
128 
129 	/* Setup the mailbox (which holds the RX buffer). */
130 	mb = set_up_mailbox();
131 	partitions = mb.recv;
132 
133 	/*
134 	 * A Null UUID requests information for all partitions
135 	 * including VMs and SPs.
136 	 */
137 	ffa_uuid_init(0, 0, 0, 0, &uuid);
138 
139 	/* Check that expected partition information is returned. */
140 	ret = ffa_partition_info_get(&uuid, 0);
141 	EXPECT_EQ(ret.func, FFA_SUCCESS_32);
142 
143 	/* Expect four partitions. */
144 	EXPECT_EQ(ret.arg2, 4);
145 
146 	/*
147 	 * Check the partition info descriptor size returned in w3 is
148 	 * correct.
149 	 */
150 	EXPECT_EQ(ret.arg3, sizeof(struct ffa_partition_info));
151 
152 	/* Expect the PVM as first partition. */
153 	check_v1_1_partition_info_descriptors(partitions);
154 
155 	EXPECT_EQ(ffa_rx_release().func, FFA_SUCCESS_32);
156 }
157 
TEST(ffa,ffa_partition_info_get_count_flag)158 TEST(ffa, ffa_partition_info_get_count_flag)
159 {
160 	struct ffa_value ret;
161 	struct ffa_uuid uuid;
162 
163 	ffa_uuid_init(0, 0, 0, 0, &uuid);
164 
165 	ret = ffa_partition_info_get(&uuid, FFA_PARTITION_COUNT_FLAG);
166 	EXPECT_EQ(ret.func, FFA_SUCCESS_32);
167 
168 	/* Expect four partitions. */
169 	EXPECT_EQ(ret.arg2, 4);
170 
171 	/* Check when the count flag is set w3 MBZ. */
172 	EXPECT_EQ(ret.arg3, 0);
173 }
174 
TEST(ffa,ffa_partition_info_get_flags_mbz_fail)175 TEST(ffa, ffa_partition_info_get_flags_mbz_fail)
176 {
177 	struct ffa_value ret;
178 	struct ffa_uuid uuid;
179 
180 	ffa_uuid_init(0, 0, 0, 0, &uuid);
181 
182 	ret = ffa_partition_info_get(&uuid, 0xffff);
183 	EXPECT_FFA_ERROR(ret, FFA_INVALID_PARAMETERS);
184 }
185 
TEST(ffa,ffa_partition_info_get_uuid_fixed)186 TEST(ffa, ffa_partition_info_get_uuid_fixed)
187 {
188 	struct mailbox_buffers mb;
189 	struct ffa_value ret;
190 	const struct ffa_partition_info *partitions;
191 	struct ffa_uuid uuid;
192 
193 	/* Setup the mailbox (which holds the RX buffer). */
194 	mb = set_up_mailbox();
195 	partitions = mb.recv;
196 
197 	/* Search for a known secure partition UUID. */
198 	ffa_uuid_init(0xa609f132, 0x6b4f, 0x4c14, 0x9489, &uuid);
199 
200 	/* Check that a partition count of 1 is returned. */
201 	ret = ffa_partition_info_get(&uuid, FFA_PARTITION_COUNT_FLAG);
202 	EXPECT_EQ(ret.func, FFA_SUCCESS_32);
203 
204 	/* Expect one partition. */
205 	EXPECT_EQ(ret.arg2, 1);
206 
207 	/* Check when the count flag is set w3 MBZ. */
208 	EXPECT_EQ(ret.arg3, 0);
209 
210 	/* And that the buffer is zero */
211 	EXPECT_EQ(partitions[0].vm_id, 0);
212 	EXPECT_EQ(partitions[0].vcpu_count, 0);
213 
214 	/* Check that the expected partition information is returned. */
215 	ret = ffa_partition_info_get(&uuid, 0);
216 	EXPECT_EQ(ret.func, FFA_SUCCESS_32);
217 
218 	/* Expect one partition. */
219 	EXPECT_EQ(ret.arg2, 1);
220 
221 	/*
222 	 * Check the partition info descriptor size returned in w3 is
223 	 * correct.
224 	 */
225 	EXPECT_EQ(ret.arg3, sizeof(struct ffa_partition_info));
226 
227 	/* Expect a secure partition. */
228 	EXPECT_EQ(partitions[0].vm_id, HF_SPMC_VM_ID + 2);
229 	EXPECT_TRUE(partitions[0].vcpu_count == 8 ||
230 		    partitions[0].vcpu_count == 1);
231 	EXPECT_EQ(partitions[0].properties,
232 		  FFA_PARTITION_AARCH64_EXEC | FFA_PARTITION_NOTIFICATION |
233 			  FFA_PARTITION_DIRECT_REQ_RECV);
234 
235 	/*
236 	 * If a uuid is specified (not null) ensure the uuid returned in the
237 	 * partition info descriptor is zeroed.
238 	 */
239 	EXPECT_TRUE(ffa_uuid_is_null(&partitions[0].uuid));
240 
241 	EXPECT_EQ(ffa_rx_release().func, FFA_SUCCESS_32);
242 }
243 
TEST(ffa,ffa_partition_info_get_uuid_unknown)244 TEST(ffa, ffa_partition_info_get_uuid_unknown)
245 {
246 	struct ffa_value ret;
247 	struct ffa_uuid uuid;
248 
249 	/* Search for a unknown partition UUID. */
250 	ffa_uuid_init(1, 1, 1, 1, &uuid);
251 
252 	/* Expect no partition is found with such UUID. */
253 	ret = ffa_partition_info_get(&uuid, 0);
254 	EXPECT_EQ(ret.func, FFA_ERROR_32);
255 }
256 
TEST(ffa,ffa_partition_info_get_v1_0_descriptors)257 TEST(ffa, ffa_partition_info_get_v1_0_descriptors)
258 {
259 	struct mailbox_buffers mb;
260 	struct ffa_value ret;
261 	const struct ffa_partition_info_v1_0 *partitions_v1_0;
262 	struct ffa_uuid uuid;
263 	enum ffa_version version;
264 
265 	/*
266 	 * First call FF-A version to tell the SPMC our version
267 	 * is v1.0.
268 	 */
269 	version = ffa_version(FFA_VERSION_1_0);
270 	EXPECT_EQ(version, FFA_VERSION_COMPILED);
271 
272 	/* Setup the mailbox (which holds the RX buffer). */
273 	mb = set_up_mailbox();
274 
275 	partitions_v1_0 = mb.recv;
276 
277 	/*
278 	 * A Null UUID requests information for all partitions
279 	 * including VMs and SPs.
280 	 */
281 	ffa_uuid_init(0, 0, 0, 0, &uuid);
282 
283 	/* Check that expected partition information is returned. */
284 	ret = ffa_partition_info_get(&uuid, 0);
285 	EXPECT_EQ(ret.func, FFA_SUCCESS_32);
286 
287 	/* Expect four partitions. */
288 	EXPECT_EQ(ret.arg2, 4);
289 
290 	/*
291 	 * Check the partition info descriptor size returned in w3 is
292 	 * correct.
293 	 */
294 	EXPECT_EQ(ret.arg3, sizeof(struct ffa_partition_info_v1_0));
295 
296 	/* Expect the PVM as first partition. */
297 	EXPECT_EQ(partitions_v1_0[0].vm_id, hf_vm_get_id());
298 	EXPECT_TRUE(partitions_v1_0[0].vcpu_count == 8 ||
299 		    partitions_v1_0[0].vcpu_count == 1);
300 	EXPECT_EQ(partitions_v1_0[0].properties,
301 		  FFA_PARTITION_INDIRECT_MSG | FFA_PARTITION_DIRECT_REQ_SEND);
302 	EXPECT_EQ(partitions_v1_0[0].properties & FFA_PARTITION_v1_0_RES_MASK,
303 		  0);
304 
305 	/* Expect a primary SP as second partition. */
306 	EXPECT_EQ(partitions_v1_0[1].vm_id, SP_ID(1));
307 	EXPECT_EQ(partitions_v1_0[1].vcpu_count, 8);
308 	EXPECT_EQ(partitions_v1_0[1].properties, FFA_PARTITION_DIRECT_REQ_RECV);
309 	EXPECT_EQ(partitions_v1_0[1].properties & FFA_PARTITION_v1_0_RES_MASK,
310 		  0);
311 
312 	/* Expect a secondary SP as third partition. */
313 	EXPECT_EQ(partitions_v1_0[2].vm_id, SP_ID(2));
314 	EXPECT_TRUE(partitions_v1_0[2].vcpu_count == 8 ||
315 		    partitions_v1_0[2].vcpu_count == 1);
316 	EXPECT_EQ(partitions_v1_0[2].properties, FFA_PARTITION_DIRECT_REQ_RECV);
317 	EXPECT_EQ(partitions_v1_0[2].properties & FFA_PARTITION_v1_0_RES_MASK,
318 		  0);
319 
320 	/* Expect a tertiary SP as fourth partition. */
321 	EXPECT_EQ(partitions_v1_0[3].vm_id, SP_ID(3));
322 	EXPECT_EQ(partitions_v1_0[3].vcpu_count, 8);
323 	EXPECT_EQ(partitions_v1_0[3].properties, FFA_PARTITION_DIRECT_REQ_RECV);
324 	EXPECT_EQ(partitions_v1_0[3].properties & FFA_PARTITION_v1_0_RES_MASK,
325 		  0);
326 
327 	EXPECT_EQ(ffa_rx_release().func, FFA_SUCCESS_32);
328 }
329 
330 /*
331  * Check FFA_SPM_ID_GET response.
332  * DEN0077A FF-A v1.1 Beta0 section 13.9 FFA_SPM_ID_GET.
333  */
TEST(ffa,ffa_spm_id_get)334 TEST(ffa, ffa_spm_id_get)
335 {
336 	struct ffa_value ret = ffa_spm_id_get();
337 
338 	EXPECT_EQ(ret.func, FFA_SUCCESS_32);
339 
340 	/* Expect the SPMC FF-A ID at NS virtual FF-A instance. */
341 	EXPECT_EQ(ret.arg2, HF_SPMC_VM_ID);
342 }
343 
TEST_PRECONDITION(ffa,npi_not_supported,service2_is_el0)344 TEST_PRECONDITION(ffa, npi_not_supported, service2_is_el0)
345 {
346 	const ffa_id_t own_id = hf_vm_get_id();
347 	/* SP is expected to be S-EL0 partition */
348 	const ffa_id_t receiver_id = SP_ID(2);
349 	struct ffa_value res;
350 
351 	res = sp_ffa_features_cmd_send(own_id, receiver_id, FFA_FEATURE_NPI);
352 	EXPECT_EQ(res.func, FFA_MSG_SEND_DIRECT_RESP_32);
353 	EXPECT_EQ(res.arg3, FFA_ERROR_32);
354 	EXPECT_EQ((int32_t)res.arg4, FFA_NOT_SUPPORTED);
355 }
356