blob: 04906de360f76f48e560bd1b28dd07a84ff08bb9 [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>
19#include <xlat_tables.h>
20
Soby Mathew26727ea2023-03-06 13:26:50 +000021
22IMPORT_SYM(uintptr_t, rmm_text_start, RMM_CODE_START);
23IMPORT_SYM(uintptr_t, rmm_text_end, RMM_CODE_END);
24IMPORT_SYM(uintptr_t, rmm_ro_start, RMM_RO_START);
25IMPORT_SYM(uintptr_t, rmm_ro_end, RMM_RO_END);
26IMPORT_SYM(uintptr_t, rmm_rw_start, RMM_RW_START);
27IMPORT_SYM(uintptr_t, rmm_rw_end, RMM_RW_END);
28
Soby Mathewb4c6df42022-11-09 11:13:29 +000029/*
30 * Memory map REGIONS used for the RMM runtime (static mappings)
31 */
32#define RMM_CODE_SIZE (RMM_CODE_END - RMM_CODE_START)
33#define RMM_RO_SIZE (RMM_RO_END - RMM_RO_START)
34#define RMM_RW_SIZE (RMM_RW_END - RMM_RW_START)
35
36#define RMM_CODE MAP_REGION_FLAT( \
37 RMM_CODE_START, \
38 RMM_CODE_SIZE, \
39 MT_CODE | MT_REALM)
40
41#define RMM_RO MAP_REGION_FLAT( \
42 RMM_RO_START, \
43 RMM_RO_SIZE, \
44 MT_RO_DATA | MT_REALM)
45
46#define RMM_RW MAP_REGION_FLAT( \
47 RMM_RW_START, \
48 RMM_RW_SIZE, \
49 MT_RW_DATA | MT_REALM)
50
51/*
Soby Mathew26727ea2023-03-06 13:26:50 +000052 * Leave an invalid page between the end of RMM memory and the beginning
53 * of the shared buffer VA. This will help to detect any memory access
54 * underflow by RMM.
55 */
56#define RMM_SHARED_BUFFER_START (RMM_RW_END + SZ_4K)
57
58/*
Soby Mathewb4c6df42022-11-09 11:13:29 +000059 * Some of the fields for the RMM_SHARED region will be populated
60 * at runtime.
61 */
62#define RMM_SHARED MAP_REGION( \
63 0U, \
64 RMM_SHARED_BUFFER_START, \
65 0U, \
66 MT_RW_DATA | MT_REALM)
67
Javier Almansa Sobrinoed932592023-01-24 12:50:41 +000068/* Number of common memory mapping regions */
69#define COMMON_REGIONS (4U)
Soby Mathewb4c6df42022-11-09 11:13:29 +000070
Javier Almansa Sobrinoed932592023-01-24 12:50:41 +000071/* Total number of memory mapping regions */
72#define TOTAL_MMAP_REGIONS (COMMON_REGIONS + PLAT_CMN_EXTRA_MMAP_REGIONS)
73
74/* Memory mapping regions for the system runtime */
75static struct xlat_mmap_region static_regions[TOTAL_MMAP_REGIONS];
76
Javier Almansa Sobrino765a3162023-04-27 17:42:58 +010077/*
78 * Allocate the runtime translation tables.
79 * Although a base table at level -1 when FEAT_LPA2 is enabled only has
80 * 16 entries, all tables are allocated a page for simplicity.
81 */
Javier Almansa Sobrinoed932592023-01-24 12:50:41 +000082static uint64_t static_s1tt[XLAT_TABLE_ENTRIES * PLAT_CMN_CTX_MAX_XLAT_TABLES]
83 __aligned(XLAT_TABLES_ALIGNMENT)
84 __section("xlat_static_tables");
85
86/* Structures to hold the runtime translation context information */
87static struct xlat_ctx_tbls runtime_tbls;
88static struct xlat_ctx_cfg runtime_xlat_ctx_cfg;
89static struct xlat_ctx runtime_xlat_ctx;
Soby Mathewb4c6df42022-11-09 11:13:29 +000090
91/*
92 * Platform common cold boot setup for RMM.
93 *
94 * This function should only be invoked once during cold boot
95 * and is expected to setup architecture and platform components
Soby Mathew26727ea2023-03-06 13:26:50 +000096 * common for all PEs executing RMM. The rmm_el3_ifc, the xlat tables
97 * and GIC driver are initialized by this function.
Soby Mathewb4c6df42022-11-09 11:13:29 +000098 */
99int plat_cmn_setup(unsigned long x0, unsigned long x1,
100 unsigned long x2, unsigned long x3,
Javier Almansa Sobrinoed932592023-01-24 12:50:41 +0000101 struct xlat_mmap_region *plat_regions,
102 unsigned int nregions)
Soby Mathewb4c6df42022-11-09 11:13:29 +0000103{
104 int ret;
Javier Almansa Sobrinoed932592023-01-24 12:50:41 +0000105 unsigned int plat_offset, cmn_offset;
106
107 /* Common regions sorted by ascending VA */
108 struct xlat_mmap_region regions[COMMON_REGIONS] = {
109 RMM_CODE,
110 RMM_RO,
111 RMM_RW,
112 RMM_SHARED
113 };
114
115 if (nregions > PLAT_CMN_EXTRA_MMAP_REGIONS) {
116 return -ERANGE;
117 }
118
119 if (nregions > 0U && plat_regions == NULL) {
120 return -EINVAL;
121 }
Soby Mathewb4c6df42022-11-09 11:13:29 +0000122
Soby Mathew26727ea2023-03-06 13:26:50 +0000123 /* Initialize the RMM <-> EL3 interface */
124 ret = rmm_el3_ifc_init(x0, x1, x2, x3, get_shared_buf_va(x3));
125 if (ret != 0) {
126 ERROR("%s (%u): Failed to initialize the RMM EL3 Interface\n",
127 __func__, __LINE__);
128 return ret;
129 }
130
Soby Mathewb4c6df42022-11-09 11:13:29 +0000131 /* Setup the parameters of the shared area */
Soby Mathew26727ea2023-03-06 13:26:50 +0000132 regions[3].base_pa = get_shared_buf_pa();
Javier Almansa Sobrinoed932592023-01-24 12:50:41 +0000133 regions[3].size = rmm_el3_ifc_get_shared_buf_size();
Soby Mathewb4c6df42022-11-09 11:13:29 +0000134
Javier Almansa Sobrinoed932592023-01-24 12:50:41 +0000135 plat_offset = COMMON_REGIONS;
136 cmn_offset = 0U;
137 if (nregions > 0U) {
138 /*
139 * Combine the common memory regions with the platform ones
140 * in an array where they are sorted as per VA.
141 */
142 if (plat_regions[0].base_va < RMM_CODE_START) {
143 plat_offset = 0U;
144 cmn_offset = nregions;
145 }
146 (void)memcpy((void *)&static_regions[plat_offset],
147 (void *)&plat_regions[0U],
148 sizeof(struct xlat_mmap_region) * nregions);
149 }
150
151 (void)memcpy((void *)&static_regions[cmn_offset], (void *)&regions[0U],
152 sizeof(struct xlat_mmap_region) * COMMON_REGIONS);
153
154 ret = xlat_ctx_cfg_init(&runtime_xlat_ctx_cfg, VA_LOW_REGION,
155 &static_regions[0], nregions + COMMON_REGIONS,
156 VIRT_ADDR_SPACE_SIZE);
157
Soby Mathewb4c6df42022-11-09 11:13:29 +0000158 if (ret != 0) {
Javier Almansa Sobrinoed932592023-01-24 12:50:41 +0000159 ERROR("%s (%u): %s (%i)\n",
160 __func__, __LINE__,
161 "Failed to initialize the xlat ctx within the xlat library ",
162 ret);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000163 return ret;
164 }
165
Javier Almansa Sobrinoed932592023-01-24 12:50:41 +0000166 ret = xlat_ctx_init(&runtime_xlat_ctx, &runtime_xlat_ctx_cfg,
167 &runtime_tbls,
168 &static_s1tt[0],
169 PLAT_CMN_CTX_MAX_XLAT_TABLES);
170
Soby Mathewb4c6df42022-11-09 11:13:29 +0000171 if (ret != 0) {
Javier Almansa Sobrinoed932592023-01-24 12:50:41 +0000172 ERROR("%s (%u): %s (%i)\n",
173 __func__, __LINE__,
174 "Failed to create the xlat ctx within the xlat library ",
175 ret);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000176 return ret;
177 }
178
179 /* Read supported GIC virtualization features and init GIC variables */
180 gic_get_virt_features();
181
Javier Almansa Sobrinoed932592023-01-24 12:50:41 +0000182 /* Perform coold boot initialization of the slot buffer mechanism */
183 return slot_buf_coldboot_init();
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
205 /* Setup the MMU cfg for the slot buffer context (high region) */
206 slot_buf_setup_xlat();
207
208 VERBOSE("xlat tables configured for CPU[%u]\n", my_cpuid());
209 return 0;
210}