xref: /arm-trusted-firmware/services/std_svc/spm/spm_mm/spm_mm_xlat.c (revision 91f16700b400a8c0651d24a598fc48ee2997a0d7)
1*91f16700Schasinglulu /*
2*91f16700Schasinglulu  * Copyright (c) 2018-2023, ARM Limited and Contributors. All rights reserved.
3*91f16700Schasinglulu  *
4*91f16700Schasinglulu  * SPDX-License-Identifier: BSD-3-Clause
5*91f16700Schasinglulu  */
6*91f16700Schasinglulu 
7*91f16700Schasinglulu #include <arch.h>
8*91f16700Schasinglulu #include <arch_helpers.h>
9*91f16700Schasinglulu #include <assert.h>
10*91f16700Schasinglulu #include <errno.h>
11*91f16700Schasinglulu #include <lib/xlat_tables/xlat_tables_v2.h>
12*91f16700Schasinglulu #include <platform_def.h>
13*91f16700Schasinglulu #include <plat/common/platform.h>
14*91f16700Schasinglulu #include <services/spm_mm_partition.h>
15*91f16700Schasinglulu #include <services/spm_mm_svc.h>
16*91f16700Schasinglulu 
17*91f16700Schasinglulu #include "spm_mm_private.h"
18*91f16700Schasinglulu #include "spm_shim_private.h"
19*91f16700Schasinglulu 
20*91f16700Schasinglulu /* Lock used for SP_MEMORY_ATTRIBUTES_GET and SP_MEMORY_ATTRIBUTES_SET */
21*91f16700Schasinglulu static spinlock_t mem_attr_smc_lock;
22*91f16700Schasinglulu 
23*91f16700Schasinglulu /*
24*91f16700Schasinglulu  * Attributes are encoded using a different format in the SMC interface than in
25*91f16700Schasinglulu  * the Trusted Firmware, where the mmap_attr_t enum type is used. This function
26*91f16700Schasinglulu  * converts an attributes value from the SMC format to the mmap_attr_t format by
27*91f16700Schasinglulu  * setting MT_RW/MT_RO, MT_USER/MT_PRIVILEGED and MT_EXECUTE/MT_EXECUTE_NEVER.
28*91f16700Schasinglulu  * The other fields are left as 0 because they are ignored by the function
29*91f16700Schasinglulu  * xlat_change_mem_attributes_ctx().
30*91f16700Schasinglulu  */
31*91f16700Schasinglulu static unsigned int smc_attr_to_mmap_attr(unsigned int attributes)
32*91f16700Schasinglulu {
33*91f16700Schasinglulu 	unsigned int tf_attr = 0U;
34*91f16700Schasinglulu 
35*91f16700Schasinglulu 	unsigned int access = (attributes & MM_SP_MEMORY_ATTRIBUTES_ACCESS_MASK)
36*91f16700Schasinglulu 			      >> MM_SP_MEMORY_ATTRIBUTES_ACCESS_SHIFT;
37*91f16700Schasinglulu 
38*91f16700Schasinglulu 	if (access == MM_SP_MEMORY_ATTRIBUTES_ACCESS_RW) {
39*91f16700Schasinglulu 		tf_attr |= MT_RW | MT_USER;
40*91f16700Schasinglulu 	} else if (access ==  MM_SP_MEMORY_ATTRIBUTES_ACCESS_RO) {
41*91f16700Schasinglulu 		tf_attr |= MT_RO | MT_USER;
42*91f16700Schasinglulu 	} else {
43*91f16700Schasinglulu 		/* Other values are reserved. */
44*91f16700Schasinglulu 		assert(access == MM_SP_MEMORY_ATTRIBUTES_ACCESS_NOACCESS);
45*91f16700Schasinglulu 		/* The only requirement is that there's no access from EL0 */
46*91f16700Schasinglulu 		tf_attr |= MT_RO | MT_PRIVILEGED;
47*91f16700Schasinglulu 	}
48*91f16700Schasinglulu 
49*91f16700Schasinglulu 	if ((attributes & MM_SP_MEMORY_ATTRIBUTES_NON_EXEC) == 0) {
50*91f16700Schasinglulu 		tf_attr |= MT_EXECUTE;
51*91f16700Schasinglulu 	} else {
52*91f16700Schasinglulu 		tf_attr |= MT_EXECUTE_NEVER;
53*91f16700Schasinglulu 	}
54*91f16700Schasinglulu 
55*91f16700Schasinglulu 	return tf_attr;
56*91f16700Schasinglulu }
57*91f16700Schasinglulu 
58*91f16700Schasinglulu /*
59*91f16700Schasinglulu  * This function converts attributes from the Trusted Firmware format into the
60*91f16700Schasinglulu  * SMC interface format.
61*91f16700Schasinglulu  */
62*91f16700Schasinglulu static unsigned int smc_mmap_to_smc_attr(unsigned int attr)
63*91f16700Schasinglulu {
64*91f16700Schasinglulu 	unsigned int smc_attr = 0U;
65*91f16700Schasinglulu 
66*91f16700Schasinglulu 	unsigned int data_access;
67*91f16700Schasinglulu 
68*91f16700Schasinglulu 	if ((attr & MT_USER) == 0) {
69*91f16700Schasinglulu 		/* No access from EL0. */
70*91f16700Schasinglulu 		data_access = MM_SP_MEMORY_ATTRIBUTES_ACCESS_NOACCESS;
71*91f16700Schasinglulu 	} else {
72*91f16700Schasinglulu 		if ((attr & MT_RW) != 0) {
73*91f16700Schasinglulu 			assert(MT_TYPE(attr) != MT_DEVICE);
74*91f16700Schasinglulu 			data_access = MM_SP_MEMORY_ATTRIBUTES_ACCESS_RW;
75*91f16700Schasinglulu 		} else {
76*91f16700Schasinglulu 			data_access = MM_SP_MEMORY_ATTRIBUTES_ACCESS_RO;
77*91f16700Schasinglulu 		}
78*91f16700Schasinglulu 	}
79*91f16700Schasinglulu 
80*91f16700Schasinglulu 	smc_attr |= (data_access & MM_SP_MEMORY_ATTRIBUTES_ACCESS_MASK)
81*91f16700Schasinglulu 		    << MM_SP_MEMORY_ATTRIBUTES_ACCESS_SHIFT;
82*91f16700Schasinglulu 
83*91f16700Schasinglulu 	if ((attr & MT_EXECUTE_NEVER) != 0U) {
84*91f16700Schasinglulu 		smc_attr |= MM_SP_MEMORY_ATTRIBUTES_NON_EXEC;
85*91f16700Schasinglulu 	}
86*91f16700Schasinglulu 
87*91f16700Schasinglulu 	return smc_attr;
88*91f16700Schasinglulu }
89*91f16700Schasinglulu 
90*91f16700Schasinglulu int32_t spm_memory_attributes_get_smc_handler(sp_context_t *sp_ctx,
91*91f16700Schasinglulu 					      uintptr_t base_va)
92*91f16700Schasinglulu {
93*91f16700Schasinglulu 	uint32_t attributes;
94*91f16700Schasinglulu 
95*91f16700Schasinglulu 	spin_lock(&mem_attr_smc_lock);
96*91f16700Schasinglulu 
97*91f16700Schasinglulu 	int rc = xlat_get_mem_attributes_ctx(sp_ctx->xlat_ctx_handle,
98*91f16700Schasinglulu 				     base_va, &attributes);
99*91f16700Schasinglulu 
100*91f16700Schasinglulu 	spin_unlock(&mem_attr_smc_lock);
101*91f16700Schasinglulu 
102*91f16700Schasinglulu 	/* Convert error codes of xlat_get_mem_attributes_ctx() into SPM. */
103*91f16700Schasinglulu 	assert((rc == 0) || (rc == -EINVAL));
104*91f16700Schasinglulu 
105*91f16700Schasinglulu 	if (rc == 0) {
106*91f16700Schasinglulu 		return (int32_t) smc_mmap_to_smc_attr(attributes);
107*91f16700Schasinglulu 	} else {
108*91f16700Schasinglulu 		return SPM_MM_INVALID_PARAMETER;
109*91f16700Schasinglulu 	}
110*91f16700Schasinglulu }
111*91f16700Schasinglulu 
112*91f16700Schasinglulu int spm_memory_attributes_set_smc_handler(sp_context_t *sp_ctx,
113*91f16700Schasinglulu 					  u_register_t page_address,
114*91f16700Schasinglulu 					  u_register_t pages_count,
115*91f16700Schasinglulu 					  u_register_t smc_attributes)
116*91f16700Schasinglulu {
117*91f16700Schasinglulu 	uintptr_t base_va = (uintptr_t) page_address;
118*91f16700Schasinglulu 	size_t size = (size_t) (pages_count * PAGE_SIZE);
119*91f16700Schasinglulu 	uint32_t attributes = (uint32_t) smc_attributes;
120*91f16700Schasinglulu 
121*91f16700Schasinglulu 	INFO("  Start address  : 0x%lx\n", base_va);
122*91f16700Schasinglulu 	INFO("  Number of pages: %i (%zi bytes)\n", (int) pages_count, size);
123*91f16700Schasinglulu 	INFO("  Attributes     : 0x%x\n", attributes);
124*91f16700Schasinglulu 
125*91f16700Schasinglulu 	spin_lock(&mem_attr_smc_lock);
126*91f16700Schasinglulu 
127*91f16700Schasinglulu 	int ret = xlat_change_mem_attributes_ctx(sp_ctx->xlat_ctx_handle,
128*91f16700Schasinglulu 					base_va, size,
129*91f16700Schasinglulu 					smc_attr_to_mmap_attr(attributes));
130*91f16700Schasinglulu 
131*91f16700Schasinglulu 	spin_unlock(&mem_attr_smc_lock);
132*91f16700Schasinglulu 
133*91f16700Schasinglulu 	/* Convert error codes of xlat_change_mem_attributes_ctx() into SPM. */
134*91f16700Schasinglulu 	assert((ret == 0) || (ret == -EINVAL));
135*91f16700Schasinglulu 
136*91f16700Schasinglulu 	return (ret == 0) ? SPM_MM_SUCCESS : SPM_MM_INVALID_PARAMETER;
137*91f16700Schasinglulu }
138