[linux] 01/01: [mips*] Backport math emulation fix from 4.5.

debian-kernel at lists.debian.org debian-kernel at lists.debian.org
Wed Jan 27 21:33:52 UTC 2016


This is an automated email from the git hooks/post-receive script.

aurel32 pushed a commit to branch sid
in repository linux.

commit 237b83662e0640933bb89d2272746ac5489d1858
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Wed Jan 27 22:33:18 2016 +0100

    [mips*] Backport math emulation fix from 4.5.
---
 debian/changelog                                   |   3 +
 ...s-math-emu-correctly-handle-nop-emulation.patch | 140 +++++++++++++++++++++
 debian/patches/series                              |   1 +
 3 files changed, 144 insertions(+)

diff --git a/debian/changelog b/debian/changelog
index b529baa..2e6203d 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -59,6 +59,9 @@ linux (4.3.4-1) UNRELEASED; urgency=medium
   * tcp: fix zero cwnd in tcp_cwnd_reduction (CVE-2016-2070)
   * netfilter: nf_nat_redirect: add missing NULL pointer check (CVE-2015-8787)
 
+  [ Aurelien Jarno ]
+  * [mips*] Backport math emulation fix from 4.5.
+
  -- Ben Hutchings <ben at decadent.org.uk>  Sat, 23 Jan 2016 11:51:46 +0000
 
 linux (4.3.3-7) unstable; urgency=medium
diff --git a/debian/patches/bugfix/mips/mips-math-emu-correctly-handle-nop-emulation.patch b/debian/patches/bugfix/mips/mips-math-emu-correctly-handle-nop-emulation.patch
new file mode 100644
index 0000000..cb2e904
--- /dev/null
+++ b/debian/patches/bugfix/mips/mips-math-emu-correctly-handle-nop-emulation.patch
@@ -0,0 +1,140 @@
+From: "Maciej W. Rozycki" <macro at imgtec.com>
+Date: Fri, 22 Jan 2016 05:20:26 +0000
+Subject: MIPS: math-emu: Correctly handle NOP emulation
+Origin: https://git.kernel.org/linus/e4553573b37c3f72533683cb5f3a1ad300b18d37
+
+Fix an issue introduced with commit 9ab4471c9f1b ("MIPS: math-emu:
+Correct delay-slot exception propagation") where the emulation of a NOP
+instruction signals the need to terminate the emulation loop.  This in
+turn, if the PC has not changed from the entry to the loop, will cause
+the kernel to terminate the program with SIGILL.
+
+Consider this program:
+
+static double div(double d)
+{
+	do
+		d /= 2.0;
+	while (d > .5);
+	return d;
+}
+
+int main(int argc, char **argv)
+{
+	return div(argc);
+}
+
+which gets compiled to the following binary code:
+
+00400490 <main>:
+  400490:	44840000 	mtc1	a0,$f0
+  400494:	3c020040 	lui	v0,0x40
+  400498:	d44207f8 	ldc1	$f2,2040(v0)
+  40049c:	46800021 	cvt.d.w	$f0,$f0
+  4004a0:	46220002 	mul.d	$f0,$f0,$f2
+  4004a4:	4620103c 	c.lt.d	$f2,$f0
+  4004a8:	4501fffd 	bc1t	4004a0 <main+0x10>
+  4004ac:	00000000 	nop
+  4004b0:	4620000d 	trunc.w.d	$f0,$f0
+  4004b4:	03e00008 	jr	ra
+  4004b8:	44020000 	mfc1	v0,$f0
+  4004bc:	00000000 	nop
+
+Where the FPU emulator is used, depending on the number of command-line
+arguments this code will either run to completion or terminate with
+SIGILL.
+
+If no arguments are specified, then BC1T will not be taken, NOP will not
+be emulated and code will complete successfully.
+
+If one argument is specified, then BC1T will be taken once and NOP will
+be emulated.  At this point the entry PC value will be 0x400498 and the
+new PC value, set by `mips_dsemul' will be 0x4004a0, the target of BC1T.
+The emulation loop will terminate, but SIGILL will not be issued,
+because the PC has changed.  The FPU emulator will be entered again and
+on the second execution BC1T will not be taken, NOP will not be emulated
+and code will complete successfully.
+
+If two or more arguments are specified, then the first execution of BC1T
+will proceed as above.  Upon reentering the FPU emulator the emulation
+loop will continue to BC1T, at which point the branch will be taken and
+NOP emulated again.  At this point however the entry PC value will be
+0x4004a0, the same as the target of BC1T.  This will make the emulator
+conclude that execution has not advanced and therefore an unsupported
+FPU instruction has been encountered, and SIGILL will be sent to the
+process.
+
+Fix the problem by extending the internal API of `mips_dsemul', making
+it return -1 if no delay slot emulation frame has been made, the
+instruction has been handled and execution of the emulation loop needs
+to continue as if nothing happened.  Remove code from `mips_dsemul' to
+reproduce steps made by the emulation loop at the conclusion of each
+iteration, as those will be reached normally now.  Adjust call sites
+accordingly.  Document the API.
+
+Signed-off-by: Maciej W. Rozycki <macro at imgtec.com>
+Cc: Aurelien Jarno <aurelien at aurel32.net>
+Cc: linux-mips at linux-mips.org
+Patchwork: https://patchwork.linux-mips.org/patch/12172/
+Signed-off-by: Ralf Baechle <ralf at linux-mips.org>
+---
+ arch/mips/math-emu/cp1emu.c |  4 ++++
+ arch/mips/math-emu/dsemul.c | 14 ++++++++------
+ 2 files changed, 12 insertions(+), 6 deletions(-)
+
+diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c
+index 32f0e19..cdfd44f 100644
+--- a/arch/mips/math-emu/cp1emu.c
++++ b/arch/mips/math-emu/cp1emu.c
+@@ -1266,6 +1266,8 @@ branch_common:
+ 						 */
+ 						sig = mips_dsemul(xcp, ir,
+ 								  contpc);
++						if (sig < 0)
++							break;
+ 						if (sig)
+ 							xcp->cp0_epc = bcpc;
+ 						/*
+@@ -1319,6 +1321,8 @@ branch_common:
+ 				 * instruction in the dslot
+ 				 */
+ 				sig = mips_dsemul(xcp, ir, contpc);
++				if (sig < 0)
++					break;
+ 				if (sig)
+ 					xcp->cp0_epc = bcpc;
+ 				/* SIGILL forces out of the emulation loop.  */
+diff --git a/arch/mips/math-emu/dsemul.c b/arch/mips/math-emu/dsemul.c
+index cbb36c1..70e4824 100644
+--- a/arch/mips/math-emu/dsemul.c
++++ b/arch/mips/math-emu/dsemul.c
+@@ -31,18 +31,20 @@ struct emuframe {
+ 	unsigned long		epc;
+ };
+ 
++/*
++ * Set up an emulation frame for instruction IR, from a delay slot of
++ * a branch jumping to CPC.  Return 0 if successful, -1 if no emulation
++ * required, otherwise a signal number causing a frame setup failure.
++ */
+ int mips_dsemul(struct pt_regs *regs, mips_instruction ir, unsigned long cpc)
+ {
+ 	struct emuframe __user *fr;
+ 	int err;
+ 
++	/* NOP is easy */
+ 	if ((get_isa16_mode(regs->cp0_epc) && ((ir >> 16) == MM_NOP16)) ||
+-		(ir == 0)) {
+-		/* NOP is easy */
+-		regs->cp0_epc = cpc;
+-		clear_delay_slot(regs);
+-		return 0;
+-	}
++	    (ir == 0))
++		return -1;
+ 
+ 	pr_debug("dsemul %lx %lx\n", regs->cp0_epc, cpc);
+ 
+-- 
+2.7.0.rc3
+
diff --git a/debian/patches/series b/debian/patches/series
index a202989..6c7346b 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -51,6 +51,7 @@ bugfix/x86/drm-i915-shut-up-gen8-sde-irq-dmesg-noise.patch
 bugfix/arm/arm-dts-kirkwood-fix-qnap-ts219-power-off.patch
 bugfix/x86/drm-i915-mark-uneven-memory-banks-on-gen4-desktop-as.patch
 bugfix/x86/bios-return-actual-size-of-the-buffer-retrieved-via-_rom.patch
+bugfix/mips/mips-math-emu-correctly-handle-nop-emulation.patch
 
 # Arch features
 features/mips/MIPS-increase-MAX-PHYSMEM-BITS-on-Loongson-3-only.patch

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/kernel/linux.git



More information about the Kernel-svn-changes mailing list