refactor(psci): unify coherency exit between AArch64 and AArch32
The procedure is fairly simple: if we have hardware assisted coherency,
call into the cpu driver and let it do its thing. If we don't, then we
must turn data caches off, handle the confusion that causes with the
stack, and call into the cpu driver which will flush the caches that
need flushing.
On AArch32 the above happens in common code. On AArch64, however, the
turning off of the caches happens in the cpu driver. Since we're dealing
with the stack, we must exercise control over it and implement this in
assembly. But as the two implementations are nominally different (in the
ordering of operations), the part that is in assembly is quite large as
jumping back to C to handle the difference might involve the stack.
Presumably, the AArch difference was introduced in order to cater for a
possible implementation where turning off the caches requires an IMP DEF
sequence. Well, Arm no longer makes cores without hardware assisted
coherency, so this eventually is not possible.
So take this part out of the cpu driver and put it into common code,
just like in AArch32. With this, there is no longer a need call
prepare_cpu_pwr_dwn() in a different order either - we can delay it a
bit to happen after the stack management. So the two AArch-s flows
become identical. We can convert prepare_cpu_pwr_dwn() to C and leave
psci_do_pwrdown_cache_maintenance() only to exercise control over stack.
Change-Id: Ie4759ebe20bb74b60533c6a47dbc2b101875900f
Signed-off-by: Boyan Karatotev <boyan.karatotev@arm.com>
diff --git a/lib/psci/aarch32/psci_helpers.S b/lib/psci/aarch32/psci_helpers.S
index 929af8c..493715a 100644
--- a/lib/psci/aarch32/psci_helpers.S
+++ b/lib/psci/aarch32/psci_helpers.S
@@ -12,41 +12,45 @@
.globl psci_do_pwrup_cache_maintenance
/* -----------------------------------------------------------------------
- * void psci_do_pwrdown_cache_maintenance(unsigned int power level);
+ * void psci_do_pwrdown_cache_maintenance(void);
*
- * This function performs cache maintenance for the specified power
- * level. The levels of cache affected are determined by the power
- * level which is passed as the argument i.e. level 0 results
- * in a flush of the L1 cache. Both the L1 and L2 caches are flushed
- * for a higher power level.
- *
- * Additionally, this function also ensures that stack memory is correctly
- * flushed out to avoid coherency issues due to a change in its memory
- * attributes after the data cache is disabled.
+ * This function turns off data caches and also ensures that stack memory
+ * is correctly flushed out to avoid coherency issues due to a change in
+ * its memory attributes.
* -----------------------------------------------------------------------
*/
func psci_do_pwrdown_cache_maintenance
push {r4, lr}
+ bl plat_get_my_stack
- /* ----------------------------------------------
- * Turn OFF cache and do stack maintenance
- * prior to cpu operations . This sequence is
- * different from AArch64 because in AArch32 the
- * assembler routines for cpu operations utilize
- * the stack whereas in AArch64 it doesn't.
- * ----------------------------------------------
- */
- mov r4, r0
- bl do_stack_maintenance
+ /* Turn off the D-cache */
+ ldcopr r1, SCTLR
+ bic r1, #SCTLR_C_BIT
+ stcopr r1, SCTLR
+ isb
/* ---------------------------------------------
- * Invoke CPU-specifc power down operations for
- * the appropriate level
+ * Calculate and store the size of the used
+ * stack memory in r1.
* ---------------------------------------------
*/
- mov r0, r4
- pop {r4, lr}
- b prepare_cpu_pwr_dwn
+ mov r4, r0
+ mov r1, sp
+ sub r1, r0, r1
+ mov r0, sp
+ bl flush_dcache_range
+
+ /* ---------------------------------------------
+ * Calculate and store the size of the unused
+ * stack memory in r1. Calculate and store the
+ * stack base address in r0.
+ * ---------------------------------------------
+ */
+ sub r0, r4, #PLATFORM_STACK_SIZE
+ sub r1, sp, r0
+ bl inv_dcache_range
+
+ pop {r4, pc}
endfunc psci_do_pwrdown_cache_maintenance
@@ -92,44 +96,3 @@
pop {r12, pc}
endfunc psci_do_pwrup_cache_maintenance
-
- /* ---------------------------------------------
- * void do_stack_maintenance(void)
- * Do stack maintenance by flushing the used
- * stack to the main memory and invalidating the
- * remainder.
- * ---------------------------------------------
- */
-func do_stack_maintenance
- push {r4, lr}
- bl plat_get_my_stack
-
- /* Turn off the D-cache */
- ldcopr r1, SCTLR
- bic r1, #SCTLR_C_BIT
- stcopr r1, SCTLR
- isb
-
- /* ---------------------------------------------
- * Calculate and store the size of the used
- * stack memory in r1.
- * ---------------------------------------------
- */
- mov r4, r0
- mov r1, sp
- sub r1, r0, r1
- mov r0, sp
- bl flush_dcache_range
-
- /* ---------------------------------------------
- * Calculate and store the size of the unused
- * stack memory in r1. Calculate and store the
- * stack base address in r0.
- * ---------------------------------------------
- */
- sub r0, r4, #PLATFORM_STACK_SIZE
- sub r1, sp, r0
- bl inv_dcache_range
-
- pop {r4, pc}
-endfunc do_stack_maintenance