about summary refs log tree commit diff
diff options
context:
space:
mode:
authorLluís Batlle i Rossell <viric@vicerveza.homeunix.net>2012-06-16 10:49:03 +0000
committerLluís Batlle i Rossell <viric@vicerveza.homeunix.net>2012-06-16 10:49:03 +0000
commit3874e5812d6cf07b6ee778c3f58df73b913bae93 (patch)
tree2d445bca9d35f58b5d02365fe166c9b2fb94d2d0
parent404c21de2fa7ec36e92504f36a3dce95f8114704 (diff)
downloadnixlib-3874e5812d6cf07b6ee778c3f58df73b913bae93.tar
nixlib-3874e5812d6cf07b6ee778c3f58df73b913bae93.tar.gz
nixlib-3874e5812d6cf07b6ee778c3f58df73b913bae93.tar.bz2
nixlib-3874e5812d6cf07b6ee778c3f58df73b913bae93.tar.lz
nixlib-3874e5812d6cf07b6ee778c3f58df73b913bae93.tar.xz
nixlib-3874e5812d6cf07b6ee778c3f58df73b913bae93.tar.zst
nixlib-3874e5812d6cf07b6ee778c3f58df73b913bae93.zip
Adding two kernel patches for mips, that make the life easier on loongson2f
(less sigill, less sigbus). Related to bad handling of FPU instructions.

I apply them only to linux 3.4, although I think they can apply to many older kernels too.


