summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile2
-rw-r--r--docs/getting_started/build-options.rst6
-rw-r--r--docs/getting_started/porting-guide.rst16
-rw-r--r--lib/aarch32/cache_helpers.S22
-rw-r--r--lib/aarch64/cache_helpers.S21
-rw-r--r--make_helpers/defaults.mk4
6 files changed, 71 insertions, 0 deletions
diff --git a/Makefile b/Makefile
index 70d5338eb..b664ac0af 100644
--- a/Makefile
+++ b/Makefile
@@ -1080,6 +1080,7 @@ $(eval $(call assert_booleans,\
SIMICS_BUILD \
FEATURE_DETECTION \
TRNG_SUPPORT \
+ CONDITIONAL_CMO \
)))
$(eval $(call assert_numerics,\
@@ -1241,6 +1242,7 @@ $(eval $(call add_defines,\
FEATURE_DETECTION \
TWED_DELAY \
ENABLE_FEAT_TWED \
+ CONDITIONAL_CMO \
)))
ifeq (${SANITIZE_UB},trap)
diff --git a/docs/getting_started/build-options.rst b/docs/getting_started/build-options.rst
index 68ef4cefd..d1acf4f4e 100644
--- a/docs/getting_started/build-options.rst
+++ b/docs/getting_started/build-options.rst
@@ -1031,6 +1031,12 @@ Common build options
functionalities). When enabled (``1``), a mocked version of the APIs are used.
The default value is 0.
+- ``CONDITIONAL_CMO``: Boolean option to enable call to platform-defined routine
+ ``plat_can_cmo`` which will return zero if cache management operations should
+ be skipped and non-zero otherwise. By default, this option is disabled which
+ means platform hook won't be checked and CMOs will always be performed when
+ related functions are called.
+
GICv3 driver options
--------------------
diff --git a/docs/getting_started/porting-guide.rst b/docs/getting_started/porting-guide.rst
index 668af5714..4639fd5fd 100644
--- a/docs/getting_started/porting-guide.rst
+++ b/docs/getting_started/porting-guide.rst
@@ -1461,6 +1461,22 @@ When the MEASURED_BOOT flag is enabled:
When the MEASURED_BOOT flag is disabled, this function doesn't do anything.
+Function : plat_can_cmo()
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+ Argument : void
+ Return : uint64_t
+
+When CONDITIONAL_CMO flag is enabled:
+
+- This function indicates whether cache management operations should be
+ performed. It returns 0 if CMOs should be skipped and non-zero
+ otherwise.
+- The function must not clobber x2 and x3. It's also not safe to rely on stack.
+ Otherwise obey AAPCS.
+
Modifications specific to a Boot Loader stage
---------------------------------------------
diff --git a/lib/aarch32/cache_helpers.S b/lib/aarch32/cache_helpers.S
index 13d1872f8..fd9b33f2d 100644
--- a/lib/aarch32/cache_helpers.S
+++ b/lib/aarch32/cache_helpers.S
@@ -37,12 +37,27 @@ exit_loop_\op:
bx lr
.endm
+.macro check_plat_can_cmo
+#if CONDITIONAL_CMO
+ mov r3, lr
+ mov r2, r0
+ bl plat_can_cmo
+ mov lr, r3
+ cmp r0, #0
+ bne 1f
+ bx lr
+1:
+ mov r0, r2
+#endif
+.endm
+
/* ------------------------------------------
* Clean+Invalidate from base address till
* size. 'r0' = addr, 'r1' = size
* ------------------------------------------
*/
func flush_dcache_range
+ check_plat_can_cmo
do_dcache_maintenance_by_mva cimvac, DCCIMVAC
endfunc flush_dcache_range
@@ -52,6 +67,7 @@ endfunc flush_dcache_range
* ------------------------------------------
*/
func clean_dcache_range
+ check_plat_can_cmo
do_dcache_maintenance_by_mva cmvac, DCCMVAC
endfunc clean_dcache_range
@@ -61,6 +77,7 @@ endfunc clean_dcache_range
* ------------------------------------------
*/
func inv_dcache_range
+ check_plat_can_cmo
do_dcache_maintenance_by_mva imvac, DCIMVAC
endfunc inv_dcache_range
@@ -168,6 +185,7 @@ endfunc do_dcsw_op
* ---------------------------------------------------------------
*/
func dcsw_op_louis
+ check_plat_can_cmo
dcsw_op #LOUIS_SHIFT, #CLIDR_FIELD_WIDTH, #LEVEL_SHIFT
endfunc dcsw_op_louis
@@ -180,6 +198,7 @@ endfunc dcsw_op_louis
* ---------------------------------------------------------------
*/
func dcsw_op_all
+ check_plat_can_cmo
dcsw_op #LOC_SHIFT, #CLIDR_FIELD_WIDTH, #LEVEL_SHIFT
endfunc dcsw_op_all
@@ -205,6 +224,7 @@ endfunc dcsw_op_all
* ---------------------------------------------------------------
*/
func dcsw_op_level1
+ check_plat_can_cmo
dcsw_op_level #(1 << LEVEL_SHIFT)
endfunc dcsw_op_level1
@@ -217,6 +237,7 @@ endfunc dcsw_op_level1
* ---------------------------------------------------------------
*/
func dcsw_op_level2
+ check_plat_can_cmo
dcsw_op_level #(2 << LEVEL_SHIFT)
endfunc dcsw_op_level2
@@ -229,5 +250,6 @@ endfunc dcsw_op_level2
* ---------------------------------------------------------------
*/
func dcsw_op_level3
+ check_plat_can_cmo
dcsw_op_level #(3 << LEVEL_SHIFT)
endfunc dcsw_op_level3
diff --git a/lib/aarch64/cache_helpers.S b/lib/aarch64/cache_helpers.S
index 6faf545a1..67fafb1e7 100644
--- a/lib/aarch64/cache_helpers.S
+++ b/lib/aarch64/cache_helpers.S
@@ -36,12 +36,26 @@ loop_\op:
exit_loop_\op:
ret
.endm
+
+.macro check_plat_can_cmo
+#if CONDITIONAL_CMO
+ mov x3, x30
+ mov x2, x0
+ bl plat_can_cmo
+ mov x30, x3
+ cbnz x0, 1f
+ ret
+1:
+ mov x0, x2
+#endif
+.endm
/* ------------------------------------------
* Clean+Invalidate from base address till
* size. 'x0' = addr, 'x1' = size
* ------------------------------------------
*/
func flush_dcache_range
+ check_plat_can_cmo
do_dcache_maintenance_by_mva civac
endfunc flush_dcache_range
@@ -51,6 +65,7 @@ endfunc flush_dcache_range
* ------------------------------------------
*/
func clean_dcache_range
+ check_plat_can_cmo
do_dcache_maintenance_by_mva cvac
endfunc clean_dcache_range
@@ -60,6 +75,7 @@ endfunc clean_dcache_range
* ------------------------------------------
*/
func inv_dcache_range
+ check_plat_can_cmo
do_dcache_maintenance_by_mva ivac
endfunc inv_dcache_range
@@ -79,6 +95,7 @@ endfunc inv_dcache_range
func flush_dcache_to_popa_range
/* Exit early if size is zero */
cbz x1, exit_loop_dc_cipapa
+ check_plat_can_cmo
dcache_line_size x2, x3
sub x3, x2, #1
bic x0, x0, x3
@@ -205,6 +222,7 @@ endfunc dcsw_op_louis
func dcsw_op_all
+ check_plat_can_cmo
dcsw_op #LOC_SHIFT, #CLIDR_FIELD_WIDTH, #LEVEL_SHIFT
endfunc dcsw_op_all
@@ -228,6 +246,7 @@ endfunc dcsw_op_all
* ---------------------------------------------------------------
*/
func dcsw_op_level1
+ check_plat_can_cmo
dcsw_op_level #(1 << LEVEL_SHIFT)
endfunc dcsw_op_level1
@@ -239,6 +258,7 @@ endfunc dcsw_op_level1
* ---------------------------------------------------------------
*/
func dcsw_op_level2
+ check_plat_can_cmo
dcsw_op_level #(2 << LEVEL_SHIFT)
endfunc dcsw_op_level2
@@ -250,5 +270,6 @@ endfunc dcsw_op_level2
* ---------------------------------------------------------------
*/
func dcsw_op_level3
+ check_plat_can_cmo
dcsw_op_level #(3 << LEVEL_SHIFT)
endfunc dcsw_op_level3
diff --git a/make_helpers/defaults.mk b/make_helpers/defaults.mk
index 772b28de0..4b238e346 100644
--- a/make_helpers/defaults.mk
+++ b/make_helpers/defaults.mk
@@ -480,3 +480,7 @@ PLAT_RSS_NOT_SUPPORTED := 0
# Dynamic Root of Trust for Measurement support
DRTM_SUPPORT := 0
+
+# Check platform if cache management operations should be performed.
+# Disabled by default.
+CONDITIONAL_CMO := 0