forked from mirrors/nixpkgs
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
This commit is contained in:
parent
404c21de2f
commit
3874e5812d
108
pkgs/os-specific/linux/kernel/mips-fpu-sigill.patch
Normal file
108
pkgs/os-specific/linux/kernel/mips-fpu-sigill.patch
Normal file
|
@ -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
|
||||
|
144
pkgs/os-specific/linux/kernel/mips-fpureg-emulation.patch
Normal file
144
pkgs/os-specific/linux/kernel/mips-fpureg-emulation.patch
Normal file
|
@ -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
|
||||
|
|
@ -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>.
|
||||
|
|
|
@ -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
|
||||
];
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in a new issue