mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2025-01-07 21:53:44 +00:00
3eb2a8b235
In the current code, if multiple hardware breakpoints/watchpoints in a user-space thread, some of them will not be triggered. When debugging the following code using gdb. lihui@bogon:~$ cat test.c #include <stdio.h> int a = 0; int main() { printf("start test\n"); a = 1; printf("a = %d\n", a); printf("end test\n"); return 0; } lihui@bogon:~$ gcc -g test.c -o test lihui@bogon:~$ gdb test ... (gdb) start ... Temporary breakpoint 1, main () at test.c:5 5 printf("start test\n"); (gdb) watch a Hardware watchpoint 2: a (gdb) hbreak 8 Hardware assisted breakpoint 3 at 0x1200006ec: file test.c, line 8. (gdb) c Continuing. start test a = 1 Breakpoint 3, main () at test.c:8 8 printf("end test\n"); ... The first hardware watchpoint is not triggered, the root causes are: 1. In hw_breakpoint_control(), The FWPnCFG1.2.4/MWPnCFG1.2.4 register settings are not distinguished. They should be set based on hardware watchpoint functions (fetch or load/store operations). 2. In breakpoint_handler() and watchpoint_handler(), it doesn't identify which watchpoint is triggered. So, all watchpoint-related perf_event callbacks are called and siginfo is sent to the user space. This will cause user-space unable to determine which watchpoint is triggered. The kernel need to identity which watchpoint is triggered via MWPS/ FWPS registers, and then call the corresponding perf event callbacks to report siginfo to the user-space. Modify the relevant code to solve above issues. All changes according to the LoongArch Reference Manual: https://loongson.github.io/LoongArch-Documentation/LoongArch-Vol1-EN.html#control-and-status-registers-related-to-watchpoints With this patch: lihui@bogon:~$ gdb test ... (gdb) start ... Temporary breakpoint 1, main () at test.c:5 5 printf("start test\n"); (gdb) watch a Hardware watchpoint 2: a (gdb) hbreak 8 Hardware assisted breakpoint 3 at 0x1200006ec: file test.c, line 8. (gdb) c Continuing. start test Hardware watchpoint 2: a Old value = 0 New value = 1 main () at test.c:7 7 printf("a = %d\n", a); (gdb) c Continuing. a = 1 Breakpoint 3, main () at test.c:8 8 printf("end test\n"); (gdb) c Continuing. end test [Inferior 1 (process 778) exited normally] Cc: stable@vger.kernel.org Signed-off-by: Hui Li <lihui@loongson.cn> Signed-off-by: Huacai Chen <chenhuacai@loongson.cn> |
||
---|---|---|
.. | ||
.gitignore | ||
access-helper.h | ||
acpi.c | ||
alternative.c | ||
asm-offsets.c | ||
cacheinfo.c | ||
cpu-probe.c | ||
crash_dump.c | ||
dma.c | ||
efi-header.S | ||
efi.c | ||
elf.c | ||
entry.S | ||
env.c | ||
fpu.S | ||
ftrace_dyn.c | ||
ftrace.c | ||
genex.S | ||
head.S | ||
hw_breakpoint.c | ||
idle.c | ||
image-vars.h | ||
inst.c | ||
io.c | ||
irq.c | ||
jump_label.c | ||
kfpu.c | ||
kgdb.c | ||
kprobes.c | ||
lbt.S | ||
machine_kexec.c | ||
Makefile | ||
mcount_dyn.S | ||
mcount.S | ||
mem.c | ||
module-sections.c | ||
module.c | ||
numa.c | ||
paravirt.c | ||
perf_event.c | ||
perf_regs.c | ||
proc.c | ||
process.c | ||
ptrace.c | ||
relocate_kernel.S | ||
relocate.c | ||
reset.c | ||
rethook_trampoline.S | ||
rethook.c | ||
rethook.h | ||
setup.c | ||
signal.c | ||
smp.c | ||
stacktrace.c | ||
switch.S | ||
syscall.c | ||
sysrq.c | ||
time.c | ||
topology.c | ||
traps.c | ||
unaligned.c | ||
unwind_guess.c | ||
unwind_orc.c | ||
unwind_prologue.c | ||
unwind.c | ||
uprobes.c | ||
vdso.c | ||
vmlinux.lds.S |