blob: 34eaa83983c7a74b06d68bf81bda8b1a29feb280 [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
Soby Mathewa694cca2023-04-24 03:42:45 +01006#include <arch_helpers.h>
Javier Almansa Sobrinoed932592023-01-24 12:50:41 +00007#include <assert.h>
Soby Mathewb4c6df42022-11-09 11:13:29 +00008#include <debug.h>
9#include <errno.h>
Mate Toth-Palaead06f2023-03-02 10:17:09 +010010#include <gic.h>
Soby Mathewb4c6df42022-11-09 11:13:29 +000011#include <host_defs.h>
12#include <host_utils.h>
13#include <plat_common.h>
Mate Toth-Palaead06f2023-03-02 10:17:09 +010014#include <rmm_el3_ifc.h>
Soby Mathewb4c6df42022-11-09 11:13:29 +000015#include <string.h>
16#include <xlat_tables.h>
17
Javier Almansa Sobrino9929a792022-11-22 16:11:13 +000018static struct sysreg_data sysregs[SYSREG_MAX_CBS];
Javier Almansa Sobrino48d68a72023-03-02 12:26:39 +000019static struct sysreg_data sysregs_snapshot[SYSREG_MAX_CBS];
Soby Mathewb4c6df42022-11-09 11:13:29 +000020static unsigned int installed_cb_idx;
Javier Almansa Sobrino9929a792022-11-22 16:11:13 +000021static unsigned int current_cpuid;
Soby Mathewb4c6df42022-11-09 11:13:29 +000022
23/*
24 * Allocate memory to emulate physical memory to initialize the
25 * granule library.
26 */
27static unsigned char granules_buffer[HOST_MEM_SIZE] __aligned(GRANULE_SIZE);
28
29/*
Mate Toth-Palaead06f2023-03-02 10:17:09 +010030 * Define and set the Boot Interface arguments.
31 */
32static unsigned char el3_rmm_shared_buffer[PAGE_SIZE] __aligned(PAGE_SIZE);
33
34/*
35 * Create a basic boot manifest.
36 */
37static struct rmm_core_manifest *boot_manifest =
38 (struct rmm_core_manifest *)el3_rmm_shared_buffer;
39
40/*
Soby Mathewb4c6df42022-11-09 11:13:29 +000041 * Generic callback to access a sysreg for reading.
42 */
43static u_register_t sysreg_rd_cb(u_register_t *reg)
44{
45 return *reg;
46}
47
48/*
49 * Generic callback to access a sysreg for writing.
50 */
51static void sysreg_wr_cb(u_register_t val, u_register_t *reg)
52{
53 *reg = val;
54}
55
56struct sysreg_cb *host_util_get_sysreg_cb(char *name)
57{
58 for (unsigned int i = 0U; i < SYSREG_MAX_CBS; i++) {
Javier Almansa Sobrino9929a792022-11-22 16:11:13 +000059 if (strncmp(name, &sysregs[i].name[0],
Soby Mathewb4c6df42022-11-09 11:13:29 +000060 MAX_SYSREG_NAME_LEN) == 0) {
Javier Almansa Sobrino9929a792022-11-22 16:11:13 +000061
62 /*
63 * Get a pointer to the register value for the
64 * current CPU.
65 */
66 sysregs[i].callbacks.reg =
67 &(sysregs[i].value[current_cpuid]);
68 return &sysregs[i].callbacks;
Soby Mathewb4c6df42022-11-09 11:13:29 +000069 }
70 }
71
72 return (struct sysreg_cb *)NULL;
73}
74
75int host_util_set_sysreg_cb(char *name, rd_cb_t rd_cb, wr_cb_t wr_cb,
76 u_register_t init)
77{
78 if (installed_cb_idx < SYSREG_MAX_CBS) {
Javier Almansa Sobrino9929a792022-11-22 16:11:13 +000079 sysregs[installed_cb_idx].callbacks.rd_cb = rd_cb;
80 sysregs[installed_cb_idx].callbacks.wr_cb = wr_cb;
81 sysregs[installed_cb_idx].callbacks.reg =
82 (u_register_t *)NULL;
Soby Mathewb4c6df42022-11-09 11:13:29 +000083
Javier Almansa Sobrino9929a792022-11-22 16:11:13 +000084 for (unsigned int i = 0U; i < MAX_CPUS; i++) {
85 sysregs[installed_cb_idx].value[i] = init;
86 }
87
88 (void)strncpy(&(sysregs[installed_cb_idx].name[0]),
Soby Mathewb4c6df42022-11-09 11:13:29 +000089 &name[0], MAX_SYSREG_NAME_LEN);
90
91 /*
92 * Add a string termination character in case the
93 * name were truncated.
94 */
Javier Almansa Sobrino9929a792022-11-22 16:11:13 +000095 sysregs[installed_cb_idx].name[MAX_SYSREG_NAME_LEN] = '\0';
Soby Mathewb4c6df42022-11-09 11:13:29 +000096
97 ++installed_cb_idx;
98
99 return 0;
100 }
101
102 return -ENOMEM;
103}
104
Javier Almansa Sobrino48d68a72023-03-02 12:26:39 +0000105void host_util_take_sysreg_snapshot(void)
106{
107 memcpy((void *)&sysregs_snapshot[0], (void *)&sysregs[0],
108 sizeof(struct sysreg_data) * SYSREG_MAX_CBS);
109}
110
111void host_util_restore_sysreg_snapshot(void)
112{
113 memcpy((void *)&sysregs[0], (void *)&sysregs_snapshot[0],
114 sizeof(struct sysreg_data) * SYSREG_MAX_CBS);
115}
116
117void host_util_zero_sysregs_and_cbs(void)
Soby Mathewb4c6df42022-11-09 11:13:29 +0000118{
119
Javier Almansa Sobrino9929a792022-11-22 16:11:13 +0000120 (void)memset((void *)sysregs, 0,
121 sizeof(struct sysreg_data) * SYSREG_MAX_CBS);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000122
123 installed_cb_idx = 0U;
124}
125
126int host_util_set_default_sysreg_cb(char *name, u_register_t init)
127{
128 return host_util_set_sysreg_cb(name, &sysreg_rd_cb,
Javier Almansa Sobrino9929a792022-11-22 16:11:13 +0000129 &sysreg_wr_cb, init);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000130}
131
132unsigned long host_util_get_granule_base(void)
133{
134 return (unsigned long)granules_buffer;
135}
Javier Almansa Sobrino9929a792022-11-22 16:11:13 +0000136
137void host_util_set_cpuid(unsigned int cpuid)
138{
139 assert(cpuid < MAX_CPUS);
140
141 current_cpuid = cpuid;
142}
Mate Toth-Palaead06f2023-03-02 10:17:09 +0100143
144unsigned char *host_util_get_el3_rmm_shared_buffer(void)
145{
146 return el3_rmm_shared_buffer;
147}
148
149void host_util_setup_sysreg_and_boot_manifest(void)
150{
151 int ret;
152
153 /*
AlexeiFedoroveaec0c42023-02-01 18:13:32 +0000154 * Initialize ID_AA64DFR0_EL1 with PMUVer field to PMUv3p7.
155 * (ID_AA64DFR0_EL1.PMUVer, bits [11:8] set to 7)
156 */
157 ret = host_util_set_default_sysreg_cb("id_aa64dfr0_el1",
158 INPLACE(ID_AA64DFR0_EL1_PMUVer, 7UL));
159
160 /*
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +0100161 * Setup id_aa64mmfr0_el1 with a PA size of 48 bits
162 * and 4K granularity with LPA2 support for stages 1 and 2.
Mate Toth-Palaead06f2023-03-02 10:17:09 +0100163 */
164 ret = host_util_set_default_sysreg_cb("id_aa64mmfr0_el1",
Javier Almansa Sobrino2fa8abe2023-06-06 13:18:17 +0100165 INPLACE(ID_AA64MMFR0_EL1_PARANGE, 5UL) |
166 INPLACE(ID_AA64MMFR0_EL1_TGRAN4,
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +0100167 ID_AA64MMFR0_EL1_TGRAN4_LPA2) |
168 INPLACE(ID_AA64MMFR0_EL1_TGRAN4_2,
169 ID_AA64MMFR0_EL1_TGRAN4_2_TGRAN4));
Mate Toth-Palaead06f2023-03-02 10:17:09 +0100170
171 /*
172 * Initialize ICH_VTR_EL2 with 6 preemption bits.
173 * (PREbits is equal number of preemption bits minus one)
174 */
175 ret = host_util_set_default_sysreg_cb("ich_vtr_el2",
176 INPLACE(ICH_VTR_EL2_PRE_BITS, 5UL));
177
178 /* SCTLR_EL2 is reset to zero */
179 ret = host_util_set_default_sysreg_cb("sctlr_el2", 0UL);
180
Javier Almansa Sobrinoc173f1e2023-03-21 12:53:08 +0000181 /* HCR_EL2 is reset to zero */
182 ret = host_util_set_default_sysreg_cb("hcr_el2", 0UL);
183
Mate Toth-Palaead06f2023-03-02 10:17:09 +0100184 /* TPIDR_EL2 is reset to zero */
185 ret = host_util_set_default_sysreg_cb("tpidr_el2", 0UL);
186
Mate Toth-Pal40193e42023-03-01 13:17:48 +0100187 /* ID_AA64ISAR0.RNDR is reset to 1 */
188 ret = host_util_set_default_sysreg_cb("id_aa64isar0_el1",
189 INPLACE(ID_AA64ISAR0_EL1_RNDR, 1UL));
190
Mate Toth-Palaead06f2023-03-02 10:17:09 +0100191 /*
Mate Toth-Pal2611c552023-02-28 10:28:32 +0100192 * Add callback to elr_el2 so that the realm entry point can be accessed
193 * by host_run_realm
194 */
195 ret = host_util_set_default_sysreg_cb("elr_el2", 0UL);
196
197 /*
Soby Mathewa694cca2023-04-24 03:42:45 +0100198 * Add callback to esr_el2 so that the realm exceptions can be handled.
199 */
200 ret = host_util_set_default_sysreg_cb("esr_el2", 0UL);
201
202 /*
AlexeiFedoroveaec0c42023-02-01 18:13:32 +0000203 * Set number of event counters implemented to 31.
204 * (PMCR_EL0.N, bits [15:11] set to 31)
205 */
206 ret = host_util_set_default_sysreg_cb("pmcr_el0",
207 INPLACE(PMCR_EL0_N, 31UL));
208
Soby Mathew76e9b452023-05-16 15:11:34 +0100209 /* Set ISR_EL1 to 0 */
210 ret = host_util_set_default_sysreg_cb("isr_el1", 0UL);
211
AlexeiFedoroveaec0c42023-02-01 18:13:32 +0000212 /*
Mate Toth-Palaead06f2023-03-02 10:17:09 +0100213 * Only check the return value of the last callback setup, to detect
214 * if we are out of callback slots.
215 */
216 if (ret != 0) {
217 panic();
218 }
219
220 /* Initialize the boot manifest */
Soby Mathewda3ecb12023-05-22 16:56:38 +0100221 boot_manifest->version = RMM_EL3_MANIFEST_MAKE_VERSION(
222 RMM_EL3_MANIFEST_VERS_MAJOR,
223 RMM_EL3_MANIFEST_VERS_MINOR);
Mate Toth-Palaead06f2023-03-02 10:17:09 +0100224 boot_manifest->plat_data = (uintptr_t)NULL;
225}
Soby Mathewa694cca2023-04-24 03:42:45 +0100226
227int host_util_rec_run(unsigned long *regs)
228{
229 unsigned long pc = read_elr_el2();
230 realm_entrypoint_t realm_ep = (void *)pc;
231
232 write_esr_el2(0x0);
233 return realm_ep(regs);
234}
235
236int host_util_rsi_helper(realm_entrypoint_t ep)
237{
238 /* Reduce the ep by 0x4 as RMM will advance_pc as part of handling RSI */
239 write_elr_el2((u_register_t) ep - 0x4);
240 write_esr_el2(ESR_EL2_EC_SMC);
241
242 return ARM_EXCEPTION_SYNC_LEL;
243}