From 57fec88a2e981a315de8f987e63768f65b959287 Mon Sep 17 00:00:00 2001 From: Clement Faure Date: Thu, 7 Dec 2023 18:26:55 +0100 Subject: [PATCH] core: arm: allow cache_op_outer() to operate on non-secure buffers According the ARM PL310 documentation, if the operation is specific to the PA, the behavior is presented in the following manner: - Secure access: The data in the cache is only affected by the the operation if it is secure. - Non-secure access: The data in the cache is only affected by the operation if it is non-secure. Depending on the buffer location, use the secure or non-secure PL310 base address to do physical address based cache operation on the buffer. Link: https://developer.arm.com/documentation/ddi0246/a/programmer-s-model/register-descriptions/register-7--cache-maintenance-operations Signed-off-by: Clement Faure Signed-off-by: Cedric Neveux --- core/arch/arm/mm/core_mmu.c | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/core/arch/arm/mm/core_mmu.c b/core/arch/arm/mm/core_mmu.c index e25f5cc510e..0b6af6ad063 100644 --- a/core/arch/arm/mm/core_mmu.c +++ b/core/arch/arm/mm/core_mmu.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -99,6 +100,26 @@ TEE_Result cache_op_outer(enum cache_op op, paddr_t pa, size_t len) { TEE_Result ret = TEE_SUCCESS; uint32_t exceptions = thread_mask_exceptions(THREAD_EXCP_FOREIGN_INTR); + vaddr_t pl310_base_pa_op = 0; + + /* + * According the ARM PL310 documentation, if the operation is specific + * to the PA, the behavior is presented in the following manner: + * - Secure access: The data in the cache is only affected by the + * operation if it is secure. + * - Non-secure access: The data in the cache is only affected by the + * operation if it is non-secure. + * + * https://developer.arm.com/documentation/ddi0246/a/programmer-s-model/register-descriptions/register-7--cache-maintenance-operations + * + * Depending on the buffer location, use the secure or non-secure PL310 + * base address to do physical address based cache operation on the + * buffer. + */ + if (tee_pbuf_is_sec(pa, len)) + pl310_base_pa_op = pl310_base(); + else + pl310_base_pa_op = pl310_nsbase(); tee_l2cc_mutex_lock(); switch (op) { @@ -107,21 +128,22 @@ TEE_Result cache_op_outer(enum cache_op op, paddr_t pa, size_t len) break; case DCACHE_AREA_INVALIDATE: if (len) - arm_cl2_invbypa(pl310_base(), pa, pa + len - 1); + arm_cl2_invbypa(pl310_base_pa_op, pa, pa + len - 1); break; case DCACHE_CLEAN: arm_cl2_cleanbyway(pl310_base()); break; case DCACHE_AREA_CLEAN: if (len) - arm_cl2_cleanbypa(pl310_base(), pa, pa + len - 1); + arm_cl2_cleanbypa(pl310_base_pa_op, pa, pa + len - 1); break; case DCACHE_CLEAN_INV: arm_cl2_cleaninvbyway(pl310_base()); break; case DCACHE_AREA_CLEAN_INV: if (len) - arm_cl2_cleaninvbypa(pl310_base(), pa, pa + len - 1); + arm_cl2_cleaninvbypa(pl310_base_pa_op, pa, + pa + len - 1); break; default: ret = TEE_ERROR_NOT_IMPLEMENTED;