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,
44 	int force_npriv, int rw)
45 {
46 	int flags = 0;
47 
48 	if (force_npriv != 0) {
49 		flags |= CMSE_MPU_UNPRIV;
50 	}
51 	if (rw) {
52 		flags |= CMSE_MPU_READWRITE;
53 	} else {
54 		flags |= CMSE_MPU_READ;
55 	}
56 	if (cmse_check_address_range((void *)addr, size, flags) != NULL) {
57 		return 1;
58 	} else {
59 		return 0;
60 	}
61 }
62 
arm_cmse_addr_range_read_ok(uint32_t addr,uint32_t size,int force_npriv)63 int arm_cmse_addr_range_read_ok(uint32_t addr, uint32_t size, int force_npriv)
64 {
65 	return arm_cmse_addr_range_read_write_ok(addr, size, force_npriv, 0);
66 }
67 
arm_cmse_addr_range_readwrite_ok(uint32_t addr,uint32_t size,int force_npriv)68 int arm_cmse_addr_range_readwrite_ok(uint32_t addr, uint32_t size, int force_npriv)
69 {
70 	return arm_cmse_addr_range_read_write_ok(addr, size, force_npriv, 1);
71 }
72 
73 #if defined(CONFIG_ARM_SECURE_FIRMWARE)
74 
arm_cmse_mpu_nonsecure_region_get(uint32_t addr)75 int arm_cmse_mpu_nonsecure_region_get(uint32_t addr)
76 {
77 	cmse_address_info_t addr_info =	cmse_TTA((void *)addr);
78 
79 	if (addr_info.flags.mpu_region_valid) {
80 		return  addr_info.flags.mpu_region;
81 	}
82 
83 	return -EINVAL;
84 }
85 
arm_cmse_sau_region_get(uint32_t addr)86 int arm_cmse_sau_region_get(uint32_t addr)
87 {
88 	cmse_address_info_t addr_info =	cmse_TT((void *)addr);
89 
90 	if (addr_info.flags.sau_region_valid) {
91 		return addr_info.flags.sau_region;
92 	}
93 
94 	return -EINVAL;
95 }
96 
arm_cmse_idau_region_get(uint32_t addr)97 int arm_cmse_idau_region_get(uint32_t addr)
98 {
99 	cmse_address_info_t addr_info =	cmse_TT((void *)addr);
100 
101 	if (addr_info.flags.idau_region_valid) {
102 		return addr_info.flags.idau_region;
103 	}
104 
105 	return -EINVAL;
106 }
107 
arm_cmse_addr_is_secure(uint32_t addr)108 int arm_cmse_addr_is_secure(uint32_t addr)
109 {
110 	cmse_address_info_t addr_info =	cmse_TT((void *)addr);
111 
112 	return addr_info.flags.secure;
113 }
114 
arm_cmse_addr_nonsecure_read_write_ok(uint32_t addr,int force_npriv,int rw)115 static int arm_cmse_addr_nonsecure_read_write_ok(uint32_t addr,
116 	int force_npriv, int rw)
117 {
118 	cmse_address_info_t addr_info;
119 	if (force_npriv) {
120 		addr_info = cmse_TTAT((void *)addr);
121 	} else {
122 		addr_info = cmse_TTA((void *)addr);
123 	}
124 
125 	return rw ? addr_info.flags.nonsecure_readwrite_ok :
126 		addr_info.flags.nonsecure_read_ok;
127 }
128 
arm_cmse_addr_nonsecure_read_ok(uint32_t addr,int force_npriv)129 int arm_cmse_addr_nonsecure_read_ok(uint32_t addr, int force_npriv)
130 {
131 	return arm_cmse_addr_nonsecure_read_write_ok(addr, force_npriv, 0);
132 }
133 
arm_cmse_addr_nonsecure_readwrite_ok(uint32_t addr,int force_npriv)134 int arm_cmse_addr_nonsecure_readwrite_ok(uint32_t addr, int force_npriv)
135 {
136 	return arm_cmse_addr_nonsecure_read_write_ok(addr, force_npriv, 1);
137 }
138 
arm_cmse_addr_range_nonsecure_read_write_ok(uint32_t addr,uint32_t size,int force_npriv,int rw)139 static int arm_cmse_addr_range_nonsecure_read_write_ok(uint32_t addr, uint32_t size,
140 	int force_npriv, int rw)
141 {
142 	int flags = CMSE_NONSECURE;
143 
144 	if (force_npriv != 0) {
145 		flags |= CMSE_MPU_UNPRIV;
146 	}
147 	if (rw) {
148 		flags |= CMSE_MPU_READWRITE;
149 	} else {
150 		flags |= CMSE_MPU_READ;
151 	}
152 	if (cmse_check_address_range((void *)addr, size, flags) != NULL) {
153 		return 1;
154 	} else {
155 		return 0;
156 	}
157 }
158 
arm_cmse_addr_range_nonsecure_read_ok(uint32_t addr,uint32_t size,int force_npriv)159 int arm_cmse_addr_range_nonsecure_read_ok(uint32_t addr, uint32_t size,
160 	int force_npriv)
161 {
162 	return arm_cmse_addr_range_nonsecure_read_write_ok(addr, size,
163 		force_npriv, 0);
164 }
165 
arm_cmse_addr_range_nonsecure_readwrite_ok(uint32_t addr,uint32_t size,int force_npriv)166 int arm_cmse_addr_range_nonsecure_readwrite_ok(uint32_t addr, uint32_t size,
167 	int force_npriv)
168 {
169 	return arm_cmse_addr_range_nonsecure_read_write_ok(addr, size,
170 		force_npriv, 1);
171 }
172 
173 #endif /* CONFIG_ARM_SECURE_FIRMWARE */
174