Skip to content

Commit 4cf4040

Browse files
Andrew Boieandrewboie
authored andcommitted
arc: print human-readable exception info
Right now only numerical values are printed which must be looked up in the Designware ARCv2 ISA Programmer's Reference, which is not public. Add a non-default Kconfig to print more information at the expense of footprint, and enable it for all the simulator targets. We only print code/parameter details for machine check and protection violations, more may be added later as desired. This should cover all the exceptions we commonly encounter for memory protection. Signed-off-by: Andrew Boie <[email protected]>
1 parent 36ff55c commit 4cf4040

File tree

7 files changed

+286
-11
lines changed

7 files changed

+286
-11
lines changed

arch/arc/Kconfig

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,4 +199,13 @@ config CACHE_FLUSHING
199199

200200
endmenu
201201

202+
config ARC_EXCEPTION_DEBUG
203+
bool "Unhandled exception debugging information"
204+
default n
205+
depends on PRINTK
206+
help
207+
Print human-readable information about exception vectors, cause codes,
208+
and parameters, at a cost of code/data size for the human-readable
209+
strings.
210+
202211
endmenu

arch/arc/core/fault.c

Lines changed: 257 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,249 @@ static u32_t z_check_thread_stack_fail(const u32_t fault_addr, u32_t sp)
123123

124124
#endif
125125

