Skip to content

fix: ARM64 TPIDR_EL0, signal trampoline, and /dev/tty controlling terminal#235

Merged
ryanbreen merged 2 commits intomainfrom
fix/aarch64-tpidr-signal-trampoline
Feb 19, 2026
Merged

fix: ARM64 TPIDR_EL0, signal trampoline, and /dev/tty controlling terminal#235
ryanbreen merged 2 commits intomainfrom
fix/aarch64-tpidr-signal-trampoline

Conversation

@ryanbreen
Copy link
Owner

@ryanbreen ryanbreen commented Feb 19, 2026

Summary

  • TPIDR_EL0 save/restore in context switches: The ARM64 Thread Local Storage register was never saved or restored, causing musl libc programs to crash with DATA_ABORT at FAR=0xffffffffffffff5c when TLS accesses (errno, pthread) used a clobbered base pointer
  • Signal trampoline syscall number: Fixed rt_sigreturn from x86_64 number (15) to ARM64 number (139)
  • /dev/tty controlling terminal lookup: Changed from PID match to session ID match so child processes (like ash inside bsh) can find their session's controlling PTY
  • TIOCSCTTY job control: Now also sets foreground_pgid so tcgetpgrp() returns a valid value
  • bwm TIOCSCTTY call: spawn_child now calls TIOCSCTTY after opening PTY slave

Test plan

  • ARM64 boot test passes (zero DATA_ABORT crashes, full boot to window manager)
  • x86_64 boot test passes (no regressions, all kthread/contract tests pass)
  • Interactive ash shell: no "can't access tty" message, job control works

🤖 Generated with Claude Code

ryanbreen and others added 2 commits February 19, 2026 05:16
…e syscall number

Two ARM64 fixes that resolve DATA_ABORT crashes at FAR=0xffffffffffffff5c
when running BusyBox ash shell and musl-linked programs:

1. TPIDR_EL0 (Thread Local Storage pointer) was never saved or restored
   during context switches. When multiple userspace processes share a CPU,
   they clobber each other's TLS pointer. musl libc stores errno and
   pthread structures via TPIDR_EL0, so a zeroed/wrong value causes
   accesses to addresses like 0 - 164 = 0xffffffffffffff5c.

   Added tpidr_el0 field to CpuContext and mrs/msr instructions in all
   5 context switch paths: save_userspace, save_kernel, restore_kernel,
   restore_userspace, and setup_first_entry. Also preserved in
   from_aarch64_frame for fork inheritance.

2. Signal trampoline used x86_64 syscall number 15 for rt_sigreturn
   instead of the correct ARM64 number 139. This caused "Unknown syscall"
   errors when signal handlers returned via the trampoline.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…b control setup

Three fixes for BusyBox ash "can't access tty; job control turned off":

1. /dev/tty open now matches by session ID instead of PID. The controlling
   terminal belongs to the entire session, not just the session leader.
   When ash (child of bsh) opens /dev/tty, it needs to find the PTY that
   bsh (the session leader) set up via TIOCSCTTY. Previously matched by
   PID which failed for any non-session-leader process.

2. TIOCSCTTY now also sets foreground_pgid so tcgetpgrp() returns a valid
   value instead of 0.

3. bwm's spawn_child calls TIOCSCTTY after opening PTY slave, and
   libbreenix gains set_controlling_terminal() wrapper.

Root cause confirmed by independent Codex + Opus investigation (panel of
experts pattern).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@ryanbreen ryanbreen changed the title fix: ARM64 TPIDR_EL0 context switch and signal trampoline fix: ARM64 TPIDR_EL0, signal trampoline, and /dev/tty controlling terminal Feb 19, 2026
@ryanbreen ryanbreen merged commit afe2e5c into main Feb 19, 2026
2 of 4 checks passed
@ryanbreen ryanbreen deleted the fix/aarch64-tpidr-signal-trampoline branch February 19, 2026 11:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant