Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2dede2d8 authored by Nicolas Pitre's avatar Nicolas Pitre Committed by Russell King
Browse files

[ARM] 3102/1: ARM EABI: stack pointer must be 64-bit aligned after a CPU exception



Patch from Nicolas Pitre

The ARM EABI says that the stack pointer has to be 64-bit aligned for
reasons already mentioned in patch #3101 when calling C functions.

We therefore must verify and adjust sp accordingly when taking an
exception from kernel mode since sp might not necessarily be 64-bit
aligned if the exception occurs in the middle of a kernel function.

If the exception occurs while in user mode then no sp fixup is needed as
long as sizeof(struct pt_regs) as well as any additional syscall data
stack space remain multiples of 8.

Signed-off-by: default avatarNicolas Pitre <nico@cam.org>
Signed-off-by: default avatarRussell King <rmk+kernel@arm.linux.org.uk>
parent da2b1cd6
Loading
Loading
Loading
Loading
+17 −0
Original line number Diff line number Diff line
@@ -105,14 +105,24 @@ common_invalid:
/*
 * SVC mode handlers
 */

#if defined(CONFIG_AEABI) && (__LINUX_ARM_ARCH__ >= 5)
#define SPFIX(code...) code
#else
#define SPFIX(code...)
#endif

	.macro	svc_entry
	sub	sp, sp, #S_FRAME_SIZE
 SPFIX(	tst	sp, #4		)
 SPFIX(	bicne	sp, sp, #4	)
	stmib	sp, {r1 - r12}

	ldmia	r0, {r1 - r3}
	add	r5, sp, #S_SP		@ here for interlock avoidance
	mov	r4, #-1			@  ""  ""      ""       ""
	add	r0, sp, #S_FRAME_SIZE   @  ""  ""      ""       ""
 SPFIX(	addne	r0, r0, #4	)
	str	r1, [sp]		@ save the "real" r0 copied
					@ from the exception stack

@@ -303,7 +313,14 @@ __pabt_svc:

/*
 * User mode handlers
 *
 * EABI note: sp_svc is always 64-bit aligned here, so should S_FRAME_SIZE
 */

#if defined(CONFIG_AEABI) && (__LINUX_ARM_ARCH__ >= 5) && (S_FRAME_SIZE & 7)
#error "sizeof(struct pt_regs) must be a multiple of 8"
#endif

	.macro	usr_entry
	sub	sp, sp, #S_FRAME_SIZE
	stmib	sp, {r1 - r12}
+1 −0
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@
@
@ Most of the stack format comes from struct pt_regs, but with
@ the addition of 8 bytes for storing syscall args 5 and 6.
@ This _must_ remain a multiple of 8 for EABI.
@
#define S_OFF		8

+5 −3
Original line number Diff line number Diff line
@@ -60,9 +60,11 @@

#ifndef __ASSEMBLY__

/* this struct defines the way the registers are stored on the
   stack during a system call. */

/*
 * This struct defines the way the registers are stored on the
 * stack during a system call.  Note that sizeof(struct pt_regs)
 * has to be a multiple of 8.
 */
struct pt_regs {
	long uregs[18];
};