blob: 9cbd8f2f748406b11576aa78d2a7a139803b4989 [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
nabkah01002e5692022-10-10 12:36:46 +010016#include <host_realm_helper.h>
Olivier Deprez82bbc572022-01-11 11:50:36 +010017#include <lib/aarch64/arch_features.h>
nabkah01002e5692022-10-10 12:36:46 +010018#include <test_helpers.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>
Manish Pandey5f513d62022-01-17 11:05:53 +000021#include <platform_def.h>
nabkah0146b418d2022-02-16 17:01:54 +000022#include <cactus_test_cmds.h>
23#include <ffa_endpoints.h>
24
Manish Pandey5f513d62022-01-17 11:05:53 +000025/*
26 * Using "__aarch64__" here looks weird but its unavoidable because of following reason
27 * This test is part of standard test which runs on all platforms but pre-requisite
28 * to run this test (custom sync exception handler) is only implemented for aarch64.
29 * TODO: Write a framework so that tests kept in standard list can be selectively
30 * run on a given architecture
31 */
32#ifdef __aarch64__
33
nabkah0146b418d2022-02-16 17:01:54 +000034#define SENDER HYP_ID
35#define RECEIVER SP_ID(1)
36
Manish Pandey5f513d62022-01-17 11:05:53 +000037static volatile bool sync_exception_triggered;
38static volatile bool data_abort_triggered;
nabkah0146b418d2022-02-16 17:01:54 +000039static const struct ffa_uuid expected_sp_uuids[] = {
40 {PRIMARY_UUID}, {SECONDARY_UUID}, {TERTIARY_UUID}
41};
Manish Pandey5f513d62022-01-17 11:05:53 +000042
Olivier Deprez82bbc572022-01-11 11:50:36 +010043static __aligned(PAGE_SIZE) uint64_t share_page[PAGE_SIZE / sizeof(uint64_t)];
44
Manish Pandey5f513d62022-01-17 11:05:53 +000045static bool data_abort_handler(void)
46{
47 uint64_t esr_elx = IS_IN_EL2() ? read_esr_el2() : read_esr_el1();
48 unsigned int rme_supported = get_armv9_2_feat_rme_support();
49
50 sync_exception_triggered = true;
51
52 VERBOSE("%s esr_elx %llx\n", __func__, esr_elx);
53
54 if (EC_BITS(esr_elx) == EC_DABORT_CUR_EL) {
55 if (rme_supported == 0) {
56 /* Synchronous external data abort triggered by trustzone controller */
57 if ((ISS_BITS(esr_elx) & ISS_DFSC_MASK) == DFSC_EXT_DABORT) {
58 VERBOSE("%s TZC Data Abort caught\n", __func__);
59 data_abort_triggered = true;
60 return true;
61 }
62 } else {
63 /* Synchronous data abort triggered by Granule protection */
64 if ((ISS_BITS(esr_elx) & ISS_DFSC_MASK) == DFSC_GPF_DABORT) {
65 VERBOSE("%s GPF Data Abort caught\n", __func__);
66 data_abort_triggered = true;
67 return true;
68 }
69 }
70 }
71
72 return false;
73}
74
nabkah01bf00f8d2022-03-22 12:37:19 +000075test_result_t el3_memory_cannot_be_accessed_in_ns(void)
Manish Pandey5f513d62022-01-17 11:05:53 +000076{
77 const uintptr_t test_address = EL3_MEMORY_ACCESS_ADDR;
78
Manish Pandey5f513d62022-01-17 11:05:53 +000079 VERBOSE("Attempt to access el3 memory (0x%lx)\n", test_address);
80
Manish Pandey368054b2022-03-15 13:24:59 +000081 sync_exception_triggered = false;
Manish Pandey5f513d62022-01-17 11:05:53 +000082 data_abort_triggered = false;
Manish Pandey368054b2022-03-15 13:24:59 +000083
84 int rc = mmap_add_dynamic_region(test_address, test_address, PAGE_SIZE,
85 MT_MEMORY | MT_RW | MT_NS);
86 if (rc != 0) {
87 tftf_testcase_printf("%d: mmap_add_dynamic_region() = %d\n", __LINE__, rc);
88 return TEST_RESULT_FAIL;
89 }
90
Manish Pandey5f513d62022-01-17 11:05:53 +000091 register_custom_sync_exception_handler(data_abort_handler);
Manish Pandey5f513d62022-01-17 11:05:53 +000092 *((volatile uint64_t *)test_address);
Manish Pandey5f513d62022-01-17 11:05:53 +000093 unregister_custom_sync_exception_handler();
94
Manish Pandey368054b2022-03-15 13:24:59 +000095 rc = mmap_remove_dynamic_region(test_address, PAGE_SIZE);
96 if (rc != 0) {
97 tftf_testcase_printf("%d: mmap_remove_dynamic_region() = %d\n", __LINE__, rc);
98 return TEST_RESULT_FAIL;
99 }
100
Manish Pandey5f513d62022-01-17 11:05:53 +0000101 if (sync_exception_triggered == false) {
102 tftf_testcase_printf("No sync exception while accessing (0x%lx)\n", test_address);
103 return TEST_RESULT_SKIPPED;
104 }
105
106 if (data_abort_triggered == false) {
107 tftf_testcase_printf("Sync exception is not data abort\n");
108 return TEST_RESULT_FAIL;
109 }
110
111 return TEST_RESULT_SUCCESS;
112}
Olivier Deprez82bbc572022-01-11 11:50:36 +0100113
114/**
115 * @Test_Aim@ Check a realm region cannot be accessed from normal world.
116 *
117 * This test delegates a TFTF allocated buffer to Realm. It then attempts
118 * a read access to the region from normal world. This results in the PE
119 * triggering a GPF caught by a custom synchronous abort handler.
120 *
121 */
122test_result_t rl_memory_cannot_be_accessed_in_ns(void)
123{
124 test_result_t result = TEST_RESULT_FAIL;
125 u_register_t retmm;
126
127 if (get_armv9_2_feat_rme_support() == 0U) {
128 return TEST_RESULT_SKIPPED;
129 }
130
131 sync_exception_triggered = false;
132 data_abort_triggered = false;
133 register_custom_sync_exception_handler(data_abort_handler);
134
135 /* First read access to the test region must not fail. */
136 *((volatile uint64_t *)share_page);
137
138 if ((sync_exception_triggered != false) ||
139 (data_abort_triggered != false)) {
140 goto out_unregister;
141 }
142
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000143 host_rmi_init_cmp_result();
AlexeiFedorov380b2af2022-11-23 17:31:27 +0000144
Olivier Deprez82bbc572022-01-11 11:50:36 +0100145 /* Delegate the shared page to Realm. */
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000146 retmm = host_rmi_granule_delegate((u_register_t)&share_page);
Olivier Deprez82bbc572022-01-11 11:50:36 +0100147 if (retmm != 0UL) {
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000148 ERROR("%s() failed\n", "host_rmi_granule_delegate");
Olivier Deprez82bbc572022-01-11 11:50:36 +0100149 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
AlexeiFedorov380b2af2022-11-23 17:31:27 +0000160 result = host_cmp_result();
Olivier Deprez82bbc572022-01-11 11:50:36 +0100161
162out_undelegate:
163 /* Undelegate the shared page. */
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000164 retmm = host_rmi_granule_undelegate((u_register_t)&share_page);
Olivier Deprez82bbc572022-01-11 11:50:36 +0100165 if (retmm != 0UL) {
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000166 ERROR("Granule undelegate failed, ret=0x%lx\n", retmm);
Olivier Deprez82bbc572022-01-11 11:50:36 +0100167 }
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;
AlexeiFedorovc21694d2022-12-16 12:19:52 +0000230 test_result_t result = TEST_RESULT_FAIL;
nabkah01905b2c72022-02-10 10:46:32 +0000231 static char rd[GRANULE_SIZE] __aligned(GRANULE_SIZE);
232
233 if (get_armv9_2_feat_rme_support() == 0U) {
234 return TEST_RESULT_SKIPPED;
235 }
236
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000237 host_rmi_init_cmp_result();
AlexeiFedorov380b2af2022-11-23 17:31:27 +0000238
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000239 retrmm = host_rmi_version();
nabkah01905b2c72022-02-10 10:46:32 +0000240
241 VERBOSE("RMM version is: %lu.%lu\n",
242 RMI_ABI_VERSION_GET_MAJOR(retrmm),
243 RMI_ABI_VERSION_GET_MINOR(retrmm));
244
245 /*
246 * TODO: Remove this once SMC_RMM_REALM_CREATE is implemented in TRP
247 * For the moment skip the test if RMM is TRP, TRP version is always null.
248 */
249 if (retrmm == 0U) {
250 return TEST_RESULT_SKIPPED;
251 }
252
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000253 retrmm = host_rmi_granule_delegate((u_register_t)&rd[0]);
nabkah01905b2c72022-02-10 10:46:32 +0000254 if (retrmm != 0UL) {
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000255 ERROR("%s() failed, ret=0x%lx\n", "host_rmi_granule_delegate",
256 retrmm);
nabkah01905b2c72022-02-10 10:46:32 +0000257 return TEST_RESULT_FAIL;
258 }
259
260 /* Create a realm using a parameter in a secure physical address space should fail. */
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000261 retrmm = host_rmi_realm_create((u_register_t)&rd[0], params);
nabkah01905b2c72022-02-10 10:46:32 +0000262 if (retrmm == 0UL) {
263 ERROR("Realm create operation should fail, %lx\n", retrmm);
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000264 retrmm = host_rmi_realm_destroy((u_register_t)&rd[0]);
nabkah01905b2c72022-02-10 10:46:32 +0000265 if (retrmm != 0UL) {
266 ERROR("Realm destroy operation returns fail, %lx\n", retrmm);
nabkah01905b2c72022-02-10 10:46:32 +0000267 }
AlexeiFedorovc21694d2022-12-16 12:19:52 +0000268 } else if (retrmm != RMI_ERROR_INPUT) {
269 ERROR("Realm create operation should fail with code:%d retrmm:%ld\n",
270 RMI_ERROR_INPUT, retrmm);
271 } else {
272 result = TEST_RESULT_SUCCESS;
nabkah01905b2c72022-02-10 10:46:32 +0000273 }
274
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000275 retrmm = host_rmi_granule_undelegate((u_register_t)&rd[0]);
nabkah01905b2c72022-02-10 10:46:32 +0000276 if (retrmm != 0UL) {
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000277 INFO("Undelegate operation returns 0x%lx\n", retrmm);
nabkah01905b2c72022-02-10 10:46:32 +0000278 return TEST_RESULT_FAIL;
279 }
280
AlexeiFedorovc21694d2022-12-16 12:19:52 +0000281 if (result == TEST_RESULT_SUCCESS) {
282 return host_cmp_result();
283 }
284
285 return TEST_RESULT_FAIL;
nabkah01905b2c72022-02-10 10:46:32 +0000286}
287
nabkah0146b418d2022-02-16 17:01:54 +0000288/**
289 * @Test_Aim@ Check a root region cannot be accessed from a secure partition.
290 *
291 * This change adds TFTF and cactus test to permit checking a root region
292 * cannot be accessed from secure world.
293 * A hardcoded address marked Root in the GPT is shared to a secure
294 * partition. The SP retrieves the region from the SPM, maps it and
295 * attempts a read access to the region. It is expected to trigger a GPF
296 * data abort on the PE caught by a custom exception handler.
297 *
298 */
299test_result_t rt_memory_cannot_be_accessed_in_s(void)
300{
301 const uintptr_t test_address = EL3_MEMORY_ACCESS_ADDR;
302 struct ffa_memory_region_constituent constituents[] = {
303 {
304 (void *)test_address, 1, 0
305 }
306 };
307 const uint32_t constituents_count = sizeof(constituents) /
308 sizeof(struct ffa_memory_region_constituent);
309 ffa_memory_handle_t handle;
310 struct mailbox_buffers mb;
Daniel Boulbyce386b12022-03-29 18:36:36 +0100311 struct ffa_value ret;
nabkah0146b418d2022-02-16 17:01:54 +0000312
313 if (get_armv9_2_feat_rme_support() == 0U) {
314 return TEST_RESULT_SKIPPED;
315 }
316
Olivier Deprezfac8ed72022-12-20 11:09:43 +0100317 SKIP_TEST_IF_FFA_VERSION_LESS_THAN(1,1);
nabkah0146b418d2022-02-16 17:01:54 +0000318
Olivier Deprezfac8ed72022-12-20 11:09:43 +0100319 CHECK_SPMC_TESTING_SETUP(1, 1, expected_sp_uuids);
320
nabkah0146b418d2022-02-16 17:01:54 +0000321 GET_TFTF_MAILBOX(mb);
322
323 handle = memory_init_and_send((struct ffa_memory_region *)mb.send,
324 PAGE_SIZE, SENDER, RECEIVER,
325 constituents, constituents_count,
326 FFA_MEM_SHARE_SMC32, &ret);
327
328 if (handle == FFA_MEMORY_HANDLE_INVALID) {
329 return TEST_RESULT_FAIL;
330 }
331
332 VERBOSE("TFTF - Handle: %llx Address: %p\n",
333 handle, constituents[0].address);
334
335 /* Retrieve the shared page and attempt accessing it. */
336 ret = cactus_mem_send_cmd(SENDER, RECEIVER, FFA_MEM_SHARE_SMC32,
337 handle, 0, true, 1);
338
339 if (is_ffa_call_error(ffa_mem_reclaim(handle, 0))) {
340 ERROR("Memory reclaim failed!\n");
341 return TEST_RESULT_FAIL;
342 }
343
344 /*
345 * Expect success response with value 1 hinting an exception
346 * triggered while the SP accessed the region.
347 */
348 if (!(cactus_get_response(ret) == CACTUS_SUCCESS &&
349 cactus_error_code(ret) == 1)) {
350 ERROR("Exceptions test failed!\n");
351 return TEST_RESULT_FAIL;
352 }
353
354 return TEST_RESULT_SUCCESS;
355}
356
nabkah01905b2c72022-02-10 10:46:32 +0000357test_result_t s_memory_cannot_be_accessed_in_rl(void)
358{
359 u_register_t params = (u_register_t)SECURE_MEMORY_ACCESS_ADDR;
360 return memory_cannot_be_accessed_in_rl(params);
361}
362
nabkah01e7147862022-02-11 19:08:00 +0000363test_result_t rt_memory_cannot_be_accessed_in_rl(void)
364{
365 u_register_t params = (u_register_t)EL3_MEMORY_ACCESS_ADDR;
366 return memory_cannot_be_accessed_in_rl(params);
367}
368
Manish Pandey5f513d62022-01-17 11:05:53 +0000369#else
Olivier Deprez82bbc572022-01-11 11:50:36 +0100370
nabkah01bf00f8d2022-03-22 12:37:19 +0000371test_result_t el3_memory_cannot_be_accessed_in_ns(void)
Manish Pandey5f513d62022-01-17 11:05:53 +0000372{
373 tftf_testcase_printf("Test not ported to AArch32\n");
374 return TEST_RESULT_SKIPPED;
375}
Olivier Deprez82bbc572022-01-11 11:50:36 +0100376
377test_result_t rl_memory_cannot_be_accessed_in_ns(void)
378{
379 tftf_testcase_printf("Test not ported to AArch32\n");
380 return TEST_RESULT_SKIPPED;
381}
382
nabkah01bf00f8d2022-03-22 12:37:19 +0000383test_result_t s_memory_cannot_be_accessed_in_ns(void)
384{
385 tftf_testcase_printf("Test not ported to AArch32\n");
386 return TEST_RESULT_SKIPPED;
387}
nabkah01905b2c72022-02-10 10:46:32 +0000388
389test_result_t s_memory_cannot_be_accessed_in_rl(void)
390{
391 tftf_testcase_printf("Test not ported to AArch32\n");
392 return TEST_RESULT_SKIPPED;
393}
394
nabkah01e7147862022-02-11 19:08:00 +0000395test_result_t rt_memory_cannot_be_accessed_in_rl(void)
396{
397 tftf_testcase_printf("Test not ported to AArch32\n");
398 return TEST_RESULT_SKIPPED;
399}
400
Manish Pandey5f513d62022-01-17 11:05:53 +0000401#endif /* __aarch64__ */