Skip to content

Commit f63a47b

Browse files
lhloongsonchenhuacai
authored andcommitted
LoongArch: Fix watchpoint setting error
In the current code, when debugging the following code using gdb, "invalid argument ..." message will be displayed. lihui@bogon:~$ cat test.c #include <stdio.h> int a = 0; int main() { a = 1; return 0; } lihui@bogon:~$ gcc -g test.c -o test lihui@bogon:~$ gdb test ... (gdb) watch a Hardware watchpoint 1: a (gdb) r ... Invalid argument setting hardware debug registers There are mainly two types of issues. 1. Some incorrect judgment condition existed in user_watch_state argument parsing, causing -EINVAL to be returned. When setting up a watchpoint, gdb uses the ptrace interface, ptrace(PTRACE_SETREGSET, tid, NT_LOONGARCH_HW_WATCH, (void *) &iov)). Register values in user_watch_state as follows: addr[0] = 0x0, mask[0] = 0x0, ctrl[0] = 0x0 addr[1] = 0x0, mask[1] = 0x0, ctrl[1] = 0x0 addr[2] = 0x0, mask[2] = 0x0, ctrl[2] = 0x0 addr[3] = 0x0, mask[3] = 0x0, ctrl[3] = 0x0 addr[4] = 0x0, mask[4] = 0x0, ctrl[4] = 0x0 addr[5] = 0x0, mask[5] = 0x0, ctrl[5] = 0x0 addr[6] = 0x0, mask[6] = 0x0, ctrl[6] = 0x0 addr[7] = 0x12000803c, mask[7] = 0x0, ctrl[7] = 0x610 In arch_bp_generic_fields(), return -EINVAL when ctrl.len is LOONGARCH_BREAKPOINT_LEN_8(0b00). So delete the incorrect judgment here. In ptrace_hbp_fill_attr_ctrl(), when note_type is NT_LOONGARCH_HW_WATCH and ctrl[0] == 0x0, if ((type & HW_BREAKPOINT_RW) != type) will return -EINVAL. Here ctrl.type should be set based on note_type, and unnecessary judgments can be removed. 2. The watchpoint argument was not set correctly due to unnecessary offset and alignment_mask. Modify ptrace_hbp_fill_attr_ctrl() and hw_breakpoint_arch_parse(), which ensure the watchpont argument is set correctly. 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 Cc: [email protected] Signed-off-by: Hui Li <[email protected]> Signed-off-by: Huacai Chen <[email protected]>
1 parent 120dd41 commit f63a47b

File tree

3 files changed

+21
-32
lines changed

3 files changed

+21
-32
lines changed

arch/loongarch/include/asm/hw_breakpoint.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ struct perf_event;
101101
struct perf_event_attr;
102102

103103
extern int arch_bp_generic_fields(struct arch_hw_breakpoint_ctrl ctrl,
104-
int *gen_len, int *gen_type, int *offset);
104+
int *gen_len, int *gen_type);
105105
extern int arch_check_bp_in_kernelspace(struct arch_hw_breakpoint *hw);
106106
extern int hw_breakpoint_arch_parse(struct perf_event *bp,
107107
const struct perf_event_attr *attr,

arch/loongarch/kernel/hw_breakpoint.c

Lines changed: 5 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -283,7 +283,7 @@ int arch_check_bp_in_kernelspace(struct arch_hw_breakpoint *hw)
283283
* to generic breakpoint descriptions.
284284
*/
285285
int arch_bp_generic_fields(struct arch_hw_breakpoint_ctrl ctrl,
286-
int *gen_len, int *gen_type, int *offset)
286+
int *gen_len, int *gen_type)
287287
{
288288
/* Type */
289289
switch (ctrl.type) {
@@ -303,11 +303,6 @@ int arch_bp_generic_fields(struct arch_hw_breakpoint_ctrl ctrl,
303303
return -EINVAL;
304304
}
305305

306-
if (!ctrl.len)
307-
return -EINVAL;
308-
309-
*offset = __ffs(ctrl.len);
310-
311306
/* Len */
312307
switch (ctrl.len) {
313308
case LOONGARCH_BREAKPOINT_LEN_1:
@@ -386,21 +381,17 @@ int hw_breakpoint_arch_parse(struct perf_event *bp,
386381
struct arch_hw_breakpoint *hw)
387382
{
388383
int ret;
389-
u64 alignment_mask, offset;
384+
u64 alignment_mask;
390385

391386
/* Build the arch_hw_breakpoint. */
392387
ret = arch_build_bp_info(bp, attr, hw);
393388
if (ret)
394389
return ret;
395390

396-
if (hw->ctrl.type != LOONGARCH_BREAKPOINT_EXECUTE)
397-
alignment_mask = 0x7;
398-
else
391+
if (hw->ctrl.type == LOONGARCH_BREAKPOINT_EXECUTE) {
399392
alignment_mask = 0x3;
400-
offset = hw->address & alignment_mask;
401-
402-
hw->address &= ~alignment_mask;
403-
hw->ctrl.len <<= offset;
393+
hw->address &= ~alignment_mask;
394+
}
404395

405396
return 0;
406397
}

arch/loongarch/kernel/ptrace.c

Lines changed: 15 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -494,28 +494,14 @@ static int ptrace_hbp_fill_attr_ctrl(unsigned int note_type,
494494
struct arch_hw_breakpoint_ctrl ctrl,
495495
struct perf_event_attr *attr)
496496
{
497-
int err, len, type, offset;
497+
int err, len, type;
498498

499-
err = arch_bp_generic_fields(ctrl, &len, &type, &offset);
499+
err = arch_bp_generic_fields(ctrl, &len, &type);
500500
if (err)
501501
return err;
502502

503-
switch (note_type) {
504-
case NT_LOONGARCH_HW_BREAK:
505-
if ((type & HW_BREAKPOINT_X) != type)
506-
return -EINVAL;
507-
break;
508-
case NT_LOONGARCH_HW_WATCH:
509-
if ((type & HW_BREAKPOINT_RW) != type)
510-
return -EINVAL;
511-
break;
512-
default:
513-
return -EINVAL;
514-
}
515-
516503
attr->bp_len = len;
517504
attr->bp_type = type;
518-
attr->bp_addr += offset;
519505

520506
return 0;
521507
}
@@ -609,7 +595,19 @@ static int ptrace_hbp_set_ctrl(unsigned int note_type,
609595
return PTR_ERR(bp);
610596

611597
attr = bp->attr;
612-
decode_ctrl_reg(uctrl, &ctrl);
598+
599+
switch (note_type) {
600+
case NT_LOONGARCH_HW_BREAK:
601+
ctrl.type = LOONGARCH_BREAKPOINT_EXECUTE;
602+
ctrl.len = LOONGARCH_BREAKPOINT_LEN_4;
603+
break;
604+
case NT_LOONGARCH_HW_WATCH:
605+
decode_ctrl_reg(uctrl, &ctrl);
606+
break;
607+
default:
608+
return -EINVAL;
609+
}
610+
613611
err = ptrace_hbp_fill_attr_ctrl(note_type, ctrl, &attr);
614612
if (err)
615613
return err;

0 commit comments

Comments
 (0)