blob: 3b56d60e5110070701644159e50c6fbbf11ddbb8 [file] [log] [blame]
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +02001/*
2 * Copyright (c) 2018, Arm Limited. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#include <assert.h>
8#include <debug.h>
9#include <errno.h>
10#include <platform_def.h>
11#include <secure_partition.h>
12#include <sp_helpers.h>
Antonio Nino Diaz7f10a062018-10-30 14:14:04 +000013#include <sprt_svc.h>
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +020014#include <stdio.h>
15#include <types.h>
16#include <xlat_tables_defs.h>
17
18#include "cactus.h"
Antonio Nino Diaz1486f3b2018-06-26 10:30:10 +010019#include "cactus_def.h"
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +020020#include "cactus_tests.h"
21
22/* This is filled at runtime. */
23static uintptr_t cactus_tests_start;
24static uintptr_t cactus_tests_end;
25static uintptr_t cactus_tests_size;
26
27/*
Antonio Nino Diaz7f10a062018-10-30 14:14:04 +000028 * Send an SPRT_MEMORY_PERM_ATTR_SET_AARCH64 SVC with the given arguments.
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +020029 * Return the return value of the SVC.
30 */
31static int32_t request_mem_attr_changes(uintptr_t base_address,
32 int pages_count,
33 uint32_t memory_access_controls)
34{
35 INFO("Requesting memory attributes change\n");
36 INFO(" Start address : %p\n", (void *) base_address);
37 INFO(" Number of pages: %i\n", pages_count);
38 INFO(" Attributes : 0x%x\n", memory_access_controls);
39
Antonio Nino Diaz7f10a062018-10-30 14:14:04 +000040 svc_args svc_values = { SPRT_MEMORY_PERM_ATTR_SET_AARCH64,
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +020041 base_address,
42 pages_count,
43 memory_access_controls };
44 return sp_svc(&svc_values);
45}
46
47/*
Antonio Nino Diaz7f10a062018-10-30 14:14:04 +000048 * Send an SPRT_MEMORY_PERM_ATTR_GET_AARCH64 SVC with the given arguments.
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +020049 * Return the return value of the SVC.
50 */
51static int32_t request_get_mem_attr(uintptr_t base_address)
52{
53 INFO("Requesting memory attributes\n");
54 INFO(" Base address : %p\n", (void *) base_address);
55
Antonio Nino Diaz7f10a062018-10-30 14:14:04 +000056 svc_args svc_values = { SPRT_MEMORY_PERM_ATTR_GET_AARCH64,
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +020057 base_address };
58 return sp_svc(&svc_values);
59}
60
61/*
62 * This function expects a base address and number of pages identifying the
63 * extents of some memory region mapped as non-executable, read-only.
64 *
65 * 1) It changes its data access permissions to read-write.
66 * 2) It checks this memory can now be written to.
67 * 3) It restores the original data access permissions.
68 *
69 * If any check fails, it loops forever. It could also trigger a permission
70 * fault while trying to write to the memory.
71 */
72static void mem_attr_changes_unittest(uintptr_t addr, int pages_count)
73{
74 int32_t ret;
75 uintptr_t end_addr = addr + pages_count * PAGE_SIZE;
76 uint32_t old_attr, new_attr;
77
78 char test_desc[50];
79
80 snprintf(test_desc, sizeof(test_desc),
81 "RO -> RW (%i page(s) from address 0x%lx)", pages_count, addr);
82 announce_test_start(test_desc);
83
84 /*
85 * Ensure we don't change the attributes of some random memory
86 * location
87 */
88 assert(addr >= cactus_tests_start);
89 assert(end_addr < (cactus_tests_start + cactus_tests_size));
90
Antonio Nino Diaz7f10a062018-10-30 14:14:04 +000091 old_attr = SPRT_MEMORY_PERM_ATTR_RO;
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +020092 /* Memory was read-only, let's try changing that to RW */
Antonio Nino Diaz7f10a062018-10-30 14:14:04 +000093 new_attr = SPRT_MEMORY_PERM_ATTR_RW;
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +020094
95 ret = request_mem_attr_changes(addr, pages_count, new_attr);
Antonio Nino Diaz7f10a062018-10-30 14:14:04 +000096 expect(ret, SPRT_SUCCESS);
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +020097 printf("Successfully changed memory attributes\n");
98
99 /* The attributes should be the ones we have just written. */
100 ret = request_get_mem_attr(addr);
Antonio Nino Diaz7f10a062018-10-30 14:14:04 +0000101 expect(ret, SPRT_SUCCESS | (new_attr << SPRT_MEMORY_PERM_ATTR_SHIFT));
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +0200102
103 /* If it worked, we should be able to write to this memory now! */
104 for (unsigned char *data = (unsigned char *) addr;
105 (uintptr_t) data != end_addr;
106 ++data) {
107 *data = 42;
108 }
109 printf("Successfully wrote to the memory\n");
110
111 /* Let's revert back to the original attributes for the next test */
112 ret = request_mem_attr_changes(addr, pages_count, old_attr);
Antonio Nino Diaz7f10a062018-10-30 14:14:04 +0000113 expect(ret, SPRT_SUCCESS);
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +0200114 printf("Successfully restored the old attributes\n");
115
116 /* The attributes should be the original ones again. */
117 ret = request_get_mem_attr(addr);
Antonio Nino Diaz7f10a062018-10-30 14:14:04 +0000118 expect(ret, SPRT_SUCCESS | (old_attr << SPRT_MEMORY_PERM_ATTR_SHIFT));
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +0200119
120 announce_test_end(test_desc);
121}
122
123/*
124 * Exercise the ability of the Trusted Firmware to change the data access
125 * permissions and instruction execution permissions of some memory region.
126 */
Antonio Nino Diaz1486f3b2018-06-26 10:30:10 +0100127void mem_attr_changes_tests(void)
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +0200128{
129 uint32_t attributes;
130 int32_t ret;
131 uintptr_t addr;
132
Antonio Nino Diaz1486f3b2018-06-26 10:30:10 +0100133 cactus_tests_start = CACTUS_TEST_MEM_BASE;
134 cactus_tests_size = CACTUS_TEST_MEM_SIZE;
135 cactus_tests_end = cactus_tests_start + cactus_tests_size;
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +0200136
137 const char *test_sect_desc = "memory attributes changes";
138
139 announce_test_section_start(test_sect_desc);
140 /*
141 * Start with error cases, i.e. requests that are expected to be denied
142 */
Antonio Nino Diaz7f10a062018-10-30 14:14:04 +0000143 const char *test_desc1 = "Reserved attributes value";
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +0200144
145 announce_test_start(test_desc1);
Antonio Nino Diaz7f10a062018-10-30 14:14:04 +0000146 attributes = U(3);
Antonio Nino Diaz54287c82018-12-05 15:37:33 +0000147 ret = request_mem_attr_changes(cactus_tests_start, 1, attributes);
Antonio Nino Diaz7f10a062018-10-30 14:14:04 +0000148 expect(ret, SPRT_INVALID_PARAMETER);
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +0200149 announce_test_end(test_desc1);
150
151 const char *test_desc2 = "Size == 0";
152
153 announce_test_start(test_desc2);
Antonio Nino Diaz7f10a062018-10-30 14:14:04 +0000154 attributes = SPRT_MEMORY_PERM_ATTR_RW;
Antonio Nino Diaz54287c82018-12-05 15:37:33 +0000155 ret = request_mem_attr_changes(cactus_tests_start, 0, attributes);
Antonio Nino Diaz7f10a062018-10-30 14:14:04 +0000156 expect(ret, SPRT_INVALID_PARAMETER);
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +0200157 announce_test_end(test_desc2);
158
159 const char *test_desc3 = "Unaligned address";
160
161 announce_test_start(test_desc3);
Antonio Nino Diaz7f10a062018-10-30 14:14:04 +0000162 attributes = SPRT_MEMORY_PERM_ATTR_RW;
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +0200163 /* Choose an address not aligned to a page boundary. */
164 addr = cactus_tests_start + 5;
165 ret = request_mem_attr_changes(addr, 1, attributes);
Antonio Nino Diaz7f10a062018-10-30 14:14:04 +0000166 expect(ret, SPRT_INVALID_PARAMETER);
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +0200167 announce_test_end(test_desc3);
168
169 const char *test_desc4 = "Unmapped memory region";
170
171 announce_test_start(test_desc4);
Antonio Nino Diaz1486f3b2018-06-26 10:30:10 +0100172 addr = cactus_tests_end + 2 * PAGE_SIZE;
Antonio Nino Diaz7f10a062018-10-30 14:14:04 +0000173 attributes = SPRT_MEMORY_PERM_ATTR_RW;
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +0200174 ret = request_mem_attr_changes(addr, 3, attributes);
Antonio Nino Diaz7f10a062018-10-30 14:14:04 +0000175 expect(ret, SPRT_INVALID_PARAMETER);
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +0200176 announce_test_end(test_desc4);
177
178 const char *test_desc5 = "Partially unmapped memory region";
179
180 announce_test_start(test_desc5);
Antonio Nino Diaz1486f3b2018-06-26 10:30:10 +0100181 addr = cactus_tests_end - 2 * PAGE_SIZE;
Antonio Nino Diaz7f10a062018-10-30 14:14:04 +0000182 attributes = SPRT_MEMORY_PERM_ATTR_RW;
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +0200183 ret = request_mem_attr_changes(addr, 6, attributes);
Antonio Nino Diaz7f10a062018-10-30 14:14:04 +0000184 expect(ret, SPRT_INVALID_PARAMETER);
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +0200185 announce_test_end(test_desc5);
186
187 const char *test_desc6 = "Memory region mapped with the wrong granularity";
188
189 announce_test_start(test_desc6);
190 /*
191 * This address is usually mapped at a 2 MiB granularity. By using as
192 * test address the block after the console we make sure that in case
193 * the attributes of the block actually changed, the console would work
194 * and we would get the error message.
195 */
196 addr = ((uintptr_t)PLAT_ARM_UART_BASE + 0x200000ULL) & ~(0x200000ULL - 1ULL);
Antonio Nino Diaz7f10a062018-10-30 14:14:04 +0000197 attributes = SPRT_MEMORY_PERM_ATTR_RW;
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +0200198 ret = request_mem_attr_changes(addr, 1, attributes);
Antonio Nino Diaz7f10a062018-10-30 14:14:04 +0000199 expect(ret, SPRT_INVALID_PARAMETER);
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +0200200 announce_test_end(test_desc6);
201
202 const char *test_desc7 = "Try some valid memory change requests";
203
204 announce_test_start(test_desc7);
205 for (unsigned int i = 0; i < 20; ++i) {
206 /*
207 * Choose some random address in the pool of memory reserved
208 * for these tests.
209 */
210 const int pages_max = cactus_tests_size / PAGE_SIZE;
211 int pages_count = bound_rand(1, pages_max);
212
213 addr = bound_rand(
214 cactus_tests_start,
215 cactus_tests_end - (pages_count * PAGE_SIZE));
216 /* Align to PAGE_SIZE. */
217 addr &= ~(PAGE_SIZE - 1);
218
219 mem_attr_changes_unittest(addr, pages_count);
220 }
221 announce_test_end(test_desc7);
222
223 announce_test_section_end(test_sect_desc);
224}