diff options
| author | Maciej W. Rozycki <macro@imgtec.com> | 2016-03-03 20:44:28 -0500 |
|---|---|---|
| committer | Ralf Baechle <ralf@linux-mips.org> | 2016-04-03 06:32:09 -0400 |
| commit | 3b143cca6e1397188f507a6c727f4108861ceb8b (patch) | |
| tree | 18d40c6731a2f8f385c3f2b6f285cde8408e235c | |
| parent | 748ac56bb9533f867b25325a805d64f52a1a3a88 (diff) | |
MIPS: traps: Correct the SIGTRAP debug ABI in `do_watch' and `do_trap_or_bp'
Follow our own rules set in <asm/siginfo.h> for SIGTRAP signals issued
from `do_watch' and `do_trap_or_bp' by setting the signal code to
TRAP_HWBKPT and TRAP_BRKPT respectively, for Watch exceptions and for
those Breakpoint exceptions whose originating BREAK instruction's code
does not have a special meaning. Keep Trap exceptions unaffected as
these are not debug events.
No existing user software is expected to examine signal codes for these
signals as SI_KERNEL has been always used here. This change makes the
MIPS port more like other Linux ports, which reduces the complexity and
provides for performance improvement in GDB.
Signed-off-by: Maciej W. Rozycki <macro@imgtec.com>
Cc: Pedro Alves <palves@redhat.com>
Cc: Luis Machado <lgustavo@codesourcery.com>
Cc: linux-mips@linux-mips.org
Cc: gdb@sourceware.org
Patchwork: https://patchwork.linux-mips.org/patch/12758/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
| -rw-r--r-- | arch/mips/include/asm/mips-r2-to-r6-emul.h | 2 | ||||
| -rw-r--r-- | arch/mips/kernel/mips-r2-to-r6-emul.c | 12 | ||||
| -rw-r--r-- | arch/mips/kernel/traps.c | 18 |
3 files changed, 20 insertions, 12 deletions
diff --git a/arch/mips/include/asm/mips-r2-to-r6-emul.h b/arch/mips/include/asm/mips-r2-to-r6-emul.h index 1f6ea8352ca9..20621e1ca238 100644 --- a/arch/mips/include/asm/mips-r2-to-r6-emul.h +++ b/arch/mips/include/asm/mips-r2-to-r6-emul.h | |||
| @@ -79,7 +79,7 @@ struct r2_decoder_table { | |||
| 79 | }; | 79 | }; |
| 80 | 80 | ||
| 81 | 81 | ||
| 82 | extern void do_trap_or_bp(struct pt_regs *regs, unsigned int code, | 82 | extern void do_trap_or_bp(struct pt_regs *regs, unsigned int code, int si_code, |
| 83 | const char *str); | 83 | const char *str); |
| 84 | 84 | ||
| 85 | #ifndef CONFIG_MIPSR2_TO_R6_EMULATOR | 85 | #ifndef CONFIG_MIPSR2_TO_R6_EMULATOR |
diff --git a/arch/mips/kernel/mips-r2-to-r6-emul.c b/arch/mips/kernel/mips-r2-to-r6-emul.c index 1f5aac7f9ec3..3fff89ae760b 100644 --- a/arch/mips/kernel/mips-r2-to-r6-emul.c +++ b/arch/mips/kernel/mips-r2-to-r6-emul.c | |||
| @@ -940,42 +940,42 @@ repeat: | |||
| 940 | switch (rt) { | 940 | switch (rt) { |
| 941 | case tgei_op: | 941 | case tgei_op: |
| 942 | if ((long)regs->regs[rs] >= MIPSInst_SIMM(inst)) | 942 | if ((long)regs->regs[rs] >= MIPSInst_SIMM(inst)) |
| 943 | do_trap_or_bp(regs, 0, "TGEI"); | 943 | do_trap_or_bp(regs, 0, 0, "TGEI"); |
| 944 | 944 | ||
| 945 | MIPS_R2_STATS(traps); | 945 | MIPS_R2_STATS(traps); |
| 946 | 946 | ||
| 947 | break; | 947 | break; |
| 948 | case tgeiu_op: | 948 | case tgeiu_op: |
| 949 | if (regs->regs[rs] >= MIPSInst_UIMM(inst)) | 949 | if (regs->regs[rs] >= MIPSInst_UIMM(inst)) |
| 950 | do_trap_or_bp(regs, 0, "TGEIU"); | 950 | do_trap_or_bp(regs, 0, 0, "TGEIU"); |
| 951 | 951 | ||
| 952 | MIPS_R2_STATS(traps); | 952 | MIPS_R2_STATS(traps); |
| 953 | 953 | ||
| 954 | break; | 954 | break; |
| 955 | case tlti_op: | 955 | case tlti_op: |
| 956 | if ((long)regs->regs[rs] < MIPSInst_SIMM(inst)) | 956 | if ((long)regs->regs[rs] < MIPSInst_SIMM(inst)) |
| 957 | do_trap_or_bp(regs, 0, "TLTI"); | 957 | do_trap_or_bp(regs, 0, 0, "TLTI"); |
| 958 | 958 | ||
| 959 | MIPS_R2_STATS(traps); | 959 | MIPS_R2_STATS(traps); |
| 960 | 960 | ||
| 961 | break; | 961 | break; |
| 962 | case tltiu_op: | 962 | case tltiu_op: |
| 963 | if (regs->regs[rs] < MIPSInst_UIMM(inst)) | 963 | if (regs->regs[rs] < MIPSInst_UIMM(inst)) |
| 964 | do_trap_or_bp(regs, 0, "TLTIU"); | 964 | do_trap_or_bp(regs, 0, 0, "TLTIU"); |
| 965 | 965 | ||
| 966 | MIPS_R2_STATS(traps); | 966 | MIPS_R2_STATS(traps); |
| 967 | 967 | ||
| 968 | break; | 968 | break; |
| 969 | case teqi_op: | 969 | case teqi_op: |
| 970 | if (regs->regs[rs] == MIPSInst_SIMM(inst)) | 970 | if (regs->regs[rs] == MIPSInst_SIMM(inst)) |
| 971 | do_trap_or_bp(regs, 0, "TEQI"); | 971 | do_trap_or_bp(regs, 0, 0, "TEQI"); |
| 972 | 972 | ||
| 973 | MIPS_R2_STATS(traps); | 973 | MIPS_R2_STATS(traps); |
| 974 | 974 | ||
| 975 | break; | 975 | break; |
| 976 | case tnei_op: | 976 | case tnei_op: |
| 977 | if (regs->regs[rs] != MIPSInst_SIMM(inst)) | 977 | if (regs->regs[rs] != MIPSInst_SIMM(inst)) |
| 978 | do_trap_or_bp(regs, 0, "TNEI"); | 978 | do_trap_or_bp(regs, 0, 0, "TNEI"); |
| 979 | 979 | ||
| 980 | MIPS_R2_STATS(traps); | 980 | MIPS_R2_STATS(traps); |
| 981 | 981 | ||
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index e701eb0aa99c..80339ce64521 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c | |||
| @@ -56,6 +56,7 @@ | |||
| 56 | #include <asm/pgtable.h> | 56 | #include <asm/pgtable.h> |
| 57 | #include <asm/ptrace.h> | 57 | #include <asm/ptrace.h> |
| 58 | #include <asm/sections.h> | 58 | #include <asm/sections.h> |
| 59 | #include <asm/siginfo.h> | ||
| 59 | #include <asm/tlbdebug.h> | 60 | #include <asm/tlbdebug.h> |
| 60 | #include <asm/traps.h> | 61 | #include <asm/traps.h> |
| 61 | #include <asm/uaccess.h> | 62 | #include <asm/uaccess.h> |
| @@ -871,7 +872,7 @@ out: | |||
| 871 | exception_exit(prev_state); | 872 | exception_exit(prev_state); |
| 872 | } | 873 | } |
| 873 | 874 | ||
| 874 | void do_trap_or_bp(struct pt_regs *regs, unsigned int code, | 875 | void do_trap_or_bp(struct pt_regs *regs, unsigned int code, int si_code, |
| 875 | const char *str) | 876 | const char *str) |
| 876 | { | 877 | { |
| 877 | siginfo_t info = { 0 }; | 878 | siginfo_t info = { 0 }; |
| @@ -928,7 +929,13 @@ void do_trap_or_bp(struct pt_regs *regs, unsigned int code, | |||
| 928 | default: | 929 | default: |
| 929 | scnprintf(b, sizeof(b), "%s instruction in kernel code", str); | 930 | scnprintf(b, sizeof(b), "%s instruction in kernel code", str); |
| 930 | die_if_kernel(b, regs); | 931 | die_if_kernel(b, regs); |
| 931 | force_sig(SIGTRAP, current); | 932 | if (si_code) { |
| 933 | info.si_signo = SIGTRAP; | ||
| 934 | info.si_code = si_code; | ||
| 935 | force_sig_info(SIGTRAP, &info, current); | ||
| 936 | } else { | ||
| 937 | force_sig(SIGTRAP, current); | ||
| 938 | } | ||
| 932 | } | 939 | } |
| 933 | } | 940 | } |
| 934 | 941 | ||
| @@ -1012,7 +1019,7 @@ asmlinkage void do_bp(struct pt_regs *regs) | |||
| 1012 | break; | 1019 | break; |
| 1013 | } | 1020 | } |
| 1014 | 1021 | ||
| 1015 | do_trap_or_bp(regs, bcode, "Break"); | 1022 | do_trap_or_bp(regs, bcode, TRAP_BRKPT, "Break"); |
| 1016 | 1023 | ||
| 1017 | out: | 1024 | out: |
| 1018 | set_fs(seg); | 1025 | set_fs(seg); |
| @@ -1054,7 +1061,7 @@ asmlinkage void do_tr(struct pt_regs *regs) | |||
| 1054 | tcode = (opcode >> 6) & ((1 << 10) - 1); | 1061 | tcode = (opcode >> 6) & ((1 << 10) - 1); |
| 1055 | } | 1062 | } |
| 1056 | 1063 | ||
| 1057 | do_trap_or_bp(regs, tcode, "Trap"); | 1064 | do_trap_or_bp(regs, tcode, 0, "Trap"); |
| 1058 | 1065 | ||
| 1059 | out: | 1066 | out: |
| 1060 | set_fs(seg); | 1067 | set_fs(seg); |
| @@ -1492,6 +1499,7 @@ asmlinkage void do_mdmx(struct pt_regs *regs) | |||
| 1492 | */ | 1499 | */ |
| 1493 | asmlinkage void do_watch(struct pt_regs *regs) | 1500 | asmlinkage void do_watch(struct pt_regs *regs) |
| 1494 | { | 1501 | { |
| 1502 | siginfo_t info = { .si_signo = SIGTRAP, .si_code = TRAP_HWBKPT }; | ||
| 1495 | enum ctx_state prev_state; | 1503 | enum ctx_state prev_state; |
| 1496 | u32 cause; | 1504 | u32 cause; |
| 1497 | 1505 | ||
| @@ -1512,7 +1520,7 @@ asmlinkage void do_watch(struct pt_regs *regs) | |||
| 1512 | if (test_tsk_thread_flag(current, TIF_LOAD_WATCH)) { | 1520 | if (test_tsk_thread_flag(current, TIF_LOAD_WATCH)) { |
| 1513 | mips_read_watch_registers(); | 1521 | mips_read_watch_registers(); |
| 1514 | local_irq_enable(); | 1522 | local_irq_enable(); |
| 1515 | force_sig(SIGTRAP, current); | 1523 | force_sig_info(SIGTRAP, &info, current); |
| 1516 | } else { | 1524 | } else { |
| 1517 | mips_clear_watch_registers(); | 1525 | mips_clear_watch_registers(); |
| 1518 | local_irq_enable(); | 1526 | local_irq_enable(); |
