1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3 * Copyright (c) 2014, STMicroelectronics International N.V.
4 * Copyright (c) 2015, Linaro Limited
5 */
6
7 #include <mm/core_memprot.h>
8 #include <mm/core_mmu.h>
9 #include <tee/cache.h>
10
11 /*
12 * tee_uta_cache_operation - dynamic cache clean/inval request from a TA.
13 * It follows ARM recommendation:
14 * https://developer.arm.com/documentation/ddi0246/c/Beicdhde
15 * Note that this implementation assumes dsb operations are part of
16 * cache_op_inner(), and outer cache sync are part of cache_op_outer().
17 */
cache_operation(enum utee_cache_operation op,void * va,size_t len)18 TEE_Result cache_operation(enum utee_cache_operation op, void *va, size_t len)
19 {
20 TEE_Result res;
21 paddr_t pa;
22
23 pa = virt_to_phys(va);
24 if (!pa)
25 return TEE_ERROR_ACCESS_DENIED;
26
27 switch (op) {
28 case TEE_CACHEFLUSH:
29 #ifdef CFG_PL310 /* prevent initial L1 clean in case there is no outer L2 */
30 /* Clean L1, Flush L2, Flush L1 */
31 res = cache_op_inner(DCACHE_AREA_CLEAN, va, len);
32 if (res != TEE_SUCCESS)
33 return res;
34 res = cache_op_outer(DCACHE_AREA_CLEAN_INV, pa, len);
35 if (res != TEE_SUCCESS)
36 return res;
37 #endif
38 return cache_op_inner(DCACHE_AREA_CLEAN_INV, va, len);
39
40 case TEE_CACHECLEAN:
41 /* Clean L1, Clean L2 */
42 res = cache_op_inner(DCACHE_AREA_CLEAN, va, len);
43 if (res != TEE_SUCCESS)
44 return res;
45 return cache_op_outer(DCACHE_AREA_CLEAN, pa, len);
46
47 case TEE_CACHEINVALIDATE:
48 /* Inval L2, Inval L1 */
49 res = cache_op_outer(DCACHE_AREA_INVALIDATE, pa, len);
50 if (res != TEE_SUCCESS)
51 return res;
52 return cache_op_inner(DCACHE_AREA_INVALIDATE, va, len);
53
54 default:
55 return TEE_ERROR_NOT_SUPPORTED;
56 }
57 }
58