blob: ecb3c19366ce1986fedd332aff72e66e2fdba980 [file] [log] [blame]
Soby Mathewb4c6df42022-11-09 11:13:29 +00001/*
2 * SPDX-License-Identifier: BSD-3-Clause
3 * SPDX-FileCopyrightText: Copyright TF-RMM Contributors.
4 */
5
6#include <arch_helpers.h>
7#include <assert.h>
8#include <buffer.h>
9#include <cpuid.h>
10#include <debug.h>
Javier Almansa Sobrinoed932592023-01-24 12:50:41 +000011#include <errno.h>
Soby Mathewb4c6df42022-11-09 11:13:29 +000012#include <gic.h>
Soby Mathew26727ea2023-03-06 13:26:50 +000013#include <plat_cmn_arch.h>
Soby Mathewb4c6df42022-11-09 11:13:29 +000014#include <rmm_el3_ifc.h>
15#include <sizes.h>
16#include <stdint.h>
Javier Almansa Sobrinoed932592023-01-24 12:50:41 +000017#include <string.h>
Soby Mathewb4c6df42022-11-09 11:13:29 +000018#include <xlat_contexts.h>
Mate Toth-Pal7f5b27d2023-08-08 13:49:19 +020019#include <xlat_high_va.h>
Soby Mathewb4c6df42022-11-09 11:13:29 +000020#include <xlat_tables.h>
21
Soby Mathew26727ea2023-03-06 13:26:50 +000022
23IMPORT_SYM(uintptr_t, rmm_text_start, RMM_CODE_START);
24IMPORT_SYM(uintptr_t, rmm_text_end, RMM_CODE_END);
25IMPORT_SYM(uintptr_t, rmm_ro_start, RMM_RO_START);
26IMPORT_SYM(uintptr_t, rmm_ro_end, RMM_RO_END);
27IMPORT_SYM(uintptr_t, rmm_rw_start, RMM_RW_START);
28IMPORT_SYM(uintptr_t, rmm_rw_end, RMM_RW_END);
29
Soby Mathewb4c6df42022-11-09 11:13:29 +000030/*
31 * Memory map REGIONS used for the RMM runtime (static mappings)
32 */
33#define RMM_CODE_SIZE (RMM_CODE_END - RMM_CODE_START)
34#define RMM_RO_SIZE (RMM_RO_END - RMM_RO_START)
35#define RMM_RW_SIZE (RMM_RW_END - RMM_RW_START)
36
37#define RMM_CODE MAP_REGION_FLAT( \
38 RMM_CODE_START, \
39 RMM_CODE_SIZE, \
AlexeiFedorov3f5d6272023-10-23 16:27:37 +010040 (MT_CODE | MT_REALM))
Soby Mathewb4c6df42022-11-09 11:13:29 +000041
42#define RMM_RO MAP_REGION_FLAT( \
43 RMM_RO_START, \
44 RMM_RO_SIZE, \
AlexeiFedorov3f5d6272023-10-23 16:27:37 +010045 (MT_RO_DATA | MT_REALM))
Soby Mathewb4c6df42022-11-09 11:13:29 +000046
47#define RMM_RW MAP_REGION_FLAT( \
48 RMM_RW_START, \
49 RMM_RW_SIZE, \
AlexeiFedorov3f5d6272023-10-23 16:27:37 +010050 (MT_RW_DATA | MT_REALM))
Soby Mathewb4c6df42022-11-09 11:13:29 +000051
52/*
Soby Mathew26727ea2023-03-06 13:26:50 +000053 * Leave an invalid page between the end of RMM memory and the beginning
54 * of the shared buffer VA. This will help to detect any memory access
55 * underflow by RMM.
56 */
57#define RMM_SHARED_BUFFER_START (RMM_RW_END + SZ_4K)
58
59/*
Soby Mathewb4c6df42022-11-09 11:13:29 +000060 * Some of the fields for the RMM_SHARED region will be populated
61 * at runtime.
62 */
63#define RMM_SHARED MAP_REGION( \
64 0U, \
65 RMM_SHARED_BUFFER_START, \
66 0U, \
AlexeiFedorov3f5d6272023-10-23 16:27:37 +010067 (MT_RW_DATA | MT_REALM))
Soby Mathewb4c6df42022-11-09 11:13:29 +000068
Javier Almansa Sobrinoed932592023-01-24 12:50:41 +000069/* Number of common memory mapping regions */
70#define COMMON_REGIONS (4U)
Soby Mathewb4c6df42022-11-09 11:13:29 +000071
Javier Almansa Sobrinoed932592023-01-24 12:50:41 +000072/* Total number of memory mapping regions */
73#define TOTAL_MMAP_REGIONS (COMMON_REGIONS + PLAT_CMN_EXTRA_MMAP_REGIONS)
74
75/* Memory mapping regions for the system runtime */
76static struct xlat_mmap_region static_regions[TOTAL_MMAP_REGIONS];
77
Javier Almansa Sobrino765a3162023-04-27 17:42:58 +010078/*
79 * Allocate the runtime translation tables.
80 * Although a base table at level -1 when FEAT_LPA2 is enabled only has
81 * 16 entries, all tables are allocated a page for simplicity.
82 */
Javier Almansa Sobrinoed932592023-01-24 12:50:41 +000083static uint64_t static_s1tt[XLAT_TABLE_ENTRIES * PLAT_CMN_CTX_MAX_XLAT_TABLES]
84 __aligned(XLAT_TABLES_ALIGNMENT)
85 __section("xlat_static_tables");
86
87/* Structures to hold the runtime translation context information */
88static struct xlat_ctx_tbls runtime_tbls;
89static struct xlat_ctx_cfg runtime_xlat_ctx_cfg;
90static struct xlat_ctx runtime_xlat_ctx;
Soby Mathewb4c6df42022-11-09 11:13:29 +000091
92/*
93 * Platform common cold boot setup for RMM.
94 *
95 * This function should only be invoked once during cold boot
96 * and is expected to setup architecture and platform components
Soby Mathew26727ea2023-03-06 13:26:50 +000097 * common for all PEs executing RMM. The rmm_el3_ifc, the xlat tables
98 * and GIC driver are initialized by this function.
Soby Mathewb4c6df42022-11-09 11:13:29 +000099 */
100int plat_cmn_setup(unsigned long x0, unsigned long x1,
101 unsigned long x2, unsigned long x3,
Javier Almansa Sobrinoed932592023-01-24 12:50:41 +0000102 struct xlat_mmap_region *plat_regions,
103 unsigned int nregions)
Soby Mathewb4c6df42022-11-09 11:13:29 +0000104{
105 int ret;
Javier Almansa Sobrinoed932592023-01-24 12:50:41 +0000106 unsigned int plat_offset, cmn_offset;
107
108 /* Common regions sorted by ascending VA */
109 struct xlat_mmap_region regions[COMMON_REGIONS] = {
110 RMM_CODE,
111 RMM_RO,
112 RMM_RW,
113 RMM_SHARED
114 };
115
116 if (nregions > PLAT_CMN_EXTRA_MMAP_REGIONS) {
117 return -ERANGE;
118 }
119
AlexeiFedorov56e1a8e2023-09-01 17:06:13 +0100120 if ((nregions != 0U) && (plat_regions == NULL)) {
Javier Almansa Sobrinoed932592023-01-24 12:50:41 +0000121 return -EINVAL;
122 }
Soby Mathewb4c6df42022-11-09 11:13:29 +0000123
Soby Mathew26727ea2023-03-06 13:26:50 +0000124 /* Initialize the RMM <-> EL3 interface */
125 ret = rmm_el3_ifc_init(x0, x1, x2, x3, get_shared_buf_va(x3));
126 if (ret != 0) {
127 ERROR("%s (%u): Failed to initialize the RMM EL3 Interface\n",
128 __func__, __LINE__);
129 return ret;
130 }
131
Soby Mathewb4c6df42022-11-09 11:13:29 +0000132 /* Setup the parameters of the shared area */
Soby Mathew26727ea2023-03-06 13:26:50 +0000133 regions[3].base_pa = get_shared_buf_pa();
Javier Almansa Sobrinoed932592023-01-24 12:50:41 +0000134 regions[3].size = rmm_el3_ifc_get_shared_buf_size();
Soby Mathewb4c6df42022-11-09 11:13:29 +0000135
Javier Almansa Sobrinoed932592023-01-24 12:50:41 +0000136 plat_offset = COMMON_REGIONS;
137 cmn_offset = 0U;
138 if (nregions > 0U) {
139 /*
140 * Combine the common memory regions with the platform ones
141 * in an array where they are sorted as per VA.
142 */
143 if (plat_regions[0].base_va < RMM_CODE_START) {
144 plat_offset = 0U;
145 cmn_offset = nregions;
146 }
147 (void)memcpy((void *)&static_regions[plat_offset],
148 (void *)&plat_regions[0U],
149 sizeof(struct xlat_mmap_region) * nregions);
150 }
151
152 (void)memcpy((void *)&static_regions[cmn_offset], (void *)&regions[0U],
153 sizeof(struct xlat_mmap_region) * COMMON_REGIONS);
154
155 ret = xlat_ctx_cfg_init(&runtime_xlat_ctx_cfg, VA_LOW_REGION,
156 &static_regions[0], nregions + COMMON_REGIONS,
157 VIRT_ADDR_SPACE_SIZE);
158
Soby Mathewb4c6df42022-11-09 11:13:29 +0000159 if (ret != 0) {
Javier Almansa Sobrinoed932592023-01-24 12:50:41 +0000160 ERROR("%s (%u): %s (%i)\n",
161 __func__, __LINE__,
162 "Failed to initialize the xlat ctx within the xlat library ",
163 ret);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000164 return ret;
165 }
166
Javier Almansa Sobrinoed932592023-01-24 12:50:41 +0000167 ret = xlat_ctx_init(&runtime_xlat_ctx, &runtime_xlat_ctx_cfg,
168 &runtime_tbls,
169 &static_s1tt[0],
170 PLAT_CMN_CTX_MAX_XLAT_TABLES);
171
Soby Mathewb4c6df42022-11-09 11:13:29 +0000172 if (ret != 0) {
Javier Almansa Sobrinoed932592023-01-24 12:50:41 +0000173 ERROR("%s (%u): %s (%i)\n",
174 __func__, __LINE__,
175 "Failed to create the xlat ctx within the xlat library ",
176 ret);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000177 return ret;
178 }
179
180 /* Read supported GIC virtualization features and init GIC variables */
181 gic_get_virt_features();
182
Mate Toth-Pal7f5b27d2023-08-08 13:49:19 +0200183 return 0;
Soby Mathewb4c6df42022-11-09 11:13:29 +0000184}
185
186/*
187 * Local PE common platform setup for RMM.
188 *
189 * This function will only be invoked during
190 * warm boot and is expected to setup architecture and platform
191 * components local to a PE executing RMM.
192 */
193int plat_cmn_warmboot_setup(void)
194{
195 int ret;
196
AlexeiFedorov7c5001a2022-12-14 13:22:33 +0000197 /* Setup the MMU cfg for the low region (runtime context) */
Soby Mathewb4c6df42022-11-09 11:13:29 +0000198 ret = xlat_arch_setup_mmu_cfg(&runtime_xlat_ctx);
199 if (ret != 0) {
200 ERROR("%s (%u): Failed to setup xlat tables for CPU[%u]\n",
AlexeiFedorov7c5001a2022-12-14 13:22:33 +0000201 __func__, __LINE__, my_cpuid());
Soby Mathewb4c6df42022-11-09 11:13:29 +0000202 return ret;
203 }
204
Mate Toth-Pal7f5b27d2023-08-08 13:49:19 +0200205 /* Perform warm boot initialization of the high VA region */
206 ret = xlat_high_va_setup();
207 if (ret != 0) {
208 ERROR("%s (%u): Failed to setup high VA for CPU[%u]\n",
209 __func__, __LINE__, my_cpuid());
210 return ret;
211 }
Soby Mathewb4c6df42022-11-09 11:13:29 +0000212
213 VERBOSE("xlat tables configured for CPU[%u]\n", my_cpuid());
214 return 0;
215}