mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2025-01-13 16:40:22 +00:00
powerpc, hw_breakpoint: Discard extraneous interrupt due to accesses outside symbol length
Many a times, the requested breakpoint length can be less than the fixed breakpoint length i.e. 8 bytes supported by PowerPC 64-bit server (Book III S) processors. This could lead to extraneous interrupts resulting in false breakpoint notifications. This detects and discards such interrupts for non-ptrace requests. We don't change ptrace behaviour to avoid breaking compatability. [Suggestion from Paul Mackerras <paulus@samba.org> to add a new flag in 'struct arch_hw_breakpoint' to identify extraneous interrupts] Signed-off-by: K.Prasad <prasad@linux.vnet.ibm.com> Signed-off-by: Paul Mackerras <paulus@samba.org>
This commit is contained in:
parent
06532a6743
commit
e3e94084ad
@ -27,6 +27,7 @@
|
||||
#ifdef CONFIG_HAVE_HW_BREAKPOINT
|
||||
|
||||
struct arch_hw_breakpoint {
|
||||
bool extraneous_interrupt;
|
||||
u8 len; /* length of the target data symbol */
|
||||
int type;
|
||||
unsigned long address;
|
||||
|
@ -204,6 +204,7 @@ int __kprobes hw_breakpoint_handler(struct die_args *args)
|
||||
int stepped = 1;
|
||||
struct arch_hw_breakpoint *info;
|
||||
unsigned int instr;
|
||||
unsigned long dar = regs->dar;
|
||||
|
||||
/* Disable breakpoints during exception handling */
|
||||
set_dabr(0);
|
||||
@ -234,6 +235,22 @@ int __kprobes hw_breakpoint_handler(struct die_args *args)
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* Verify if dar lies within the address range occupied by the symbol
|
||||
* being watched to filter extraneous exceptions.
|
||||
*/
|
||||
if (!((bp->attr.bp_addr <= dar) &&
|
||||
(dar <= (bp->attr.bp_addr + bp->attr.bp_len)))) {
|
||||
/*
|
||||
* This exception is triggered not because of a memory access
|
||||
* on the monitored variable but in the double-word address
|
||||
* range in which it is contained. We will consume this
|
||||
* exception, considering it as 'noise'.
|
||||
*/
|
||||
info->extraneous_interrupt = true;
|
||||
} else
|
||||
info->extraneous_interrupt = false;
|
||||
|
||||
/* Do not emulate user-space instructions, instead single-step them */
|
||||
if (user_mode(regs)) {
|
||||
bp->ctx->task->thread.last_hit_ubp = bp;
|
||||
@ -261,7 +278,8 @@ int __kprobes hw_breakpoint_handler(struct die_args *args)
|
||||
* As a policy, the callback is invoked in a 'trigger-after-execute'
|
||||
* fashion
|
||||
*/
|
||||
perf_bp_event(bp, regs);
|
||||
if (!info->extraneous_interrupt)
|
||||
perf_bp_event(bp, regs);
|
||||
|
||||
set_dabr(info->address | info->type | DABR_TRANSLATION);
|
||||
out:
|
||||
@ -292,7 +310,8 @@ int __kprobes single_step_dabr_instruction(struct die_args *args)
|
||||
* We shall invoke the user-defined callback function in the single
|
||||
* stepping handler to confirm to 'trigger-after-execute' semantics
|
||||
*/
|
||||
perf_bp_event(bp, regs);
|
||||
if (!bp_info->extraneous_interrupt)
|
||||
perf_bp_event(bp, regs);
|
||||
|
||||
/*
|
||||
* Do not disable MSR_SE if the process was already in
|
||||
|
Loading…
x
Reference in New Issue
Block a user