Skip to content

Commit

Permalink
x86/hw-breakpoints: Don't lose GE flag while disabling a breakpoint
Browse files Browse the repository at this point in the history
When we schedule out a breakpoint from the cpu, we also
incidentally remove the "Global exact breakpoint" flag from the
breakpoint control register. It makes us losing the fine grained
precision about the origin of the instructions that may trigger
breakpoint exceptions for the other breakpoints running in this
cpu.

Reported-by: Prasad <prasad@linux.vnet.ibm.com>
Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com>
LKML-Reference: <1259211878-6013-1-git-send-regression-fweisbec@gmail.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
  • Loading branch information
fweisbec authored and Ingo Molnar committed Nov 26, 2009
1 parent 605bfae commit 2c31b79
Showing 1 changed file with 14 additions and 8 deletions.
22 changes: 14 additions & 8 deletions arch/x86/kernel/hw_breakpoint.c
Original file line number Diff line number Diff line change
Expand Up @@ -59,21 +59,27 @@ static DEFINE_PER_CPU(unsigned long, cpu_debugreg[HBP_NUM]);
static DEFINE_PER_CPU(struct perf_event *, bp_per_reg[HBP_NUM]);


/*
* Encode the length, type, Exact, and Enable bits for a particular breakpoint
* as stored in debug register 7.
*/
unsigned long encode_dr7(int drnum, unsigned int len, unsigned int type)
static inline unsigned long
__encode_dr7(int drnum, unsigned int len, unsigned int type)
{
unsigned long bp_info;

bp_info = (len | type) & 0xf;
bp_info <<= (DR_CONTROL_SHIFT + drnum * DR_CONTROL_SIZE);
bp_info |= (DR_GLOBAL_ENABLE << (drnum * DR_ENABLE_SIZE)) |
DR_GLOBAL_SLOWDOWN;
bp_info |= (DR_GLOBAL_ENABLE << (drnum * DR_ENABLE_SIZE));

return bp_info;
}

/*
* Encode the length, type, Exact, and Enable bits for a particular breakpoint
* as stored in debug register 7.
*/
unsigned long encode_dr7(int drnum, unsigned int len, unsigned int type)
{
return __encode_dr7(drnum, len, type) | DR_GLOBAL_SLOWDOWN;
}

/*
* Decode the length and type bits for a particular breakpoint as
* stored in debug register 7. Return the "enabled" status.
Expand Down Expand Up @@ -154,7 +160,7 @@ void arch_uninstall_hw_breakpoint(struct perf_event *bp)
return;

dr7 = &__get_cpu_var(cpu_dr7);
*dr7 &= ~encode_dr7(i, info->len, info->type);
*dr7 &= ~__encode_dr7(i, info->len, info->type);

set_debugreg(*dr7, 7);
}
Expand Down

0 comments on commit 2c31b79

Please sign in to comment.