From 41ca86e8502952116234fa558f4277092a5aaae9 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Thu, 22 May 2014 23:19:00 +0200 Subject: MIPS: Fix branch emulation of branch likely instructions. Two issues: o For beql_op, beql_op, bne_op, bnel_op, blez_op, blezl_op, bgtz_op and bgtzl_op the wrong field was being checked for the instruction opcode. o For blez_op / blezl_op and bgtz_op / bgtzl_op the test was testing for the wrong opcode. This bug got introduced by d8d4e3ae0b5c179c0bfd3f0af5b352d13bea9cfa [MIPS Kprobes: Refactor branch emulation]. Signed-off-by: Ralf Baechle Acked-by: Leonid Yegoshin Acked-by: Victor Kamensky --- arch/mips/kernel/branch.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'arch/mips/kernel') diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c index 4d78bf445a9c..76122ff5cb5e 100644 --- a/arch/mips/kernel/branch.c +++ b/arch/mips/kernel/branch.c @@ -317,7 +317,7 @@ int __compute_return_epc_for_insn(struct pt_regs *regs, if (regs->regs[insn.i_format.rs] == regs->regs[insn.i_format.rt]) { epc = epc + 4 + (insn.i_format.simmediate << 2); - if (insn.i_format.rt == beql_op) + if (insn.i_format.opcode == beql_op) ret = BRANCH_LIKELY_TAKEN; } else epc += 8; @@ -329,7 +329,7 @@ int __compute_return_epc_for_insn(struct pt_regs *regs, if (regs->regs[insn.i_format.rs] != regs->regs[insn.i_format.rt]) { epc = epc + 4 + (insn.i_format.simmediate << 2); - if (insn.i_format.rt == bnel_op) + if (insn.i_format.opcode == bnel_op) ret = BRANCH_LIKELY_TAKEN; } else epc += 8; @@ -341,7 +341,7 @@ int __compute_return_epc_for_insn(struct pt_regs *regs, /* rt field assumed to be zero */ if ((long)regs->regs[insn.i_format.rs] <= 0) { epc = epc + 4 + (insn.i_format.simmediate << 2); - if (insn.i_format.rt == bnel_op) + if (insn.i_format.opcode == blezl_op) ret = BRANCH_LIKELY_TAKEN; } else epc += 8; @@ -353,7 +353,7 @@ int __compute_return_epc_for_insn(struct pt_regs *regs, /* rt field assumed to be zero */ if ((long)regs->regs[insn.i_format.rs] > 0) { epc = epc + 4 + (insn.i_format.simmediate << 2); - if (insn.i_format.rt == bnel_op) + if (insn.i_format.opcode == bgtzl_op) ret = BRANCH_LIKELY_TAKEN; } else epc += 8; -- cgit From 721a9205396c4ef2a811dd665ec2a232163b583d Mon Sep 17 00:00:00 2001 From: Markos Chandras Date: Wed, 21 May 2014 12:35:00 +0100 Subject: MIPS: Fix typo when reporting cache and ftlb errors for ImgTec cores Introduced by the following two commits: 75b5b5e0a262790fa11043fe45700499c7e3d818 "MIPS: Add support for FTLBs" 6de20451857ed14a4eecc28d08f6de5925d1cf96 "MIPS: Add printing of ES bit for Imgtec cores when cache error occurs" Signed-off-by: Markos Chandras Reported-by: Matheus Almeida Cc: linux-mips@linux-mips.org Cc: Markos Chandras Cc: stable@vger.kernel.org # v3.14+ Patchwork: https://patchwork.linux-mips.org/patch/6980/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/traps.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch/mips/kernel') diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index 074e857ced28..8119ac2fdfc9 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c @@ -1545,7 +1545,7 @@ asmlinkage void cache_parity_error(void) reg_val & (1<<30) ? "secondary" : "primary", reg_val & (1<<31) ? "data" : "insn"); if (cpu_has_mips_r2 && - ((current_cpu_data.processor_id && 0xff0000) == PRID_COMP_MIPS)) { + ((current_cpu_data.processor_id & 0xff0000) == PRID_COMP_MIPS)) { pr_err("Error bits: %s%s%s%s%s%s%s%s\n", reg_val & (1<<29) ? "ED " : "", reg_val & (1<<28) ? "ET " : "", @@ -1585,7 +1585,7 @@ asmlinkage void do_ftlb(void) /* For the moment, report the problem and hang. */ if (cpu_has_mips_r2 && - ((current_cpu_data.processor_id && 0xff0000) == PRID_COMP_MIPS)) { + ((current_cpu_data.processor_id & 0xff0000) == PRID_COMP_MIPS)) { pr_err("FTLB error exception, cp0_ecc=0x%08x:\n", read_c0_ecc()); pr_err("cp0_errorepc == %0*lx\n", field, read_c0_errorepc()); -- cgit From 57c7ea513f0e4b033ba602550992e2ca0e6b8d2c Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Thu, 1 May 2014 12:51:19 +0100 Subject: MIPS: ptrace: Avoid smp_processor_id() in preemptible code ptrace_{get,set}_watch_regs access current_cpu_data to get the watch register count/masks, which calls smp_processor_id(). However they are run in preemptible context and therefore trigger warnings like so: [ 6340.092000] BUG: using smp_processor_id() in preemptible [00000000] code: gdb/367 [ 6340.092000] caller is ptrace_get_watch_regs+0x44/0x220 Since the watch register count/masks should be the same across all CPUs, use boot_cpu_data instead. Note that this may need to change in future should a heterogenous system be supported where the count/masks are not the same across all CPUs (the current code is also incorrect for this scenario - current_cpu_data here would not necessarily be correct for the CPU that the target task will execute on). Signed-off-by: Alex Smith Reviewed-by: Paul Burton Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/6879/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/ptrace.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'arch/mips/kernel') diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c index 71f85f427034..f639ccd5060c 100644 --- a/arch/mips/kernel/ptrace.c +++ b/arch/mips/kernel/ptrace.c @@ -163,7 +163,7 @@ int ptrace_get_watch_regs(struct task_struct *child, enum pt_watch_style style; int i; - if (!cpu_has_watch || current_cpu_data.watch_reg_use_cnt == 0) + if (!cpu_has_watch || boot_cpu_data.watch_reg_use_cnt == 0) return -EIO; if (!access_ok(VERIFY_WRITE, addr, sizeof(struct pt_watch_regs))) return -EIO; @@ -177,14 +177,14 @@ int ptrace_get_watch_regs(struct task_struct *child, #endif __put_user(style, &addr->style); - __put_user(current_cpu_data.watch_reg_use_cnt, + __put_user(boot_cpu_data.watch_reg_use_cnt, &addr->WATCH_STYLE.num_valid); - for (i = 0; i < current_cpu_data.watch_reg_use_cnt; i++) { + for (i = 0; i < boot_cpu_data.watch_reg_use_cnt; i++) { __put_user(child->thread.watch.mips3264.watchlo[i], &addr->WATCH_STYLE.watchlo[i]); __put_user(child->thread.watch.mips3264.watchhi[i] & 0xfff, &addr->WATCH_STYLE.watchhi[i]); - __put_user(current_cpu_data.watch_reg_masks[i], + __put_user(boot_cpu_data.watch_reg_masks[i], &addr->WATCH_STYLE.watch_masks[i]); } for (; i < 8; i++) { @@ -204,12 +204,12 @@ int ptrace_set_watch_regs(struct task_struct *child, unsigned long lt[NUM_WATCH_REGS]; u16 ht[NUM_WATCH_REGS]; - if (!cpu_has_watch || current_cpu_data.watch_reg_use_cnt == 0) + if (!cpu_has_watch || boot_cpu_data.watch_reg_use_cnt == 0) return -EIO; if (!access_ok(VERIFY_READ, addr, sizeof(struct pt_watch_regs))) return -EIO; /* Check the values. */ - for (i = 0; i < current_cpu_data.watch_reg_use_cnt; i++) { + for (i = 0; i < boot_cpu_data.watch_reg_use_cnt; i++) { __get_user(lt[i], &addr->WATCH_STYLE.watchlo[i]); #ifdef CONFIG_32BIT if (lt[i] & __UA_LIMIT) @@ -228,7 +228,7 @@ int ptrace_set_watch_regs(struct task_struct *child, return -EINVAL; } /* Install them. */ - for (i = 0; i < current_cpu_data.watch_reg_use_cnt; i++) { + for (i = 0; i < boot_cpu_data.watch_reg_use_cnt; i++) { if (lt[i] & 7) watch_active = 1; child->thread.watch.mips3264.watchlo[i] = lt[i]; -- cgit From f7a89f1b8eb598ac5da61c9795b3d847baa73d12 Mon Sep 17 00:00:00 2001 From: Davidlohr Bueso Date: Sat, 19 Apr 2014 19:26:28 -0700 Subject: MIPS: Call find_vma with the mmap_sem held Performing vma lookups without taking the mm->mmap_sem is asking for trouble. While doing the search, the vma in question can be modified or even removed before returning to the caller. Take the lock (exclusively) in order to avoid races while iterating through the vmacache and/or rbtree. Updates two functions: - process_fpemu_return() - cteon_flush_cache_sigtramp() Signed-off-by: Davidlohr Bueso Tested-by: Andreas Herrmann Cc: linux-mips@linux-mips.org Cc: akpm@linux-foundation.org Cc: zeus@gnu.org Cc: aswin@hp.com Cc: davidlohr@hp.com Cc: linux-mm@kvack.org Cc: linux-kernel@vger.kernel.org Patchwork: http://patchwork.linux-mips.org/patch/6811/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/traps.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'arch/mips/kernel') diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index 8119ac2fdfc9..d57fc10df773 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c @@ -712,10 +712,12 @@ int process_fpemu_return(int sig, void __user *fault_addr) si.si_addr = fault_addr; si.si_signo = sig; if (sig == SIGSEGV) { + down_read(¤t->mm->mmap_sem); if (find_vma(current->mm, (unsigned long)fault_addr)) si.si_code = SEGV_ACCERR; else si.si_code = SEGV_MAPERR; + up_read(¤t->mm->mmap_sem); } else { si.si_code = BUS_ADRERR; } -- cgit