NetBSD-Bugs archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: port-alpha/60865 (NetBSD-current/alpha panics running getcwd test)



The following reply was made to PR port-alpha/60865; it has been noted by GNATS.

From: Rin Okuyama <rokuyama.rk%gmail.com@localhost>
To: gnats-bugs%netbsd.org@localhost, port-alpha-maintainer%netbsd.org@localhost,
 kern-bug-people%netbsd.org@localhost, netbsd-bugs%netbsd.org@localhost, gnats-admin%netbsd.org@localhost,
 Andreas Gustafsson <gson%gson.org@localhost>
Cc: 
Subject: Re: port-alpha/60865 (NetBSD-current/alpha panics running getcwd
 test)
Date: Tue, 20 Oct 2026 21:06:45 +0900

 I could reproduce this problem more easily:
 
 ```
 # ls /proc
 
 [  12.6627837] CPU 0: fatal kernel trap:
 
 [  12.6747358] CPU 0    trap entry = 0x2 (memory management fault)
 [  12.6924180] CPU 0    a0         = 0x0
 [  12.7033379] CPU 0    a1         = 0x1
 [  12.7142582] CPU 0    a2         = 0xffffffffffffffff
 [  12.7290796] CPU 0    pc         = 0x0
 [  12.7400000] CPU 0    ra         = 0x0
 [  12.7509206] CPU 0    pv         = 0xfffffc0000a67ea8
 [  12.7657422] CPU 0    curlwp     = 0xfffffc007f636a40
 [  12.7805637] CPU 0        pid = 126, comm = ls
 
 [  12.7940843] panic: trap
 [  12.8013654] cpu0: Begin traceback...
 [  12.8120241] at 0xfffffc00007f79a0 pc 0xfffffc000119eb4c
 [  12.8297761] vpanic() at netbsd:vpanic+0x14c
 [  12.8444251] printf() at netbsd:printf_nostamp+0xf0
 [  12.8594534] --- root of call graph ---
 [  12.8706338] cpu0: End traceback...
 Stopped in pid 126.126 (ls) at  netbsd:cpu_Debugger+0x4:        ret 
 zero,(ra)
 ```
 
 TL;DR This is because kernel stack is only aligned to 8-byte
 boundaries. If it is properly aligned to 16-byte boundaries,
 panic disappears. We fixed user-space stack alignment few years
 ago, but we overlooked kernel stack at that time.
 
 Carrying out bisectioning, I've found that this is due to
 kern_proc.c::proclist_foreach_call().
 
 (1) If this function is compiled with
 __attribute__((optimize("trivial-auto-var-init=uninitialized"))),
 panic does not occur.
 
 (2) With
 __attribute__((optimize("trivial-auto-var-init=zero"))),
 panic occurs.
 
 (3) With
 __attribute__((optimize("trivial-auto-var-init=uninitialized"))),
 but memset(&marker, 0, sizeof(marker)) in that function,
 panic occurs.
 
 So, I guess that marker does not fit within stack frame, and
 initialization corrupts caller's stack frame for
 -ftrivial-auto-var-init=pattern (default), (2), and (3),
 
 Actually, objdump for (3) reads:
 
 ```
 0000000000003c60 <proclist_foreach_call>:
 {
      3c60:       00 00 bb 27     ldah    gp,0(t12)
      3c64:       00 00 bd 23     lda     gp,0(gp)
      3c68:       50 fc de 23     lda     sp,-944(sp)
      3c6c:       00 00 5e b7     stq     ra,0(sp)
      3c70:       08 00 3e b5     stq     s0,8(sp)
      3c74:       10 00 5e b5     stq     s1,16(sp)
      3c78:       18 00 7e b5     stq     s2,24(sp)
      3c7c:       20 00 9e b5     stq     s3,32(sp)
      3c80:       28 00 be b5     stq     s4,40(sp)
      3c84:       30 00 de b5     stq     s5,48(sp)
      3c88:       38 00 fe b5     stq     fp,56(sp)
      3c8c:       7f 00 5e 20     lda     t1,127(sp)
          memset(&marker, 0, sizeof(marker));
      3c90:       00 00 7d a7     ldq     t12,0(gp)
 {
      3c94:       0d f1 47 44     andnot  t1,0x3f,s4
      3c98:       09 04 f0 47     mov     a0,s0
      3c9c:       0b 04 f1 47     mov     a1,s2
          memset(&marker, 0, sizeof(marker));
      3ca0:       10 04 ed 47     mov     s4,a0
      3ca4:       11 04 ff 47     clr     a1
 {
      3ca8:       0c 04 f2 47     mov     a2,s3
          memset(&marker, 0, sizeof(marker));
      3cac:       40 03 5f 22     lda     a2,832
      3cb0:       00 40 5b 6b     jsr     ra,(t12),3cb4 
 <proclist_foreach_call+0x54>
 ```
 
 So, this code does:
 
 sp <-- sp - 944
 &marker <-- roundup(sp + 64, 64)
 memset(&marker, 0, 832)
 
 If sp is aligned to 16-byte boundaries, as ABI (there's no ELF
 ABI for alpha, so ABI means GCC here) requires, marker always
 fits within stack frame.
 
 However, if sp is aligned only aligned to 8-byte boundaries,
 marker generally does not fit, and memset() corrupts caller's
 stack frame.
 
 Actually, inserting this code into proclist_foreach_call()
 causes KASSERT failure:
 
 ```
 	uint64_t sp;
 
 	__asm__ volatile ("mov $30, %0" : "=r" (sp) ::);
 	KASSERTMSG((sp & 0xf) == 0, "sp 0x%016" PRIx64, sp);
 ```
 
 With attached patch below, panic no longer occurs for me.
 But, I'm not sure that this fix is enough for proper kernel
 stack alignments.
 
 Thanks,
 rin
 
 ```
 commit 23014dd67d0
 Author: Rin Okuyama <rokuyama.rk%gmail.com@localhost>
 Date:   Tue Oct 20 20:32:59 2026 +0900
 
      alpha: Align kernel stack pointer to 16-byte bourndaries
 
 diff --git a/sys/arch/alpha/alpha/machdep.c b/sys/arch/alpha/alpha/machdep.c
 index 8a4f98beb1d..79f2bd0c444 100644
 --- a/sys/arch/alpha/alpha/machdep.c
 +++ b/sys/arch/alpha/alpha/machdep.c
 @@ -725,7 +725,8 @@ nobootinfo:
   	 * Set the kernel sp, reserving space for an (empty) trapframe,
   	 * and make lwp0's trapframe pointer point to it for sanity.
   	 */
 -	pcb0->pcb_hw.apcb_ksp = v + USPACE - sizeof(struct trapframe);
 +	pcb0->pcb_hw.apcb_ksp = (v + USPACE - sizeof(struct trapframe)) &
 +	    ~STACK_ALIGNBYTES;
   	lwp0.l_md.md_tf = (struct trapframe *)pcb0->pcb_hw.apcb_ksp;
 
   	/* Indicate that lwp0 has a CPU. */
 diff --git a/sys/arch/alpha/alpha/vm_machdep.c 
 b/sys/arch/alpha/alpha/vm_machdep.c
 index 3cbaaf6a380..b6dd44c04c3 100644
 --- a/sys/arch/alpha/alpha/vm_machdep.c
 +++ b/sys/arch/alpha/alpha/vm_machdep.c
 @@ -152,8 +152,9 @@ cpu_lwp_fork(struct lwp *l1, struct lwp *l2, void 
 *stack, size_t stacksize,
   		 * copy trapframe from parent so return to user mode
   		 * will be to right address, with correct registers.
   		 */
 -		l2tf = l2->l_md.md_tf = (struct trapframe *)
 -		    (uvm_lwp_getuarea(l2) + USPACE - sizeof(struct trapframe));
 +		l2tf = l2->l_md.md_tf = (struct trapframe *)((uintptr_t)
 +		    (uvm_lwp_getuarea(l2) + USPACE - sizeof(struct trapframe)) &
 +			~STACK_ALIGNBYTES);
   		memcpy(l2->l_md.md_tf, l1->l_md.md_tf,
   		    sizeof(struct trapframe));
 
 ```
 



Home | Main Index | Thread Index | Old Index