diff --git a/Makefile b/Makefile index f57413098..afb610f01 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 eba31daf5..0b42a79ea 100644 --- a/docs/getting_started/build-options.rst +++ b/docs/getting_started/build-options.rst @@ -1032,6 +1032,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 d216d815a..9019e833c 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 @@ -35,6 +35,19 @@ loop_\op: dsb sy 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 @@ -42,6 +55,7 @@ exit_loop_\op: * ------------------------------------------ */ 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 2aa84ffde..52a7a393f 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