Page MenuHomeFreeBSD

arm,arm64: Save TLS register in mcontext_t.
Needs ReviewPublic

Authored by jhb on Sep 9 2022, 9:26 AM.
Tags
None
Referenced Files
Unknown Object (File)
Jan 12 2024, 9:01 AM
Unknown Object (File)
Jan 11 2024, 12:15 PM
Unknown Object (File)
Jan 10 2024, 2:48 PM
Unknown Object (File)
Dec 20 2023, 1:49 AM
Unknown Object (File)
Sep 5 2023, 10:36 PM
Unknown Object (File)
Jun 11 2023, 6:28 PM
Unknown Object (File)
May 8 2023, 4:24 AM
Unknown Object (File)
Mar 31 2023, 10:32 AM
Subscribers

Details

Summary

Save the relevent register (tpidrurw for arm, tpidr for arm64) in
mcontext_t in an existing spare slot. Define a new _MC_TLS_VALID flag
set in mc_flags to indicate when the new register field is valid. To
simplify freebsd32 support, this flag uses the same value on both
platforms even though 32-bit arm doesn't use bit 0 of the flags field.
Note that the flags field had to be added on 32-bit arm using a second
spare slot.

Reported by: jrtc27

Diff Detail

Repository
rG FreeBSD src repository
Lint
Lint Skipped
Unit
Tests Skipped
Build Status
Buildable 50548
Build 47439: arc lint + arc unit

Event Timeline

I tested this on arm64 at least and checked the ucontext_t in a signal handler under gdb and mc_tpidr and mc_flags were both correct.

bsd-user will need to be updated...

But this looks good to my eye.

This revision is now accepted and ready to land.Sep 23 2022, 10:11 PM
sys/arm64/arm64/freebsd32_machdep.c
199

This is a bit weird... TPIDRURW is the AArch32 sub register of TPIDR_EL0, with TPIDRURO corresponding to TPIDRRO_EL0. Given TPIDRURW is documented in sys/arm as the "authoritative" one for get_tls, if we're only going to save one then it should be TPIDR_EL0. Note arm64's cpu_set_user_tls's comment is a bit wrong as a result...

sys/arm64/arm64/freebsd32_machdep.c
199

Hmm, then presumably D36503 should be abandoned?

sys/arm64/arm64/freebsd32_machdep.c
199

Yes; the comment in cpu_set_user_tls should be updated instead (though please verify this yourself by looking at sys/arm in case I'm being stupid...)

sys/arm64/arm64/freebsd32_machdep.c
199

So this is all quite odd. In userspace __aeabi_read_tp defined in libc and called by the compiler to resolve TLS returns the value of TPIDRURO. get_tcb() in sys/arm/include/tls.h follows this example (and also matches what the old pthread_md.h used to do).

However, the helper function get_tls() in sys/arm/include/cpufunc.h used in the kernel returns TPIDRURW, and the helper function set_tls() sets both.

In practice what seems to happen is that we store a single TLS value in the pcb in the kernel, and the kernel views TPIDRURW as the source of truth when updating that value in the pcb in cpu_switch. It restores this value to both registers in cpu_switch when switching to the new thread. However, userland only uses TPDIRURO.

Given that we expose mcontext_t to userland, maybe I should rename the 32-bit field to mc_tpidruro instead (or maybe even just call it mc_tp or mc_tpidr)?

Renamed 32-bit field to mc_tipdr

This revision now requires review to proceed.Mar 23 2023, 9:34 PM