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