Skip to content

linux-user: arm kuser helpers, commpage and signal frames - #333

Merged
tamnd merged 1 commit into
mainfrom
m7-a32-sig
Oct 14, 2026
Merged

tamnd merged 1 commit into
mainfrom
m7-a32-sig

Conversation

@tamnd

@tamnd tamnd commented Oct 14, 2026

Copy link
Copy Markdown
Owner

The second qemu-arm slice: the commpage with the kuser helpers, and the arm signal frames.

  • Commpage at 0xffff0000, read and execute, kuser version 5 at 0xffff0ffc. The helpers run in do_kernel_trap() as in QEMU: memory barrier, __kernel_cmpxchg, __kernel_get_tls and __kernel_cmpxchg64, on host atomics. An unaligned address is SIGBUS BUS_ADRALN, a bad one SIGSEGV. Any other address in the page is QEMU's "unhandled CPU exception" abort.
  • sigframe and rt_sigframe with QEMU's layout: the ucontext, the VFP frame (D registers, FPSCR, FPEXC) and the A32 retcode words. Handlers return through the Thumb sigreturn and rt_sigreturn trampolines on their own page. With mmap(0) the page lands where QEMU loads its vDSO, so later mappings line up. Without SA_RESTORER, LR points at the trampolines. Thumb handlers and sigaltstack work. sigreturn and rt_sigreturn restore the core registers, CPSR, the VFP registers and FPSCR. A bad VFP frame is SIGSEGV.
  • target-arm exposes vfp_get_fpscr and vfp_set_fpscr to user mode.

Not included: the trampoline page is not labelled [vdso] and AT_SYSINFO_EHDR stays 0. There is no FDPIC. FPINST and FPINST2 are not kept. Neon comes next.

Compared against QEMU 11.1 qemu-arm on server3 with a static armhf test, built for both Thumb and A32. The output is identical. The test covers:

  • SA_SIGINFO and plain handlers, including the uc_mcontext registers, CPSR, the mask and the VFP frame contents
  • D8 and FPSCR clobbered in a handler and restored after it
  • handlers without SA_RESTORER through a raw rt_sigaction, and A32 handlers from a Thumb program
  • SIGSEGV from a store to 0x10 and to the commpage
  • sigaltstack, and a nested signal held back by sa_mask
  • all four kuser helpers, including a four-thread __kernel_cmpxchg counter, and SIGBUS and SIGSEGV from bad cmpxchg addresses

Hello, the VFP tests and the maps test are unchanged. The maps test differs only in the [vdso] label and AT_SYSINFO_EHDR. A jump to an unknown kuser address aborts as in QEMU, with ruvm's usual short register dump.

Checks:

  • clippy -D warnings, native and x86_64-unknown-linux-gnu
  • fmt
  • the four xtasks
  • the Windows check
  • ruvm-linux-user tests on server3
  • ruvm-target-arm and ruvm-machine-arm tests, which include AArch64 system mode

@tamnd tamnd added this to the M7: User mode milestone Oct 14, 2026
@tamnd tamnd added kind/feature It should do something it does not. area/target Guest ISAs and CPU models. area/user-mode linux-user and bsd-user. labels Oct 14, 2026
@tamnd
tamnd merged commit 320c580 into main Oct 14, 2026
2 checks passed
@tamnd
tamnd deleted the m7-a32-sig branch October 14, 2026 13:06
tamnd added a commit that referenced this pull request Oct 15, 2026
…#346)

Part of #8.

The first Neon slice for AArch32: the integer data-processing
instructions, the loads and stores, and VMOV and VDUP between core
registers and scalars. It covers A32 and T32.

- `neon-dp.decode` and `neon-ls.decode` are generated as for QEMU. T32
encodings are rewritten to their A32 form before decoding, as in
`translate.c`.
- The integer ops include:
  - three registers of the same length, and three of different lengths
  - two registers and a shift, including the narrowing and long forms
  - two registers and a scalar
  - the two-register miscellaneous group without the FP ops
  - VEXT, VTBL/VTBX, VDUP (scalar), VSWP, VTRN/VUZP/VZIP
  - the modified immediates
- They run on the A64 vector helper through a new `a32_neon` helper,
which maps D registers onto the Q registers. FPSCR.QC is set on
saturation. Pair ops write Dm and then Dd, as QEMU does, so VTRN, VUZP
and VZIP with d == m match.
- VLDn/VSTn cover all forms: multiple structures, single lane and all
lanes, with writeback by size or by register. Alignment checks follow
QEMU's `finalize_memop` in user mode, so a hint is checked and the
default alignment is not.
- VMOV between core registers and scalars, and VDUP from a core
register.

Not included: the FP ops (VADD.F32, the FP 2-reg-misc and the
conversions), VRECPE/VRSQRTE, crypto, the neon-shared group, and the
BF16 and dot product ops. They UNDEF for now. HWCAP_NEON stays clear
until the next slice adds them, so glibc doesn't pick Neon routines.

Compared against QEMU 11.1 qemu-arm on server3:
- 10714 generated tests, one instruction each. They are random encodings
in the dp and ls groups plus the VMOV and VDUP forms, with objdump's FP
and crypto forms filtered out. The inputs are random and special D
register values, and base addresses at offsets 0 to 32, so misaligned
hints fault. The tests compare the changed D registers, FPSCR, the base
and Rm registers, the memory written, and SIGILL, SIGSEGV and SIGBUS.
- Built for A32 and for T32, so all 10714 run in both states. 6271 of
them UNDEF on both emulators.
  - The output is identical in both states.
- A vectorized C program at -O1 and -O3 with intrinsics: vld3,
vtbl3/vtbx1, saturating and rounding ops, vmlal_lane, vqdmlsl, zip/uzp
and vpadd. It ran as A32 and as Thumb, and the output and the final
FPSCR match.
- Hello and the VFP tests match.
- The signal tests differ from QEMU in the same way they did before this
slice (already present at #333). In the same environment, one line
differs: the CPSR GE bits in the handler. Change the environment size
and the fault address can also move by 0x10. There are two causes, and
both are in the loader:
- ruvm doesn't provide AT_SYSINFO_EHDR yet, so the auxv is one 8 byte
entry shorter and the initial stack sits 8 bytes higher. After 16 byte
alignment that shows up as a 0x10 shift, depending on the environment
size.
- ruvm masks HWCAP (0x005fa0d7 against QEMU's 0x0fdfb0d7, HWCAP2 0x70
against 0x7f), so glibc picks other string routines. These leave
different GE bits behind.
  The next slice addresses both, along with HWCAP_NEON.

All of the above ran on the merge commit e498d17 (this branch with main
at 2a32ea6 merged in).

Checks, all on e498d17:
- fmt
- clippy -D warnings, native x86_64 Linux and cross for
x86_64-pc-windows-gnu and aarch64-apple-darwin
- tests: ruvm-linux-user, ruvm-target-arm and ruvm-machine-arm (which
include AArch64 system mode), and ruvm-system --lib
- the four xtasks: provenance, unsafe-audit, layers and style
- the release build of ruvm-cli
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/target Guest ISAs and CPU models. area/user-mode linux-user and bsd-user. kind/feature It should do something it does not.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant