1 /*
2  * Copyright (c) 2018 Nordic Semiconductor ASA
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/kernel.h>
8 #include <cortex_m/cmse.h>
9 
arm_cmse_mpu_region_get(uint32_t addr)10 int arm_cmse_mpu_region_get(uint32_t addr)
11 {
12 	cmse_address_info_t addr_info = cmse_TT((void *)addr);
13 
14 	if (addr_info.flags.mpu_region_valid) {
15 		return addr_info.flags.mpu_region;
16 	}
17 
18 	return -EINVAL;
19 }
20 
arm_cmse_addr_read_write_ok(uint32_t addr,int force_npriv,int rw)21 static int arm_cmse_addr_read_write_ok(uint32_t addr, int force_npriv, int rw)
22 {
23 	cmse_address_info_t addr_info;
24 	if (force_npriv) {
25 		addr_info = cmse_TTT((void *)addr);
26 	} else {
27 		addr_info = cmse_TT((void *)addr);
28 	}
29 
30 	return rw ? addr_info.flags.readwrite_ok : addr_info.flags.read_ok;
31 }
32 
arm_cmse_addr_read_ok(uint32_t addr,int force_npriv)33 int arm_cmse_addr_read_ok(uint32_t addr, int force_npriv)
34 {
35 	return arm_cmse_addr_read_write_ok(addr, force_npriv, 0);
36 }
37 
arm_cmse_addr_readwrite_ok(uint32_t addr,int force_npriv)38 int arm_cmse_addr_readwrite_ok(uint32_t addr, int force_npriv)
39 {
40 	return arm_cmse_addr_read_write_ok(addr, force_npriv, 1);
41 }
42 
arm_cmse_addr_range_read_write_ok(uint32_t addr,uint32_t size,int force_npriv,int rw)43 static int arm_cmse_addr_range_read_write_ok(uint32_t addr, uint32_t size, int force_npriv, int rw)
44 {
45 	int flags = 0;
46 
47 	if (force_npriv != 0) {
48 		flags |= CMSE_MPU_UNPRIV;
49 	}
50 	if (rw) {
51 		flags |= CMSE_MPU_READWRITE;
52 	} else {
53 		flags |= CMSE_MPU_READ;
54 	}
55 	if (cmse_check_address_range((void *)addr, size, flags) != NULL) {
56 		return 1;
57 	} else {
58 		return 0;
59 	}
60 }
61 
arm_cmse_addr_range_read_ok(uint32_t addr,uint32_t size,int force_npriv)62 int arm_cmse_addr_range_read_ok(uint32_t addr, uint32_t size, int force_npriv)
63 {
64 	return arm_cmse_addr_range_read_write_ok(addr, size, force_npriv, 0);
65 }
66 
arm_cmse_addr_range_readwrite_ok(uint32_t addr,uint32_t size,int force_npriv)67 int arm_cmse_addr_range_readwrite_ok(uint32_t addr, uint32_t size, int force_npriv)
68 {
69 	return arm_cmse_addr_range_read_write_ok(addr, size, force_npriv, 1);
70 }
71 
72 #if defined(CONFIG_ARM_SECURE_FIRMWARE)
73 
arm_cmse_mpu_nonsecure_region_get(uint32_t addr)74 int arm_cmse_mpu_nonsecure_region_get(uint32_t addr)
75 {
76 	cmse_address_info_t addr_info = cmse_TTA((void *)addr);
77 
78 	if (addr_info.flags.mpu_region_valid) {
79 		return addr_info.flags.mpu_region;
80 	}
81 
82 	return -EINVAL;
83 }
84 
arm_cmse_sau_region_get(uint32_t addr)85 int arm_cmse_sau_region_get(uint32_t addr)
86 {
87 	cmse_address_info_t addr_info = cmse_TT((void *)addr);
88 
89 	if (addr_info.flags.sau_region_valid) {
90 		return addr_info.flags.sau_region;
91 	}
92 
93 	return -EINVAL;
94 }
95 
arm_cmse_idau_region_get(uint32_t addr)96 int arm_cmse_idau_region_get(uint32_t addr)
97 {
98 	cmse_address_info_t addr_info = cmse_TT((void *)addr);
99 
100 	if (addr_info.flags.idau_region_valid) {
101 		return addr_info.flags.idau_region;
102 	}
103 
104 	return -EINVAL;
105 }
106 
arm_cmse_addr_is_secure(uint32_t addr)107 int arm_cmse_addr_is_secure(uint32_t addr)
108 {
109 	cmse_address_info_t addr_info = cmse_TT((void *)addr);
110 
111 	return addr_info.flags.secure;
112 }
113 
arm_cmse_addr_nonsecure_read_write_ok(uint32_t addr,int force_npriv,int rw)114 static int arm_cmse_addr_nonsecure_read_write_ok(uint32_t addr, int force_npriv, int rw)
115 {
116 	cmse_address_info_t addr_info;
117 	if (force_npriv) {
118 		addr_info = cmse_TTAT((void *)addr);
119 	} else {
120 		addr_info = cmse_TTA((void *)addr);
121 	}
122 
123 	return rw ? addr_info.flags.nonsecure_readwrite_ok : addr_info.flags.nonsecure_read_ok;
124 }
125 
arm_cmse_addr_nonsecure_read_ok(uint32_t addr,int force_npriv)126 int arm_cmse_addr_nonsecure_read_ok(uint32_t addr, int force_npriv)
127 {
128 	return arm_cmse_addr_nonsecure_read_write_ok(addr, force_npriv, 0);
129 }
130 
arm_cmse_addr_nonsecure_readwrite_ok(uint32_t addr,int force_npriv)131 int arm_cmse_addr_nonsecure_readwrite_ok(uint32_t addr, int force_npriv)
132 {
133 	return arm_cmse_addr_nonsecure_read_write_ok(addr, force_npriv, 1);
134 }
135 
arm_cmse_addr_range_nonsecure_read_write_ok(uint32_t addr,uint32_t size,int force_npriv,int rw)136 static int arm_cmse_addr_range_nonsecure_read_write_ok(uint32_t addr, uint32_t size,
137 						       int force_npriv, int rw)
138 {
139 	int flags = CMSE_NONSECURE;
140 
141 	if (force_npriv != 0) {
142 		flags |= CMSE_MPU_UNPRIV;
143 	}
144 	if (rw) {
145 		flags |= CMSE_MPU_READWRITE;
146 	} else {
147 		flags |= CMSE_MPU_READ;
148 	}
149 	if (cmse_check_address_range((void *)addr, size, flags) != NULL) {
150 		return 1;
151 	} else {
152 		return 0;
153 	}
154 }
155 
arm_cmse_addr_range_nonsecure_read_ok(uint32_t addr,uint32_t size,int force_npriv)156 int arm_cmse_addr_range_nonsecure_read_ok(uint32_t addr, uint32_t size, int force_npriv)
157 {
158 	return arm_cmse_addr_range_nonsecure_read_write_ok(addr, size, force_npriv, 0);
159 }
160 
arm_cmse_addr_range_nonsecure_readwrite_ok(uint32_t addr,uint32_t size,int force_npriv)161 int arm_cmse_addr_range_nonsecure_readwrite_ok(uint32_t addr, uint32_t size, int force_npriv)
162 {
163 	return arm_cmse_addr_range_nonsecure_read_write_ok(addr, size, force_npriv, 1);
164 }
165 
166 #endif /* CONFIG_ARM_SECURE_FIRMWARE */
167