blob: 14be340db7bd6e0038fcd91dbe79554d965802b0 [file] [log] [blame]
Manish Pandey5f513d62022-01-17 11:05:53 +00001/*
2 * Copyright (c) 2022, Arm Limited. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
Olivier Deprez82bbc572022-01-11 11:50:36 +01007#include <plat/common/platform.h>
8
Manish Pandey5f513d62022-01-17 11:05:53 +00009#include <arch.h>
10#include <arch_helpers.h>
11#include <arch_features.h>
12#include <debug.h>
13#ifdef __aarch64__
14#include <sync.h>
15#endif
16#include <test_helpers.h>
Olivier Deprez82bbc572022-01-11 11:50:36 +010017#include <lib/aarch64/arch_features.h>
18#include <runtime_services/realm_payload/realm_payload_test.h>
Manish Pandey5f513d62022-01-17 11:05:53 +000019#include <tftf_lib.h>
Manish Pandey368054b2022-03-15 13:24:59 +000020#include <xlat_tables_v2.h>
21
Manish Pandey5f513d62022-01-17 11:05:53 +000022#include <platform_def.h>
nabkah0146b418d2022-02-16 17:01:54 +000023#include <cactus_test_cmds.h>
24#include <ffa_endpoints.h>
25
Manish Pandey5f513d62022-01-17 11:05:53 +000026
27/*
28 * Using "__aarch64__" here looks weird but its unavoidable because of following reason
29 * This test is part of standard test which runs on all platforms but pre-requisite
30 * to run this test (custom sync exception handler) is only implemented for aarch64.
31 * TODO: Write a framework so that tests kept in standard list can be selectively
32 * run on a given architecture
33 */
34#ifdef __aarch64__
35
nabkah0146b418d2022-02-16 17:01:54 +000036#define SENDER HYP_ID
37#define RECEIVER SP_ID(1)
38
Manish Pandey5f513d62022-01-17 11:05:53 +000039static volatile bool sync_exception_triggered;
40static volatile bool data_abort_triggered;
nabkah0146b418d2022-02-16 17:01:54 +000041static const struct ffa_uuid expected_sp_uuids[] = {
42 {PRIMARY_UUID}, {SECONDARY_UUID}, {TERTIARY_UUID}
43};
Manish Pandey5f513d62022-01-17 11:05:53 +000044
Olivier Deprez82bbc572022-01-11 11:50:36 +010045static __aligned(PAGE_SIZE) uint64_t share_page[PAGE_SIZE / sizeof(uint64_t)];
46
Manish Pandey5f513d62022-01-17 11:05:53 +000047static bool data_abort_handler(void)
48{
49 uint64_t esr_elx = IS_IN_EL2() ? read_esr_el2() : read_esr_el1();
50 unsigned int rme_supported = get_armv9_2_feat_rme_support();
51
52 sync_exception_triggered = true;
53
54 VERBOSE("%s esr_elx %llx\n", __func__, esr_elx);
55
56 if (EC_BITS(esr_elx) == EC_DABORT_CUR_EL) {
57 if (rme_supported == 0) {
58 /* Synchronous external data abort triggered by trustzone controller */
59 if ((ISS_BITS(esr_elx) & ISS_DFSC_MASK) == DFSC_EXT_DABORT) {
60 VERBOSE("%s TZC Data Abort caught\n", __func__);
61 data_abort_triggered = true;
62 return true;
63 }
64 } else {
65 /* Synchronous data abort triggered by Granule protection */
66 if ((ISS_BITS(esr_elx) & ISS_DFSC_MASK) == DFSC_GPF_DABORT) {
67 VERBOSE("%s GPF Data Abort caught\n", __func__);
68 data_abort_triggered = true;
69 return true;
70 }
71 }
72 }
73
74 return false;
75}
76
nabkah01bf00f8d2022-03-22 12:37:19 +000077test_result_t el3_memory_cannot_be_accessed_in_ns(void)
Manish Pandey5f513d62022-01-17 11:05:53 +000078{
79 const uintptr_t test_address = EL3_MEMORY_ACCESS_ADDR;
80
Manish Pandey5f513d62022-01-17 11:05:53 +000081 VERBOSE("Attempt to access el3 memory (0x%lx)\n", test_address);
82
Manish Pandey368054b2022-03-15 13:24:59 +000083 sync_exception_triggered = false;
Manish Pandey5f513d62022-01-17 11:05:53 +000084 data_abort_triggered = false;
Manish Pandey368054b2022-03-15 13:24:59 +000085
86 int rc = mmap_add_dynamic_region(test_address, test_address, PAGE_SIZE,
87 MT_MEMORY | MT_RW | MT_NS);
88 if (rc != 0) {
89 tftf_testcase_printf("%d: mmap_add_dynamic_region() = %d\n", __LINE__, rc);
90 return TEST_RESULT_FAIL;
91 }
92
Manish Pandey5f513d62022-01-17 11:05:53 +000093 register_custom_sync_exception_handler(data_abort_handler);
Manish Pandey5f513d62022-01-17 11:05:53 +000094 *((volatile uint64_t *)test_address);
Manish Pandey5f513d62022-01-17 11:05:53 +000095 unregister_custom_sync_exception_handler();
96
Manish Pandey368054b2022-03-15 13:24:59 +000097 rc = mmap_remove_dynamic_region(test_address, PAGE_SIZE);
98 if (rc != 0) {
99 tftf_testcase_printf("%d: mmap_remove_dynamic_region() = %d\n", __LINE__, rc);
100 return TEST_RESULT_FAIL;
101 }
102
Manish Pandey5f513d62022-01-17 11:05:53 +0000103 if (sync_exception_triggered == false) {
104 tftf_testcase_printf("No sync exception while accessing (0x%lx)\n", test_address);
105 return TEST_RESULT_SKIPPED;
106 }
107
108 if (data_abort_triggered == false) {
109 tftf_testcase_printf("Sync exception is not data abort\n");
110 return TEST_RESULT_FAIL;
111 }
112
113 return TEST_RESULT_SUCCESS;
114}
Olivier Deprez82bbc572022-01-11 11:50:36 +0100115
116/**
117 * @Test_Aim@ Check a realm region cannot be accessed from normal world.
118 *
119 * This test delegates a TFTF allocated buffer to Realm. It then attempts
120 * a read access to the region from normal world. This results in the PE
121 * triggering a GPF caught by a custom synchronous abort handler.
122 *
123 */
124test_result_t rl_memory_cannot_be_accessed_in_ns(void)
125{
126 test_result_t result = TEST_RESULT_FAIL;
127 u_register_t retmm;
128
129 if (get_armv9_2_feat_rme_support() == 0U) {
130 return TEST_RESULT_SKIPPED;
131 }
132
133 sync_exception_triggered = false;
134 data_abort_triggered = false;
135 register_custom_sync_exception_handler(data_abort_handler);
136
137 /* First read access to the test region must not fail. */
138 *((volatile uint64_t *)share_page);
139
140 if ((sync_exception_triggered != false) ||
141 (data_abort_triggered != false)) {
142 goto out_unregister;
143 }
144
145 /* Delegate the shared page to Realm. */
146 retmm = realm_granule_delegate((u_register_t)&share_page);
147 if (retmm != 0UL) {
148 ERROR("Granule delegate failed!\n");
149 goto out_unregister;
150 }
151
152 /* This access shall trigger a GPF. */
153 *((volatile uint64_t *)share_page);
154
155 if ((sync_exception_triggered != true) ||
156 (data_abort_triggered != true)) {
157 goto out_undelegate;
158 }
159
160 result = TEST_RESULT_SUCCESS;
161
162out_undelegate:
163 /* Undelegate the shared page. */
164 retmm = realm_granule_undelegate((u_register_t)&share_page);
165 if (retmm != 0UL) {
166 ERROR("Granule undelegate failed!\n");
167 }
168
169out_unregister:
170 unregister_custom_sync_exception_handler();
171
172 return result;
173}
174
nabkah01bf00f8d2022-03-22 12:37:19 +0000175/**
176 * @Test_Aim@ Check a secure region cannot be accessed from normal world.
177 *
178 * Following test intends to run on RME enabled platforms when EL3
179 * is Root world. In a non RME platform, EL3 is secure.
180 * Access to secure memory from NS world is already covered
181 * by el3_memory_cannot_be_accessed_in_ns.
182 */
183test_result_t s_memory_cannot_be_accessed_in_ns(void)
184{
185 const uintptr_t test_address = SECURE_MEMORY_ACCESS_ADDR;
186
187 /* skipp non RME platforms */
188 if (get_armv9_2_feat_rme_support() == 0U) {
189 return TEST_RESULT_SKIPPED;
190 }
191
192 VERBOSE("Attempt to access secure memory (0x%lx)\n", test_address);
193
194 data_abort_triggered = false;
195 sync_exception_triggered = false;
196 register_custom_sync_exception_handler(data_abort_handler);
197 dsbsy();
198
199 int rc = mmap_add_dynamic_region(test_address, test_address, PAGE_SIZE,
200 MT_MEMORY | MT_RW | MT_NS);
201
202 if (rc != 0) {
203 tftf_testcase_printf("%d: mmap_add_dynamic_region() = %d\n", __LINE__, rc);
204 return TEST_RESULT_FAIL;
205 }
206
207 *((volatile uint64_t *)test_address);
208
209 mmap_remove_dynamic_region(test_address, PAGE_SIZE);
210
211 dsbsy();
212 unregister_custom_sync_exception_handler();
213
214 if (sync_exception_triggered == false) {
215 tftf_testcase_printf("No sync exception while accessing (0x%lx)\n", test_address);
216 return TEST_RESULT_SKIPPED;
217 }
218
219 if (data_abort_triggered == false) {
220 tftf_testcase_printf("Sync exception is not data abort\n");
221 return TEST_RESULT_FAIL;
222 }
223
224 return TEST_RESULT_SUCCESS;
225}
226
nabkah01905b2c72022-02-10 10:46:32 +0000227static test_result_t memory_cannot_be_accessed_in_rl(u_register_t params)
228{
229 u_register_t retrmm;
230 static char rd[GRANULE_SIZE] __aligned(GRANULE_SIZE);
231
232 if (get_armv9_2_feat_rme_support() == 0U) {
233 return TEST_RESULT_SKIPPED;
234 }
235
236 retrmm = realm_version();
237
238 VERBOSE("RMM version is: %lu.%lu\n",
239 RMI_ABI_VERSION_GET_MAJOR(retrmm),
240 RMI_ABI_VERSION_GET_MINOR(retrmm));
241
242 /*
243 * TODO: Remove this once SMC_RMM_REALM_CREATE is implemented in TRP
244 * For the moment skip the test if RMM is TRP, TRP version is always null.
245 */
246 if (retrmm == 0U) {
247 return TEST_RESULT_SKIPPED;
248 }
249
250 retrmm = realm_granule_delegate((u_register_t)&rd[0]);
251 if (retrmm != 0UL) {
252 ERROR("Delegate operation returns fail, %lx\n", retrmm);
253 return TEST_RESULT_FAIL;
254 }
255
256 /* Create a realm using a parameter in a secure physical address space should fail. */
257 retrmm = realm_create((u_register_t)&rd[0], params);
258 if (retrmm == 0UL) {
259 ERROR("Realm create operation should fail, %lx\n", retrmm);
260 retrmm = realm_destroy((u_register_t)&rd[0]);
261 if (retrmm != 0UL) {
262 ERROR("Realm destroy operation returns fail, %lx\n", retrmm);
263 return TEST_RESULT_FAIL;
264 }
265 return TEST_RESULT_FAIL;
266 } else if (retrmm != RMM_STATUS_ERROR_INPUT) {
267 ERROR("Realm create operation should fail with code:%ld retrmm:%ld\n",
268 RMM_STATUS_ERROR_INPUT, retrmm);
269 return TEST_RESULT_FAIL;
270 }
271
272 retrmm = realm_granule_undelegate((u_register_t)&rd[0]);
273 if (retrmm != 0UL) {
274 INFO("Undelegate operation returns fail, %lx\n", retrmm);
275 return TEST_RESULT_FAIL;
276 }
277
278 return TEST_RESULT_SUCCESS;
279}
280
nabkah0146b418d2022-02-16 17:01:54 +0000281/**
282 * @Test_Aim@ Check a root region cannot be accessed from a secure partition.
283 *
284 * This change adds TFTF and cactus test to permit checking a root region
285 * cannot be accessed from secure world.
286 * A hardcoded address marked Root in the GPT is shared to a secure
287 * partition. The SP retrieves the region from the SPM, maps it and
288 * attempts a read access to the region. It is expected to trigger a GPF
289 * data abort on the PE caught by a custom exception handler.
290 *
291 */
292test_result_t rt_memory_cannot_be_accessed_in_s(void)
293{
294 const uintptr_t test_address = EL3_MEMORY_ACCESS_ADDR;
295 struct ffa_memory_region_constituent constituents[] = {
296 {
297 (void *)test_address, 1, 0
298 }
299 };
300 const uint32_t constituents_count = sizeof(constituents) /
301 sizeof(struct ffa_memory_region_constituent);
302 ffa_memory_handle_t handle;
303 struct mailbox_buffers mb;
Daniel Boulbyce386b12022-03-29 18:36:36 +0100304 struct ffa_value ret;
nabkah0146b418d2022-02-16 17:01:54 +0000305
306 if (get_armv9_2_feat_rme_support() == 0U) {
307 return TEST_RESULT_SKIPPED;
308 }
309
310 INIT_TFTF_MAILBOX(mb);
311
312 CHECK_SPMC_TESTING_SETUP(1, 1, expected_sp_uuids);
313
314 GET_TFTF_MAILBOX(mb);
315
316 handle = memory_init_and_send((struct ffa_memory_region *)mb.send,
317 PAGE_SIZE, SENDER, RECEIVER,
318 constituents, constituents_count,
319 FFA_MEM_SHARE_SMC32, &ret);
320
321 if (handle == FFA_MEMORY_HANDLE_INVALID) {
322 return TEST_RESULT_FAIL;
323 }
324
325 VERBOSE("TFTF - Handle: %llx Address: %p\n",
326 handle, constituents[0].address);
327
328 /* Retrieve the shared page and attempt accessing it. */
329 ret = cactus_mem_send_cmd(SENDER, RECEIVER, FFA_MEM_SHARE_SMC32,
330 handle, 0, true, 1);
331
332 if (is_ffa_call_error(ffa_mem_reclaim(handle, 0))) {
333 ERROR("Memory reclaim failed!\n");
334 return TEST_RESULT_FAIL;
335 }
336
337 /*
338 * Expect success response with value 1 hinting an exception
339 * triggered while the SP accessed the region.
340 */
341 if (!(cactus_get_response(ret) == CACTUS_SUCCESS &&
342 cactus_error_code(ret) == 1)) {
343 ERROR("Exceptions test failed!\n");
344 return TEST_RESULT_FAIL;
345 }
346
347 return TEST_RESULT_SUCCESS;
348}
349
nabkah01905b2c72022-02-10 10:46:32 +0000350test_result_t s_memory_cannot_be_accessed_in_rl(void)
351{
352 u_register_t params = (u_register_t)SECURE_MEMORY_ACCESS_ADDR;
353 return memory_cannot_be_accessed_in_rl(params);
354}
355
nabkah01e7147862022-02-11 19:08:00 +0000356test_result_t rt_memory_cannot_be_accessed_in_rl(void)
357{
358 u_register_t params = (u_register_t)EL3_MEMORY_ACCESS_ADDR;
359 return memory_cannot_be_accessed_in_rl(params);
360}
361
Manish Pandey5f513d62022-01-17 11:05:53 +0000362#else
Olivier Deprez82bbc572022-01-11 11:50:36 +0100363
nabkah01bf00f8d2022-03-22 12:37:19 +0000364test_result_t el3_memory_cannot_be_accessed_in_ns(void)
Manish Pandey5f513d62022-01-17 11:05:53 +0000365{
366 tftf_testcase_printf("Test not ported to AArch32\n");
367 return TEST_RESULT_SKIPPED;
368}
Olivier Deprez82bbc572022-01-11 11:50:36 +0100369
370test_result_t rl_memory_cannot_be_accessed_in_ns(void)
371{
372 tftf_testcase_printf("Test not ported to AArch32\n");
373 return TEST_RESULT_SKIPPED;
374}
375
nabkah01bf00f8d2022-03-22 12:37:19 +0000376test_result_t s_memory_cannot_be_accessed_in_ns(void)
377{
378 tftf_testcase_printf("Test not ported to AArch32\n");
379 return TEST_RESULT_SKIPPED;
380}
nabkah01905b2c72022-02-10 10:46:32 +0000381
382test_result_t s_memory_cannot_be_accessed_in_rl(void)
383{
384 tftf_testcase_printf("Test not ported to AArch32\n");
385 return TEST_RESULT_SKIPPED;
386}
387
nabkah01e7147862022-02-11 19:08:00 +0000388test_result_t rt_memory_cannot_be_accessed_in_rl(void)
389{
390 tftf_testcase_printf("Test not ported to AArch32\n");
391 return TEST_RESULT_SKIPPED;
392}
393
Manish Pandey5f513d62022-01-17 11:05:53 +0000394#endif /* __aarch64__ */