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