blob: 13642b1f19495b2fe7723ba9717bd6d3c3b61392 [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 /*
Mate Toth-Palaead06f2023-03-02 10:17:09 +0100161 * Initialize ID_AA64MMFR0_EL1 with a physical address
162 * range of 48 bits (PARange bits set to 0b0101)
163 */
164 ret = host_util_set_default_sysreg_cb("id_aa64mmfr0_el1",
165 INPLACE(ID_AA64MMFR0_EL1_PARANGE, 5UL));
166
167 /*
168 * Initialize ICH_VTR_EL2 with 6 preemption bits.
169 * (PREbits is equal number of preemption bits minus one)
170 */
171 ret = host_util_set_default_sysreg_cb("ich_vtr_el2",
172 INPLACE(ICH_VTR_EL2_PRE_BITS, 5UL));
173
174 /* SCTLR_EL2 is reset to zero */
175 ret = host_util_set_default_sysreg_cb("sctlr_el2", 0UL);
176
Javier Almansa Sobrinoc173f1e2023-03-21 12:53:08 +0000177 /* HCR_EL2 is reset to zero */
178 ret = host_util_set_default_sysreg_cb("hcr_el2", 0UL);
179
Mate Toth-Palaead06f2023-03-02 10:17:09 +0100180 /* TPIDR_EL2 is reset to zero */
181 ret = host_util_set_default_sysreg_cb("tpidr_el2", 0UL);
182
Mate Toth-Pal40193e42023-03-01 13:17:48 +0100183 /* ID_AA64ISAR0.RNDR is reset to 1 */
184 ret = host_util_set_default_sysreg_cb("id_aa64isar0_el1",
185 INPLACE(ID_AA64ISAR0_EL1_RNDR, 1UL));
186
Mate Toth-Palaead06f2023-03-02 10:17:09 +0100187 /*
Mate Toth-Pal2611c552023-02-28 10:28:32 +0100188 * Add callback to elr_el2 so that the realm entry point can be accessed
189 * by host_run_realm
190 */
191 ret = host_util_set_default_sysreg_cb("elr_el2", 0UL);
192
193 /*
Soby Mathewa694cca2023-04-24 03:42:45 +0100194 * Add callback to esr_el2 so that the realm exceptions can be handled.
195 */
196 ret = host_util_set_default_sysreg_cb("esr_el2", 0UL);
197
198 /*
AlexeiFedoroveaec0c42023-02-01 18:13:32 +0000199 * Set number of event counters implemented to 31.
200 * (PMCR_EL0.N, bits [15:11] set to 31)
201 */
202 ret = host_util_set_default_sysreg_cb("pmcr_el0",
203 INPLACE(PMCR_EL0_N, 31UL));
204
Soby Mathew76e9b452023-05-16 15:11:34 +0100205 /* Set ISR_EL1 to 0 */
206 ret = host_util_set_default_sysreg_cb("isr_el1", 0UL);
207
AlexeiFedoroveaec0c42023-02-01 18:13:32 +0000208 /*
Mate Toth-Palaead06f2023-03-02 10:17:09 +0100209 * Only check the return value of the last callback setup, to detect
210 * if we are out of callback slots.
211 */
212 if (ret != 0) {
213 panic();
214 }
215
216 /* Initialize the boot manifest */
Soby Mathewda3ecb12023-05-22 16:56:38 +0100217 boot_manifest->version = RMM_EL3_MANIFEST_MAKE_VERSION(
218 RMM_EL3_MANIFEST_VERS_MAJOR,
219 RMM_EL3_MANIFEST_VERS_MINOR);
Mate Toth-Palaead06f2023-03-02 10:17:09 +0100220 boot_manifest->plat_data = (uintptr_t)NULL;
221}
Soby Mathewa694cca2023-04-24 03:42:45 +0100222
223int host_util_rec_run(unsigned long *regs)
224{
225 unsigned long pc = read_elr_el2();
226 realm_entrypoint_t realm_ep = (void *)pc;
227
228 write_esr_el2(0x0);
229 return realm_ep(regs);
230}
231
232int host_util_rsi_helper(realm_entrypoint_t ep)
233{
234 /* Reduce the ep by 0x4 as RMM will advance_pc as part of handling RSI */
235 write_elr_el2((u_register_t) ep - 0x4);
236 write_esr_el2(ESR_EL2_EC_SMC);
237
238 return ARM_EXCEPTION_SYNC_LEL;
239}