1 /*
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>
11 #include <gic.h>
12 #include <import_sym.h>
13 #include <rmm_el3_ifc.h>
14 #include <sizes.h>
15 #include <stdint.h>
16 #include <xlat_contexts.h>
17 #include <xlat_tables.h>
18
19 IMPORT_SYM(uintptr_t, rmm_text_start, RMM_CODE_START);
20 IMPORT_SYM(uintptr_t, rmm_text_end, RMM_CODE_END);
21 IMPORT_SYM(uintptr_t, rmm_ro_start, RMM_RO_START);
22 IMPORT_SYM(uintptr_t, rmm_ro_end, RMM_RO_END);
23 IMPORT_SYM(uintptr_t, rmm_rw_start, RMM_RW_START);
24 IMPORT_SYM(uintptr_t, rmm_rw_end, RMM_RW_END);
25
26 /*
27 * Leave an invalid page between the end of RMM memory and the beginning
28 * of the shared buffer VA. This will help to detect any memory access
29 * underflow by RMM.
30 */
31 #define RMM_SHARED_BUFFER_START (RMM_RW_END + SZ_4K)
32 /*
33 * Memory map REGIONS used for the RMM runtime (static mappings)
34 */
35 #define RMM_CODE_SIZE (RMM_CODE_END - RMM_CODE_START)
36 #define RMM_RO_SIZE (RMM_RO_END - RMM_RO_START)
37 #define RMM_RW_SIZE (RMM_RW_END - RMM_RW_START)
38
39 #define RMM_CODE MAP_REGION_FLAT( \
40 RMM_CODE_START, \
41 RMM_CODE_SIZE, \
42 MT_CODE | MT_REALM)
43
44 #define RMM_RO MAP_REGION_FLAT( \
45 RMM_RO_START, \
46 RMM_RO_SIZE, \
47 MT_RO_DATA | MT_REALM)
48
49 #define RMM_RW MAP_REGION_FLAT( \
50 RMM_RW_START, \
51 RMM_RW_SIZE, \
52 MT_RW_DATA | MT_REALM)
53
54 /*
55 * Some of the fields for the RMM_SHARED region will be populated
56 * at runtime.
57 */
58 #define RMM_SHARED MAP_REGION( \
59 0U, \
60 RMM_SHARED_BUFFER_START, \
61 0U, \
62 MT_RW_DATA | MT_REALM)
63
64
65 XLAT_REGISTER_CONTEXT(runtime, VA_LOW_REGION, PLAT_CMN_MAX_MMAP_REGIONS,
66 PLAT_CMN_CTX_MAX_XLAT_TABLES,
67 VIRT_ADDR_SPACE_SIZE,
68 "xlat_static_tables");
69
70 /*
71 * Platform common cold boot setup for RMM.
72 *
73 * This function should only be invoked once during cold boot
74 * and is expected to setup architecture and platform components
75 * common for all PEs executing RMM.
76 * The xlat tables and GIC driver are initialized by this function.
77 */
plat_cmn_setup(unsigned long x0,unsigned long x1,unsigned long x2,unsigned long x3,struct xlat_mmap_region * plat_regions)78 int plat_cmn_setup(unsigned long x0, unsigned long x1,
79 unsigned long x2, unsigned long x3,
80 struct xlat_mmap_region *plat_regions)
81 {
82 int ret;
83
84 /* Initialize the RMM <-> EL3 interface */
85 ret = rmm_el3_ifc_init(x0, x1, x2, x3, RMM_SHARED_BUFFER_START);
86 if (ret != 0) {
87 ERROR("%s (%u): Failed to initialized RMM EL3 Interface\n",
88 __func__, __LINE__);
89 return ret;
90 }
91
92 /*
93 * xlat library might modify the memory mappings
94 * to optimize it, so don't make this constant.
95 */
96 struct xlat_mmap_region runtime_regions[] = {
97 RMM_CODE,
98 RMM_RO,
99 RMM_RW,
100 RMM_SHARED,
101 {0}
102 };
103
104 assert(plat_regions != NULL);
105
106 ret = xlat_mmap_add_ctx(&runtime_xlat_ctx, plat_regions, false);
107 if (ret != 0) {
108 ERROR("%s (%u): Failed to add platform regions to xlat mapping\n",
109 __func__, __LINE__);
110 return ret;
111 }
112
113 /* Setup the parameters of the shared area */
114 runtime_regions[3].base_pa = rmm_el3_ifc_get_shared_buf_pa();
115 runtime_regions[3].size = rmm_el3_ifc_get_shared_buf_size();
116
117 ret = xlat_mmap_add_ctx(&runtime_xlat_ctx, runtime_regions, true);
118 if (ret != 0) {
119 ERROR("%s (%u): Failed to add RMM common regions to xlat mapping\n",
120 __func__, __LINE__);
121 return ret;
122 }
123
124 ret = xlat_init_tables_ctx(&runtime_xlat_ctx);
125 if (ret != 0) {
126 ERROR("%s (%u): xlat initialization failed\n", __func__, __LINE__);
127 return ret;
128 }
129
130 /* Read supported GIC virtualization features and init GIC variables */
131 gic_get_virt_features();
132
133 return 0;
134 }
135
136 /*
137 * Local PE common platform setup for RMM.
138 *
139 * This function will only be invoked during
140 * warm boot and is expected to setup architecture and platform
141 * components local to a PE executing RMM.
142 */
plat_cmn_warmboot_setup(void)143 int plat_cmn_warmboot_setup(void)
144 {
145 int ret;
146
147 /* Setup the MMU cfg for the low region (runtime context). */
148 ret = xlat_arch_setup_mmu_cfg(&runtime_xlat_ctx);
149 if (ret != 0) {
150 ERROR("%s (%u): Failed to setup xlat tables for CPU[%u]\n",
151 __func__, __LINE__, my_cpuid());
152 return ret;
153 }
154
155 /* Setup the MMU cfg for the slot buffer context (high region) */
156 slot_buf_setup_xlat();
157
158 VERBOSE("xlat tables configured for CPU[%u]\n", my_cpuid());
159 return 0;
160 }
161