linux/arch
Maciej W. Rozycki e4553573b3 MIPS: math-emu: Correctly handle NOP emulation
Fix an issue introduced with commit 9ab4471c9f ("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@imgtec.com>
Cc: Aurelien Jarno <aurelien@aurel32.net>
Cc: linux-mips@linux-mips.org
Patchwork: https://patchwork.linux-mips.org/patch/12172/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
2016-01-24 01:34:47 +01:00
..
alpha mm: mlock: add mlock flags to enable VM_LOCKONFAULT usage 2015-11-05 19:34:48 -08:00
arc ARC: dw2 unwind: Catch Dwarf SNAFUs early 2015-12-21 14:01:49 +05:30
arm [PATCH] arm: fix handling of F_OFD_... in oabi_fcntl64() 2015-12-29 13:04:21 -05:00
arm64 Merge branch 'irq-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip 2015-12-13 12:41:10 -08:00
avr32 dmaengine updates for 4.4-rc1 2015-11-10 10:05:17 -08:00
blackfin treewide: Remove old email address 2015-11-23 09:44:58 +01:00
c6x
cris cris: Drop reference to get_cmos_time() 2015-11-02 20:03:05 +01:00
frv kmap_atomic_to_page() has no users, remove it 2015-11-09 15:11:24 -08:00
h8300 h8300 update for v4.4 2015-11-12 15:26:39 -08:00
hexagon
ia64 [IA64] Enable mlock2 syscall for ia64 2015-12-14 10:30:02 -08:00
m32r m32r: add io*_rep helpers 2015-12-29 17:45:49 -08:00
m68k m68k: Wire up mlock2 2015-11-22 11:35:26 +01:00
metag Metag architecture changes for v4.4 2015-11-10 16:24:25 -08:00
microblaze Revert "scatterlist: use sg_phys()" 2015-12-15 12:54:06 -08:00
mips MIPS: math-emu: Correctly handle NOP emulation 2016-01-24 01:34:47 +01:00
mn10300 mn10300: Select CONFIG_HAVE_UID16 to fix build failure 2015-11-30 07:01:40 -08:00
nios2 nios2: fix cache coherency 2015-11-26 22:25:58 +08:00
openrisc
parisc parisc: Fix syscall restarts 2015-12-21 10:16:18 +01:00
powerpc KVM/ARM fixes for v4.4-rc7 2015-12-22 15:47:39 -08:00
s390 s390/dis: Fix handling of format specifiers 2015-12-18 14:43:21 +01:00
score
sh sh64: fix __NR_fgetxattr 2015-12-12 10:15:34 -08:00
sparc sparc: Wire up mlock2 system call. 2015-12-31 15:38:56 -05:00
tile treewide: Remove old email address 2015-11-23 09:44:58 +01:00
um um: fix returns without va_end 2015-12-08 22:26:00 +01:00
unicore32 pwm: Changes for v4.4-rc1 2015-11-11 09:16:10 -08:00
x86 arch/x86/xen/suspend.c: include xen/xen.h 2015-12-29 17:45:49 -08:00
xtensa Merge branch 'for-4.4/io-poll' of git://git.kernel.dk/linux-block 2015-11-10 17:23:49 -08:00
.gitignore
Kconfig