powerpc: Little endian builds double word swap VSX state during context save/restore
authorAnton Blanchard <anton@samba.org>
Mon, 23 Sep 2013 02:04:39 +0000 (12:04 +1000)
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>
Fri, 11 Oct 2013 05:48:28 +0000 (16:48 +1100)
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>
arch/powerpc/include/asm/ppc-opcode.h
arch/powerpc/include/asm/ppc_asm.h

index d7fe9f5b46d457cf0895c7dee542bc2e40fb3e49..ad5fcf51b25225c7827f45347ce94d8f7c2584b6 100644 (file)
 #define PPC_INST_TLBIVAX               0x7c000624
 #define PPC_INST_TLBSRX_DOT            0x7c0006a5
 #define PPC_INST_XXLOR                 0xf0000510
+#define PPC_INST_XXSWAPD               0xf0000250
 #define PPC_INST_XVCPSGNDP             0xf0000780
 #define PPC_INST_TRECHKPT              0x7c0007dd
 #define PPC_INST_TRECLAIM              0x7c00075d
                                               VSX_XX1((s), a, b))
 #define XXLOR(t, a, b)         stringify_in_c(.long PPC_INST_XXLOR | \
                                               VSX_XX3((t), a, b))
+#define XXSWAPD(t, a)          stringify_in_c(.long PPC_INST_XXSWAPD | \
+                                              VSX_XX3((t), a, a))
 #define XVCPSGNDP(t, a, b)     stringify_in_c(.long (PPC_INST_XVCPSGNDP | \
                                               VSX_XX3((t), (a), (b))))
 
index 599545738af3e2354b137221cf1c07cf68e25440..0c51fb4fd2aa7635dfc86f02f8f6d9c74fcc4d1a 100644 (file)
@@ -180,9 +180,20 @@ END_FW_FTR_SECTION_IFSET(FW_FEATURE_SPLPAR)
 #define REST_32VRS_TRANSACT(n,b,base)  REST_16VRS_TRANSACT(n,b,base);  \
                                        REST_16VRS_TRANSACT(n+16,b,base)
 
+#ifdef __BIG_ENDIAN__
+#define STXVD2X_ROT(n,b,base)          STXVD2X(n,b,base)
+#define LXVD2X_ROT(n,b,base)           LXVD2X(n,b,base)
+#else
+#define STXVD2X_ROT(n,b,base)          XXSWAPD(n,n);           \
+                                       STXVD2X(n,b,base);      \
+                                       XXSWAPD(n,n)
+
+#define LXVD2X_ROT(n,b,base)           LXVD2X(n,b,base);       \
+                                       XXSWAPD(n,n)
+#endif
 
 #define SAVE_VSR_TRANSACT(n,b,base)    li b,THREAD_TRANSACT_VSR0+(16*(n)); \
-                                       STXVD2X(n,R##base,R##b)
+                                       STXVD2X_ROT(n,R##base,R##b)
 #define SAVE_2VSRS_TRANSACT(n,b,base)  SAVE_VSR_TRANSACT(n,b,base);    \
                                        SAVE_VSR_TRANSACT(n+1,b,base)
 #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)
                                        SAVE_16VSRS_TRANSACT(n+16,b,base)
 
 #define REST_VSR_TRANSACT(n,b,base)    li b,THREAD_TRANSACT_VSR0+(16*(n)); \
-                                       LXVD2X(n,R##base,R##b)
+                                       LXVD2X_ROT(n,R##base,R##b)
 #define REST_2VSRS_TRANSACT(n,b,base)  REST_VSR_TRANSACT(n,b,base);    \
                                        REST_VSR_TRANSACT(n+1,b,base)
 #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)
                                        REST_16VSRS_TRANSACT(n+16,b,base)
 
 /* Save the lower 32 VSRs in the thread VSR region */
-#define SAVE_VSR(n,b,base)     li b,THREAD_VSR0+(16*(n));  STXVD2X(n,R##base,R##b)
+#define SAVE_VSR(n,b,base)     li b,THREAD_VSR0+(16*(n)); \
+                               STXVD2X_ROT(n,R##base,R##b)
 #define SAVE_2VSRS(n,b,base)   SAVE_VSR(n,b,base); SAVE_VSR(n+1,b,base)
 #define SAVE_4VSRS(n,b,base)   SAVE_2VSRS(n,b,base); SAVE_2VSRS(n+2,b,base)
 #define SAVE_8VSRS(n,b,base)   SAVE_4VSRS(n,b,base); SAVE_4VSRS(n+4,b,base)
 #define SAVE_16VSRS(n,b,base)  SAVE_8VSRS(n,b,base); SAVE_8VSRS(n+8,b,base)
 #define SAVE_32VSRS(n,b,base)  SAVE_16VSRS(n,b,base); SAVE_16VSRS(n+16,b,base)
-#define REST_VSR(n,b,base)     li b,THREAD_VSR0+(16*(n)); LXVD2X(n,R##base,R##b)
+#define REST_VSR(n,b,base)     li b,THREAD_VSR0+(16*(n)); \
+                               LXVD2X_ROT(n,R##base,R##b)
 #define REST_2VSRS(n,b,base)   REST_VSR(n,b,base); REST_VSR(n+1,b,base)
 #define REST_4VSRS(n,b,base)   REST_2VSRS(n,b,base); REST_2VSRS(n+2,b,base)
 #define REST_8VSRS(n,b,base)   REST_4VSRS(n,b,base); REST_4VSRS(n+4,b,base)