fvp: Provide per-EL MMU setup functions

Instead of having a single version of the MMU setup functions for all
bootloader images that can execute either in EL3 or in EL1, provide
separate functions for EL1 and EL3. Each bootloader image can then
call the appropriate version of these functions. The aim is to reduce
the amount of code compiled in each BL image by embedding only what's
needed (e.g. BL1 to embed only EL3 variants).

Change-Id: Ib86831d5450cf778ae78c9c1f7553fe91274c2fa
This commit is contained in:
Sandrine Bailleux 2014-05-09 11:35:36 +01:00
parent b3254e8547
commit b793e43166
8 changed files with 116 additions and 118 deletions

View File

@ -203,7 +203,7 @@ func tsp_cpu_on_entry
* Initialise the MMU
* ---------------------------------------------
*/
bl enable_mmu
bl enable_mmu_el1
/* ---------------------------------------------
* Give ourselves a stack allocated in Normal

View File

@ -47,80 +47,68 @@
static unsigned long platform_config[CONFIG_LIMIT];
/*******************************************************************************
* Enable the MMU assuming that the pagetables have already been created
*******************************************************************************/
void enable_mmu()
{
unsigned long mair, tcr, ttbr, sctlr;
/* Set the attributes in the right indices of the MAIR */
mair = MAIR_ATTR_SET(ATTR_DEVICE, ATTR_DEVICE_INDEX);
mair |= MAIR_ATTR_SET(ATTR_IWBWA_OWBWA_NTR,
ATTR_IWBWA_OWBWA_NTR_INDEX);
/*
* Set TCR bits as well. Inner & outer WBWA & shareable + T0SZ = 32
*/
tcr = TCR_SH_INNER_SHAREABLE | TCR_RGN_OUTER_WBA |
TCR_RGN_INNER_WBA | TCR_T0SZ_4GB;
/* Set TTBR bits as well */
ttbr = (unsigned long) l1_xlation_table;
if (IS_IN_EL3()) {
assert((read_sctlr_el3() & SCTLR_M_BIT) == 0);
write_mair_el3(mair);
tcr |= TCR_EL3_RES1;
/* Invalidate EL3 TLBs */
tlbialle3();
write_tcr_el3(tcr);
write_ttbr0_el3(ttbr);
/* ensure all translation table writes have drained into memory,
* the TLB invalidation is complete, and translation register
* writes are committed before enabling the MMU
*/
dsb();
isb();
sctlr = read_sctlr_el3();
sctlr |= SCTLR_WXN_BIT | SCTLR_M_BIT | SCTLR_I_BIT;
sctlr |= SCTLR_A_BIT | SCTLR_C_BIT;
write_sctlr_el3(sctlr);
} else {
assert((read_sctlr_el1() & SCTLR_M_BIT) == 0);
write_mair_el1(mair);
/* Invalidate EL1 TLBs */
tlbivmalle1();
write_tcr_el1(tcr);
write_ttbr0_el1(ttbr);
/* ensure all translation table writes have drained into memory,
* the TLB invalidation is complete, and translation register
* writes are committed before enabling the MMU
*/
dsb();
isb();
sctlr = read_sctlr_el1();
sctlr |= SCTLR_WXN_BIT | SCTLR_M_BIT | SCTLR_I_BIT;
sctlr |= SCTLR_A_BIT | SCTLR_C_BIT;
write_sctlr_el1(sctlr);
* Macro generating the code for the function enabling the MMU in the given
* exception level, assuming that the pagetables have already been created.
*
* _el: Exception level at which the function will run
* _tcr_extra: Extra bits to set in the TCR register. This mask will
* be OR'ed with the default TCR value.
* _tlbi_fct: Function to invalidate the TLBs at the current
* exception level
******************************************************************************/
#define DEFINE_ENABLE_MMU_EL(_el, _tcr_extra, _tlbi_fct) \
void enable_mmu_el##_el(void) \
{ \
uint64_t mair, tcr, ttbr; \
uint32_t sctlr; \
\
assert(IS_IN_EL(_el)); \
assert((read_sctlr_el##_el() & SCTLR_M_BIT) == 0); \
\
/* Set attributes in the right indices of the MAIR */ \
mair = MAIR_ATTR_SET(ATTR_DEVICE, ATTR_DEVICE_INDEX); \
mair |= MAIR_ATTR_SET(ATTR_IWBWA_OWBWA_NTR, \
ATTR_IWBWA_OWBWA_NTR_INDEX); \
write_mair_el##_el(mair); \
\
/* Invalidate TLBs at the current exception level */ \
_tlbi_fct(); \
\
/* Set TCR bits as well. */ \
/* Inner & outer WBWA & shareable + T0SZ = 32 */ \
tcr = TCR_SH_INNER_SHAREABLE | TCR_RGN_OUTER_WBA | \
TCR_RGN_INNER_WBA | TCR_T0SZ_4GB; \
tcr |= _tcr_extra; \
write_tcr_el##_el(tcr); \
\
/* Set TTBR bits as well */ \
ttbr = (uint64_t) l1_xlation_table; \
write_ttbr0_el##_el(ttbr); \
\
/* Ensure all translation table writes have drained */ \
/* into memory, the TLB invalidation is complete, */ \
/* and translation register writes are committed */ \
/* before enabling the MMU */ \
dsb(); \
isb(); \
\
sctlr = read_sctlr_el##_el(); \
sctlr |= SCTLR_WXN_BIT | SCTLR_M_BIT | SCTLR_I_BIT; \
sctlr |= SCTLR_A_BIT | SCTLR_C_BIT; \
write_sctlr_el##_el(sctlr); \
\
/* Ensure the MMU enable takes effect immediately */ \
isb(); \
}
/* ensure the MMU enable takes effect immediately */
isb();
return;
}
/* Define EL1 and EL3 variants of the function enabling the MMU */
DEFINE_ENABLE_MMU_EL(1, 0, tlbivmalle1)
DEFINE_ENABLE_MMU_EL(3, TCR_EL3_RES1, tlbialle3)
/*
* Table of regions to map using the MMU.
* This doesn't include TZRAM as the 'mem_layout' argument passed to to
* configure_mmu() will give the available subset of that,
* This doesn't include TZRAM as the 'mem_layout' argument passed to
* configure_mmu_elx() will give the available subset of that,
*/
const mmap_region_t fvp_mmap[] = {
{ TZROM_BASE, TZROM_SIZE, MT_MEMORY | MT_RO | MT_SECURE },
@ -138,28 +126,32 @@ const mmap_region_t fvp_mmap[] = {
};
/*******************************************************************************
* Setup the pagetables as per the platform memory map & initialize the mmu
*******************************************************************************/
void configure_mmu(meminfo_t *mem_layout,
unsigned long ro_start,
unsigned long ro_limit,
unsigned long coh_start,
unsigned long coh_limit)
{
mmap_add_region(mem_layout->total_base, mem_layout->total_size,
MT_MEMORY | MT_RW | MT_SECURE);
mmap_add_region(ro_start, ro_limit - ro_start,
MT_MEMORY | MT_RO | MT_SECURE);
mmap_add_region(coh_start, coh_limit - coh_start,
MT_DEVICE | MT_RW | MT_SECURE);
* Macro generating the code for the function setting up the pagetables as per
* the platform memory map & initialize the mmu, for the given exception level
******************************************************************************/
#define DEFINE_CONFIGURE_MMU_EL(_el) \
void configure_mmu_el##_el(meminfo_t *mem_layout, \
unsigned long ro_start, \
unsigned long ro_limit, \
unsigned long coh_start, \
unsigned long coh_limit) \
{ \
mmap_add_region(mem_layout->total_base, \
mem_layout->total_size, \
MT_MEMORY | MT_RW | MT_SECURE); \
mmap_add_region(ro_start, ro_limit - ro_start, \
MT_MEMORY | MT_RO | MT_SECURE); \
mmap_add_region(coh_start, coh_limit - coh_start, \
MT_DEVICE | MT_RW | MT_SECURE); \
mmap_add(fvp_mmap); \
init_xlat_tables(); \
\
enable_mmu_el##_el(); \
}
mmap_add(fvp_mmap);
init_xlat_tables();
enable_mmu();
return;
}
/* Define EL1 and EL3 variants of the function initialising the MMU */
DEFINE_CONFIGURE_MMU_EL(1)
DEFINE_CONFIGURE_MMU_EL(3)
/* Simple routine which returns a configuration variable value */
unsigned long platform_get_cfgvar(unsigned int var_id)

View File

@ -138,9 +138,9 @@ void bl1_plat_arch_setup(void)
cci_enable_coherency(read_mpidr());
}
configure_mmu(&bl1_tzram_layout,
TZROM_BASE,
TZROM_BASE + TZROM_SIZE,
BL1_COHERENT_RAM_BASE,
BL1_COHERENT_RAM_LIMIT);
configure_mmu_el3(&bl1_tzram_layout,
TZROM_BASE,
TZROM_BASE + TZROM_SIZE,
BL1_COHERENT_RAM_BASE,
BL1_COHERENT_RAM_LIMIT);
}

View File

@ -172,9 +172,9 @@ void bl2_platform_setup()
******************************************************************************/
void bl2_plat_arch_setup()
{
configure_mmu(&bl2_tzram_layout,
BL2_RO_BASE,
BL2_RO_LIMIT,
BL2_COHERENT_RAM_BASE,
BL2_COHERENT_RAM_LIMIT);
configure_mmu_el1(&bl2_tzram_layout,
BL2_RO_BASE,
BL2_RO_LIMIT,
BL2_COHERENT_RAM_BASE,
BL2_COHERENT_RAM_LIMIT);
}

View File

@ -172,9 +172,9 @@ void bl31_platform_setup()
******************************************************************************/
void bl31_plat_arch_setup()
{
configure_mmu(&bl2_to_bl31_args->bl31_meminfo,
BL31_RO_BASE,
BL31_RO_LIMIT,
BL31_COHERENT_RAM_BASE,
BL31_COHERENT_RAM_LIMIT);
configure_mmu_el3(&bl2_to_bl31_args->bl31_meminfo,
BL31_RO_BASE,
BL31_RO_LIMIT,
BL31_COHERENT_RAM_BASE,
BL31_COHERENT_RAM_LIMIT);
}

View File

@ -111,9 +111,9 @@ void bl32_platform_setup()
******************************************************************************/
void bl32_plat_arch_setup()
{
configure_mmu(&bl32_tzdram_layout,
BL32_RO_BASE,
BL32_RO_LIMIT,
BL32_COHERENT_RAM_BASE,
BL32_COHERENT_RAM_LIMIT);
configure_mmu_el1(&bl32_tzdram_layout,
BL32_RO_BASE,
BL32_RO_LIMIT,
BL32_COHERENT_RAM_BASE,
BL32_COHERENT_RAM_LIMIT);
}

View File

@ -370,12 +370,18 @@ extern void bl2_plat_arch_setup(void);
extern void bl31_plat_arch_setup(void);
extern int platform_setup_pm(const struct plat_pm_ops **);
extern unsigned int platform_get_core_pos(unsigned long mpidr);
extern void enable_mmu(void);
extern void configure_mmu(struct meminfo *,
unsigned long,
unsigned long,
unsigned long,
unsigned long);
extern void enable_mmu_el1(void);
extern void enable_mmu_el3(void);
extern void configure_mmu_el1(struct meminfo *mem_layout,
unsigned long ro_start,
unsigned long ro_limit,
unsigned long coh_start,
unsigned long coh_limit);
extern void configure_mmu_el3(struct meminfo *mem_layout,
unsigned long ro_start,
unsigned long ro_limit,
unsigned long coh_start,
unsigned long coh_limit);
extern unsigned long platform_get_cfgvar(unsigned int);
extern int platform_config_setup(void);
extern void plat_report_exception(unsigned long);

View File

@ -362,7 +362,7 @@ static unsigned int psci_afflvl0_on_finish(unsigned long mpidr,
/*
* Arch. management: Turn on mmu & restore architectural state
*/
enable_mmu();
enable_mmu_el3();
/*
* All the platform specific actions for turning this cpu