aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMaciej W. Rozycki <macro@linux-mips.org>2015-04-03 18:26:27 -0400
committerRalf Baechle <ralf@linux-mips.org>2015-04-07 19:09:55 -0400
commitf6a31da50158c1003bd487968d89a6b27ff25bb6 (patch)
treef883c9f7596805819d84efd7b5ba5af913ae67ed
parent68893e0051419ccdc14fd6eafcdecc96533c6cc3 (diff)
MIPS: BREAK instruction interpretation corrections
Add the missing microMIPS BREAK16 instruction code interpretation and reshape code removing instruction fetching duplication and the separate call to `do_trap_or_bp' in the MIPS16 path. Signed-off-by: Maciej W. Rozycki <macro@linux-mips.org> Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/9696/ Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
-rw-r--r--arch/mips/kernel/traps.c36
1 files changed, 18 insertions, 18 deletions
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index b6f23343a8db..a671d3358eb6 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -901,10 +901,9 @@ void do_trap_or_bp(struct pt_regs *regs, unsigned int code,
901 901
902asmlinkage void do_bp(struct pt_regs *regs) 902asmlinkage void do_bp(struct pt_regs *regs)
903{ 903{
904 unsigned long epc = msk_isa16_mode(exception_epc(regs));
904 unsigned int opcode, bcode; 905 unsigned int opcode, bcode;
905 enum ctx_state prev_state; 906 enum ctx_state prev_state;
906 unsigned long epc;
907 u16 instr[2];
908 mm_segment_t seg; 907 mm_segment_t seg;
909 908
910 seg = get_fs(); 909 seg = get_fs();
@@ -913,26 +912,28 @@ asmlinkage void do_bp(struct pt_regs *regs)
913 912
914 prev_state = exception_enter(); 913 prev_state = exception_enter();
915 if (get_isa16_mode(regs->cp0_epc)) { 914 if (get_isa16_mode(regs->cp0_epc)) {
916 /* Calculate EPC. */ 915 u16 instr[2];
917 epc = exception_epc(regs); 916
918 if (cpu_has_mmips) { 917 if (__get_user(instr[0], (u16 __user *)epc))
919 if ((__get_user(instr[0], (u16 __user *)msk_isa16_mode(epc)) || 918 goto out_sigsegv;
920 (__get_user(instr[1], (u16 __user *)msk_isa16_mode(epc + 2))))) 919
921 goto out_sigsegv; 920 if (!cpu_has_mmips) {
922 opcode = (instr[0] << 16) | instr[1];
923 } else {
924 /* MIPS16e mode */ 921 /* MIPS16e mode */
925 if (__get_user(instr[0],
926 (u16 __user *)msk_isa16_mode(epc)))
927 goto out_sigsegv;
928 bcode = (instr[0] >> 5) & 0x3f; 922 bcode = (instr[0] >> 5) & 0x3f;
929 do_trap_or_bp(regs, bcode, "Break"); 923 } else if (mm_insn_16bit(instr[0])) {
930 goto out; 924 /* 16-bit microMIPS BREAK */
925 bcode = instr[0] & 0xf;
926 } else {
927 /* 32-bit microMIPS BREAK */
928 if (__get_user(instr[1], (u16 __user *)(epc + 2)))
929 goto out_sigsegv;
930 opcode = (instr[0] << 16) | instr[1];
931 bcode = (opcode >> 6) & ((1 << 20) - 1);
931 } 932 }
932 } else { 933 } else {
933 if (__get_user(opcode, 934 if (__get_user(opcode, (unsigned int __user *)epc))
934 (unsigned int __user *) exception_epc(regs)))
935 goto out_sigsegv; 935 goto out_sigsegv;
936 bcode = (opcode >> 6) & ((1 << 20) - 1);
936 } 937 }
937 938
938 /* 939 /*
@@ -941,7 +942,6 @@ asmlinkage void do_bp(struct pt_regs *regs)
941 * Gas is bug-compatible, but not always, grrr... 942 * Gas is bug-compatible, but not always, grrr...
942 * We handle both cases with a simple heuristics. --macro 943 * We handle both cases with a simple heuristics. --macro
943 */ 944 */
944 bcode = ((opcode >> 6) & ((1 << 20) - 1));
945 if (bcode >= (1 << 10)) 945 if (bcode >= (1 << 10))
946 bcode >>= 10; 946 bcode >>= 10;
947 947