From: Philippe Bergheaud <felix@linux.vnet.ibm.com>
Subject: powerpc: Wrong DWARF CFI in the kernel vdso for little-endian / ELFv2
Git-commit: 280270828f108be56f0c486def58acabb070244f
Patch-mainline: v3.13-rc1
References: bnc#856774 fate#315275, LTC#92305

Summary:     powerpc: add little-endian support
Description: Add little-endian support for POWER8.

Upstream-Description:

    powerpc: Wrong DWARF CFI in the kernel vdso for
     little-endian / ELFv2

    I've finally tracked down why my CR signal-unwind test case still
    fails on little-endian.  The problem turned to be that the kernel
    installs a signal trampoline in the vDSO, and provides a DWARF CFI
    record for that trampoline.  This CFI describes the save location
    for CR:

      rsave (70, 38*RSIZE + (RSIZE - CRSIZE))

    which is correct for big-endian, but points to the wrong word on
    little-endian.   This is wrong no matter which ABI.

    In addition, for the ELFv2 ABI, we should not only provide a CFI
    record for register 70 (cr2), but for all CR fields separately.
    Strictly speaking, I guess this would mean providing two separate
    vDSO images, one for ELFv1 processes and one for ELFv2 processes (or
    maybe playing some tricks with conditional DWARF expressions).
    However, having CFI records for the other CR fields in ELFv1 is not
    actually wrong, they just will be ignored.   So it seems the simplest
    fix would be just to always provide CFI for all the fields.

Signed-off-by: Ulrich Weigand <Ulrich.Weigand@de.ibm.com>
Signed-off-by: Anton Blanchard <anton@samba.org>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>

Signed-off-by: Philippe Bergheaud <felix@linux.vnet.ibm.com>
Acked-by: Torsten Duwe <duwe@suse.de>
---
 arch/powerpc/kernel/vdso64/sigtramp.S | 16 +++++++++++++++-
 1 file changed, 15 insertions(+), 1 deletion(-)

diff --git a/arch/powerpc/kernel/vdso64/sigtramp.S b/arch/powerpc/kernel/vdso64/sigtramp.S
index 45ea281..542c6f42 100644
--- a/arch/powerpc/kernel/vdso64/sigtramp.S
+++ b/arch/powerpc/kernel/vdso64/sigtramp.S
@@ -142,6 +142,13 @@ V_FUNCTION_END(__kernel_sigtramp_rt64)
 /* Size of CR reg in DWARF unwind info. */
 #define CRSIZE	4
 
+/* Offset of CR reg within a full word. */
+#ifdef __LITTLE_ENDIAN__
+#define CROFF 0
+#else
+#define CROFF (RSIZE - CRSIZE)
+#endif
+
 /* This is the offset of the VMX reg pointer.  */
 #define VREGS	48*RSIZE+33*8
 
@@ -181,7 +188,14 @@ V_FUNCTION_END(__kernel_sigtramp_rt64)
   rsave (31, 31*RSIZE);							\
   rsave (67, 32*RSIZE);		/* ap, used as temp for nip */		\
   rsave (65, 36*RSIZE);		/* lr */				\
-  rsave (70, 38*RSIZE + (RSIZE - CRSIZE)) /* cr */
+  rsave (68, 38*RSIZE + CROFF);	/* cr fields */				\
+  rsave (69, 38*RSIZE + CROFF);						\
+  rsave (70, 38*RSIZE + CROFF);						\
+  rsave (71, 38*RSIZE + CROFF);						\
+  rsave (72, 38*RSIZE + CROFF);						\
+  rsave (73, 38*RSIZE + CROFF);						\
+  rsave (74, 38*RSIZE + CROFF);						\
+  rsave (75, 38*RSIZE + CROFF)
 
 /* Describe where the FP regs are saved.  */
 #define EH_FRAME_FP \
-- 
1.8.3.1

