diff options
author | Dave Kleikamp <shaggy@linux.vnet.ibm.com> | 2010-02-28 23:57:34 -0500 |
---|---|---|
committer | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2010-03-08 19:57:10 -0500 |
commit | 30124d11097e371e42052144d8a3f4a78d26e09f (patch) | |
tree | b37404e0b2c653c099401eea7e9bc988eaa84bb1 /arch/powerpc/kernel/ptrace.c | |
parent | a8e6da093ea8642b1320fb5d64134366f2a8d0ac (diff) |
powerpc/booke: Fix breakpoint/watchpoint one-shot behavior
Another fix for the extended ptrace patches in the -next tree.
The handling of breakpoints and watchpoints is inconsistent. When a
breakpoint or watchpoint is hit, the interrupt handler is clearing the
proper bits in the dbcr* registers, but leaving the dac* and iac* registers
alone. The ptrace code to delete the break/watchpoints checks the dac* and
iac* registers for zero to determine if they are enabled. Instead, they
should check the dbcr* bits.
Signed-off-by: Dave Kleikamp <shaggy@linux.vnet.ibm.com>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Diffstat (limited to 'arch/powerpc/kernel/ptrace.c')
-rw-r--r-- | arch/powerpc/kernel/ptrace.c | 12 |
1 files changed, 6 insertions, 6 deletions
diff --git a/arch/powerpc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c index 0efa2e3f40c6..ed2cfe17d25e 100644 --- a/arch/powerpc/kernel/ptrace.c +++ b/arch/powerpc/kernel/ptrace.c | |||
@@ -940,7 +940,7 @@ static int del_instruction_bp(struct task_struct *child, int slot) | |||
940 | { | 940 | { |
941 | switch (slot) { | 941 | switch (slot) { |
942 | case 1: | 942 | case 1: |
943 | if (child->thread.iac1 == 0) | 943 | if ((child->thread.dbcr0 & DBCR0_IAC1) == 0) |
944 | return -ENOENT; | 944 | return -ENOENT; |
945 | 945 | ||
946 | if (dbcr_iac_range(child) & DBCR_IAC12MODE) { | 946 | if (dbcr_iac_range(child) & DBCR_IAC12MODE) { |
@@ -952,7 +952,7 @@ static int del_instruction_bp(struct task_struct *child, int slot) | |||
952 | child->thread.dbcr0 &= ~DBCR0_IAC1; | 952 | child->thread.dbcr0 &= ~DBCR0_IAC1; |
953 | break; | 953 | break; |
954 | case 2: | 954 | case 2: |
955 | if (child->thread.iac2 == 0) | 955 | if ((child->thread.dbcr0 & DBCR0_IAC2) == 0) |
956 | return -ENOENT; | 956 | return -ENOENT; |
957 | 957 | ||
958 | if (dbcr_iac_range(child) & DBCR_IAC12MODE) | 958 | if (dbcr_iac_range(child) & DBCR_IAC12MODE) |
@@ -963,7 +963,7 @@ static int del_instruction_bp(struct task_struct *child, int slot) | |||
963 | break; | 963 | break; |
964 | #if CONFIG_PPC_ADV_DEBUG_IACS > 2 | 964 | #if CONFIG_PPC_ADV_DEBUG_IACS > 2 |
965 | case 3: | 965 | case 3: |
966 | if (child->thread.iac3 == 0) | 966 | if ((child->thread.dbcr0 & DBCR0_IAC3) == 0) |
967 | return -ENOENT; | 967 | return -ENOENT; |
968 | 968 | ||
969 | if (dbcr_iac_range(child) & DBCR_IAC34MODE) { | 969 | if (dbcr_iac_range(child) & DBCR_IAC34MODE) { |
@@ -975,7 +975,7 @@ static int del_instruction_bp(struct task_struct *child, int slot) | |||
975 | child->thread.dbcr0 &= ~DBCR0_IAC3; | 975 | child->thread.dbcr0 &= ~DBCR0_IAC3; |
976 | break; | 976 | break; |
977 | case 4: | 977 | case 4: |
978 | if (child->thread.iac4 == 0) | 978 | if ((child->thread.dbcr0 & DBCR0_IAC4) == 0) |
979 | return -ENOENT; | 979 | return -ENOENT; |
980 | 980 | ||
981 | if (dbcr_iac_range(child) & DBCR_IAC34MODE) | 981 | if (dbcr_iac_range(child) & DBCR_IAC34MODE) |
@@ -1054,7 +1054,7 @@ static int set_dac(struct task_struct *child, struct ppc_hw_breakpoint *bp_info) | |||
1054 | static int del_dac(struct task_struct *child, int slot) | 1054 | static int del_dac(struct task_struct *child, int slot) |
1055 | { | 1055 | { |
1056 | if (slot == 1) { | 1056 | if (slot == 1) { |
1057 | if (child->thread.dac1 == 0) | 1057 | if ((dbcr_dac(child) & (DBCR_DAC1R | DBCR_DAC1W)) == 0) |
1058 | return -ENOENT; | 1058 | return -ENOENT; |
1059 | 1059 | ||
1060 | child->thread.dac1 = 0; | 1060 | child->thread.dac1 = 0; |
@@ -1070,7 +1070,7 @@ static int del_dac(struct task_struct *child, int slot) | |||
1070 | child->thread.dvc1 = 0; | 1070 | child->thread.dvc1 = 0; |
1071 | #endif | 1071 | #endif |
1072 | } else if (slot == 2) { | 1072 | } else if (slot == 2) { |
1073 | if (child->thread.dac2 == 0) | 1073 | if ((dbcr_dac(child) & (DBCR_DAC2R | DBCR_DAC2W)) == 0) |
1074 | return -ENOENT; | 1074 | return -ENOENT; |
1075 | 1075 | ||
1076 | #ifdef CONFIG_PPC_ADV_DEBUG_DAC_RANGE | 1076 | #ifdef CONFIG_PPC_ADV_DEBUG_DAC_RANGE |