blob: c114763371344352f4e7bd787f7c39b56802e1d1 [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>
Mate Toth-Pal0e936512023-10-19 15:02:20 +020016#include <utils_def.h>
Soby Mathewb4c6df42022-11-09 11:13:29 +000017#include <xlat_tables.h>
18
Javier Almansa Sobrino9929a792022-11-22 16:11:13 +000019static struct sysreg_data sysregs[SYSREG_MAX_CBS];
Javier Almansa Sobrino48d68a72023-03-02 12:26:39 +000020static struct sysreg_data sysregs_snapshot[SYSREG_MAX_CBS];
Soby Mathewb4c6df42022-11-09 11:13:29 +000021static unsigned int installed_cb_idx;
Javier Almansa Sobrino9929a792022-11-22 16:11:13 +000022static unsigned int current_cpuid;
Soby Mathewb4c6df42022-11-09 11:13:29 +000023
24/*
25 * Allocate memory to emulate physical memory to initialize the
26 * granule library.
27 */
AlexeiFedorov037add62024-10-30 15:53:05 +000028IF_NCBMC(static) unsigned char host_dram_buffer[HOST_DRAM_SIZE]
29 __aligned(GRANULE_SIZE);
30IF_NCBMC(static) unsigned char host_dev_ncoh_buffer[HOST_NCOH_DEV_SIZE]
31 __aligned(GRANULE_SIZE);
Soby Mathewb4c6df42022-11-09 11:13:29 +000032
33/*
Mate Toth-Palaead06f2023-03-02 10:17:09 +010034 * Define and set the Boot Interface arguments.
35 */
36static unsigned char el3_rmm_shared_buffer[PAGE_SIZE] __aligned(PAGE_SIZE);
37
38/*
39 * Create a basic boot manifest.
40 */
41static struct rmm_core_manifest *boot_manifest =
42 (struct rmm_core_manifest *)el3_rmm_shared_buffer;
43
44/*
Soby Mathewb4c6df42022-11-09 11:13:29 +000045 * Generic callback to access a sysreg for reading.
46 */
47static u_register_t sysreg_rd_cb(u_register_t *reg)
48{
49 return *reg;
50}
51
52/*
53 * Generic callback to access a sysreg for writing.
54 */
55static void sysreg_wr_cb(u_register_t val, u_register_t *reg)
56{
57 *reg = val;
58}
59
60struct sysreg_cb *host_util_get_sysreg_cb(char *name)
61{
62 for (unsigned int i = 0U; i < SYSREG_MAX_CBS; i++) {
Javier Almansa Sobrino9929a792022-11-22 16:11:13 +000063 if (strncmp(name, &sysregs[i].name[0],
Soby Mathewb4c6df42022-11-09 11:13:29 +000064 MAX_SYSREG_NAME_LEN) == 0) {
Javier Almansa Sobrino9929a792022-11-22 16:11:13 +000065
66 /*
67 * Get a pointer to the register value for the
68 * current CPU.
69 */
70 sysregs[i].callbacks.reg =
71 &(sysregs[i].value[current_cpuid]);
72 return &sysregs[i].callbacks;
Soby Mathewb4c6df42022-11-09 11:13:29 +000073 }
74 }
75
76 return (struct sysreg_cb *)NULL;
77}
78
79int host_util_set_sysreg_cb(char *name, rd_cb_t rd_cb, wr_cb_t wr_cb,
80 u_register_t init)
81{
82 if (installed_cb_idx < SYSREG_MAX_CBS) {
Javier Almansa Sobrino9929a792022-11-22 16:11:13 +000083 sysregs[installed_cb_idx].callbacks.rd_cb = rd_cb;
84 sysregs[installed_cb_idx].callbacks.wr_cb = wr_cb;
85 sysregs[installed_cb_idx].callbacks.reg =
86 (u_register_t *)NULL;
Soby Mathewb4c6df42022-11-09 11:13:29 +000087
Javier Almansa Sobrino9929a792022-11-22 16:11:13 +000088 for (unsigned int i = 0U; i < MAX_CPUS; i++) {
89 sysregs[installed_cb_idx].value[i] = init;
90 }
91
92 (void)strncpy(&(sysregs[installed_cb_idx].name[0]),
Soby Mathewb4c6df42022-11-09 11:13:29 +000093 &name[0], MAX_SYSREG_NAME_LEN);
94
95 /*
96 * Add a string termination character in case the
97 * name were truncated.
98 */
Javier Almansa Sobrino9929a792022-11-22 16:11:13 +000099 sysregs[installed_cb_idx].name[MAX_SYSREG_NAME_LEN] = '\0';
Soby Mathewb4c6df42022-11-09 11:13:29 +0000100
101 ++installed_cb_idx;
102
103 return 0;
104 }
105
106 return -ENOMEM;
107}
108
Javier Almansa Sobrino48d68a72023-03-02 12:26:39 +0000109void host_util_take_sysreg_snapshot(void)
110{
111 memcpy((void *)&sysregs_snapshot[0], (void *)&sysregs[0],
112 sizeof(struct sysreg_data) * SYSREG_MAX_CBS);
113}
114
115void host_util_restore_sysreg_snapshot(void)
116{
117 memcpy((void *)&sysregs[0], (void *)&sysregs_snapshot[0],
118 sizeof(struct sysreg_data) * SYSREG_MAX_CBS);
119}
120
121void host_util_zero_sysregs_and_cbs(void)
Soby Mathewb4c6df42022-11-09 11:13:29 +0000122{
123
Javier Almansa Sobrino9929a792022-11-22 16:11:13 +0000124 (void)memset((void *)sysregs, 0,
125 sizeof(struct sysreg_data) * SYSREG_MAX_CBS);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000126
127 installed_cb_idx = 0U;
128}
129
130int host_util_set_default_sysreg_cb(char *name, u_register_t init)
131{
132 return host_util_set_sysreg_cb(name, &sysreg_rd_cb,
Javier Almansa Sobrino9929a792022-11-22 16:11:13 +0000133 &sysreg_wr_cb, init);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000134}
135
136unsigned long host_util_get_granule_base(void)
137{
AlexeiFedorov037add62024-10-30 15:53:05 +0000138 return (unsigned long)host_dram_buffer;
139}
140
141unsigned long host_util_get_dev_granule_base(void)
142{
143 return (unsigned long)host_dev_ncoh_buffer;
Soby Mathewb4c6df42022-11-09 11:13:29 +0000144}
Javier Almansa Sobrino9929a792022-11-22 16:11:13 +0000145
146void host_util_set_cpuid(unsigned int cpuid)
147{
148 assert(cpuid < MAX_CPUS);
149
150 current_cpuid = cpuid;
151}
Mate Toth-Palaead06f2023-03-02 10:17:09 +0100152
153unsigned char *host_util_get_el3_rmm_shared_buffer(void)
154{
155 return el3_rmm_shared_buffer;
156}
157
158void host_util_setup_sysreg_and_boot_manifest(void)
159{
160 int ret;
161
162 /*
AlexeiFedoroveaec0c42023-02-01 18:13:32 +0000163 * Initialize ID_AA64DFR0_EL1 with PMUVer field to PMUv3p7.
Soby Mathew0685a152024-09-20 16:04:04 +0100164 * (ID_AA64DFR0_EL1.PMUVer, bits [11:8] set to 7).
165 * Also setup minimum allowed by architecture number of watchpoints
166 * (ID_AA64DFR0_EL1.WRPs, bits [15:12] set to 1)
167 * and breakpoints.
168 * (ID_AA64DFR0_EL1.BRPs, bits [23:20] set to 1)
AlexeiFedoroveaec0c42023-02-01 18:13:32 +0000169 */
Chuyue Luoc06f2622023-11-03 15:18:14 +0000170 (void)host_util_set_default_sysreg_cb("id_aa64dfr0_el1",
Soby Mathew0685a152024-09-20 16:04:04 +0100171 INPLACE(ID_AA64DFR0_EL1_PMUVer, 7UL) |
172 INPLACE(ID_AA64DFR0_EL1_WRPs, 1UL) |
173 INPLACE(ID_AA64DFR0_EL1_BRPs, 1UL));
AlexeiFedoroveaec0c42023-02-01 18:13:32 +0000174
175 /*
Javier Almansa Sobrinof6fff692024-02-02 17:13:57 +0000176 * Initialize ID_AA64MMFR0_EL1 with a physical address
177 * range of 48 bits (PARange bits set to 0b0101) and
178 * support for 52bits PA size with 4KB granularity;
Mate Toth-Palaead06f2023-03-02 10:17:09 +0100179 */
Chuyue Luoc06f2622023-11-03 15:18:14 +0000180 (void)host_util_set_default_sysreg_cb("id_aa64mmfr0_el1",
Javier Almansa Sobrino2fa8abe2023-06-06 13:18:17 +0100181 INPLACE(ID_AA64MMFR0_EL1_PARANGE, 5UL) |
182 INPLACE(ID_AA64MMFR0_EL1_TGRAN4,
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +0100183 ID_AA64MMFR0_EL1_TGRAN4_LPA2) |
184 INPLACE(ID_AA64MMFR0_EL1_TGRAN4_2,
185 ID_AA64MMFR0_EL1_TGRAN4_2_TGRAN4));
Mate Toth-Palaead06f2023-03-02 10:17:09 +0100186
187 /*
188 * Initialize ICH_VTR_EL2 with 6 preemption bits.
189 * (PREbits is equal number of preemption bits minus one)
190 */
Chuyue Luoc06f2622023-11-03 15:18:14 +0000191 (void)host_util_set_default_sysreg_cb("ich_vtr_el2",
Mate Toth-Palaead06f2023-03-02 10:17:09 +0100192 INPLACE(ICH_VTR_EL2_PRE_BITS, 5UL));
193
194 /* SCTLR_EL2 is reset to zero */
Chuyue Luoc06f2622023-11-03 15:18:14 +0000195 (void)host_util_set_default_sysreg_cb("sctlr_el2", 0UL);
Mate Toth-Palaead06f2023-03-02 10:17:09 +0100196
Javier Almansa Sobrinoc173f1e2023-03-21 12:53:08 +0000197 /* HCR_EL2 is reset to zero */
Chuyue Luoc06f2622023-11-03 15:18:14 +0000198 (void)host_util_set_default_sysreg_cb("hcr_el2", 0UL);
Javier Almansa Sobrinoc173f1e2023-03-21 12:53:08 +0000199
Mate Toth-Palaead06f2023-03-02 10:17:09 +0100200 /* TPIDR_EL2 is reset to zero */
Chuyue Luoc06f2622023-11-03 15:18:14 +0000201 (void)host_util_set_default_sysreg_cb("tpidr_el2", 0UL);
Mate Toth-Palaead06f2023-03-02 10:17:09 +0100202
Mate Toth-Pal40193e42023-03-01 13:17:48 +0100203 /* ID_AA64ISAR0.RNDR is reset to 1 */
Chuyue Luoc06f2622023-11-03 15:18:14 +0000204 (void)host_util_set_default_sysreg_cb("id_aa64isar0_el1",
Mate Toth-Pal40193e42023-03-01 13:17:48 +0100205 INPLACE(ID_AA64ISAR0_EL1_RNDR, 1UL));
206
Mate Toth-Palaead06f2023-03-02 10:17:09 +0100207 /*
Mate Toth-Pal2611c552023-02-28 10:28:32 +0100208 * Add callback to elr_el2 so that the realm entry point can be accessed
209 * by host_run_realm
210 */
Chuyue Luoc06f2622023-11-03 15:18:14 +0000211 (void)host_util_set_default_sysreg_cb("elr_el2", 0UL);
Mate Toth-Pal2611c552023-02-28 10:28:32 +0100212
213 /*
Soby Mathewa694cca2023-04-24 03:42:45 +0100214 * Add callback to esr_el2 so that the realm exceptions can be handled.
215 */
Chuyue Luoc06f2622023-11-03 15:18:14 +0000216 (void)host_util_set_default_sysreg_cb("esr_el2", 0UL);
Soby Mathewa694cca2023-04-24 03:42:45 +0100217
218 /*
AlexeiFedoroveaec0c42023-02-01 18:13:32 +0000219 * Set number of event counters implemented to 31.
220 * (PMCR_EL0.N, bits [15:11] set to 31)
221 */
Chuyue Luoc06f2622023-11-03 15:18:14 +0000222 (void)host_util_set_default_sysreg_cb("pmcr_el0",
AlexeiFedoroveaec0c42023-02-01 18:13:32 +0000223 INPLACE(PMCR_EL0_N, 31UL));
224
AlexeiFedorov862f96c2024-03-01 16:26:48 +0000225 /*
226 * Set DCZID_EL0 register with DZP = 0 and
Soby Mathew309e5372024-03-11 11:13:52 +0000227 * BS = 0b101 as GRANULE_SIZE on CBMC platform is 7.
AlexeiFedorov862f96c2024-03-01 16:26:48 +0000228 */
229 (void)host_util_set_default_sysreg_cb("dczid_el0",
Soby Mathew309e5372024-03-11 11:13:52 +0000230 INPLACE(DCZID_EL0_BS, 5UL));
AlexeiFedorov862f96c2024-03-01 16:26:48 +0000231
Soby Mathew76e9b452023-05-16 15:11:34 +0100232 /* Set ISR_EL1 to 0 */
233 ret = host_util_set_default_sysreg_cb("isr_el1", 0UL);
234
AlexeiFedoroveaec0c42023-02-01 18:13:32 +0000235 /*
Mate Toth-Palaead06f2023-03-02 10:17:09 +0100236 * Only check the return value of the last callback setup, to detect
237 * if we are out of callback slots.
238 */
239 if (ret != 0) {
240 panic();
241 }
242
243 /* Initialize the boot manifest */
Soby Mathewda3ecb12023-05-22 16:56:38 +0100244 boot_manifest->version = RMM_EL3_MANIFEST_MAKE_VERSION(
245 RMM_EL3_MANIFEST_VERS_MAJOR,
246 RMM_EL3_MANIFEST_VERS_MINOR);
Mate Toth-Palaead06f2023-03-02 10:17:09 +0100247 boot_manifest->plat_data = (uintptr_t)NULL;
248}
Soby Mathewa694cca2023-04-24 03:42:45 +0100249
250int host_util_rec_run(unsigned long *regs)
251{
252 unsigned long pc = read_elr_el2();
253 realm_entrypoint_t realm_ep = (void *)pc;
254
255 write_esr_el2(0x0);
256 return realm_ep(regs);
257}
258
259int host_util_rsi_helper(realm_entrypoint_t ep)
260{
261 /* Reduce the ep by 0x4 as RMM will advance_pc as part of handling RSI */
262 write_elr_el2((u_register_t) ep - 0x4);
263 write_esr_el2(ESR_EL2_EC_SMC);
264
265 return ARM_EXCEPTION_SYNC_LEL;
266}