126+
#ifdef CONFIG_ARC_EXCEPTION_DEBUG
127+
/* For EV_ProtV, the numbering/semantics of the parameter are consistent across
128+
* several codes, although not all combination will be reported.
129+
*
130+
* These codes and parameters do not have associated* names in
131+
* the technical manual, just switch on the values in Table 6-5
132+
*/
133+
static void dump_protv_access_err(u32_t parameter)
134+
{
135+
switch (parameter) {
136+
case 0x1:
137+
printk("code protection scheme");
138+
break;
139+
case 0x2:
140+
printk("stack checking scheme");
141+
break;
142+
case 0x4:
143+
printk("MPU");
144+
break;
145+
case 0x8:
146+
printk("MMU");
147+
break;
148+
case 0x10:
149+
printk("NVM");
150+
break;
151+
case 0x24:
152+
printk("Secure MPU");
153+
break;
154+
case 0x44:
155+
printk("Secure MPU with SID mismatch");
156+
break;
157+
default:
158+
printk("unknown");
159+
break;
160+
}
161+
}
162+
163+
static void dump_protv_exception(u32_t cause, u32_t parameter)
164+
{
165+
switch (cause) {
166+
case 0x0:
167+
printk("Instruction fetch violation: ");
168+
dump_protv_access_err(parameter);
169+
break;
170+
case 0x1:
171+
printk("Memory read protection violation: ");
172+
dump_protv_access_err(parameter);
173+
break;
174+
case 0x2:
175+
printk("Memory write protection violation: ");
176+
dump_protv_access_err(parameter);
177+
break;
178+
case 0x3:
179+
printk("Memory read-modify-write violation: ");
180+
dump_protv_access_err(parameter);
181+
break;
182+
case 0x10:
183+
printk("Normal vector table in secure memory");
184+
break;
185+
case 0x11:
186+
printk("NS handler code located in S memory");
187+
break;
188+
case 0x12:
189+
printk("NSC Table Range Violation");
190+
break;
191+
default:
192+
printk("unknown");
193+
break;
194+
}
195+
}
196+
197+
static void dump_machine_check_exception(u32_t cause, u32_t parameter)
198+
{
199+
switch (cause) {
200+
case 0x0:
201+
printk("double fault");
202+
break;
203+
case 0x1:
204+
printk("overlapping TLB entries");
205+
break;
206+
case 0x2:
207+
printk("fatal TLB error");
208+
break;
209+
case 0x3:
210+
printk("fatal cache error");
211+
break;
212+
case 0x4:
213+
printk("internal memory error on instruction fetch");
214+
break;
215+
case 0x5:
216+
printk("internal memory error on data fetch");
217+
break;
218+
case 0x6:
219+
printk("illegal overlapping MPU entries");
220+
if (parameter == 0x1) {
221+
printk(" (jump and branch target)");
222+
}
223+
break;
224+
case 0x10:
225+
printk("secure vector table not located in secure memory");
226+
break;
227+
case 0x11:
228+
printk("NSC jump table not located in secure memory");
229+
break;
230+
case 0x12:
231+
printk("secure handler code not located in secure memory");
232+
break;
233+
case 0x13:
234+
printk("NSC target address not located in secure memory");
235+
break;
236+
case 0x80:
237+
printk("uncorrectable ECC or parity error in vector memory");
238+
break;
239+
default:
240+
printk("unknown");
241+
break;
242+
}
243+
}
244+
245+
static void dump_privilege_exception(u32_t cause, u32_t parameter)
246+
{
247+
switch (cause) {
248+
case 0x0:
249+
printk("Privilege violation");
250+
break;
251+
case 0x1:
252+
printk("disabled extension");
253+
break;
254+
case 0x2:
255+
printk("action point hit");
256+
break;
257+
case 0x10:
258+
switch (parameter) {
259+
case 0x1:
260+
printk("N to S return using incorrect return mechanism");
261+
break;
262+
case 0x2:
263+
printk("N to S return with incorrect operating mode");
264+
break;
265+
case 0x3:
266+
printk("IRQ/exception return fetch from wrong mode");
267+
break;
268+
case 0x4:
269+
printk("attempt to halt secure processor in NS mode");
270+
break;
271+
case 0x20:
272+
printk("attempt to access secure resource from normal mode");
273+
break;
274+
case 0x40:
275+
printk("SID violation on resource access (APEX/UAUX/key NVM)");
276+
break;
277+
default:
278+
printk("unknown");
279+
break;
280+
}
281+
break;
282+
case 0x13:
283+
switch (parameter) {
284+
case 0x20:
285+
printk("attempt to access secure APEX feature from NS mode");
286+
break;
287+
case 0x40:
288+
printk("SID violation on access to APEX feature");
289+
break;
290+
default:
291+
printk("unknown");
292+
break;
293+
}
294+
break;
295+
default:
296+
printk("unknown");
297+
break;
298+
}
299+
}
300+
301+
static void dump_exception_info(u32_t vector, u32_t cause, u32_t parameter)
302+
{
303+
if (vector >= 0x10 && vector <= 0xFF) {
304+
printk("interrupt %u\n", vector);
305+
return;
306+
}
307+
308+
/* Names are exactly as they appear in Designware ARCv2 ISA
309+
* Programmer's reference manual for easy searching
310+
*/
311+
switch (vector) {
312+
case ARC_EV_RESET:
313+
printk("Reset");
314+
break;
315+
case ARC_EV_MEM_ERROR:
316+
printk("Memory Error");
317+
break;
318+
case ARC_EV_INS_ERROR:
319+
printk("Instruction Error");
320+
break;
321+
case ARC_EV_MACHINE_CHECK:
322+
printk("EV_MachineCheck: ");
323+
dump_machine_check_exception(cause, parameter);
324+
break;
325+
case ARC_EV_TLB_MISS_I:
326+
printk("EV_TLBMissI");
327+
break;
328+
case ARC_EV_TLB_MISS_D:
329+
printk("EV_TLBMissD");
330+
break;
331+
case ARC_EV_PROT_V:
332+
printk("EV_ProtV: ");
333+
dump_protv_exception(cause, parameter);
334+
break;
335+
case ARC_EV_PRIVILEGE_V:
336+
printk("EV_PrivilegeV: ");
337+
dump_privilege_exception(cause, parameter);
338+
break;
339+
case ARC_EV_SWI:
340+
printk("EV_SWI");
341+
break;
342+
case ARC_EV_TRAP:
343+
printk("EV_Trap");
344+
break;
345+
case ARC_EV_EXTENSION:
346+
printk("EV_Extension");
347+
break;
348+
case ARC_EV_DIV_ZERO:
349+
printk("EV_DivZero");
350+
break;
351+
case ARC_EV_DC_ERROR:
352+
printk("EV_DCError");
353+
break;
354+
case ARC_EV_MISALIGNED:
355+
printk("EV_Misaligned");
356+
break;
357+
case ARC_EV_VEC_UNIT:
358+
printk("EV_VecUnit");
359+
break;
360+
default:
361+
printk("unknown");
362+
break;
363+
}
364+
365+
printk("\n");
366+
}
367+
#endif /* CONFIG_ARC_EXCEPTION_DEBUG */
368+
126369
/*
127370
* @brief Fault handler
128371
*
@@ -133,12 +376,10 @@ static u32_t z_check_thread_stack_fail(const u32_t fault_addr, u32_t sp)
133376
*/
134377
void _Fault(NANO_ESF *esf)
135378
{
136-
u32_t vector, code, parameter;
379+
u32_t vector, cause, parameter;
137380
u32_t exc_addr = z_arc_v2_aux_reg_read(_ARC_V2_EFA);
138381
u32_t ecr = z_arc_v2_aux_reg_read(_ARC_V2_ECR);
139382

140-
LOG_PANIC();
141-
142383
#ifdef CONFIG_USERSPACE
143384
for (int i = 0; i < ARRAY_SIZE(exceptions); i++) {
144385
u32_t start = (u32_t)exceptions[i].start;
@@ -150,35 +391,40 @@ void _Fault(NANO_ESF *esf)
150391
}
151392
}
152393
#endif
394+
LOG_PANIC();
153395

154396
vector = Z_ARC_V2_ECR_VECTOR(ecr);
155-
code = Z_ARC_V2_ECR_CODE(ecr);
397+
cause = Z_ARC_V2_ECR_CODE(ecr);
156398
parameter = Z_ARC_V2_ECR_PARAMETER(ecr);
157399

