HW-BKPT: Allow per-cpu kernel-space Hardware Breakpoint requests
Subsystems (2)
PATCH 1/3 HW-BKPT: Allow per-cpu kernel-space Hardware Breakpoint requests
In reply to a message not in the archiveAllow kernel-space hw-breakpoints to be restricted only for a subset of CPUs using a cpumask field in 'struct hw_breakpoint'.
--- arch/x86/include/asm/hw_breakpoint.h | 1 arch/x86/kernel/hw_breakpoint.c | 12 +++ include/asm-generic/hw_breakpoint.h | 2 kernel/hw_breakpoint.c | 124 +++++++++++++++++++++++++---------- 4 files changed, 104 insertions(+), 35 deletions(-)
arch/x86/kernel/hw_breakpoint.c +11 -1
@@ -68,6 +68,12 @@ static unsigned long encode_dr7(int drnureturn bp_info; } +/* Disable breakpoints on the physical debug registers */ +void arch_disable_hw_breakpoint (void ) +{ +set_debugreg (0UL ,7 ); +} +void arch_update_kernel_hw_breakpoint (void *unused) {struct hw_breakpoint *bp;
@@ -78,7 +84,7 @@ void arch_update_kernel_hw_breakpoint(voset_debugreg (0UL ,7 );for (i = hbp_kernel_pos; i <HBP_NUM ; i++) { -per_cpu (this_hbp_kernel[i], cpu) = bp = hbp_kernel[i]; + bp =per_cpu (this_hbp_kernel[i], cpu);if (bp) { temp_kdr7 |=encode_dr7 (i, bp->info.len, bp->info.type);set_debugreg (bp->info.address, i);
@@ -207,6 +213,10 @@ int arch_validate_hwbkpt_settings(structunsigned int align;int ret = -EINVAL ; +/* User-space breakpoints cannot be restricted to a subset of CPUs */ +if (tsk && bp->cpumask) +return ret; +switch (bp->info.type) {/* * Ptrace-refactoring code
include/asm-generic/hw_breakpoint.h +2 -0
@@ -8,6 +8,7 @@#ifdef __KERNEL__#include <linux/list.h> #include <linux/types.h> +#include <linux/cpumask.h> #include <linux/kallsyms.h> /**
@@ -102,6 +103,7 @@*/ struct hw_breakpoint {void (*triggered)(struct hw_breakpoint *,struct pt_regs *); +const cpumask_t *cpumask;struct arch_hw_breakpoint info; };
kernel/hw_breakpoint.c +90 -34
175 lines not on this page · raw message
arch/x86/include/asm/hw_breakpoint.h +1 -0
@@ -48,6 +48,7 @@ extern int arch_validate_hwbkpt_settingsextern void arch_update_user_hw_breakpoint (int pos,struct task_struct *tsk);extern void arch_flush_thread_hw_breakpoint (struct task_struct *tsk);extern void arch_update_kernel_hw_breakpoint (void *); +extern void arch_disable_hw_breakpoint (void );extern int hw_breakpoint_exceptions_notify (struct notifier_block *unused,unsigned long val,void *data);#endif /* __KERNEL__ */
PATCH 2/3 HW-BKPT: Allow kernel breakpoints to be modified through a new API
In reply to a message not in the archiveIntroduce modify_kernel_hw_breakpoint() API that can quickly change the characteristics (such as address, length, type) of a kernel-space breakpoint without having to unregister first and then re-register it.
--- include/asm-generic/hw_breakpoint.h | 2 + kernel/hw_breakpoint.c | 49 ++++++++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+)
include/asm-generic/hw_breakpoint.h +2 -0
@@ -133,6 +133,8 @@ extern void unregister_user_hw_breakpoin* Kernel breakpoints are not associated with any particular thread. */ extern int register_kernel_hw_breakpoint (struct hw_breakpoint *bp); +extern int modify_kernel_hw_breakpoint (struct hw_breakpoint *old_bp, +struct hw_breakpoint *new_bp);extern void unregister_kernel_hw_breakpoint (struct hw_breakpoint *bp);extern unsigned int hbp_kernel_pos;
kernel/hw_breakpoint.c +49 -0
55 lines not on this page · raw message
PATCH 3/3 HW-BKPT: Enable/disable the breakpoints when still registered
In reply to a message not in the archiveAllow breakpoints to be enabled/disabled without yielding the breakpoint request through new APIs - <enable><disable>_hw_breakpoint()
--- arch/x86/kernel/hw_breakpoint.c | 12 +++--- include/asm-generic/hw_breakpoint.h | 10 +++++ kernel/hw_breakpoint.c | 66 ++++++++++++++++++++++++++++++++++++ 3 files changed, 83 insertions(+), 5 deletions(-)
arch/x86/kernel/hw_breakpoint.c +7 -5
@@ -85,10 +85,11 @@ void arch_update_kernel_hw_breakpoint(vofor (i = hbp_kernel_pos; i <HBP_NUM ; i++) { bp =per_cpu (this_hbp_kernel[i], cpu); -if (bp) { +if (!bp) +continue ; +set_debugreg (bp->info.address, i); +if (bp->enabled) temp_kdr7 |=encode_dr7 (i, bp->info.len, bp->info.type); -set_debugreg (bp->info.address, i); - } }/* No need to set DR6. Update the debug registers with kernel-space
@@ -288,8 +289,9 @@ void arch_update_user_hw_breakpoint(int thread->debugreg7 &= ~dr7_masks[pos];if (bp) { thread->debugreg[pos] = bp->info.address; - thread->debugreg7 |=encode_dr7 (pos, bp->info.len, - bp->info.type); +if (bp->enabled) + thread->debugreg7 |=encode_dr7 (pos, bp->info.len, + bp->info.type); }else thread->debugreg[pos] =0 ; }
include/asm-generic/hw_breakpoint.h +10 -0
@@ -102,6 +102,12 @@* ---------------------------------------------------------------------- */ struct hw_breakpoint { +/* +* Denotes if a breakpoint is currently enabled in physical debug +* registers. Not to be set directly by the end-user. Must be +* operated through <enable><disable>_hw_breakpoint() APIs only. +*/ +bool enabled;void (*triggered)(struct hw_breakpoint *,struct pt_regs *);const cpumask_t *cpumask;struct arch_hw_breakpoint info;
@@ -137,6 +143,10 @@ extern int modify_kernel_hw_breakpoint(s struct hw_breakpoint *new_bp);extern void unregister_kernel_hw_breakpoint (struct hw_breakpoint *bp); +extern void enable_hw_breakpoint (struct hw_breakpoint *bp, +struct task_struct *tsk); +extern void disable_hw_breakpoint (struct hw_breakpoint *bp, +struct task_struct *tsk);extern unsigned int hbp_kernel_pos;#endif /* __KERNEL__ */
kernel/hw_breakpoint.c +66 -0
78 lines not on this page · raw message