Bug 481874 - Add arm64 support for FreeBSD
Summary: Add arm64 support for FreeBSD
Status: RESOLVED FIXED
Alias: None
Product: valgrind
Classification: Developer tools
Component: general (other bugs)
Version First Reported In: 3.22 GIT
Platform: Other FreeBSD
: NOR normal
Target Milestone: ---
Assignee: Paul Floyd
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2024-02-26 21:15 UTC by Paul Floyd
Modified: 2024-04-16 06:06 UTC (History)
1 user (show)

See Also:
Latest Commit:
Version Fixed In:
Sentry Crash Report:


Attachments
Add FreeBSD arm64 support (3.25 MB, patch)
2024-03-14 12:42 UTC, Paul Floyd
Details
Patch with fix for PPC (3.25 MB, patch)
2024-03-14 18:49 UTC, Paul Floyd
Details
Modified except large none test files (141.42 KB, patch)
2024-04-09 18:25 UTC, Paul Floyd
Details
Added except large none test references (258.68 KB, patch)
2024-04-09 18:27 UTC, Paul Floyd
Details
slimmed down patch (363.99 KB, patch)
2024-04-12 20:21 UTC, Paul Floyd
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Paul Floyd 2024-02-26 21:15:07 UTC
Title says it all.
Comment 1 Paul Floyd 2024-03-04 04:18:28 UTC
Getting fairly close now. Roughly 30 regtest failures out of 700 odd.

The biggest problem now seems to be fixup_guest_state_after_syscall_interrupted. I need to find a cleaner way to tell that we’ve gone off into VEX to set the value of the carry flag.

Get context/setcontext aren’t working either.
Comment 2 Paul Floyd 2024-03-06 09:28:50 UTC
Fixed fixup_guest_state_after_syscall_interrupted.

Now just a few major issues outstanding.

memcheck/tests/sem is crashing with a corrupt stack. The TC does "ret = semctl (semid, 0, SETALL, semarray);" and internally we do a semctl IPC_STAT to get the number of semaphores so that we can do a PRE_MEM_READ on the semaphores of the set.

none/tests/pth_cancel1 is hanging

none/tests/freebsd/swapcontext crashes when trying to free the context stack

none/tests/freebsd/swapcontext there's a problem with the signal mask getting corrupted which means that  SIGHUP gets delivered to the guest when it should be masked.
Comment 3 Paul Floyd 2024-03-06 09:29:38 UTC
The last one above should be none/tests/pending
Comment 4 Paul Floyd 2024-03-14 07:34:39 UTC
== 725 tests, 4 stderr failures, 0 stdout failures, 0 stderrB failures, 0 stdoutB failures, 0 post failures ==
memcheck/tests/descr_belowsp             (stderr)
memcheck/tests/manuel1                   (stderr)
memcheck/tests/supp_unknown              (stderr)
memcheck/tests/thread_alloca             (stderr)


The first one is a known issue, both the kernel and libthr add guard pages to pthread stacks.
The second one is flaky.
I haven't looked at the third one.
The last one is intermittent. Maybe a real error in ldrt.

