aboutsummaryrefslogtreecommitdiff
path: root/plat
diff options
context:
space:
mode:
authorAndrew Thoelke <andrew.thoelke@arm.com>2014-04-28 12:28:39 +0100
committerAndrew Thoelke <andrew.thoelke@arm.com>2014-05-07 11:19:47 +0100
commit8cec598ba3b689b86d9dfc58bca5610bdc48f55a (patch)
tree10a3622d6a57fe02b45112fd512297238ad93dc5 /plat
parente404d7f44a190b82332bb96daffa0c6239732218 (diff)
downloadarm-trusted-firmware-8cec598ba3b689b86d9dfc58bca5610bdc48f55a.tar.gz
Correct usage of data and instruction barriers
The current code does not always use data and instruction barriers as required by the architecture and frequently uses barriers excessively due to their inclusion in all of the write_*() helper functions. Barriers should be used explicitly in assembler or C code when modifying processor state that requires the barriers in order to enable review of correctness of the code. This patch removes the barriers from the helper functions and introduces them as necessary elsewhere in the code. PORTING NOTE: check any port of Trusted Firmware for use of system register helper functions for reliance on the previous barrier behaviour and add explicit barriers as necessary. Fixes ARM-software/tf-issues#92 Change-Id: Ie63e187404ff10e0bdcb39292dd9066cb84c53bf
Diffstat (limited to 'plat')
-rw-r--r--plat/fvp/aarch64/plat_common.c21
-rw-r--r--plat/fvp/plat_gic.c3
-rw-r--r--plat/fvp/plat_pm.c6
3 files changed, 29 insertions, 1 deletions
diff --git a/plat/fvp/aarch64/plat_common.c b/plat/fvp/aarch64/plat_common.c
index c8e529d..e2f2343 100644
--- a/plat/fvp/aarch64/plat_common.c
+++ b/plat/fvp/aarch64/plat_common.c
@@ -69,6 +69,8 @@ void enable_mmu()
ttbr = (unsigned long) l1_xlation_table;
if (GET_EL(current_el) == MODE_EL3) {
+ assert((read_sctlr_el3() & SCTLR_M_BIT) == 0);
+
write_mair_el3(mair);
tcr |= TCR_EL3_RES1;
/* Invalidate EL3 TLBs */
@@ -77,11 +79,19 @@ void enable_mmu()
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 */
@@ -90,11 +100,20 @@ void enable_mmu()
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);
}
+ /* ensure the MMU enable takes effect immediately */
+ isb();
return;
}
@@ -113,6 +132,8 @@ void disable_mmu(void)
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);
diff --git a/plat/fvp/plat_gic.c b/plat/fvp/plat_gic.c
index 8457af1..db3c9cf 100644
--- a/plat/fvp/plat_gic.c
+++ b/plat/fvp/plat_gic.c
@@ -86,6 +86,7 @@ void gicv3_cpuif_setup(void)
*/
scr_val = read_scr();
write_scr(scr_val | SCR_NS_BIT);
+ isb(); /* ensure NS=1 takes effect before accessing ICC_SRE_EL2 */
/*
* By default EL2 and NS-EL1 software should be able to enable GICv3
@@ -103,9 +104,11 @@ void gicv3_cpuif_setup(void)
write_icc_sre_el2(val | ICC_SRE_EN | ICC_SRE_SRE);
write_icc_pmr_el1(GIC_PRI_MASK);
+ isb(); /* commite ICC_* changes before setting NS=0 */
/* Restore SCR_EL3 */
write_scr(scr_val);
+ isb(); /* ensure NS=0 takes effect immediately */
}
/*******************************************************************************
diff --git a/plat/fvp/plat_pm.c b/plat/fvp/plat_pm.c
index 5430fff..f80e2d7 100644
--- a/plat/fvp/plat_pm.c
+++ b/plat/fvp/plat_pm.c
@@ -54,7 +54,11 @@ int fvp_affinst_standby(unsigned int power_state)
if (target_afflvl != MPIDR_AFFLVL0)
return PSCI_E_INVALID_PARAMS;
- /* Enter standby state */
+ /*
+ * Enter standby state
+ * dsb is good practice before using wfi to enter low power states
+ */
+ dsb();
wfi();
return PSCI_E_SUCCESS;