diff --git a/arch/arm/mm/fault.c b/arch/arm/mm/fault.c index 235c3868dac..698c93e0a94 100644 --- a/arch/arm/mm/fault.c +++ b/arch/arm/mm/fault.c @@ -675,6 +675,8 @@ do_DataAbort(unsigned long addr, unsigned int fsr, struct pt_regs *regs) if (!inf->fn(addr, fsr & ~FSR_LNX_PF, regs)) return; + trace_unhandled_abort(regs, addr, fsr); + printk(KERN_ALERT "Unhandled fault: %s (0x%03x) at 0x%08lx\n", inf->name, fsr, addr); @@ -707,6 +709,8 @@ do_PrefetchAbort(unsigned long addr, unsigned int ifsr, struct pt_regs *regs) if (!inf->fn(addr, ifsr | FSR_LNX_PF, regs)) return; + trace_unhandled_abort(regs, addr, ifsr); + printk(KERN_ALERT "Unhandled prefetch abort: %s (0x%03x) at 0x%08lx\n", inf->name, ifsr, addr); diff --git a/drivers/coresight/coresight-event.c b/drivers/coresight/coresight-event.c index 96c9545af5d..95cadc27561 100644 --- a/drivers/coresight/coresight-event.c +++ b/drivers/coresight/coresight-event.c @@ -45,6 +45,17 @@ static void event_abort_undef_instr(void *ignore, } } +static void event_abort_unhandled_abort(void *ignore, + struct pt_regs *regs, + unsigned long addr, + unsigned int fsr) +{ + if (user_mode(regs)) { + coresight_abort(); + pr_debug("coresight_event: addr: %lu, fsr:%u", addr, fsr); + } +} + static int event_abort_register(void) { int ret; @@ -55,9 +66,14 @@ static int event_abort_register(void) ret = register_trace_undef_instr(event_abort_undef_instr, NULL); if (ret) goto err_undef_instr; + ret = register_trace_unhandled_abort(event_abort_unhandled_abort, NULL); + if (ret) + goto err_unhandled_abort; return 0; +err_unhandled_abort: + unregister_trace_undef_instr(event_abort_undef_instr, NULL); err_undef_instr: unregister_trace_user_fault(event_abort_user_fault, NULL); err_usr_fault: @@ -68,6 +84,7 @@ static void event_abort_unregister(void) { unregister_trace_user_fault(event_abort_user_fault, NULL); unregister_trace_undef_instr(event_abort_undef_instr, NULL); + unregister_trace_unhandled_abort(event_abort_unhandled_abort, NULL); } static int event_abort_set(const char *val, struct kernel_param *kp) diff --git a/include/trace/events/exception.h b/include/trace/events/exception.h index 110e920fe56..69dbf7cebdc 100644 --- a/include/trace/events/exception.h +++ b/include/trace/events/exception.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2012, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -63,6 +63,27 @@ TRACE_EVENT(undef_instr, TP_printk("pc:%p", __entry->prog_cnt) ); +TRACE_EVENT(unhandled_abort, + + TP_PROTO(struct pt_regs *regs, unsigned long addr, unsigned int fsr), + + TP_ARGS(regs, addr, fsr), + + TP_STRUCT__entry( + __field(struct pt_regs *, regs) + __field(unsigned long, addr) + __field(unsigned int, fsr) + ), + + TP_fast_assign( + __entry->regs = regs; + __entry->addr = addr; + __entry->fsr = fsr; + ), + + TP_printk("addr:%lu, fsr:%u", __entry->addr, __entry->fsr) +); + #endif #include