$ git diff --stat  master
 Makefile.all.am                                   |     4 +
 Makefile.tool.am                                  |    11 +
 NEWS                                              |     7 +-
 VEX/auxprogs/genoffsets.c                         |     1 +
 VEX/priv/guest_arm64_defs.h                       |     2 +-
 VEX/priv/guest_arm64_helpers.c                    |    22 +
 VEX/priv/guest_arm64_toIR.c                       |    19 +-
 VEX/pub/libvex_guest_amd64.h                      |     7 -
 VEX/pub/libvex_guest_arm64.h                      |    14 +-
 configure.ac                                      |    92 +-
 coregrind/Makefile.am                             |     4 +
 coregrind/launcher-freebsd.c                      |     6 +-
 coregrind/m_aspacemgr/aspacemgr-common.c          |     2 +-
 coregrind/m_aspacemgr/aspacemgr-linux.c           |     6 +
 coregrind/m_coredump/coredump-elf.c               |    73 +
 coregrind/m_debuginfo/d3basics.c                  |     2 +-
 coregrind/m_debuginfo/debuginfo.c                 |    14 +-
 coregrind/m_debuginfo/readdwarf.c                 |     4 +-
 coregrind/m_debuginfo/readelf.c                   |     3 +-
 coregrind/m_debuglog.c                            |    73 +
 coregrind/m_dispatch/dispatch-arm64-freebsd.S     |   316 +
 coregrind/m_initimg/initimg-freebsd.c             |    21 +
 coregrind/m_libcassert.c                          |     2 +-
 coregrind/m_libcfile.c                            |     4 +-
 coregrind/m_libcproc.c                            |     4 +-
 coregrind/m_libcsetjmp.c                          |   144 +-
 coregrind/m_machine.c                             |     3 +
 coregrind/m_main.c                                |    33 +-
 coregrind/m_redir.c                               |     2 +-
 coregrind/m_scheduler/scheduler.c                 |     2 +-
 coregrind/m_sigframe/sigframe-arm64-freebsd.c     |   373 ++
 coregrind/m_signals.c                             |    23 +
 coregrind/m_stacktrace.c                          |    10 +-
 coregrind/m_syscall.c                             |    50 +
 coregrind/m_syswrap/priv_types_n_macros.h         |    22 +-
 coregrind/m_syswrap/syscall-arm64-freebsd.S       |   195 +
 coregrind/m_syswrap/syswrap-arm64-freebsd.c       |  1132 ++++
 coregrind/m_syswrap/syswrap-freebsd.c             |    17 +-
 coregrind/m_syswrap/syswrap-main.c                |   152 +-
 coregrind/m_trampoline.S                          |    43 +
 coregrind/m_translate.c                           |     2 +-
 coregrind/pub_core_machine.h                      |     2 +-
 coregrind/pub_core_mallocfree.h                   |     1 +
 coregrind/pub_core_syscall.h                      |     1 +
 coregrind/pub_core_trampoline.h                   |     4 +
 coregrind/vgdb-invoker-freebsd.c                  |    12 +-
 freebsd-drd.supp                                  |    11 +-
 freebsd-helgrind.supp                             |     5 +
 gdbserver_tests/mcsignopass.stderr.exp            |     4 +-
 gdbserver_tests/mcsignopass.stdoutB.exp           |    48 +-
 gdbserver_tests/mcsigpass.stderr.exp              |     4 +-
 gdbserver_tests/mcsigpass.stdoutB.exp             |    12 +-
 helgrind/tests/tc07_hbl1.c                        |     5 +-
 helgrind/tests/tc08_hbl2.c                        |     5 +-
 helgrind/tests/tc11_XCHG.c                        |     6 +-
 include/Makefile.am                               |     2 +
 include/pub_tool_libcsetjmp.h                     |     4 +-
 include/pub_tool_machine.h                        |     2 +-
 include/pub_tool_vkiscnums_asm.h                  |     2 +-
 include/valgrind.h.in                             |    11 +-
 include/vki/vki-arm64-freebsd.h                   |   180 +
 include/vki/vki-freebsd.h                         |    48 +-
 include/vki/vki-machine-types-arm64-freebsd.h     |    77 +
 massif/tests/Makefile.am                          |     5 +-
 massif/tests/pages_as_heap.vgtest                 |     1 +
 memcheck/tests/Makefile.am                        |     8 +-
 memcheck/tests/brk2.vgtest                        |     1 +
 memcheck/tests/freebsd/Makefile.am                |     1 +
 memcheck/tests/freebsd/filter_context             |     3 +-
 memcheck/tests/freebsd/filter_realpathat          |     1 +
 memcheck/tests/freebsd/get_set_context.c          |    38 +-
 memcheck/tests/freebsd/get_set_context.stderr.exp |    44 +-
 memcheck/tests/freebsd/realpathat.stderr.exp      |     2 +-
 memcheck/tests/freebsd/scalar.c                   |    22 +-
 memcheck/tests/freebsd/scalar.stderr.exp-arm64    |  5452 +++++++++++++++++
 memcheck/tests/leak-segv-jmp.c                    |    50 +-
 memcheck/tests/leak-segv-jmp.stderr.exp           |    20 +-
 memcheck/tests/leak.h                             |    24 +
 memcheck/tests/overlap.stderr.exp-no_memcpy       |    20 +
 none/tests/arm64/Makefile.am                      |     2 +
 none/tests/arm64/cvtf_imm.c                       |    48 +-
 none/tests/arm64/fp_and_simd.c                    |    12 +-
 none/tests/arm64/fp_and_simd.stdout.exp           |     4 +-
 none/tests/arm64/fp_and_simd.stdout.exp-freebsd   | 29511 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 none/tests/arm64/integer.c                        |  1664 ++---
 none/tests/arm64/integer.stdout.exp               |   476 +-
 none/tests/arm64/memory.stdout.exp-clang          | 26358 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 none/tests/arm64/simd_v81.c                       |    52 +-
 none/tests/arm64/simd_v81.stdout.exp              |    48 +-
 none/tests/faultstatus.c                          |     4 +
 none/tests/freebsd/Makefile.am                    |     1 +
 none/tests/freebsd/auxv.stderr.exp-arm64          |    30 +
 shared/vg_replace_strmem.c                        |     3 +-
 tests/arch_test.c                                 |     2 +-
 tests/arm64_features.c                            |   109 +
 95 files changed, 65909 insertions(+), 1469 deletions(-)
Comment 5 Paul Floyd 2024-03-14 09:34:41 UTC
Most of the changes are the stuff that's needed for any new VGP: adding VGP_arm64_freebsd to may places, implementing initimg, aspacemgr, debuglog, syscall, sigframe, trampoline, vki headers.

There is no brk function so I had to disable that in the tests.

I had a lot of problems with none/tests/arm64. clang really did not like the GCC dialect or aarch64 assembler. I had to fix a lot of errors
 - use of redundant offsets that GCC accepts but clang rejects
 - use of x registers where w registers should be used
There were also a huge number of warnings (I still haven't fixed them all).
I added new expecteds for fp_and_simd because there's a printf of a nan that has the topmost (negative) bit set. glibc outputs "-nan" but FreeBSD libc outputs just "nan". The behaviour is defined as platform dependent in the C standard. Nevertheless I did open a bugzilla item for it https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=277612 .
There's also a new expected for memory. The problem here is that the testcase reads its own code, which is using inline assembler. That means it is at the mercy of the compiler for the register allocation. GCC uses x0, clang uses x8. Maybe the testcase should be modified to select opcodes that don't depend on the compiler.

Next few steps
 - clean up the none tests warnings
 - test on buildbot
 - test on a few cfarm machines
Comment 6 Paul Floyd 2024-03-14 12:42:40 UTC
Created attachment 167164 [details]
Add FreeBSD arm64 support
Comment 7 Paul Floyd 2024-03-14 13:42:06 UTC
(In reply to Paul Floyd from comment #6)
> Created attachment 167164 [details]
> Add FreeBSD arm64 support

Broke ppc64. Will try again soon.
Comment 8 Paul Floyd 2024-03-14 18:49:29 UTC
Created attachment 167199 [details]
Patch with fix for PPC
Comment 9 Mark Wielaard 2024-04-09 16:46:42 UTC
This is such a huge patch that I don't really know where to start.
Can this be split up a little?

Maybe have the changes needed to compile with clang instead of gcc separate from the rest? Or does freebsd arm64 only support building with clang?

Likewise maybe separate the VEX/corgrind stuff from the tools and the tests?

I randomly looked at the sbrk changes for the testcases. Which seems necessary because freebsd doesn't have sbrk on arm64 or riscv. That configure check and disabling of dw4 and pages_as_heap seem fine.

In VEX. What are the priv/guest_arm64_toIR.c changes for?

You need LibVEX_GuestARM64_put_nzcv_c to signal syscall success/failure.
I am not fully clear what the guest_SETC is for. The guest_SC_CLASS seems to be to determine how syscall numbers are passed.
Would it make sense to only include those fields, and padding, for freebsd?
Comment 10 Paul Floyd 2024-04-09 18:05:54 UTC
(In reply to Mark Wielaard from comment #9)

> You need LibVEX_GuestARM64_put_nzcv_c to signal syscall success/failure.
> I am not fully clear what the guest_SETC is for.

If there is an asynchronous interrupt during a guest syscall we need to figure out where to restart the syscall. On Linux that is fairly straightforward. The assembler for ML_(do_syscall_for_client_WRK) has markers for the various stages and we just compare the PC to those markers.

On FreeBSD and macOS things are different because of the carry flag for the syscall status. That gets set by a function call. So if the interrupt happens in the function call (LibVEX_GuestARM64_put_nzcv_c) the PC is no good. We can reliably know the address of the start of the function, but that's all. In this case there are also several helper functions. A while back I was using a hack by putting a dummy function after the 'set carry' function. That doesn't work on ARM64 so I switched to using a flag.
Comment 11 Paul Floyd 2024-04-09 18:12:43 UTC
(In reply to Mark Wielaard from comment #9)
 
> In VEX. What are the priv/guest_arm64_toIR.c changes for?

Just some whitespace diffs. I've restored them.

> Would it make sense to only include those fields, and padding, for freebsd?

Yes but that won't work with genoffsets which doesn't support conditional compilation.
Comment 12 Paul Floyd 2024-04-09 18:25:14 UTC
Created attachment 168311 [details]
Modified except large none test files

git diff master --diff-filter=M  ':(exclude)none/tests/arm64/integer.c' ':(exclude)none/tests/arm64/integer.stdout.exp' > modified1.diff
Comment 13 Paul Floyd 2024-04-09 18:27:28 UTC
Created attachment 168313 [details]
Added except large none test references

 git diff master --diff-filter=A  ':(exclude)none/tests/arm64/fp_and_simd.stdout.exp-freebsd' ':(exclude)none/tests/arm64/memory_test.stdout.exp-clang' > added1.diff
Comment 14 Paul Floyd 2024-04-09 18:29:47 UTC
The diffs for the new none expecteds (compared to the originals) are fairly small

diff none/tests/arm64/fp_and_simd.stdout.exp-freebsd none/tests/arm64/fp_and_simd.stdout.exp
44c44
< special value 7 = nan
---
> special value 7 = -nan

I could add a filter instead of the expected.

iff none/tests/arm64/memory_test.stdout.exp none/tests/arm64/memory_test.stdout.exp-clang
7582c7582
<   76e0f98045156b32  v17.d[0] (xor, xfer vecreg #1)
---
>   76e0f98045156a32  v17.d[0] (xor, xfer vecreg #1)
7612c7612
<   07cfd3de4a8087e3  v17.d[0] (xor, xfer vecreg #1)
---
>   07cfd2de4a8086e3  v17.d[0] (xor, xfer vecreg #1)
7642,7643c7642,7643
<   04a3c72e55e713a0  v17.d[0] (xor, xfer vecreg #1)
<   67bbbee861cf4eb2  v17.d[1] (xor, xfer vecreg #1)
---
>   04a3c62e55e712a0  v17.d[0] (xor, xfer vecreg #1)
>   67bbbfe861cf4fb2  v17.d[1] (xor, xfer vecreg #1)

That would be a bit trickier to filter.
Comment 15 Paul Floyd 2024-04-09 18:34:04 UTC
The last two files with big diffs are

none/tests/arm64/integer.c

(clang moaned about integer conversions so I added LL suffixes and also clang was strict about only accepting 32bit w registers where gcc accepts x registers).

The expected reflects the change from x to w.
Comment 16 Paul Floyd 2024-04-12 20:21:52 UTC
Created attachment 168432 [details]
slimmed down patch

I've updated the 'none' testcases from Linux arm64 which makes the patch a lot smaller.

The big bits are now the scalar expected and the new files.
Comment 17 Mark Wielaard 2024-04-15 17:20:28 UTC
.git-blame-ignore-revs references a clang-format rev that doesn't exist in tree.

Makefile.all.am and Makefile.tool.am look correct.

NEWS OK.

VEX changes OK, except for unnecessarily extending VexGuestARM64State for non-freebsd systems.
Would be really nice if that VEX/auxprogs/genoffsets.c GENOFFSET(ARM64,arm64,SETC); could only
be done of freebsd. 

configure.ac looks OK (but not a fan of the reindentations, it makes looking for the actual changes a bit of a pain)

coregrind/launcher-freebsd.c OK

coregrind/m_aspacemgr changes OK (aspacemgr-linux.c is clearly a bad name, but lets not rename it for now).

coregrind/m_coredump/coredump-elf.c looks correct (do we have any tests for this? I don't believe we do).

coregrind/m_debuginfo changes look OK.

coregrind/m_debuglog.c dunno why there is a clang and gcc variant of local_sys_write_stderr. One uses SizeT the other Unt (should be Int).

coregrind/m_dispatch/dispatch-arm64-freebsd.S Not sure I am qualified to review this voodoo.

coregrind/m_initimg/initimg-freebsd.c looks OK

coregrind/m_libcassert.c, coregrind/m_libcfile.c, coregrind/m_libcsetjmp.c OK
Comment 18 Paul Floyd 2024-04-15 18:13:53 UTC
(In reply to Mark Wielaard from comment #17)
> .git-blame-ignore-revs references a clang-format rev that doesn't exist in
> tree.

Its for the repo on github. I'm not planning on pushing that.

> VEX changes OK, except for unnecessarily extending VexGuestARM64State for
> non-freebsd systems.
> Would be really nice if that VEX/auxprogs/genoffsets.c
> GENOFFSET(ARM64,arm64,SETC); could only
> be done of freebsd. 

I don't think it's too much a big deal - there's only one VexGuestARM64State  per thread.

> 
> coregrind/m_coredump/coredump-elf.c looks correct (do we have any tests for
> this? I don't believe we do).

FreeBSD needs to have its own core dump routines - as I understand it each OS uses a different layout. Nobody has asked me to fix it yet. It builds and it dumps a core file.

> coregrind/m_debuglog.c dunno why there is a clang and gcc variant of
> local_sys_write_stderr. One uses SizeT the other Unt (should be Int).

I used two version, the Linux and one from the out of tree Darwin port. Both only work with one compiler. I'll leave it for now and add it to my todo list.
Comment 19 Paul Floyd 2024-04-16 06:06:52 UTC
commit 26924849826afac5de630916d9fb516a270a51ee (HEAD -> master, origin/master, origin/HEAD)
Author: Paul Floyd <pjfloyd@wanadoo.fr>
Date:   Tue Apr 16 07:39:33 2024 +0200

    Bug 481874 - Add arm64 support for FreeBSD