arm_common.c 6.69 KB
Newer Older
1
/*
2
 * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved.
3
 *
dp-arm's avatar
dp-arm committed
4
 * SPDX-License-Identifier: BSD-3-Clause
5
 */
6
7
8
9
10

#include <assert.h>

#include <platform_def.h>

11
12
#include <arch.h>
#include <arch_helpers.h>
13
14
15
#include <common/debug.h>
#include <common/romlib.h>
#include <lib/mmio.h>
16
#include <lib/smccc.h>
17
#include <lib/xlat_tables/xlat_tables_compat.h>
18
#include <services/arm_arch_svc.h>
19
#include <plat/arm/common/plat_arm.h>
20
21
#include <plat/common/platform.h>

22
23
/* Weak definitions may be overridden in specific ARM standard platform */
#pragma weak plat_get_ns_image_entrypoint
24
#pragma weak plat_arm_get_mmap
25
26
27
28

/* Conditionally provide a weak definition of plat_get_syscnt_freq2 to avoid
 * conflicts with the definition in plat/common. */
#pragma weak plat_get_syscnt_freq2
29

30
31
32
/* Get ARM SOC-ID */
#pragma weak plat_arm_get_soc_id

33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
/*******************************************************************************
 * Changes the memory attributes for the region of mapped memory where the BL
 * image's translation tables are located such that the tables will have
 * read-only permissions.
 ******************************************************************************/
#if PLAT_RO_XLAT_TABLES
void arm_xlat_make_tables_readonly(void)
{
	int rc = xlat_make_tables_readonly();

	if (rc != 0) {
		ERROR("Failed to make translation tables read-only at EL%u.\n",
		      get_current_el());
		panic();
	}

	INFO("Translation tables are now read-only at EL%u.\n",
	     get_current_el());
}
#endif
Roberto Vargas's avatar
Roberto Vargas committed
53
54
55
56
57
58
59
60
61

void arm_setup_romlib(void)
{
#if USE_ROMLIB
	if (!rom_lib_init(ROMLIB_VERSION))
		panic();
#endif
}

62
uintptr_t plat_get_ns_image_entrypoint(void)
63
{
64
65
66
#ifdef PRELOADED_BL33_BASE
	return PRELOADED_BL33_BASE;
#else
67
	return PLAT_ARM_NS_IMAGE_BASE;
68
#endif
69
70
71
72
73
74
75
76
77
}

/*******************************************************************************
 * Gets SPSR for BL32 entry
 ******************************************************************************/
uint32_t arm_get_spsr_for_bl32_entry(void)
{
	/*
	 * The Secure Payload Dispatcher service is responsible for
78
	 * setting the SPSR prior to entry into the BL32 image.
79
80
81
82
83
84
85
	 */
	return 0;
}

/*******************************************************************************
 * Gets SPSR for BL33 entry
 ******************************************************************************/
86
#ifdef __aarch64__
87
88
89
90
91
92
uint32_t arm_get_spsr_for_bl33_entry(void)
{
	unsigned int mode;
	uint32_t spsr;

	/* Figure out what mode we enter the non-secure world in */
93
	mode = (el_implemented(2) != EL_IMPL_NONE) ? MODE_EL2 : MODE_EL1;
94
95
96
97
98
99

	/*
	 * TODO: Consider the possibility of specifying the SPSR in
	 * the FIP ToC and allowing the platform to have a say as
	 * well.
	 */
100
	spsr = SPSR_64((uint64_t)mode, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS);
101
102
	return spsr;
}
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
#else
/*******************************************************************************
 * Gets SPSR for BL33 entry
 ******************************************************************************/
uint32_t arm_get_spsr_for_bl33_entry(void)
{
	unsigned int hyp_status, mode, spsr;

	hyp_status = GET_VIRT_EXT(read_id_pfr1());

	mode = (hyp_status) ? MODE32_hyp : MODE32_svc;

	/*
	 * TODO: Consider the possibility of specifying the SPSR in
	 * the FIP ToC and allowing the platform to have a say as
	 * well.
	 */
	spsr = SPSR_MODE32(mode, plat_get_ns_image_entrypoint() & 0x1,
			SPSR_E_LITTLE, DISABLE_ALL_EXCEPTIONS);
	return spsr;
}
124
#endif /* __aarch64__ */
125

126
127
128
/*******************************************************************************
 * Configures access to the system counter timer module.
 ******************************************************************************/
