On Sun, May 24, 2026 at 4:44 AM Paulo Duarte <[email protected]> wrote:
>
> Three test sources still had only __i386__ / __x86_64__ paths; the
> aarch64 build either failed to compile or had no useful coverage.
> Add aarch64 arms that mirror what the x86 versions exercise:
>
>   tests/test-machmsg.c  test_recv_interrupted_setreturn uses
>        thread_get_state / thread_set_state to override the recv
>        thread's return register before resuming it.  Add an aarch64
>        branch that uses struct aarch64_thread_state and writes the
>        expected return value to x[0] (AAPCS return register).
>
>   tests/test-syscalls.c
>        - test_bad_syscall_num: emit `svc #0` with an unallocated
>          number in w8 (Mach trap numbers are negative; a positive
>          value lands in the kernel's unallocated-trap path).  Update
>          the expected exception in main() to EXC_SOFTWARE /
>          EXC_AARCH64_SVC (the aarch64 categorisation; i386 uses
>          EXC_BAD_INSTRUCTION/EXC_I386_INVOP because its sysenter/
>          lcall paths are typed as illegal instructions instead).
>        - test_syscall_bad_arg_on_stack: skip on aarch64.  AAPCS
>          passes all 7 mach_msg arguments in x0..x6, so there's no
>          "arg on stack" to corrupt;

Have you actually looked at how I ported the tests to AArch64 in my
branch? and at the actual .load_stack_args code path in locore.S that
this is intended to test?

mach_msg is not the only Mach trap that one can test; and specifically
vm_map_trap passes arguments on the stack, which can be corrupted,
which is what test_syscall_bad_arg_on_stack tests in my branch.

> the analogous "bad msg pointer"
>          test is caught by copyinmsg's recovery handler and returns
>          a syscall error rather than raising an exception, so the
>          test's wait-for-EXC_BAD_ACCESS would just hang.
>        - both: replace `FAILURE("we shouldn't be here!")` after the
>          trapping asm with thread_terminate(mach_thread_self()) +
>          busy loop.  The aarch64 SVC entry path always advances ELR
>          past the svc (hardware behaviour, documented in
>          aarch64/trap.c), so when the kernel resumes the thread
>          after the exception handler returns KERN_SUCCESS, user
>          code runs and would otherwise emit a spurious failure
>          marker.  Self-terminate to avoid that race.
>
>   tests/test-thread-state-fp.c
>        New test_fp_state_getset_aarch64() exercises NEON V
>        registers + FPCR via thread_get_state/thread_set_state.
>        Shape mirrors the x86 test_xfp_state_getset:
>          1. test thread loads known values into V3 and FPCR
>          2. spawns helper, suspends self
>          3. helper reads state, verifies V3 / FPCR are preserved,
>             writes V7 + new FPCR, resumes
>          4. test thread reads V7 / FPCR via inline asm and asserts
>             they reflect the helper's writes
>        Use a file-scope `static struct aarch64_float_state state` —
>        the type's 16-byte alignment requirement from __int128 v[32]
>        isn't always honoured by aarch64-unknown-none-elf-gcc when
>        the struct is a function-local across nested calls.
>        main() gains an `__aarch64__` branch that calls the new
>        test in place of the x86 test_fp_state_getset /
>        test_xfp_state_getset.
>
> All 11 USER_TESTS now pass under qemu-system-aarch64 -M virt + the
> guest-loader test harness on top of the aarch64-port commits.
> ---
>  tests/test-machmsg.c         |  15 +++++
>  tests/test-syscalls.c        |  83 +++++++++++++++++++++--
>  tests/test-thread-state-fp.c | 123 +++++++++++++++++++++++++++++++++++
>  3 files changed, 217 insertions(+), 4 deletions(-)

The actually interesting test is test-thread-state.c, which modules
something like what the glibc signal/fault handling code path does,
via thread_set_state and thread_set_self_state.

Reply via email to