Skip to content

Commit

Permalink
x86: Support for instruction breakpoints
Browse files Browse the repository at this point in the history
Instruction breakpoints need to have a specific length of 0 to
be working. Bring this support but also take care the user is not
trying to set an unsupported length, like a range breakpoint for
example.

Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Prasad <prasad@linux.vnet.ibm.com>
Cc: Mahesh Salgaonkar <mahesh@linux.vnet.ibm.com>
Cc: Will Deacon <will.deacon@arm.com>
Cc: Jason Wessel <jason.wessel@windriver.com>
  • Loading branch information
Frederic Weisbecker committed Jun 24, 2010
1 parent 0c4519e commit f7809da
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 16 deletions.
2 changes: 1 addition & 1 deletion arch/x86/include/asm/hw_breakpoint.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@ struct arch_hw_breakpoint {
#include <linux/list.h>

/* Available HW breakpoint length encodings */
#define X86_BREAKPOINT_LEN_X 0x00
#define X86_BREAKPOINT_LEN_1 0x40
#define X86_BREAKPOINT_LEN_2 0x44
#define X86_BREAKPOINT_LEN_4 0x4c
#define X86_BREAKPOINT_LEN_EXECUTE 0x40

#ifdef CONFIG_X86_64
#define X86_BREAKPOINT_LEN_8 0x48
Expand Down
44 changes: 29 additions & 15 deletions arch/x86/kernel/hw_breakpoint.c
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,9 @@ int arch_bp_generic_fields(int x86_len, int x86_type,
{
/* Len */
switch (x86_len) {
case X86_BREAKPOINT_LEN_X:
*gen_len = sizeof(long);
break;
case X86_BREAKPOINT_LEN_1:
*gen_len = HW_BREAKPOINT_LEN_1;
break;
Expand Down Expand Up @@ -251,6 +254,29 @@ static int arch_build_bp_info(struct perf_event *bp)

info->address = bp->attr.bp_addr;

/* Type */
switch (bp->attr.bp_type) {
case HW_BREAKPOINT_W:
info->type = X86_BREAKPOINT_WRITE;
break;
case HW_BREAKPOINT_W | HW_BREAKPOINT_R:
info->type = X86_BREAKPOINT_RW;
break;
case HW_BREAKPOINT_X:
info->type = X86_BREAKPOINT_EXECUTE;
/*
* x86 inst breakpoints need to have a specific undefined len.
* But we still need to check userspace is not trying to setup
* an unsupported length, to get a range breakpoint for example.
*/
if (bp->attr.bp_len == sizeof(long)) {
info->len = X86_BREAKPOINT_LEN_X;
return 0;
}
default:
return -EINVAL;
}

/* Len */
switch (bp->attr.bp_len) {
case HW_BREAKPOINT_LEN_1:
Expand All @@ -271,21 +297,6 @@ static int arch_build_bp_info(struct perf_event *bp)
return -EINVAL;
}

/* Type */
switch (bp->attr.bp_type) {
case HW_BREAKPOINT_W:
info->type = X86_BREAKPOINT_WRITE;
break;
case HW_BREAKPOINT_W | HW_BREAKPOINT_R:
info->type = X86_BREAKPOINT_RW;
break;
case HW_BREAKPOINT_X:
info->type = X86_BREAKPOINT_EXECUTE;
break;
default:
return -EINVAL;
}

return 0;
}
/*
Expand All @@ -305,6 +316,9 @@ int arch_validate_hwbkpt_settings(struct perf_event *bp)
ret = -EINVAL;

switch (info->len) {
case X86_BREAKPOINT_LEN_X:
align = sizeof(long) -1;
break;
case X86_BREAKPOINT_LEN_1:
align = 0;
break;
Expand Down

0 comments on commit f7809da

Please sign in to comment.