diff options
author | Anton Blanchard <anton@samba.org> | 2013-09-22 22:04:39 -0400 |
---|---|---|
committer | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2013-10-11 01:48:28 -0400 |
commit | 926f160f460170b0361f600f365369685ad74009 (patch) | |
tree | 04537aba608b597cbf3af3d8a774b4c09bd52924 /arch | |
parent | 87fec0514f613f8ac43c01b0bc0bc7072c5d10ae (diff) |
powerpc: Little endian builds double word swap VSX state during context save/restore
The elements within VSX loads and stores are big endian ordered
regardless of endianness. Our VSX context save/restore code uses
lxvd2x and stxvd2x which is a 2x doubleword operation. This means
the two doublewords will be swapped and we have to perform another
swap to undo it.
We need to do this on save and restore.
Signed-off-by: Anton Blanchard <anton@samba.org>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/powerpc/include/asm/ppc-opcode.h | 3 | ||||
-rw-r--r-- | arch/powerpc/include/asm/ppc_asm.h | 21 |
2 files changed, 20 insertions, 4 deletions
diff --git a/arch/powerpc/include/asm/ppc-opcode.h b/arch/powerpc/include/asm/ppc-opcode.h index d7fe9f5b46d4..ad5fcf51b252 100644 --- a/arch/powerpc/include/asm/ppc-opcode.h +++ b/arch/powerpc/include/asm/ppc-opcode.h | |||
@@ -181,6 +181,7 @@ | |||
181 | #define PPC_INST_TLBIVAX 0x7c000624 | 181 | #define PPC_INST_TLBIVAX 0x7c000624 |
182 | #define PPC_INST_TLBSRX_DOT 0x7c0006a5 | 182 | #define PPC_INST_TLBSRX_DOT 0x7c0006a5 |
183 | #define PPC_INST_XXLOR 0xf0000510 | 183 | #define PPC_INST_XXLOR 0xf0000510 |
184 | #define PPC_INST_XXSWAPD 0xf0000250 | ||
184 | #define PPC_INST_XVCPSGNDP 0xf0000780 | 185 | #define PPC_INST_XVCPSGNDP 0xf0000780 |
185 | #define PPC_INST_TRECHKPT 0x7c0007dd | 186 | #define PPC_INST_TRECHKPT 0x7c0007dd |
186 | #define PPC_INST_TRECLAIM 0x7c00075d | 187 | #define PPC_INST_TRECLAIM 0x7c00075d |
@@ -344,6 +345,8 @@ | |||
344 | VSX_XX1((s), a, b)) | 345 | VSX_XX1((s), a, b)) |
345 | #define XXLOR(t, a, b) stringify_in_c(.long PPC_INST_XXLOR | \ | 346 | #define XXLOR(t, a, b) stringify_in_c(.long PPC_INST_XXLOR | \ |
346 | VSX_XX3((t), a, b)) | 347 | VSX_XX3((t), a, b)) |
348 | #define XXSWAPD(t, a) stringify_in_c(.long PPC_INST_XXSWAPD | \ | ||
349 | VSX_XX3((t), a, a)) | ||
347 | #define XVCPSGNDP(t, a, b) stringify_in_c(.long (PPC_INST_XVCPSGNDP | \ | 350 | #define XVCPSGNDP(t, a, b) stringify_in_c(.long (PPC_INST_XVCPSGNDP | \ |
348 | VSX_XX3((t), (a), (b)))) | 351 | VSX_XX3((t), (a), (b)))) |
349 | 352 | ||
diff --git a/arch/powerpc/include/asm/ppc_asm.h b/arch/powerpc/include/asm/ppc_asm.h index 599545738af3..0c51fb4fd2aa 100644 --- a/arch/powerpc/include/asm/ppc_asm.h +++ b/arch/powerpc/include/asm/ppc_asm.h | |||
@@ -180,9 +180,20 @@ END_FW_FTR_SECTION_IFSET(FW_FEATURE_SPLPAR) | |||
180 | #define REST_32VRS_TRANSACT(n,b,base) REST_16VRS_TRANSACT(n,b,base); \ | 180 | #define REST_32VRS_TRANSACT(n,b,base) REST_16VRS_TRANSACT(n,b,base); \ |
181 | REST_16VRS_TRANSACT(n+16,b,base) | 181 | REST_16VRS_TRANSACT(n+16,b,base) |
182 | 182 | ||
183 | #ifdef __BIG_ENDIAN__ | ||
184 | #define STXVD2X_ROT(n,b,base) STXVD2X(n,b,base) | ||
185 | #define LXVD2X_ROT(n,b,base) LXVD2X(n,b,base) | ||
186 | #else | ||
187 | #define STXVD2X_ROT(n,b,base) XXSWAPD(n,n); \ | ||
188 | STXVD2X(n,b,base); \ | ||
189 | XXSWAPD(n,n) | ||
190 | |||
191 | #define LXVD2X_ROT(n,b,base) LXVD2X(n,b,base); \ | ||
192 | XXSWAPD(n,n) | ||
193 | #endif | ||
183 | 194 | ||
184 | #define SAVE_VSR_TRANSACT(n,b,base) li b,THREAD_TRANSACT_VSR0+(16*(n)); \ | 195 | #define SAVE_VSR_TRANSACT(n,b,base) li b,THREAD_TRANSACT_VSR0+(16*(n)); \ |
185 | STXVD2X(n,R##base,R##b) | 196 | STXVD2X_ROT(n,R##base,R##b) |
186 | #define SAVE_2VSRS_TRANSACT(n,b,base) SAVE_VSR_TRANSACT(n,b,base); \ | 197 | #define SAVE_2VSRS_TRANSACT(n,b,base) SAVE_VSR_TRANSACT(n,b,base); \ |
187 | SAVE_VSR_TRANSACT(n+1,b,base) | 198 | SAVE_VSR_TRANSACT(n+1,b,base) |
188 | #define SAVE_4VSRS_TRANSACT(n,b,base) SAVE_2VSRS_TRANSACT(n,b,base); \ | 199 | #define SAVE_4VSRS_TRANSACT(n,b,base) SAVE_2VSRS_TRANSACT(n,b,base); \ |
@@ -195,7 +206,7 @@ END_FW_FTR_SECTION_IFSET(FW_FEATURE_SPLPAR) | |||
195 | SAVE_16VSRS_TRANSACT(n+16,b,base) | 206 | SAVE_16VSRS_TRANSACT(n+16,b,base) |
196 | 207 | ||
197 | #define REST_VSR_TRANSACT(n,b,base) li b,THREAD_TRANSACT_VSR0+(16*(n)); \ | 208 | #define REST_VSR_TRANSACT(n,b,base) li b,THREAD_TRANSACT_VSR0+(16*(n)); \ |
198 | LXVD2X(n,R##base,R##b) | 209 | LXVD2X_ROT(n,R##base,R##b) |
199 | #define REST_2VSRS_TRANSACT(n,b,base) REST_VSR_TRANSACT(n,b,base); \ | 210 | #define REST_2VSRS_TRANSACT(n,b,base) REST_VSR_TRANSACT(n,b,base); \ |
200 | REST_VSR_TRANSACT(n+1,b,base) | 211 | REST_VSR_TRANSACT(n+1,b,base) |
201 | #define REST_4VSRS_TRANSACT(n,b,base) REST_2VSRS_TRANSACT(n,b,base); \ | 212 | #define REST_4VSRS_TRANSACT(n,b,base) REST_2VSRS_TRANSACT(n,b,base); \ |
@@ -208,13 +219,15 @@ END_FW_FTR_SECTION_IFSET(FW_FEATURE_SPLPAR) | |||
208 | REST_16VSRS_TRANSACT(n+16,b,base) | 219 | REST_16VSRS_TRANSACT(n+16,b,base) |
209 | 220 | ||
210 | /* Save the lower 32 VSRs in the thread VSR region */ | 221 | /* Save the lower 32 VSRs in the thread VSR region */ |
211 | #define SAVE_VSR(n,b,base) li b,THREAD_VSR0+(16*(n)); STXVD2X(n,R##base,R##b) | 222 | #define SAVE_VSR(n,b,base) li b,THREAD_VSR0+(16*(n)); \ |
223 | STXVD2X_ROT(n,R##base,R##b) | ||
212 | #define SAVE_2VSRS(n,b,base) SAVE_VSR(n,b,base); SAVE_VSR(n+1,b,base) | 224 | #define SAVE_2VSRS(n,b,base) SAVE_VSR(n,b,base); SAVE_VSR(n+1,b,base) |
213 | #define SAVE_4VSRS(n,b,base) SAVE_2VSRS(n,b,base); SAVE_2VSRS(n+2,b,base) | 225 | #define SAVE_4VSRS(n,b,base) SAVE_2VSRS(n,b,base); SAVE_2VSRS(n+2,b,base) |
214 | #define SAVE_8VSRS(n,b,base) SAVE_4VSRS(n,b,base); SAVE_4VSRS(n+4,b,base) | 226 | #define SAVE_8VSRS(n,b,base) SAVE_4VSRS(n,b,base); SAVE_4VSRS(n+4,b,base) |
215 | #define SAVE_16VSRS(n,b,base) SAVE_8VSRS(n,b,base); SAVE_8VSRS(n+8,b,base) | 227 | #define SAVE_16VSRS(n,b,base) SAVE_8VSRS(n,b,base); SAVE_8VSRS(n+8,b,base) |
216 | #define SAVE_32VSRS(n,b,base) SAVE_16VSRS(n,b,base); SAVE_16VSRS(n+16,b,base) | 228 | #define SAVE_32VSRS(n,b,base) SAVE_16VSRS(n,b,base); SAVE_16VSRS(n+16,b,base) |
217 | #define REST_VSR(n,b,base) li b,THREAD_VSR0+(16*(n)); LXVD2X(n,R##base,R##b) | 229 | #define REST_VSR(n,b,base) li b,THREAD_VSR0+(16*(n)); \ |
230 | LXVD2X_ROT(n,R##base,R##b) | ||
218 | #define REST_2VSRS(n,b,base) REST_VSR(n,b,base); REST_VSR(n+1,b,base) | 231 | #define REST_2VSRS(n,b,base) REST_VSR(n,b,base); REST_VSR(n+1,b,base) |
219 | #define REST_4VSRS(n,b,base) REST_2VSRS(n,b,base); REST_2VSRS(n+2,b,base) | 232 | #define REST_4VSRS(n,b,base) REST_2VSRS(n,b,base); REST_2VSRS(n+2,b,base) |
220 | #define REST_8VSRS(n,b,base) REST_4VSRS(n,b,base); REST_4VSRS(n+4,b,base) | 233 | #define REST_8VSRS(n,b,base) REST_4VSRS(n,b,base); REST_4VSRS(n+4,b,base) |