-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Adding two kernel patches for mips, that make the life easier on loon…
…gson2f (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. git-svn-id: https://nixos.org/repos/nix/nixpkgs/trunk@34522 70bd8c7a-acb8-0310-9f0d-9cc1c95dcdbb
- Loading branch information
viric
committed
Jun 16, 2012
1 parent
972563f
commit 6bddc77
Showing
4 changed files
with
265 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 changes: 144 additions & 0 deletions
144
pkgs/os-specific/linux/kernel/mips-fpureg-emulation.patch
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters