diff options
author | ed <ed@FreeBSD.org> | 2016-10-12 09:17:41 +0000 |
---|---|---|
committer | ed <ed@FreeBSD.org> | 2016-10-12 09:17:41 +0000 |
commit | 7c05d1bcc3ae1e7fdf6581cd249a5b0de28fd5c2 (patch) | |
tree | 7ab7108cb2dabd10dfe3a6fdea36e435803075d1 /sys/arm/include | |
parent | 0febaaa5838430d3356cb105ed697d82bbb6397c (diff) | |
download | FreeBSD-src-7c05d1bcc3ae1e7fdf6581cd249a5b0de28fd5c2.zip FreeBSD-src-7c05d1bcc3ae1e7fdf6581cd249a5b0de28fd5c2.tar.gz |
MFC r306162:
Make it possible to safely use TPIDRURW from userspace.
On amd64, arm64 and i386, we have the possibility to switch between TLS
areas in userspace. The nice thing about this is that it makes it easier
to do light-weight threading, if we ever feel like doing that. On armv6,
let's go into the same direction by making it possible to safely use the
TPIDRURW register, which is intended for this purpose.
Clean up the ARMv6 code to remove md_tp entirely. Simply add a dedicated
field to the PCB to hold the value of TPIDRURW across context switches,
like we do for any other register. As userspace currently uses the
read-only TPIDRURO register, simply ensure that we keep both values in
sync where possible. The system calls for modifying the read-only
register will simply write the intended value into both registers, so
that it lazily ends up in the PCB during the next context switch.
Approved by: andrew
Reviewed by: imp
Differential Revision: https://reviews.freebsd.org/D7951
Diffstat (limited to 'sys/arm/include')
-rw-r--r-- | sys/arm/include/frame.h | 4 | ||||
-rw-r--r-- | sys/arm/include/pcpu.h | 13 | ||||
-rw-r--r-- | sys/arm/include/proc.h | 2 |
3 files changed, 16 insertions, 3 deletions
diff --git a/sys/arm/include/frame.h b/sys/arm/include/frame.h index 7655d89..929bc96 100644 --- a/sys/arm/include/frame.h +++ b/sys/arm/include/frame.h @@ -117,6 +117,10 @@ struct switchframe register_t sf_sp; register_t sf_lr; register_t sf_pc; +#if __ARM_ARCH >= 6 + register_t sf_tpidrurw; + register_t sf_spare0; +#endif }; diff --git a/sys/arm/include/pcpu.h b/sys/arm/include/pcpu.h index 19cb666..c9ebd5e 100644 --- a/sys/arm/include/pcpu.h +++ b/sys/arm/include/pcpu.h @@ -103,7 +103,8 @@ get_tls(void) { void *tls; - __asm __volatile("mrc p15, 0, %0, c13, c0, 3" : "=r" (tls)); + /* TPIDRURW contains the authoritative value. */ + __asm __volatile("mrc p15, 0, %0, c13, c0, 2" : "=r" (tls)); return (tls); } @@ -111,7 +112,15 @@ static inline void set_tls(void *tls) { - __asm __volatile("mcr p15, 0, %0, c13, c0, 3" : : "r" (tls)); + /* + * Update both TPIDRURW and TPIDRURO. TPIDRURW needs to be written + * first to ensure that a context switch between the two writes will + * still give the desired result of updating both. + */ + __asm __volatile( + "mcr p15, 0, %0, c13, c0, 2\n" + "mcr p15, 0, %0, c13, c0, 3\n" + : : "r" (tls)); } #define curthread get_curthread() diff --git a/sys/arm/include/proc.h b/sys/arm/include/proc.h index 5d42d07..fc4b31e 100644 --- a/sys/arm/include/proc.h +++ b/sys/arm/include/proc.h @@ -53,8 +53,8 @@ struct mdthread { int md_ptrace_addr; int md_ptrace_instr_alt; int md_ptrace_addr_alt; - register_t md_tp; #if __ARM_ARCH < 6 + register_t md_tp; void *md_ras_start; void *md_ras_end; #endif |