158-
159400
/* exception raised by kernel */
160-
if (vector == 0x9 && parameter == _TRAP_S_CALL_RUNTIME_EXCEPT) {
401+
if (vector == ARC_EV_TRAP && parameter == _TRAP_S_CALL_RUNTIME_EXCEPT) {
161402
z_NanoFatalErrorHandler(esf->r0, esf);
162403
return;
163404
}
164405

165-
printk("Exception vector: 0x%x, cause code: 0x%x, parameter 0x%x\n",
166-
vector, code, parameter);
406+
printk("***** Exception vector: 0x%x, cause code: 0x%x, parameter 0x%x\n",
407+
vector, cause, parameter);
167408
printk("Address 0x%x\n", exc_addr);
409+
#ifdef CONFIG_ARC_EXCEPTION_DEBUG
410+
dump_exception_info(vector, cause, parameter);
411+
#endif
412+
168413
#ifdef CONFIG_ARC_STACK_CHECKING
169-
/* Vector 6 = EV_ProV. Regardless of code, parameter 2 means stack
414+
/* Vector 6 = EV_ProV. Regardless of cause, parameter 2 means stack
170415
* check violation
171416
* stack check and mpu violation can come out together, then
172417
* parameter = 0x2 | [0x4 | 0x8 | 0x1]
173418
*/
174-
if (vector == 6U && parameter & 0x2) {
419+
if (vector == ARC_EV_PROT_V && parameter & 0x2) {
175420
z_NanoFatalErrorHandler(_NANO_ERR_STACK_CHK_FAIL, esf);
176421
return;
177422
}
178423
#endif
179424

180425
#ifdef CONFIG_MPU_STACK_GUARD
181-
if (vector == 0x6 && ((parameter == 0x4) || (parameter == 0x24))) {
426+
if (vector == ARC_EV_PROT_V && ((parameter == 0x4) ||
427+
(parameter == 0x24))) {
182428
if (z_check_thread_stack_fail(exc_addr, arc_exc_saved_sp)) {
183429
z_NanoFatalErrorHandler(_NANO_ERR_STACK_CHK_FAIL, esf);
184430
return;

boards/arc/nsim_em/nsim_em_defconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,4 @@ CONFIG_ARC_MPU_ENABLE=y
1414
CONFIG_CONSOLE=y
1515
CONFIG_UART_CONSOLE=y
1616
CONFIG_SERIAL=y
17+
CONFIG_ARC_EXCEPTION_DEBUG=y

boards/arc/nsim_em/nsim_em_mpu_stack_guard_defconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,4 @@ CONFIG_ARC_MPU_ENABLE=y
1515
CONFIG_CONSOLE=y
1616
CONFIG_UART_CONSOLE=y
1717
CONFIG_SERIAL=y
18+
CONFIG_ARC_EXCEPTION_DEBUG=y

boards/arc/nsim_em/nsim_sem_defconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,4 @@ CONFIG_ARC_MPU_ENABLE=y
1414
CONFIG_CONSOLE=y
1515
CONFIG_UART_CONSOLE=y
1616
CONFIG_SERIAL=y
17+
CONFIG_ARC_EXCEPTION_DEBUG=y

boards/arc/nsim_em/nsim_sem_mpu_stack_guard_defconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,4 @@ CONFIG_ARC_MPU_ENABLE=y
1515
CONFIG_CONSOLE=y
1616
CONFIG_UART_CONSOLE=y
1717
CONFIG_SERIAL=y
18+
CONFIG_ARC_EXCEPTION_DEBUG=y

include/arch/arc/v2/exc.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,5 +27,21 @@ typedef struct _irq_stack_frame NANO_ESF;
2727
}
2828
#endif
2929

30+
/* ARCv2 Exception vector numbers */
31+
#define ARC_EV_RESET 0x0
32+
#define ARC_EV_MEM_ERROR 0x1
33+
#define ARC_EV_INS_ERROR 0x2
34+
#define ARC_EV_MACHINE_CHECK 0x3
35+
#define ARC_EV_TLB_MISS_I 0x4
36+
#define ARC_EV_TLB_MISS_D 0x5
37+
#define ARC_EV_PROT_V 0x6
38+
#define ARC_EV_PRIVILEGE_V 0x7
39+
#define ARC_EV_SWI 0x8
40+
#define ARC_EV_TRAP 0x9
41+
#define ARC_EV_EXTENSION 0xA
42+
#define ARC_EV_DIV_ZERO 0xB
43+
#define ARC_EV_DC_ERROR 0xC
44+
#define ARC_EV_MISALIGNED 0xD
45+
#define ARC_EV_VEC_UNIT 0xE
3046

3147
#endif /* ZEPHYR_INCLUDE_ARCH_ARC_V2_EXC_H_ */

0 commit comments

Comments
 (0)