From: Greg Kroah-Hartman Date: Thu, 13 Aug 2015 21:27:14 +0000 (-0700) Subject: 4.1-stable patches X-Git-Tag: v3.10.87~31 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=69cde64765fe2a96476197879d32847b71db5355;p=thirdparty%2Fkernel%2Fstable-queue.git 4.1-stable patches added patches: sparc64-fix-userspace-fpu-register-corruptions.patch --- diff --git a/queue-4.1/series b/queue-4.1/series index 1be9e7b3311..c5ee20f037e 100644 --- a/queue-4.1/series +++ b/queue-4.1/series @@ -39,3 +39,4 @@ dmaengine-at_xdmac-fix-transfer-data-width-in-at_xdmac_prep_slave_sg.patch crypto-nx-fixing-nx-data-alignment-with-nx_sg-list.patch crypto-nx-fixing-sha-update-bug.patch crypto-nx-fix-reentrancy-bugs.patch +sparc64-fix-userspace-fpu-register-corruptions.patch diff --git a/queue-4.1/sparc64-fix-userspace-fpu-register-corruptions.patch b/queue-4.1/sparc64-fix-userspace-fpu-register-corruptions.patch new file mode 100644 index 00000000000..3484b205490 --- /dev/null +++ b/queue-4.1/sparc64-fix-userspace-fpu-register-corruptions.patch @@ -0,0 +1,196 @@ +From foo@baz Thu Aug 13 14:27:02 PDT 2015 +From: "David S. Miller" +Date: Thu, 6 Aug 2015 19:13:25 -0700 +Subject: [PATCH] sparc64: Fix userspace FPU register corruptions. + +From: "David S. Miller" + +[ Upstream commit 44922150d87cef616fd183220d43d8fde4d41390 ] + +If we have a series of events from userpsace, with %fprs=FPRS_FEF, +like follows: + +ETRAP + ETRAP + VIS_ENTRY(fprs=0x4) + VIS_EXIT + RTRAP (kernel FPU restore with fpu_saved=0x4) + RTRAP + +We will not restore the user registers that were clobbered by the FPU +using kernel code in the inner-most trap. + +Traps allocate FPU save slots in the thread struct, and FPU using +sequences save the "dirty" FPU registers only. + +This works at the initial trap level because all of the registers +get recorded into the top-level FPU save area, and we'll return +to userspace with the FPU disabled so that any FPU use by the user +will take an FPU disabled trap wherein we'll load the registers +back up properly. + +But this is not how trap returns from kernel to kernel operate. + +The simplest fix for this bug is to always save all FPU register state +for anything other than the top-most FPU save area. + +Getting rid of the optimized inner-slot FPU saving code ends up +making VISEntryHalf degenerate into plain VISEntry. + +Longer term we need to do something smarter to reinstate the partial +save optimizations. Perhaps the fundament error is having trap entry +and exit allocate FPU save slots and restore register state. Instead, +the VISEntry et al. calls should be doing that work. + +This bug is about two decades old. + +Reported-by: James Y Knight +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + arch/sparc/include/asm/visasm.h | 16 ++------- + arch/sparc/lib/NG4memcpy.S | 5 ++ + arch/sparc/lib/VISsave.S | 67 +--------------------------------------- + arch/sparc/lib/ksyms.c | 4 -- + 4 files changed, 11 insertions(+), 81 deletions(-) + +--- a/arch/sparc/include/asm/visasm.h ++++ b/arch/sparc/include/asm/visasm.h +@@ -28,16 +28,10 @@ + * Must preserve %o5 between VISEntryHalf and VISExitHalf */ + + #define VISEntryHalf \ +- rd %fprs, %o5; \ +- andcc %o5, FPRS_FEF, %g0; \ +- be,pt %icc, 297f; \ +- sethi %hi(298f), %g7; \ +- sethi %hi(VISenterhalf), %g1; \ +- jmpl %g1 + %lo(VISenterhalf), %g0; \ +- or %g7, %lo(298f), %g7; \ +- clr %o5; \ +-297: wr %o5, FPRS_FEF, %fprs; \ +-298: ++ VISEntry ++ ++#define VISExitHalf \ ++ VISExit + + #define VISEntryHalfFast(fail_label) \ + rd %fprs, %o5; \ +@@ -47,7 +41,7 @@ + ba,a,pt %xcc, fail_label; \ + 297: wr %o5, FPRS_FEF, %fprs; + +-#define VISExitHalf \ ++#define VISExitHalfFast \ + wr %o5, 0, %fprs; + + #ifndef __ASSEMBLY__ +--- a/arch/sparc/lib/NG4memcpy.S ++++ b/arch/sparc/lib/NG4memcpy.S +@@ -240,8 +240,11 @@ FUNC_NAME: /* %o0=dst, %o1=src, %o2=len + add %o0, 0x40, %o0 + bne,pt %icc, 1b + LOAD(prefetch, %g1 + 0x200, #n_reads_strong) ++#ifdef NON_USER_COPY ++ VISExitHalfFast ++#else + VISExitHalf +- ++#endif + brz,pn %o2, .Lexit + cmp %o2, 19 + ble,pn %icc, .Lsmall_unaligned +--- a/arch/sparc/lib/VISsave.S ++++ b/arch/sparc/lib/VISsave.S +@@ -44,9 +44,8 @@ vis1: ldub [%g6 + TI_FPSAVED], %g3 + + stx %g3, [%g6 + TI_GSR] + 2: add %g6, %g1, %g3 +- cmp %o5, FPRS_DU +- be,pn %icc, 6f +- sll %g1, 3, %g1 ++ mov FPRS_DU | FPRS_DL | FPRS_FEF, %o5 ++ sll %g1, 3, %g1 + stb %o5, [%g3 + TI_FPSAVED] + rd %gsr, %g2 + add %g6, %g1, %g3 +@@ -80,65 +79,3 @@ vis1: ldub [%g6 + TI_FPSAVED], %g3 + .align 32 + 80: jmpl %g7 + %g0, %g0 + nop +- +-6: ldub [%g3 + TI_FPSAVED], %o5 +- or %o5, FPRS_DU, %o5 +- add %g6, TI_FPREGS+0x80, %g2 +- stb %o5, [%g3 + TI_FPSAVED] +- +- sll %g1, 5, %g1 +- add %g6, TI_FPREGS+0xc0, %g3 +- wr %g0, FPRS_FEF, %fprs +- membar #Sync +- stda %f32, [%g2 + %g1] ASI_BLK_P +- stda %f48, [%g3 + %g1] ASI_BLK_P +- membar #Sync +- ba,pt %xcc, 80f +- nop +- +- .align 32 +-80: jmpl %g7 + %g0, %g0 +- nop +- +- .align 32 +-VISenterhalf: +- ldub [%g6 + TI_FPDEPTH], %g1 +- brnz,a,pn %g1, 1f +- cmp %g1, 1 +- stb %g0, [%g6 + TI_FPSAVED] +- stx %fsr, [%g6 + TI_XFSR] +- clr %o5 +- jmpl %g7 + %g0, %g0 +- wr %g0, FPRS_FEF, %fprs +- +-1: bne,pn %icc, 2f +- srl %g1, 1, %g1 +- ba,pt %xcc, vis1 +- sub %g7, 8, %g7 +-2: addcc %g6, %g1, %g3 +- sll %g1, 3, %g1 +- andn %o5, FPRS_DU, %g2 +- stb %g2, [%g3 + TI_FPSAVED] +- +- rd %gsr, %g2 +- add %g6, %g1, %g3 +- stx %g2, [%g3 + TI_GSR] +- add %g6, %g1, %g2 +- stx %fsr, [%g2 + TI_XFSR] +- sll %g1, 5, %g1 +-3: andcc %o5, FPRS_DL, %g0 +- be,pn %icc, 4f +- add %g6, TI_FPREGS, %g2 +- +- add %g6, TI_FPREGS+0x40, %g3 +- membar #Sync +- stda %f0, [%g2 + %g1] ASI_BLK_P +- stda %f16, [%g3 + %g1] ASI_BLK_P +- membar #Sync +- ba,pt %xcc, 4f +- nop +- +- .align 32 +-4: and %o5, FPRS_DU, %o5 +- jmpl %g7 + %g0, %g0 +- wr %o5, FPRS_FEF, %fprs +--- a/arch/sparc/lib/ksyms.c ++++ b/arch/sparc/lib/ksyms.c +@@ -135,10 +135,6 @@ EXPORT_SYMBOL(copy_user_page); + void VISenter(void); + EXPORT_SYMBOL(VISenter); + +-/* CRYPTO code needs this */ +-void VISenterhalf(void); +-EXPORT_SYMBOL(VISenterhalf); +- + extern void xor_vis_2(unsigned long, unsigned long *, unsigned long *); + extern void xor_vis_3(unsigned long, unsigned long *, unsigned long *, + unsigned long *);