The hw_breakpoint subsystem consumes all the hardware breakpoint exceptions since it hooks the notify_die handlers first, this means that kgdb doesn't get the opportunity to handle hw breakpoint exceptions generated by kgdb itself.
This patch adds an extend flag to perf_event_attr for hw_breakpoint_handler() to decide to pass or stop the DIE_DEBUG notification. As KGDB set that flag, hw_breakpoint_handler() will pass the DIE_DEBUG notification, thus kgdb have the chance to take DIE_DEBUG notification. Signed-off-by: Dongdong Deng <[email protected]> Reviewed-by: Bruce Ashfield <[email protected]> --- arch/x86/kernel/hw_breakpoint.c | 14 ++++++++++++++ arch/x86/kernel/kgdb.c | 2 ++ include/linux/perf_event.h | 9 +++++++++ 3 files changed, 25 insertions(+), 0 deletions(-) diff --git a/arch/x86/kernel/hw_breakpoint.c b/arch/x86/kernel/hw_breakpoint.c index a8f1b80..b38f786 100644 --- a/arch/x86/kernel/hw_breakpoint.c +++ b/arch/x86/kernel/hw_breakpoint.c @@ -406,6 +406,8 @@ EXPORT_SYMBOL_GPL(hw_breakpoint_restore); * ii) When there are more bits than trap<n> set in DR6 register (such * as BD, BS or BT) indicating that more than one debug condition is * met and requires some more action in do_debug(). + * iii) The source of hw breakpoint event want to handle the event + * by itself, currently just KGDB have this notion. * * NOTIFY_STOP returned for all other cases * @@ -464,6 +466,18 @@ static int __kprobes hw_breakpoint_handler(struct die_args *args) break; } + if (bp->attr.flag == SKIP_HWBP_EVENT_PERF_FLAG) { + /* + * when attr.flag is set to SKIP_HWBP_EVENT_PERF_FLAG + * it indicates currently hw breakpoint event + * source want to handle this event by itself. + * thus return NOTIFY_DONE here. + */ + rc = NOTIFY_DONE; + rcu_read_unlock(); + break; + } + perf_bp_event(bp, args->regs); rcu_read_unlock(); diff --git a/arch/x86/kernel/kgdb.c b/arch/x86/kernel/kgdb.c index 4f4af75..bc3321f 100644 --- a/arch/x86/kernel/kgdb.c +++ b/arch/x86/kernel/kgdb.c @@ -641,6 +641,8 @@ void kgdb_arch_late(void) attr.bp_len = HW_BREAKPOINT_LEN_1; attr.bp_type = HW_BREAKPOINT_W; attr.disabled = 1; + /* set kgdb's special requires flag to perf_event */ + attr.flag = SKIP_HWBP_EVENT_PERF_FLAG; for (i = 0; i < 4; i++) { if (breakinfo[i].pev) continue; diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h index 5d0266d..fcefb09 100644 --- a/include/linux/perf_event.h +++ b/include/linux/perf_event.h @@ -160,6 +160,11 @@ enum perf_event_read_format { #define PERF_ATTR_SIZE_VER0 64 /* sizeof first published struct */ +enum perf_event_attr_flag { + NOSET_PERF_FLAG = 0, + SKIP_HWBP_EVENT_PERF_FLAG = 1, +}; + /* * Hardware event_id to monitor via a performance monitoring event: */ @@ -225,6 +230,10 @@ struct perf_event_attr { __u32 bp_type; __u64 bp_addr; __u64 bp_len; + /* + * Ext flag, currently just kgdb used it. + */ + enum perf_event_attr_flag flag; }; /* -- 1.6.0.4 ------------------------------------------------------------------------------ This SF.net email is sponsored by Sprint What will you do first with EVO, the first 4G phone? Visit sprint.com/first -- http://p.sf.net/sfu/sprint-com-first _______________________________________________ Kgdb-bugreport mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/kgdb-bugreport
