mirror of
https://github.com/NixOS/nixpkgs.git
synced 2024-11-20 04:31:52 +00:00
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;
|
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 =
|
guruplug_defconfig =
|
||||||
{ # Default configuration for the GuruPlug. From
|
{ # Default configuration for the GuruPlug. From
|
||||||
# <http://www.openplug.org/plugwiki/images/c/c6/Guruplug-patchset-2.6.33.2.tar.bz2>.
|
# <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.fbcondecor_2_6_38
|
||||||
kernelPatches.sec_perm_2_6_24
|
kernelPatches.sec_perm_2_6_24
|
||||||
kernelPatches.aufs3_4
|
kernelPatches.aufs3_4
|
||||||
|
] ++ lib.optionals (platform.kernelArch == "mips")
|
||||||
|
[ kernelPatches.mips_fpureg_emu
|
||||||
|
kernelPatches.mips_fpu_sigill
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue