diff options
author | Lluís Batlle i Rossell <viric@vicerveza.homeunix.net> | 2012-06-16 10:49:03 +0000 |
---|---|---|
committer | Lluís Batlle i Rossell <viric@vicerveza.homeunix.net> | 2012-06-16 10:49:03 +0000 |
commit | 3874e5812d6cf07b6ee778c3f58df73b913bae93 (patch) | |
tree | 2d445bca9d35f58b5d02365fe166c9b2fb94d2d0 /pkgs/os-specific/linux/kernel/mips-fpureg-emulation.patch | |
parent | 404c21de2fa7ec36e92504f36a3dce95f8114704 (diff) | |
download | nixpkgs-3874e5812d6cf07b6ee778c3f58df73b913bae93.tar nixpkgs-3874e5812d6cf07b6ee778c3f58df73b913bae93.tar.gz nixpkgs-3874e5812d6cf07b6ee778c3f58df73b913bae93.tar.bz2 nixpkgs-3874e5812d6cf07b6ee778c3f58df73b913bae93.tar.lz nixpkgs-3874e5812d6cf07b6ee778c3f58df73b913bae93.tar.xz nixpkgs-3874e5812d6cf07b6ee778c3f58df73b913bae93.tar.zst nixpkgs-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
Diffstat (limited to 'pkgs/os-specific/linux/kernel/mips-fpureg-emulation.patch')
-rw-r--r-- | pkgs/os-specific/linux/kernel/mips-fpureg-emulation.patch | 144 |
1 files changed, 144 insertions, 0 deletions
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 00000000000..452c4f26f6f --- /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 + |