blob: d7f7710c8ab3ce9875bb5c3debc2a1b3c5095fad [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
77/* Allocate the runtime translation tables */
78static uint64_t static_s1tt[XLAT_TABLE_ENTRIES * PLAT_CMN_CTX_MAX_XLAT_TABLES]
79 __aligned(XLAT_TABLES_ALIGNMENT)
80 __section("xlat_static_tables");
81
82/* Structures to hold the runtime translation context information */
83static struct xlat_ctx_tbls runtime_tbls;
84static struct xlat_ctx_cfg runtime_xlat_ctx_cfg;
85static struct xlat_ctx runtime_xlat_ctx;
Soby Mathewb4c6df42022-11-09 11:13:29 +000086
87/*
88 * Platform common cold boot setup for RMM.
89 *
90 * This function should only be invoked once during cold boot
91 * and is expected to setup architecture and platform components
Soby Mathew26727ea2023-03-06 13:26:50 +000092 * common for all PEs executing RMM. The rmm_el3_ifc, the xlat tables
93 * and GIC driver are initialized by this function.
Soby Mathewb4c6df42022-11-09 11:13:29 +000094 */
95int plat_cmn_setup(unsigned long x0, unsigned long x1,
96 unsigned long x2, unsigned long x3,
Javier Almansa Sobrinoed932592023-01-24 12:50:41 +000097 struct xlat_mmap_region *plat_regions,
98 unsigned int nregions)
Soby Mathewb4c6df42022-11-09 11:13:29 +000099{
100 int ret;
Javier Almansa Sobrinoed932592023-01-24 12:50:41 +0000101 unsigned int plat_offset, cmn_offset;
102
103 /* Common regions sorted by ascending VA */
104 struct xlat_mmap_region regions[COMMON_REGIONS] = {
105 RMM_CODE,
106 RMM_RO,
107 RMM_RW,
108 RMM_SHARED
109 };
110
111 if (nregions > PLAT_CMN_EXTRA_MMAP_REGIONS) {
112 return -ERANGE;
113 }
114
115 if (nregions > 0U && plat_regions == NULL) {
116 return -EINVAL;
117 }
Soby Mathewb4c6df42022-11-09 11:13:29 +0000118
Soby Mathew26727ea2023-03-06 13:26:50 +0000119 /* Initialize the RMM <-> EL3 interface */
120 ret = rmm_el3_ifc_init(x0, x1, x2, x3, get_shared_buf_va(x3));
121 if (ret != 0) {
122 ERROR("%s (%u): Failed to initialize the RMM EL3 Interface\n",
123 __func__, __LINE__);
124 return ret;
125 }
126
Soby Mathewb4c6df42022-11-09 11:13:29 +0000127 /* Setup the parameters of the shared area */
Soby Mathew26727ea2023-03-06 13:26:50 +0000128 regions[3].base_pa = get_shared_buf_pa();
Javier Almansa Sobrinoed932592023-01-24 12:50:41 +0000129 regions[3].size = rmm_el3_ifc_get_shared_buf_size();
Soby Mathewb4c6df42022-11-09 11:13:29 +0000130
Javier Almansa Sobrinoed932592023-01-24 12:50:41 +0000131 plat_offset = COMMON_REGIONS;
132 cmn_offset = 0U;
133 if (nregions > 0U) {
134 /*
135 * Combine the common memory regions with the platform ones
136 * in an array where they are sorted as per VA.
137 */
138 if (plat_regions[0].base_va < RMM_CODE_START) {
139 plat_offset = 0U;
140 cmn_offset = nregions;
141 }
142 (void)memcpy((void *)&static_regions[plat_offset],
143 (void *)&plat_regions[0U],
144 sizeof(struct xlat_mmap_region) * nregions);
145 }
146
147 (void)memcpy((void *)&static_regions[cmn_offset], (void *)&regions[0U],
148 sizeof(struct xlat_mmap_region) * COMMON_REGIONS);
149
150 ret = xlat_ctx_cfg_init(&runtime_xlat_ctx_cfg, VA_LOW_REGION,
151 &static_regions[0], nregions + COMMON_REGIONS,
152 VIRT_ADDR_SPACE_SIZE);
153
Soby Mathewb4c6df42022-11-09 11:13:29 +0000154 if (ret != 0) {
Javier Almansa Sobrinoed932592023-01-24 12:50:41 +0000155 ERROR("%s (%u): %s (%i)\n",
156 __func__, __LINE__,
157 "Failed to initialize the xlat ctx within the xlat library ",
158 ret);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000159 return ret;
160 }
161
Javier Almansa Sobrinoed932592023-01-24 12:50:41 +0000162 ret = xlat_ctx_init(&runtime_xlat_ctx, &runtime_xlat_ctx_cfg,
163 &runtime_tbls,
164 &static_s1tt[0],
165 PLAT_CMN_CTX_MAX_XLAT_TABLES);
166
Soby Mathewb4c6df42022-11-09 11:13:29 +0000167 if (ret != 0) {
Javier Almansa Sobrinoed932592023-01-24 12:50:41 +0000168 ERROR("%s (%u): %s (%i)\n",
169 __func__, __LINE__,
170 "Failed to create the xlat ctx within the xlat library ",
171 ret);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000172 return ret;
173 }
174
175 /* Read supported GIC virtualization features and init GIC variables */
176 gic_get_virt_features();
177
Javier Almansa Sobrinoed932592023-01-24 12:50:41 +0000178 /* Perform coold boot initialization of the slot buffer mechanism */
179 return slot_buf_coldboot_init();
Soby Mathewb4c6df42022-11-09 11:13:29 +0000180}
181
182/*
183 * Local PE common platform setup for RMM.
184 *
185 * This function will only be invoked during
186 * warm boot and is expected to setup architecture and platform
187 * components local to a PE executing RMM.
188 */
189int plat_cmn_warmboot_setup(void)
190{
191 int ret;
192
AlexeiFedorov7c5001a2022-12-14 13:22:33 +0000193 /* Setup the MMU cfg for the low region (runtime context) */
Soby Mathewb4c6df42022-11-09 11:13:29 +0000194 ret = xlat_arch_setup_mmu_cfg(&runtime_xlat_ctx);
195 if (ret != 0) {
196 ERROR("%s (%u): Failed to setup xlat tables for CPU[%u]\n",
AlexeiFedorov7c5001a2022-12-14 13:22:33 +0000197 __func__, __LINE__, my_cpuid());
Soby Mathewb4c6df42022-11-09 11:13:29 +0000198 return ret;
199 }
200
201 /* Setup the MMU cfg for the slot buffer context (high region) */
202 slot_buf_setup_xlat();
203
204 VERBOSE("xlat tables configured for CPU[%u]\n", my_cpuid());
205 return 0;
206}