Received: by 10.223.185.116 with SMTP id b49csp6405368wrg; Wed, 28 Feb 2018 08:53:13 -0800 (PST) X-Google-Smtp-Source: AG47ELteoT39L6ZnnjBnrMjvU/yrqrdO6DNS9iJop3COtWm23/KXZ/YQ6sOobmSUVsl14ABj9muD X-Received: by 10.99.170.5 with SMTP id e5mr6229135pgf.92.1519836792900; Wed, 28 Feb 2018 08:53:12 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1519836792; cv=none; d=google.com; s=arc-20160816; b=XxNZMgEgMevD1ObbN1NSYx92JnAaSShJKRGsjjY6luW235kCTyIxSKD+w23/KbJ1JK r+ftFb/l+502cCWq4ckIj4cz8SKmO867W4lG0MR1n7bRWu+afbBFkQ8uBbKtxtMZCof9 2T2MShm2vPrbbUsKRUwVUrwF6rP+OL5prUGhfHX328tPebMavKnqb4pn6NoGLS0gRbsZ ///eBfkp0zb4xzH05bLUD3zHc3T8tdrtQ505PmG8YrnV8bhcs2aHqEIUTBagS0RwGs9z ENUJK4Fr3GDpBRCfRLP1g1ujHuqMbOC0Li0Ne2G6D+XznKwjsY+iGBG/Rz4MC9npA6XZ T3/g== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:in-reply-to:subject:message-id:date:cc:to :from:mime-version:content-transfer-encoding:content-disposition :arc-authentication-results; bh=sLc/U8dSU8ZMx6KkjjmoqZ7hcm29p38qvP4M8LuOHTQ=; b=qXxIvnsi0uZI50ojBbqLohMZflL3XvlhjDgz0+AnHeD6UQdF9OK0xES1W3iwpPEFVL fWM9o6RgCkw32uXOTYOwtDDfTfH56u7uaPJSYE/oVnghY/z8RgllqbnwdS4rDALG9iHR 2A8RWbE3muFeJTozh7Z8uUKBXuqRCx81djz64mhTGwXHHehNP5toNPaqt5XZdIBcOqUU xRE8dWEjboMWO5tFVgAA7Giq8Q2iCh1LUyzw2Ldyv0A4utWZbCMrhUDqNCQZRsMWHP8W QwPY8IDEcmYGJgdNf++mDr8uy8lFfhV3jUbvfnZrfffew6Kl/Qy68wmp50PdiWL+00E9 CDuA== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id c10si1218685pgf.230.2018.02.28.08.52.57; Wed, 28 Feb 2018 08:53:12 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753023AbeB1Qu4 (ORCPT + 99 others); Wed, 28 Feb 2018 11:50:56 -0500 Received: from shadbolt.e.decadent.org.uk ([88.96.1.126]:34555 "EHLO shadbolt.e.decadent.org.uk" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753005AbeB1P6V (ORCPT ); Wed, 28 Feb 2018 10:58:21 -0500 Received: from [2a02:8011:400e:2:6f00:88c8:c921:d332] (helo=deadeye) by shadbolt.decadent.org.uk with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from ) id 1er3Yt-0006Xk-H0; Wed, 28 Feb 2018 15:22:31 +0000 Received: from ben by deadeye with local (Exim 4.90_1) (envelope-from ) id 1er3Yg-0008WK-8a; Wed, 28 Feb 2018 15:22:18 +0000 Content-Type: text/plain; charset="UTF-8" Content-Disposition: inline Content-Transfer-Encoding: 8bit MIME-Version: 1.0 From: Ben Hutchings To: linux-kernel@vger.kernel.org, stable@vger.kernel.org CC: akpm@linux-foundation.org, "Ralf Baechle" , "Maciej W. Rozycki" , linux-mips@linux-mips.org Date: Wed, 28 Feb 2018 15:20:18 +0000 Message-ID: X-Mailer: LinuxStableQueue (scripts by bwh) Subject: [PATCH 3.16 098/254] MIPS: Set `si_code' for SIGFPE signals sent from emulation too In-Reply-To: X-SA-Exim-Connect-IP: 2a02:8011:400e:2:6f00:88c8:c921:d332 X-SA-Exim-Mail-From: ben@decadent.org.uk X-SA-Exim-Scanned: No (on shadbolt.decadent.org.uk); SAEximRunCond expanded to false Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org 3.16.55-rc1 review patch. If anyone has any objections, please let me know. ------------------ From: "Maciej W. Rozycki" commit 304acb717e5b67cf56f05bc5b21123758e1f7ea0 upstream. Rework `process_fpemu_return' and move IEEE 754 exception interpretation there, from `do_fpe'. Record the cause bits set in FCSR before they are cleared and pass them through to `process_fpemu_return' so as to set `si_code' correctly too for SIGFPE signals sent from emulation rather than those issued by hardware with the FPE processor exception only. For simplicity `mipsr2_decoder' assumes `*fcr31' has been preinitialised and only sets it to anything if an FPU instruction has been emulated, which in turn is the only case SIGFPE can be issued for here. Signed-off-by: Maciej W. Rozycki Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/9705/ Signed-off-by: Ralf Baechle [bwh: Backported to 3.16: - Drop changes in mips-r2-to-r6-emul and simulate_fp() - Adjust context] Signed-off-by: Ben Hutchings --- --- a/arch/mips/include/asm/fpu_emulator.h +++ b/arch/mips/include/asm/fpu_emulator.h @@ -65,7 +65,8 @@ extern int do_dsemulret(struct pt_regs * extern int fpu_emulator_cop1Handler(struct pt_regs *xcp, struct mips_fpu_struct *ctx, int has_fpu, void *__user *fault_addr); -int process_fpemu_return(int sig, void __user *fault_addr); +int process_fpemu_return(int sig, void __user *fault_addr, + unsigned long fcr31); int mm_isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn, unsigned long *contpc); --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c @@ -707,29 +707,60 @@ asmlinkage void do_ov(struct pt_regs *re exception_exit(prev_state); } -int process_fpemu_return(int sig, void __user *fault_addr) +int process_fpemu_return(int sig, void __user *fault_addr, unsigned long fcr31) { - if (sig == SIGSEGV || sig == SIGBUS) { - struct siginfo si = {0}; + struct siginfo si = { 0 }; + + switch (sig) { + case 0: + return 0; + + case SIGFPE: 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; - } + /* + * Inexact can happen together with Overflow or Underflow. + * Respect the mask to deliver the correct exception. + */ + fcr31 &= (fcr31 & FPU_CSR_ALL_E) << + (ffs(FPU_CSR_ALL_X) - ffs(FPU_CSR_ALL_E)); + if (fcr31 & FPU_CSR_INV_X) + si.si_code = FPE_FLTINV; + else if (fcr31 & FPU_CSR_DIV_X) + si.si_code = FPE_FLTDIV; + else if (fcr31 & FPU_CSR_OVF_X) + si.si_code = FPE_FLTOVF; + else if (fcr31 & FPU_CSR_UDF_X) + si.si_code = FPE_FLTUND; + else if (fcr31 & FPU_CSR_INE_X) + si.si_code = FPE_FLTRES; + else + si.si_code = __SI_FAULT; + force_sig_info(sig, &si, current); + return 1; + + case SIGBUS: + si.si_addr = fault_addr; + si.si_signo = sig; + si.si_code = BUS_ADRERR; + force_sig_info(sig, &si, current); + return 1; + + case SIGSEGV: + si.si_addr = fault_addr; + si.si_signo = sig; + 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); force_sig_info(sig, &si, current); return 1; - } else if (sig) { + + default: force_sig(sig, current); return 1; - } else { - return 0; } } @@ -739,7 +770,8 @@ int process_fpemu_return(int sig, void _ asmlinkage void do_fpe(struct pt_regs *regs, unsigned long fcr31) { enum ctx_state prev_state; - siginfo_t info = {0}; + void __user *fault_addr; + int sig; prev_state = exception_enter(); if (notify_die(DIE_FP, "FP exception", regs, 0, regs_to_trapnr(regs), @@ -753,9 +785,6 @@ asmlinkage void do_fpe(struct pt_regs *r die_if_kernel("FP exception in kernel code", regs); if (fcr31 & FPU_CSR_UNI_X) { - int sig; - void __user *fault_addr = NULL; - /* * Unimplemented operation exception. If we've got the full * software emulator on-board, let's use it... @@ -772,6 +801,7 @@ asmlinkage void do_fpe(struct pt_regs *r /* Run the emulator */ sig = fpu_emulator_cop1Handler(regs, ¤t->thread.fpu, 1, &fault_addr); + fcr31 = current->thread.fpu.fcr31; /* * We can't allow the emulated instruction to leave any of @@ -781,35 +811,13 @@ asmlinkage void do_fpe(struct pt_regs *r /* Restore the hardware register state */ own_fpu(1); /* Using the FPU again. */ - - /* If something went wrong, signal */ - process_fpemu_return(sig, fault_addr); - - goto out; + } else { + sig = SIGFPE; + fault_addr = (void __user *) regs->cp0_epc; } - /* - * Inexact can happen together with Overflow or Underflow. - * Respect the mask to deliver the correct exception. - */ - fcr31 &= (fcr31 & FPU_CSR_ALL_E) << - (ffs(FPU_CSR_ALL_X) - ffs(FPU_CSR_ALL_E)); - if (fcr31 & FPU_CSR_INV_X) - info.si_code = FPE_FLTINV; - else if (fcr31 & FPU_CSR_DIV_X) - info.si_code = FPE_FLTDIV; - else if (fcr31 & FPU_CSR_OVF_X) - info.si_code = FPE_FLTOVF; - else if (fcr31 & FPU_CSR_UDF_X) - info.si_code = FPE_FLTUND; - else if (fcr31 & FPU_CSR_INE_X) - info.si_code = FPE_FLTRES; - else - info.si_code = __SI_FAULT; - info.si_signo = SIGFPE; - info.si_errno = 0; - info.si_addr = (void __user *) regs->cp0_epc; - force_sig_info(SIGFPE, &info, current); + /* Send a signal if required. */ + process_fpemu_return(sig, fault_addr, fcr31); out: exception_exit(prev_state); @@ -1210,10 +1218,13 @@ asmlinkage void do_cpu(struct pt_regs *r enum ctx_state prev_state; unsigned int __user *epc; unsigned long old_epc, old31; + void __user *fault_addr; unsigned int opcode; + unsigned long fcr31; unsigned int cpid; int status, err; unsigned long __maybe_unused flags; + int sig; prev_state = exception_enter(); cpid = (regs->cp0_cause >> CAUSEB_CE) & 3; @@ -1286,22 +1297,22 @@ asmlinkage void do_cpu(struct pt_regs *r case 1: err = enable_restore_fp_context(0); - if (!raw_cpu_has_fpu || err) { - int sig; - void __user *fault_addr = NULL; - sig = fpu_emulator_cop1Handler(regs, - ¤t->thread.fpu, - 0, &fault_addr); - - /* - * We can't allow the emulated instruction to leave - * any of the cause bits set in $fcr31. - */ - current->thread.fpu.fcr31 &= ~FPU_CSR_ALL_X; + if (raw_cpu_has_fpu && !err) + break; - if (!process_fpemu_return(sig, fault_addr) && !err) - mt_ase_fp_affinity(); - } + sig = fpu_emulator_cop1Handler(regs, ¤t->thread.fpu, 0, + &fault_addr); + fcr31 = current->thread.fpu.fcr31; + + /* + * We can't allow the emulated instruction to leave + * any of the cause bits set in $fcr31. + */ + current->thread.fpu.fcr31 &= ~FPU_CSR_ALL_X; + + /* Send a signal if required. */ + if (!process_fpemu_return(sig, fault_addr, fcr31) && !err) + mt_ase_fp_affinity(); goto out; --- a/arch/mips/kernel/unaligned.c +++ b/arch/mips/kernel/unaligned.c @@ -697,7 +697,7 @@ static void emulate_load_store_insn(stru own_fpu(1); /* Restore FPU state. */ /* Signal if something went wrong. */ - process_fpemu_return(res, fault_addr); + process_fpemu_return(res, fault_addr, 0); if (res == 0) break; @@ -1129,7 +1129,7 @@ fpu_emul: own_fpu(1); /* restore FPU state */ /* If something went wrong, signal */ - process_fpemu_return(res, fault_addr); + process_fpemu_return(res, fault_addr, 0); if (res == 0) goto success;