On Fri, Jan 24, 2025 at 05:57:05PM +0100, Magnus Lindholm wrote:
> Are there other parts of the code that might unalign the stack, even
> if the stack is properly aligned to begin with? i.e passing an uneven
> number of function arguments on the stack or inside interrupt
> handlers? Alpha does not make use of a separate interrupt stack,
> right?

Good questions. No, there is no separate interrupt stack, it's always the
kernel one. Stack frames from interrupts in user mode are 64-byte aligned
though. Interrupts in kernel mode, user mode syscalls and exceptions all
use 6 x 64-bit word frames and do not change the stack [mis]alignment.

So, what we have now:
1. The "normal" kernel stack is always misaligned by 8, thanks to
   the sizeof(struct pt_regs);
2. Syscalls and exceptions handlers receive 16-byte aligned stack, as it
   gets "fixed" by SAVE_ALL macro in entry.S, which pushes the odd number
   of registers on the stack;
3. Interrupt handlers may, or may not, have got an aligned stack depending
   on kernel/user mode in which the interrupt had come.

Ugh.

> On stack alignment in "ALPHA Calling Standard":
> D.3.1 Stack Alignment
> 
> "This standard requires that stacks be octaword aligned at the time a
> new procedure is invoked. During the body of a procedure, however,
> there is no requirement to keep this level of alignment (even though
> it may be beneficial). This implies that any asynchronous interrupt
> handlers must properly align the stack before any standard calls are
> made."

I hope we can rely on GCC changing $sp only by multiplies of 16.

Magnus, can you please try this variant?

(Yes, there is still the UAPI issue that Maciej pointed out, but that's
another story.)

Ivan.

diff --git a/arch/alpha/include/uapi/asm/ptrace.h 
b/arch/alpha/include/uapi/asm/ptrace.h
index 5ca45934fcbb..72ed913a910f 100644
--- a/arch/alpha/include/uapi/asm/ptrace.h
+++ b/arch/alpha/include/uapi/asm/ptrace.h
@@ -42,6 +42,8 @@ struct pt_regs {
        unsigned long trap_a0;
        unsigned long trap_a1;
        unsigned long trap_a2;
+/* This makes the stack 16-byte aligned as GCC expects */
+       unsigned long __pad0;
 /* These are saved by PAL-code: */
        unsigned long ps;
        unsigned long pc;
diff --git a/arch/alpha/kernel/asm-offsets.c b/arch/alpha/kernel/asm-offsets.c
index 4cfeae42c79a..e9dad60b147f 100644
--- a/arch/alpha/kernel/asm-offsets.c
+++ b/arch/alpha/kernel/asm-offsets.c
@@ -19,9 +19,13 @@ static void __used foo(void)
        DEFINE(TI_STATUS, offsetof(struct thread_info, status));
        BLANK();
 
+       DEFINE(SP_OFF, offsetof(struct pt_regs, ps));
        DEFINE(SIZEOF_PT_REGS, sizeof(struct pt_regs));
        BLANK();
 
+       DEFINE(SWITCH_STACK_SIZE, sizeof(struct switch_stack));
+       BLANK();
+
        DEFINE(HAE_CACHE, offsetof(struct alpha_machine_vector, hae_cache));
        DEFINE(HAE_REG, offsetof(struct alpha_machine_vector, hae_register));
 }
diff --git a/arch/alpha/kernel/entry.S b/arch/alpha/kernel/entry.S
index dd26062d75b3..6fb38365539d 100644
--- a/arch/alpha/kernel/entry.S
+++ b/arch/alpha/kernel/entry.S
@@ -15,10 +15,6 @@
        .set noat
        .cfi_sections   .debug_frame
 
-/* Stack offsets.  */
-#define SP_OFF                 184
-#define SWITCH_STACK_SIZE      64
-
 .macro CFI_START_OSF_FRAME     func
        .align  4
        .globl  \func

Reply via email to