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