]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blame - releases/2.6.32.3/powerpc-handle-vsx-alignment-faults-correctly-in-little-endian-mode.patch
4.14-stable patches
[thirdparty/kernel/stable-queue.git] / releases / 2.6.32.3 / powerpc-handle-vsx-alignment-faults-correctly-in-little-endian-mode.patch
CommitLineData
80e6ae8f
GKH
1From bb7f20b1c639606def3b91f4e4aca6daeee5d80a Mon Sep 17 00:00:00 2001
2From: Neil Campbell <neilc@linux.vnet.ibm.com>
3Date: Mon, 14 Dec 2009 04:08:57 +0000
4Subject: powerpc: Handle VSX alignment faults correctly in little-endian mode
5
6From: Neil Campbell <neilc@linux.vnet.ibm.com>
7
8commit bb7f20b1c639606def3b91f4e4aca6daeee5d80a upstream.
9
10This patch fixes the handling of VSX alignment faults in little-endian
11mode (the current code assumes the processor is in big-endian mode).
12
13The patch also makes the handlers clear the top 8 bytes of the register
14when handling an 8 byte VSX load.
15
16This is based on 2.6.32.
17
18Signed-off-by: Neil Campbell <neilc@linux.vnet.ibm.com>
19Acked-by: Michael Neuling <mikey@neuling.org>
20Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
21Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
22
23---
24 arch/powerpc/kernel/align.c | 63 ++++++++++++++++++++++++++++++++------------
25 1 file changed, 46 insertions(+), 17 deletions(-)
26
27--- a/arch/powerpc/kernel/align.c
28+++ b/arch/powerpc/kernel/align.c
29@@ -642,10 +642,14 @@ static int emulate_spe(struct pt_regs *r
30 */
31 static int emulate_vsx(unsigned char __user *addr, unsigned int reg,
32 unsigned int areg, struct pt_regs *regs,
33- unsigned int flags, unsigned int length)
34+ unsigned int flags, unsigned int length,
35+ unsigned int elsize)
36 {
37 char *ptr;
38+ unsigned long *lptr;
39 int ret = 0;
40+ int sw = 0;
41+ int i, j;
42
43 flush_vsx_to_thread(current);
44
45@@ -654,19 +658,35 @@ static int emulate_vsx(unsigned char __u
46 else
47 ptr = (char *) &current->thread.vr[reg - 32];
48
49- if (flags & ST)
50- ret = __copy_to_user(addr, ptr, length);
51- else {
52- if (flags & SPLT){
53- ret = __copy_from_user(ptr, addr, length);
54- ptr += length;
55+ lptr = (unsigned long *) ptr;
56+
57+ if (flags & SW)
58+ sw = elsize-1;
59+
60+ for (j = 0; j < length; j += elsize) {
61+ for (i = 0; i < elsize; ++i) {
62+ if (flags & ST)
63+ ret |= __put_user(ptr[i^sw], addr + i);
64+ else
65+ ret |= __get_user(ptr[i^sw], addr + i);
66 }
67- ret |= __copy_from_user(ptr, addr, length);
68+ ptr += elsize;
69+ addr += elsize;
70 }
71- if (flags & U)
72- regs->gpr[areg] = regs->dar;
73- if (ret)
74+
75+ if (!ret) {
76+ if (flags & U)
77+ regs->gpr[areg] = regs->dar;
78+
79+ /* Splat load copies the same data to top and bottom 8 bytes */
80+ if (flags & SPLT)
81+ lptr[1] = lptr[0];
82+ /* For 8 byte loads, zero the top 8 bytes */
83+ else if (!(flags & ST) && (8 == length))
84+ lptr[1] = 0;
85+ } else
86 return -EFAULT;
87+
88 return 1;
89 }
90 #endif
91@@ -767,16 +787,25 @@ int fix_alignment(struct pt_regs *regs)
92
93 #ifdef CONFIG_VSX
94 if ((instruction & 0xfc00003e) == 0x7c000018) {
95- /* Additional register addressing bit (64 VSX vs 32 FPR/GPR */
96+ unsigned int elsize;
97+
98+ /* Additional register addressing bit (64 VSX vs 32 FPR/GPR) */
99 reg |= (instruction & 0x1) << 5;
100 /* Simple inline decoder instead of a table */
101+ /* VSX has only 8 and 16 byte memory accesses */
102+ nb = 8;
103 if (instruction & 0x200)
104 nb = 16;
105- else if (instruction & 0x080)
106- nb = 8;
107- else
108- nb = 4;
109+
110+ /* Vector stores in little-endian mode swap individual
111+ elements, so process them separately */
112+ elsize = 4;
113+ if (instruction & 0x80)
114+ elsize = 8;
115+
116 flags = 0;
117+ if (regs->msr & MSR_LE)
118+ flags |= SW;
119 if (instruction & 0x100)
120 flags |= ST;
121 if (instruction & 0x040)
122@@ -787,7 +816,7 @@ int fix_alignment(struct pt_regs *regs)
123 nb = 8;
124 }
125 PPC_WARN_EMULATED(vsx);
126- return emulate_vsx(addr, reg, areg, regs, flags, nb);
127+ return emulate_vsx(addr, reg, areg, regs, flags, nb, elsize);
128 }
129 #endif
130 /* A size of 0 indicates an instruction we don't support, with