svn path=/nixpkgs/trunk/; revision=34522
-rw-r--r--pkgs/os-specific/linux/kernel/mips-fpu-sigill.patch108
-rw-r--r--pkgs/os-specific/linux/kernel/mips-fpureg-emulation.patch144
-rw-r--r--pkgs/os-specific/linux/kernel/patches.nix10
-rw-r--r--pkgs/top-level/all-packages.nix3
4 files changed, 265 insertions, 0 deletions
diff --git a/pkgs/os-specific/linux/kernel/mips-fpu-sigill.patch b/pkgs/os-specific/linux/kernel/mips-fpu-sigill.patch
new file mode 100644
index 000000000000..5a54f77dcb85
--- /dev/null
+++ b/pkgs/os-specific/linux/kernel/mips-fpu-sigill.patch
@@ -0,0 +1,108 @@
+From bf55ef4e3c2f622ac013f196affbd11b67b59223 Mon Sep 17 00:00:00 2001
+From: Mark H Weaver <mhw@netris.org>
+Date: Fri, 28 Oct 2011 13:24:37 -0400
+Subject: [PATCH 2/4] Fix handling of prefx instruction in mips/math-emu
+
+* The instruction is named prefx, not pfetch, and its function
+  field is 0x17, not 0x07.
+
+* Recognize the prefx instruction regardless of what bits happen to be
+  in bits 21-25, which is the format field of the floating-point ops,
+  but holds the base register of the prefx instruction.
+---
+ arch/mips/include/asm/inst.h |    4 ++--
+ arch/mips/math-emu/cp1emu.c  |   16 +++++++---------
+ 2 files changed, 9 insertions(+), 11 deletions(-)
+
+diff --git a/arch/mips/include/asm/inst.h b/arch/mips/include/asm/inst.h
+index ab84064..3048edc 100644
+--- a/arch/mips/include/asm/inst.h
++++ b/arch/mips/include/asm/inst.h
+@@ -161,8 +161,8 @@ enum cop1_sdw_func {
+  */
+ enum cop1x_func {
+ 	lwxc1_op     =  0x00, ldxc1_op     =  0x01,
+-	pfetch_op    =  0x07, swxc1_op     =  0x08,
+-	sdxc1_op     =  0x09, madd_s_op    =  0x20,
++	swxc1_op     =  0x08, sdxc1_op     =  0x09,
++	prefx_op     =  0x17, madd_s_op    =  0x20,
+ 	madd_d_op    =  0x21, madd_e_op    =  0x22,
+ 	msub_s_op    =  0x28, msub_d_op    =  0x29,
+ 	msub_e_op    =  0x2a, nmadd_s_op   =  0x30,
+diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c
+index dbf2f93..87ddba1 100644
+--- a/arch/mips/math-emu/cp1emu.c
++++ b/arch/mips/math-emu/cp1emu.c
+@@ -739,7 +739,7 @@ static int fpux_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
+ 			break;
+ 
+ 		default:
+-			return SIGILL;
++			goto SIGILL_unless_prefx_op;
+ 		}
+ 		break;
+ 	}
+@@ -809,19 +809,17 @@ static int fpux_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
+ 			goto copcsr;
+ 
+ 		default:
+-			return SIGILL;
++			goto SIGILL_unless_prefx_op;
+ 		}
+ 		break;
+ 	}
+ 
+-	case 0x7:		/* 7 */
+-		if (MIPSInst_FUNC(ir) != pfetch_op) {
+-			return SIGILL;
+-		}
+-		/* ignore prefx operation */
+-		break;
+-
+ 	default:
++	      SIGILL_unless_prefx_op:
++		if (MIPSInst_FUNC(ir) == prefx_op) {
++			/* ignore prefx operation */
++			break;
++		}
+ 		return SIGILL;
+ 	}
+ 
+-- 
+1.7.5.4
+
+From 97a564e3eddbfb84844b8eccb3bd751c71dfb3eb Mon Sep 17 00:00:00 2001
+From: Mark H Weaver <mhw@netris.org>
+Date: Fri, 28 Oct 2011 13:35:27 -0400
+Subject: [PATCH 3/4] Don't process empty cause flags after simple fp move on
+ mips
+
+---
+ arch/mips/math-emu/cp1emu.c |    4 ++--
+ 1 files changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c
+index 87ddba1..fefcba2 100644
+--- a/arch/mips/math-emu/cp1emu.c
++++ b/arch/mips/math-emu/cp1emu.c
+@@ -912,7 +912,7 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
+ 		case fmov_op:
+ 			/* an easy one */
+ 			SPFROMREG(rv.s, MIPSInst_FS(ir));
+-			goto copcsr;
++			break;
+ 
+ 			/* binary op on handler */
+ 		      scopbop:
+@@ -1099,7 +1099,7 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
+ 		case fmov_op:
+ 			/* an easy one */
+ 			DPFROMREG(rv.d, MIPSInst_FS(ir));
+-			goto copcsr;
++			break;
+ 
+ 			/* binary op on handler */
+ 		      dcopbop:{
+-- 
+1.7.5.4
+
diff --git a/pkgs/os-specific/linux/kernel/mips-fpureg-emulation.patch b/pkgs/os-specific/linux/kernel/mips-fpureg-emulation.patch
new file mode 100644
index 000000000000..452c4f26f6fd
--- /dev/null
+++ b/pkgs/os-specific/linux/kernel/mips-fpureg-emulation.patch
@@ -0,0 +1,144 @@
+From ab1ce0a6cd51ca83194a865837f3b90f366a733d Mon Sep 17 00:00:00 2001
+From: Lluis Batlle i Rossell <viric@viric.name>
+Date: Sat, 16 Jun 2012 00:22:53 +0200
+Subject: [PATCH] MIPS: Add emulation for fpureg-mem unaligned access
+To: linux-mips@linux-mips.org
+Cc: loongson-dev@googlegroups.com
+
+Reusing most of the code from lw,ld,sw,sd emulation,
+I add the emulation for lwc1,ldc1,swc1,sdc1.
+
+This avoids the direct SIGBUS sent to userspace processes that have
+misaligned memory accesses.
+
+I've tested the change in Loongson2F, with an own test program, and
+WebKit 1.4.0, as both were killed by sigbus without this patch.
+
+Signed-off: Lluis Batlle i Rossell <viric@viric.name>
+---
+ arch/mips/kernel/unaligned.c |   43 +++++++++++++++++++++++++++++-------------
+ 1 file changed, 30 insertions(+), 13 deletions(-)
+
+diff --git a/arch/mips/kernel/unaligned.c b/arch/mips/kernel/unaligned.c
+index 9c58bdf..4531e6c 100644
+--- a/arch/mips/kernel/unaligned.c
++++ b/arch/mips/kernel/unaligned.c
+@@ -85,6 +85,7 @@
+ #include <asm/cop2.h>
+ #include <asm/inst.h>
+ #include <asm/uaccess.h>
++#include <asm/fpu.h>
+ 
+ #define STR(x)  __STR(x)
+ #define __STR(x)  #x
+@@ -108,6 +109,7 @@ static void emulate_load_store_insn(struct pt_regs *regs,
+ 	union mips_instruction insn;
+ 	unsigned long value;
+ 	unsigned int res;
++	fpureg_t *fpuregs;
+ 
+ 	perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, regs, 0);
+ 
+@@ -183,6 +185,7 @@ static void emulate_load_store_insn(struct pt_regs *regs,
+ 		break;
+ 
+ 	case lw_op:
++	case lwc1_op:
+ 		if (!access_ok(VERIFY_READ, addr, 4))
+ 			goto sigbus;
+ 
+@@ -209,7 +212,12 @@ static void emulate_load_store_insn(struct pt_regs *regs,
+ 		if (res)
+ 			goto fault;
+ 		compute_return_epc(regs);
+-		regs->regs[insn.i_format.rt] = value;
++		if (insn.i_format.opcode == lw_op) {
++			regs->regs[insn.i_format.rt] = value;
++		} else {
++			fpuregs = get_fpu_regs(current);
++			fpuregs[insn.i_format.rt] = value;
++		}
+ 		break;
+ 
+ 	case lhu_op:
+@@ -291,6 +299,7 @@ static void emulate_load_store_insn(struct pt_regs *regs,
+ 		goto sigill;
+ 
+ 	case ld_op:
++	case ldc1_op:
+ #ifdef CONFIG_64BIT
+ 		/*
+ 		 * A 32-bit kernel might be running on a 64-bit processor.  But
+@@ -325,7 +334,12 @@ static void emulate_load_store_insn(struct pt_regs *regs,
+ 		if (res)
+ 			goto fault;
+ 		compute_return_epc(regs);
+-		regs->regs[insn.i_format.rt] = value;
++		if (insn.i_format.opcode == ld_op) {
++			regs->regs[insn.i_format.rt] = value;
++		} else {
++			fpuregs = get_fpu_regs(current);
++			fpuregs[insn.i_format.rt] = value;
++		}
+ 		break;
+ #endif /* CONFIG_64BIT */
+ 
+@@ -370,10 +384,16 @@ static void emulate_load_store_insn(struct pt_regs *regs,
+ 		break;
+ 
+ 	case sw_op:
++	case swc1_op:
+ 		if (!access_ok(VERIFY_WRITE, addr, 4))
+ 			goto sigbus;
+ 
+-		value = regs->regs[insn.i_format.rt];
++		if (insn.i_format.opcode == sw_op) {
++			value = regs->regs[insn.i_format.rt];
++		} else {
++			fpuregs = get_fpu_regs(current);
++			value = fpuregs[insn.i_format.rt];
++		}
+ 		__asm__ __volatile__ (
+ #ifdef __BIG_ENDIAN
+ 			"1:\tswl\t%1,(%2)\n"
+@@ -401,6 +421,7 @@ static void emulate_load_store_insn(struct pt_regs *regs,
+ 		break;
+ 
+ 	case sd_op:
++	case sdc1_op:
+ #ifdef CONFIG_64BIT
+ 		/*
+ 		 * A 32-bit kernel might be running on a 64-bit processor.  But
+@@ -412,7 +433,12 @@ static void emulate_load_store_insn(struct pt_regs *regs,
+ 		if (!access_ok(VERIFY_WRITE, addr, 8))
+ 			goto sigbus;
+ 
+-		value = regs->regs[insn.i_format.rt];
++		if (insn.i_format.opcode == sd_op) {
++			value = regs->regs[insn.i_format.rt];
++		} else {
++			fpuregs = get_fpu_regs(current);
++			value = fpuregs[insn.i_format.rt];
++		}
+ 		__asm__ __volatile__ (
+ #ifdef __BIG_ENDIAN
+ 			"1:\tsdl\t%1,(%2)\n"
+@@ -443,15 +469,6 @@ static void emulate_load_store_insn(struct pt_regs *regs,
+ 		/* Cannot handle 64-bit instructions in 32-bit kernel */
+ 		goto sigill;
+ 
+-	case lwc1_op:
+-	case ldc1_op:
+-	case swc1_op:
+-	case sdc1_op:
+-		/*
+-		 * I herewith declare: this does not happen.  So send SIGBUS.
+-		 */
+-		goto sigbus;
+-
+ 	/*
+ 	 * COP2 is available to implementor for application specific use.
+ 	 * It's up to applications to register a notifier chain and do
+-- 
+1.7.9.5
+
diff --git a/pkgs/os-specific/linux/kernel/patches.nix b/pkgs/os-specific/linux/kernel/patches.nix
index 7aefc7c5c0f6..4ac33380398a 100644
--- a/pkgs/os-specific/linux/kernel/patches.nix
+++ b/pkgs/os-specific/linux/kernel/patches.nix
@@ -353,6 +353,16 @@ rec {
       patch = ./mips_restart.patch;
     };
 
+  mips_fpureg_emu =
+    { name = "mips-fpureg-emulation";
+      patch = ./mips-fpureg-emulation.patch;
+    };
+
+  mips_fpu_sigill =
+    { name = "mips-fpu-sigill";
+      patch = ./mips-fpu-sigill.patch;
+    };
+
   guruplug_defconfig =
     { # Default configuration for the GuruPlug.  From
       # <http://www.openplug.org/plugwiki/images/c/c6/Guruplug-patchset-2.6.33.2.tar.bz2>.
diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix
index 843379dbd4d6..f3131898bd38 100644
--- a/pkgs/top-level/all-packages.nix
+++ b/pkgs/top-level/all-packages.nix
@@ -5681,6 +5681,9 @@ let
       [ #kernelPatches.fbcondecor_2_6_38
         kernelPatches.sec_perm_2_6_24
         kernelPatches.aufs3_4
+      ] ++ lib.optionals (platform.kernelArch == "mips")
+      [ kernelPatches.mips_fpureg_emu
+        kernelPatches.mips_fpu_sigill
       ];
   };