1 /*
2 * Copyright (C) 2015-2017 Alibaba Group Holding Limited
3 */
4
5 #if AOS_COMP_DEBUG
6
7 #include <stdio.h>
8 #include "panic_mpu.h"
9 #include "k_compiler.h"
10 #include "k_api.h"
11
12 typedef struct {
13 unsigned long start;
14 unsigned long size;
15 unsigned long mpusize;
16 } mem_region_t;
17
18 static void mpu_enable(void);
19 static void mpu_disable(void);
20 static void mpu_config_region(MPU_Region_Init_t *init);
21 static unsigned int size_to_mpusize(unsigned int size);
22
23 /*
24 * Func: mpu is valid in mcu
25 * IN : none
26 * Out : 0 -- valid; 1 -- invalid
27 * */
mpu_is_valid(void)28 static unsigned int mpu_is_valid(void)
29 {
30 return ((MPU->type) & MPU_TYPE_DREGION_MASK == 0) ? 1: 0;
31 }
32
mpu_enable(void)33 static void mpu_enable(void)
34 {
35 MPU->ctrl = MPU_CTRL_ENABLE_MASK | MPU_CTRL_PRIVDEFENA_MASK;
36
37 /* Enable memory manage fault */
38 *(SHCSR_M) |= (1<<16);
39
40 OS_DSB();
41 OS_ISB();
42 OS_DMB();
43 }
44
mpu_disable(void)45 static void mpu_disable(void)
46 {
47 MPU->ctrl = 0U;
48
49 OS_DSB();
50 OS_ISB();
51 OS_DMB();
52 }
53
enable_region(mem_region_t * region,int rng_no,int subregion_disable,int ext_type,int access_permission,int disable_exec,int shareable,int cacheable,int bufferable)54 static void enable_region(mem_region_t *region, int rng_no,
55 int subregion_disable, int ext_type,
56 int access_permission, int disable_exec,
57 int shareable, int cacheable, int bufferable)
58 {
59 MPU_Region_Init_t init;
60
61 init.range_no = rng_no;
62 init.base_addr = region->start;
63 init.size = region->mpusize;
64 init.subregion_disable = subregion_disable;
65 init.ext_type = ext_type;
66 init.access_permission = access_permission;
67 init.disable_exec = disable_exec;
68 init.shareable = shareable;
69 init.cacheable = cacheable;
70 init.bufferable = bufferable;
71 init.enable = 1;
72
73 mpu_config_region(&init);
74 }
75
76
mpu_config_region(MPU_Region_Init_t * init)77 static void mpu_config_region(MPU_Region_Init_t *init)
78 {
79 MPU->rnr = init->range_no;
80
81 if (init->enable) {
82 MPU->rbar = init->base_addr;
83 MPU->rasr = (init->disable_exec << MPU_RASR_XN_OFFSET
84 | init->access_permission << MPU_RASR_AP_OFFSET
85 | init->ext_type << MPU_RASR_TEX_OFFSET
86 | init->shareable << MPU_RASR_S_OFFSET
87 | init->cacheable << MPU_RASR_C_OFFSET
88 | init->bufferable << MPU_RASR_B_OFFSET
89 | init->subregion_disable << MPU_RASR_SRD_OFFSET
90 | init->size << MPU_RASR_SIZE_OFFSET
91 | init->enable << MPU_RASR_ENABLE_OFFSET);
92 } else {
93 MPU->rbar = 0;
94 MPU->rasr = 0;
95 }
96
97 OS_DSB();
98 OS_ISB();
99 OS_DMB();
100 }
101
size_to_mpusize(unsigned int size)102 static unsigned int size_to_mpusize(unsigned int size)
103 {
104 switch (size) {
105 case 0x20: return MPU_REGION_SIZE_32B;
106 case 0x40: return MPU_REGION_SIZE_64B;
107 case 0x80: return MPU_REGION_SIZE_128B;
108 case 0x100: return MPU_REGION_SIZE_256B;
109 case 0x200: return MPU_REGION_SIZE_512B;
110 case 0x400: return MPU_REGION_SIZE_1KB;
111 case 0x800: return MPU_REGION_SIZE_2KB;
112 case 0x1000: return MPU_REGION_SIZE_4KB;
113 case 0x2000: return MPU_REGION_SIZE_8KB;
114 case 0x4000: return MPU_REGION_SIZE_16KB;
115 case 0x8000: return MPU_REGION_SIZE_32KB;
116 case 0x10000: return MPU_REGION_SIZE_64KB;
117 case 0x20000: return MPU_REGION_SIZE_128KB;
118 case 0x40000: return MPU_REGION_SIZE_256KB;
119 case 0x80000: return MPU_REGION_SIZE_512KB;
120 case 0x100000: return MPU_REGION_SIZE_1MB;
121 case 0x200000: return MPU_REGION_SIZE_2MB;
122 case 0x400000: return MPU_REGION_SIZE_4MB;
123 case 0x800000: return MPU_REGION_SIZE_8MB;
124 case 0x1000000: return MPU_REGION_SIZE_16MB;
125 case 0x2000000: return MPU_REGION_SIZE_32MB;
126 case 0x4000000: return MPU_REGION_SIZE_64MB;
127 case 0x8000000: return MPU_REGION_SIZE_128MB;
128 case 0x10000000: return MPU_REGION_SIZE_256MB;
129 case 0x20000000: return MPU_REGION_SIZE_512MB;
130 case 0x40000000: return MPU_REGION_SIZE_1GB;
131 case 0x80000000: return MPU_REGION_SIZE_2GB;
132
133 default: return 0;
134 }
135 }
136
mpu_set(unsigned long addr,unsigned long size,unsigned int mode)137 static void mpu_set(unsigned long addr, unsigned long size, unsigned int mode)
138 {
139 mem_region_t region;
140
141 region.start = addr;
142 region.size = size;
143 region.mpusize = size_to_mpusize(region.size);
144
145 mpu_disable();
146
147 enable_region(®ion, 0, 0, 0, mode, 0, 0, 1, 1);
148
149 mpu_enable();
150 }
151
mpu_check(unsigned long addr,unsigned long size)152 static unsigned int mpu_check(unsigned long addr, unsigned long size)
153 {
154 if ((size < 0x20) || (size > 0x80000000)) {
155 printf("mpu region size error\r\n");
156 return 1;
157 }
158
159 if (mpu_is_valid() != 0) {
160 printf("error:no mpu in mcu\r\n");
161 return 1;
162 }
163
164 return 0;
165 }
166
167 /**
168 * set mpu region for memory unauthorized access check
169 *
170 * @param[in] addr_start monitor start addr
171 * @param[in] addr_size monitor size
172 * @param[in] mode prohibit access (0) or read only(>0)
173 */
debug_memory_access_err_check(unsigned long addr_start,unsigned long addr_size,unsigned int mode)174 void debug_memory_access_err_check(unsigned long addr_start, unsigned long addr_size, unsigned int mode)
175 {
176 unsigned int mpu_region_type;
177
178 if (mpu_check(addr_start, addr_size) != 0)
179 return;
180
181 if ((addr_start % addr_size) != 0)
182 addr_start = (addr_start + (addr_size - 1)) & ~(addr_size - 1);
183
184 if (mode > 0) {
185 mpu_region_type = MPU_AP_RO_NA;
186 } else
187 mpu_region_type = MPU_AP_NA_NA;
188
189 mpu_set(addr_start, addr_size, mpu_region_type);
190 printf("mpu addr: 0x%x\n", addr_start);
191 }
192
debug_task_stack_ovf_check(char * task_name)193 void debug_task_stack_ovf_check(char *task_name)
194 {
195 int ret;
196 ktask_t *task;
197 cpu_stack_t *task_stack_base;
198
199 if (task_name == NULL) {
200 printf("error: task name invalid\r\n");
201 return;
202 }
203
204 task = krhino_task_find(task_name);
205 if (task == NULL) {
206 printf("error: task do not exist\r\n");
207 return;
208 }
209
210 task_stack_base = task->task_stack_base;
211 if (task_stack_base == NULL) {
212 printf("error: task_stack_base err\r\n");
213 return;
214 }
215
216 debug_memory_access_err_check((unsigned long)task_stack_base, 0x20, 1);
217 }
218
debug_check_mem_access_disable(void)219 void debug_check_mem_access_disable(void)
220 {
221 mpu_disable();
222 }
223
224 #endif
225