Back to home page

OSCL-LXR

 
 

    


0001 .. SPDX-License-Identifier: GPL-2.0
0002 
0003 Using FS and GS segments in user space applications
0004 ===================================================
0005 
0006 The x86 architecture supports segmentation. Instructions which access
0007 memory can use segment register based addressing mode. The following
0008 notation is used to address a byte within a segment:
0009 
0010   Segment-register:Byte-address
0011 
0012 The segment base address is added to the Byte-address to compute the
0013 resulting virtual address which is accessed. This allows to access multiple
0014 instances of data with the identical Byte-address, i.e. the same code. The
0015 selection of a particular instance is purely based on the base-address in
0016 the segment register.
0017 
0018 In 32-bit mode the CPU provides 6 segments, which also support segment
0019 limits. The limits can be used to enforce address space protections.
0020 
0021 In 64-bit mode the CS/SS/DS/ES segments are ignored and the base address is
0022 always 0 to provide a full 64bit address space. The FS and GS segments are
0023 still functional in 64-bit mode.
0024 
0025 Common FS and GS usage
0026 ------------------------------
0027 
0028 The FS segment is commonly used to address Thread Local Storage (TLS). FS
0029 is usually managed by runtime code or a threading library. Variables
0030 declared with the '__thread' storage class specifier are instantiated per
0031 thread and the compiler emits the FS: address prefix for accesses to these
0032 variables. Each thread has its own FS base address so common code can be
0033 used without complex address offset calculations to access the per thread
0034 instances. Applications should not use FS for other purposes when they use
0035 runtimes or threading libraries which manage the per thread FS.
0036 
0037 The GS segment has no common use and can be used freely by
0038 applications. GCC and Clang support GS based addressing via address space
0039 identifiers.
0040 
0041 Reading and writing the FS/GS base address
0042 ------------------------------------------
0043 
0044 There exist two mechanisms to read and write the FS/GS base address:
0045 
0046  - the arch_prctl() system call
0047 
0048  - the FSGSBASE instruction family
0049 
0050 Accessing FS/GS base with arch_prctl()
0051 --------------------------------------
0052 
0053  The arch_prctl(2) based mechanism is available on all 64-bit CPUs and all
0054  kernel versions.
0055 
0056  Reading the base:
0057 
0058    arch_prctl(ARCH_GET_FS, &fsbase);
0059    arch_prctl(ARCH_GET_GS, &gsbase);
0060 
0061  Writing the base:
0062 
0063    arch_prctl(ARCH_SET_FS, fsbase);
0064    arch_prctl(ARCH_SET_GS, gsbase);
0065 
0066  The ARCH_SET_GS prctl may be disabled depending on kernel configuration
0067  and security settings.
0068 
0069 Accessing FS/GS base with the FSGSBASE instructions
0070 ---------------------------------------------------
0071 
0072  With the Ivy Bridge CPU generation Intel introduced a new set of
0073  instructions to access the FS and GS base registers directly from user
0074  space. These instructions are also supported on AMD Family 17H CPUs. The
0075  following instructions are available:
0076 
0077   =============== ===========================
0078   RDFSBASE %reg   Read the FS base register
0079   RDGSBASE %reg   Read the GS base register
0080   WRFSBASE %reg   Write the FS base register
0081   WRGSBASE %reg   Write the GS base register
0082   =============== ===========================
0083 
0084  The instructions avoid the overhead of the arch_prctl() syscall and allow
0085  more flexible usage of the FS/GS addressing modes in user space
0086  applications. This does not prevent conflicts between threading libraries
0087  and runtimes which utilize FS and applications which want to use it for
0088  their own purpose.
0089 
0090 FSGSBASE instructions enablement
0091 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
0092  The instructions are enumerated in CPUID leaf 7, bit 0 of EBX. If
0093  available /proc/cpuinfo shows 'fsgsbase' in the flag entry of the CPUs.
0094 
0095  The availability of the instructions does not enable them
0096  automatically. The kernel has to enable them explicitly in CR4. The
0097  reason for this is that older kernels make assumptions about the values in
0098  the GS register and enforce them when GS base is set via
0099  arch_prctl(). Allowing user space to write arbitrary values to GS base
0100  would violate these assumptions and cause malfunction.
0101 
0102  On kernels which do not enable FSGSBASE the execution of the FSGSBASE
0103  instructions will fault with a #UD exception.
0104 
0105  The kernel provides reliable information about the enabled state in the
0106  ELF AUX vector. If the HWCAP2_FSGSBASE bit is set in the AUX vector, the
0107  kernel has FSGSBASE instructions enabled and applications can use them.
0108  The following code example shows how this detection works::
0109 
0110    #include <sys/auxv.h>
0111    #include <elf.h>
0112 
0113    /* Will be eventually in asm/hwcap.h */
0114    #ifndef HWCAP2_FSGSBASE
0115    #define HWCAP2_FSGSBASE        (1 << 1)
0116    #endif
0117 
0118    ....
0119 
0120    unsigned val = getauxval(AT_HWCAP2);
0121 
0122    if (val & HWCAP2_FSGSBASE)
0123         printf("FSGSBASE enabled\n");
0124 
0125 FSGSBASE instructions compiler support
0126 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
0127 
0128 GCC version 4.6.4 and newer provide instrinsics for the FSGSBASE
0129 instructions. Clang 5 supports them as well.
0130 
0131   =================== ===========================
0132   _readfsbase_u64()   Read the FS base register
0133   _readfsbase_u64()   Read the GS base register
0134   _writefsbase_u64()  Write the FS base register
0135   _writegsbase_u64()  Write the GS base register
0136   =================== ===========================
0137 
0138 To utilize these instrinsics <immintrin.h> must be included in the source
0139 code and the compiler option -mfsgsbase has to be added.
0140 
0141 Compiler support for FS/GS based addressing
0142 -------------------------------------------
0143 
0144 GCC version 6 and newer provide support for FS/GS based addressing via
0145 Named Address Spaces. GCC implements the following address space
0146 identifiers for x86:
0147 
0148   ========= ====================================
0149   __seg_fs  Variable is addressed relative to FS
0150   __seg_gs  Variable is addressed relative to GS
0151   ========= ====================================
0152 
0153 The preprocessor symbols __SEG_FS and __SEG_GS are defined when these
0154 address spaces are supported. Code which implements fallback modes should
0155 check whether these symbols are defined. Usage example::
0156 
0157   #ifdef __SEG_GS
0158 
0159   long data0 = 0;
0160   long data1 = 1;
0161 
0162   long __seg_gs *ptr;
0163 
0164   /* Check whether FSGSBASE is enabled by the kernel (HWCAP2_FSGSBASE) */
0165   ....
0166 
0167   /* Set GS base to point to data0 */
0168   _writegsbase_u64(&data0);
0169 
0170   /* Access offset 0 of GS */
0171   ptr = 0;
0172   printf("data0 = %ld\n", *ptr);
0173 
0174   /* Set GS base to point to data1 */
0175   _writegsbase_u64(&data1);
0176   /* ptr still addresses offset 0! */
0177   printf("data1 = %ld\n", *ptr);
0178 
0179 
0180 Clang does not provide the GCC address space identifiers, but it provides
0181 address spaces via an attribute based mechanism in Clang 2.6 and newer
0182 versions:
0183 
0184  ==================================== =====================================
0185   __attribute__((address_space(256))  Variable is addressed relative to GS
0186   __attribute__((address_space(257))  Variable is addressed relative to FS
0187  ==================================== =====================================
0188 
0189 FS/GS based addressing with inline assembly
0190 -------------------------------------------
0191 
0192 In case the compiler does not support address spaces, inline assembly can
0193 be used for FS/GS based addressing mode::
0194 
0195         mov %fs:offset, %reg
0196         mov %gs:offset, %reg
0197 
0198         mov %reg, %fs:offset
0199         mov %reg, %gs:offset