22.8. Using FS and GS segments in user space applications¶
The x86 architecture supports segmentation. Instructions which accessmemory can use segment register based addressing mode. The followingnotation is used to address a byte within a segment:
Segment-register:Byte-address
The segment base address is added to the Byte-address to compute theresulting virtual address which is accessed. This allows to access multipleinstances of data with the identical Byte-address, i.e. the same code. Theselection of a particular instance is purely based on the base-address inthe segment register.
In 32-bit mode the CPU provides 6 segments, which also support segmentlimits. The limits can be used to enforce address space protections.
In 64-bit mode the CS/SS/DS/ES segments are ignored and the base address isalways 0 to provide a full 64bit address space. The FS and GS segments arestill functional in 64-bit mode.
22.8.1. Common FS and GS usage¶
The FS segment is commonly used to address Thread Local Storage (TLS). FSis usually managed by runtime code or a threading library. Variablesdeclared with the ‘__thread’ storage class specifier are instantiated perthread and the compiler emits the FS: address prefix for accesses to thesevariables. Each thread has its own FS base address so common code can beused without complex address offset calculations to access the per threadinstances. Applications should not use FS for other purposes when they useruntimes or threading libraries which manage the per thread FS.
The GS segment has no common use and can be used freely byapplications. GCC and Clang support GS based addressing via address spaceidentifiers.
22.8.2. Reading and writing the FS/GS base address¶
There exist two mechanisms to read and write the FS/GS base address:
- the arch_prctl() system call
- the FSGSBASE instruction family
22.8.3. Accessing FS/GS base with arch_prctl()¶
The arch_prctl(2) based mechanism is available on all 64-bit CPUs and allkernel versions.
Reading the base:
arch_prctl(ARCH_GET_FS, &fsbase);arch_prctl(ARCH_GET_GS, &gsbase);Writing the base:
arch_prctl(ARCH_SET_FS, fsbase);arch_prctl(ARCH_SET_GS, gsbase);The ARCH_SET_GS prctl may be disabled depending on kernel configurationand security settings.
22.8.4. Accessing FS/GS base with the FSGSBASE instructions¶
With the Ivy Bridge CPU generation Intel introduced a new set ofinstructions to access the FS and GS base registers directly from userspace. These instructions are also supported on AMD Family 17H CPUs. Thefollowing instructions are available:
RDFSBASE %reg Read the FS base register RDGSBASE %reg Read the GS base register WRFSBASE %reg Write the FS base register WRGSBASE %reg Write the GS base register The instructions avoid the overhead of the arch_prctl() syscall and allowmore flexible usage of the FS/GS addressing modes in user spaceapplications. This does not prevent conflicts between threading librariesand runtimes which utilize FS and applications which want to use it fortheir own purpose.
22.8.4.1. FSGSBASE instructions enablement¶
The instructions are enumerated in CPUID leaf 7, bit 0 of EBX. Ifavailable /proc/cpuinfo shows ‘fsgsbase’ in the flag entry of the CPUs.
The availability of the instructions does not enable themautomatically. The kernel has to enable them explicitly in CR4. Thereason for this is that older kernels make assumptions about the values inthe GS register and enforce them when GS base is set viaarch_prctl(). Allowing user space to write arbitrary values to GS basewould violate these assumptions and cause malfunction.
On kernels which do not enable FSGSBASE the execution of the FSGSBASEinstructions will fault with a #UD exception.
The kernel provides reliable information about the enabled state in theELF AUX vector. If the HWCAP2_FSGSBASE bit is set in the AUX vector, thekernel has FSGSBASE instructions enabled and applications can use them.The following code example shows how this detection works:
#include <sys/auxv.h>#include <elf.h>/* Will be eventually in asm/hwcap.h */#ifndef HWCAP2_FSGSBASE#define HWCAP2_FSGSBASE (1 << 1)#endif....unsigned val = getauxval(AT_HWCAP2);if (val & HWCAP2_FSGSBASE) printf("FSGSBASE enabled\n");
22.8.4.2. FSGSBASE instructions compiler support¶
GCC version 4.6.4 and newer provide instrinsics for the FSGSBASEinstructions. Clang 5 supports them as well.
_readfsbase_u64() Read the FS base register _readfsbase_u64() Read the GS base register _writefsbase_u64() Write the FS base register _writegsbase_u64() Write the GS base register
To utilize these instrinsics <immintrin.h> must be included in the sourcecode and the compiler option -mfsgsbase has to be added.
22.8.5. Compiler support for FS/GS based addressing¶
GCC version 6 and newer provide support for FS/GS based addressing viaNamed Address Spaces. GCC implements the following address spaceidentifiers for x86:
__seg_fs Variable is addressed relative to FS __seg_gs Variable is addressed relative to GS
The preprocessor symbols __SEG_FS and __SEG_GS are defined when theseaddress spaces are supported. Code which implements fallback modes shouldcheck whether these symbols are defined. Usage example:
#ifdef __SEG_GSlong data0 = 0;long data1 = 1;long __seg_gs *ptr;/* Check whether FSGSBASE is enabled by the kernel (HWCAP2_FSGSBASE) */..../* Set GS base to point to data0 */_writegsbase_u64(&data0);/* Access offset 0 of GS */ptr = 0;printf("data0 = %ld\n", *ptr);/* Set GS base to point to data1 */_writegsbase_u64(&data1);/* ptr still addresses offset 0! */printf("data1 = %ld\n", *ptr);Clang does not provide the GCC address space identifiers, but it providesaddress spaces via an attribute based mechanism in Clang 2.6 and newerversions:
__attribute__((address_space(256)) Variable is addressed relative to GS __attribute__((address_space(257)) Variable is addressed relative to FS
22.8.6. FS/GS based addressing with inline assembly¶
In case the compiler does not support address spaces, inline assembly canbe used for FS/GS based addressing mode:
mov %fs:offset, %regmov %gs:offset, %regmov %reg, %fs:offsetmov %reg, %gs:offset