129
#ifdef ARM_SYS_TIMCTL_BASE
130
131
132
133
void arm_configure_sys_timer(void)
{
	unsigned int reg_val;

134
135
136
	/* Read the frequency of the system counter */
	unsigned int freq_val = plat_get_syscnt_freq2();

137
#if ARM_CONFIG_CNTACR
138
139
140
	reg_val = (1U << CNTACR_RPCT_SHIFT) | (1U << CNTACR_RVCT_SHIFT);
	reg_val |= (1U << CNTACR_RFRQ_SHIFT) | (1U << CNTACR_RVOFF_SHIFT);
	reg_val |= (1U << CNTACR_RWVT_SHIFT) | (1U << CNTACR_RWPT_SHIFT);
141
	mmio_write_32(ARM_SYS_TIMCTL_BASE + CNTACR_BASE(PLAT_ARM_NSTIMER_FRAME_ID), reg_val);
142
#endif /* ARM_CONFIG_CNTACR */
143

144
	reg_val = (1U << CNTNSAR_NS_SHIFT(PLAT_ARM_NSTIMER_FRAME_ID));
145
	mmio_write_32(ARM_SYS_TIMCTL_BASE + CNTNSAR, reg_val);
146
147
148
149
150
151
152
153

	/*
	 * Initialize CNTFRQ register in CNTCTLBase frame. The CNTFRQ
	 * system register initialized during psci_arch_setup() is different
	 * from this and has to be updated independently.
	 */
	mmio_write_32(ARM_SYS_TIMCTL_BASE + CNTCTLBASE_CNTFRQ, freq_val);

154
#if defined(PLAT_juno) || defined(PLAT_n1sdp)
155
156
	/*
	 * Initialize CNTFRQ register in Non-secure CNTBase frame.
157
158
159
	 * This is only required for Juno and N1SDP, because they do not
	 * follow ARM ARM in that the value updated in CNTFRQ is not
	 * reflected in CNTBASEN_CNTFRQ. Hence update the value manually.
160
	 */
161
	mmio_write_32(ARM_SYS_CNT_BASE_NS + CNTBASEN_CNTFRQ, freq_val);
162
#endif
163
}
164
#endif /* ARM_SYS_TIMCTL_BASE */
165
166
167
168
169
170
171
172

/*******************************************************************************
 * Returns ARM platform specific memory map regions.
 ******************************************************************************/
const mmap_region_t *plat_arm_get_mmap(void)
{
	return plat_arm_mmap;
}
173

174
#ifdef ARM_SYS_CNTCTL_BASE
175
176
177

unsigned int plat_get_syscnt_freq2(void)
{
Sandrine Bailleux's avatar
Sandrine Bailleux committed
178
	unsigned int counter_base_frequency;
179
180
181
182
183

	/* Read the frequency from Frequency modes table */
	counter_base_frequency = mmio_read_32(ARM_SYS_CNTCTL_BASE + CNTFID_OFF);

	/* The first entry of the frequency modes table must not be 0 */
184
	if (counter_base_frequency == 0U)
185
186
187
188
		panic();

	return counter_base_frequency;
}
189

190
#endif /* ARM_SYS_CNTCTL_BASE */
191
192
193
194
195
196
197
198
199

#if SDEI_SUPPORT
/*
 * Translate SDEI entry point to PA, and perform standard ARM entry point
 * validation on it.
 */
int plat_sdei_validate_entry_point(uintptr_t ep, unsigned int client_mode)
{
	uint64_t par, pa;
200
	u_register_t scr_el3;
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218

	/* Doing Non-secure address translation requires SCR_EL3.NS set */
	scr_el3 = read_scr_el3();
	write_scr_el3(scr_el3 | SCR_NS_BIT);
	isb();

	assert((client_mode == MODE_EL2) || (client_mode == MODE_EL1));
	if (client_mode == MODE_EL2) {
		/*
		 * Translate entry point to Physical Address using the EL2
		 * translation regime.
		 */
		ats1e2r(ep);
	} else {
		/*
		 * Translate entry point to Physical Address using the EL1&0
		 * translation regime, including stage 2.
		 */
219
		AT(ats12e1r, ep);
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
	}
	isb();
	par = read_par_el1();

	/* Restore original SCRL_EL3 */
	write_scr_el3(scr_el3);
	isb();

	/* If the translation resulted in fault, return failure */
	if ((par & PAR_F_MASK) != 0)
		return -1;

	/* Extract Physical Address from PAR */
	pa = (par & (PAR_ADDR_MASK << PAR_ADDR_SHIFT));

	/* Perform NS entry point validation on the physical address */
	return arm_validate_ns_entrypoint(pa);
}
#endif
239