Commit 2f5dcfef authored by Andrew Thoelke's avatar Andrew Thoelke
Browse files

Replace disable_mmu with assembler version

disable_mmu() cannot work as a C function as there is no control
over data accesses generated by the compiler between disabling and
cleaning the data cache. This results in reading stale data from
main memory.

As assembler version is provided for EL3, and a variant that also
disables the instruction cache which is now used by the BL1
exception handling function.

Fixes ARM-software/tf-issues#147

Change-Id: I0cf394d2579a125a23c2f2989c2e92ace6ddb1a6
parent 8cec598b
...@@ -212,18 +212,10 @@ func process_exception ...@@ -212,18 +212,10 @@ func process_exception
/* --------------------------------------------- /* ---------------------------------------------
* If BL31 is to be executed in EL3 as well * If BL31 is to be executed in EL3 as well
* then turn off the MMU so that it can perform * then turn off the MMU so that it can perform
* its own setup. TODO: Assuming flat mapped * its own setup.
* translations here. Also all should go into a
* separate MMU teardown function
* --------------------------------------------- * ---------------------------------------------
*/ */
mov x1, #(SCTLR_M_BIT | SCTLR_C_BIT | SCTLR_I_BIT) bl disable_mmu_icache_el3
bl read_sctlr_el3
bic x0, x0, x1
bl write_sctlr_el3
isb
mov x0, #DCCISW
bl dcsw_op_all
bl tlbialle3 bl tlbialle3
skip_mmu_teardown: skip_mmu_teardown:
ldp x6, x7, [sp, #0x30] ldp x6, x7, [sp, #0x30]
......
...@@ -78,6 +78,9 @@ extern void inv_dcache_range(unsigned long, unsigned long); ...@@ -78,6 +78,9 @@ extern void inv_dcache_range(unsigned long, unsigned long);
extern void dcsw_op_louis(unsigned int); extern void dcsw_op_louis(unsigned int);
extern void dcsw_op_all(unsigned int); extern void dcsw_op_all(unsigned int);
extern void disable_mmu_el3(void);
extern void disable_mmu_icache_el3(void);
/******************************************************************************* /*******************************************************************************
* Misc. accessor prototypes * Misc. accessor prototypes
******************************************************************************/ ******************************************************************************/
......
...@@ -79,6 +79,9 @@ ...@@ -79,6 +79,9 @@
.globl zeromem16 .globl zeromem16
.globl memcpy16 .globl memcpy16
.globl disable_mmu_el3
.globl disable_mmu_icache_el3
func get_afflvl_shift func get_afflvl_shift
cmp x0, #3 cmp x0, #3
...@@ -332,3 +335,27 @@ m_loop1: ...@@ -332,3 +335,27 @@ m_loop1:
subs x2, x2, #1 subs x2, x2, #1
b.ne m_loop1 b.ne m_loop1
m_end: ret m_end: ret
/* ---------------------------------------------------------------------------
* Disable the MMU at EL3
* This is implemented in assembler to ensure that the data cache is cleaned
* and invalidated after the MMU is disabled without any intervening cacheable
* data accesses
* ---------------------------------------------------------------------------
*/
func disable_mmu_el3
mov x1, #(SCTLR_M_BIT | SCTLR_C_BIT)
do_disable_mmu:
mrs x0, sctlr_el3
bic x0, x0, x1
msr sctlr_el3, x0
isb // ensure MMU is off
mov x0, #DCCISW // DCache clean and invalidate
b dcsw_op_all
func disable_mmu_icache_el3
mov x1, #(SCTLR_M_BIT | SCTLR_C_BIT | SCTLR_I_BIT)
b do_disable_mmu
...@@ -118,29 +118,6 @@ void enable_mmu() ...@@ -118,29 +118,6 @@ void enable_mmu()
return; return;
} }
void disable_mmu(void)
{
unsigned long sctlr;
unsigned long current_el = read_current_el();
if (GET_EL(current_el) == MODE_EL3) {
sctlr = read_sctlr_el3();
sctlr = sctlr & ~(SCTLR_M_BIT | SCTLR_C_BIT);
write_sctlr_el3(sctlr);
} else {
sctlr = read_sctlr_el1();
sctlr = sctlr & ~(SCTLR_M_BIT | SCTLR_C_BIT);
write_sctlr_el1(sctlr);
}
/* ensure the MMU disable takes effect immediately */
isb();
/* Flush the caches */
dcsw_op_all(DCCISW);
return;
}
/* /*
* Table of regions to map using the MMU. * Table of regions to map using the MMU.
* This doesn't include TZRAM as the 'mem_layout' argument passed to to * This doesn't include TZRAM as the 'mem_layout' argument passed to to
......
...@@ -371,7 +371,6 @@ extern void bl2_plat_arch_setup(void); ...@@ -371,7 +371,6 @@ extern void bl2_plat_arch_setup(void);
extern void bl31_plat_arch_setup(void); extern void bl31_plat_arch_setup(void);
extern int platform_setup_pm(const struct plat_pm_ops **); extern int platform_setup_pm(const struct plat_pm_ops **);
extern unsigned int platform_get_core_pos(unsigned long mpidr); extern unsigned int platform_get_core_pos(unsigned long mpidr);
extern void disable_mmu(void);
extern void enable_mmu(void); extern void enable_mmu(void);
extern void configure_mmu(struct meminfo *, extern void configure_mmu(struct meminfo *,
unsigned long, unsigned long,
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment