1.. SPDX-License-Identifier: GPL-2.0 2 3Using FS and GS segments in user space applications 4=================================================== 5 6The x86 architecture supports segmentation. Instructions which access 7memory can use segment register based addressing mode. The following 8notation is used to address a byte within a segment: 9 10 Segment-register:Byte-address 11 12The segment base address is added to the Byte-address to compute the 13resulting virtual address which is accessed. This allows to access multiple 14instances of data with the identical Byte-address, i.e. the same code. The 15selection of a particular instance is purely based on the base-address in 16the segment register. 17 18In 32-bit mode the CPU provides 6 segments, which also support segment 19limits. The limits can be used to enforce address space protections. 20 21In 64-bit mode the CS/SS/DS/ES segments are ignored and the base address is 22always 0 to provide a full 64bit address space. The FS and GS segments are 23still functional in 64-bit mode. 24 25Common FS and GS usage 26------------------------------ 27 28The FS segment is commonly used to address Thread Local Storage (TLS). FS 29is usually managed by runtime code or a threading library. Variables 30declared with the '__thread' storage class specifier are instantiated per 31thread and the compiler emits the FS: address prefix for accesses to these 32variables. Each thread has its own FS base address so common code can be 33used without complex address offset calculations to access the per thread 34instances. Applications should not use FS for other purposes when they use 35runtimes or threading libraries which manage the per thread FS. 36 37The GS segment has no common use and can be used freely by 38applications. GCC and Clang support GS based addressing via address space 39identifiers. 40 41Reading and writing the FS/GS base address 42------------------------------------------ 43 44There exist two mechanisms to read and write the FS/GS base address: 45 46 - the arch_prctl() system call 47 48 - the FSGSBASE instruction family 49 50Accessing FS/GS base with arch_prctl() 51-------------------------------------- 52 53 The arch_prctl(2) based mechanism is available on all 64-bit CPUs and all 54 kernel versions. 55 56 Reading the base: 57 58 arch_prctl(ARCH_GET_FS, &fsbase); 59 arch_prctl(ARCH_GET_GS, &gsbase); 60 61 Writing the base: 62 63 arch_prctl(ARCH_SET_FS, fsbase); 64 arch_prctl(ARCH_SET_GS, gsbase); 65 66 The ARCH_SET_GS prctl may be disabled depending on kernel configuration 67 and security settings. 68 69Accessing FS/GS base with the FSGSBASE instructions 70--------------------------------------------------- 71 72 With the Ivy Bridge CPU generation Intel introduced a new set of 73 instructions to access the FS and GS base registers directly from user 74 space. These instructions are also supported on AMD Family 17H CPUs. The 75 following instructions are available: 76 77 =============== =========================== 78 RDFSBASE %reg Read the FS base register 79 RDGSBASE %reg Read the GS base register 80 WRFSBASE %reg Write the FS base register 81 WRGSBASE %reg Write the GS base register 82 =============== =========================== 83 84 The instructions avoid the overhead of the arch_prctl() syscall and allow 85 more flexible usage of the FS/GS addressing modes in user space 86 applications. This does not prevent conflicts between threading libraries 87 and runtimes which utilize FS and applications which want to use it for 88 their own purpose. 89 90FSGSBASE instructions enablement 91^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 92 The instructions are enumerated in CPUID leaf 7, bit 0 of EBX. If 93 available /proc/cpuinfo shows 'fsgsbase' in the flag entry of the CPUs. 94 95 The availability of the instructions does not enable them 96 automatically. The kernel has to enable them explicitly in CR4. The 97 reason for this is that older kernels make assumptions about the values in 98 the GS register and enforce them when GS base is set via 99 arch_prctl(). Allowing user space to write arbitrary values to GS base 100 would violate these assumptions and cause malfunction. 101 102 On kernels which do not enable FSGSBASE the execution of the FSGSBASE 103 instructions will fault with a #UD exception. 104 105 The kernel provides reliable information about the enabled state in the 106 ELF AUX vector. If the HWCAP2_FSGSBASE bit is set in the AUX vector, the 107 kernel has FSGSBASE instructions enabled and applications can use them. 108 The following code example shows how this detection works:: 109 110 #include <sys/auxv.h> 111 #include <elf.h> 112 113 /* Will be eventually in asm/hwcap.h */ 114 #ifndef HWCAP2_FSGSBASE 115 #define HWCAP2_FSGSBASE (1 << 1) 116 #endif 117 118 .... 119 120 unsigned val = getauxval(AT_HWCAP2); 121 122 if (val & HWCAP2_FSGSBASE) 123 printf("FSGSBASE enabled\n"); 124 125FSGSBASE instructions compiler support 126^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 127 128GCC version 4.6.4 and newer provide instrinsics for the FSGSBASE 129instructions. Clang 5 supports them as well. 130 131 =================== =========================== 132 _readfsbase_u64() Read the FS base register 133 _readfsbase_u64() Read the GS base register 134 _writefsbase_u64() Write the FS base register 135 _writegsbase_u64() Write the GS base register 136 =================== =========================== 137 138To utilize these instrinsics <immintrin.h> must be included in the source 139code and the compiler option -mfsgsbase has to be added. 140 141Compiler support for FS/GS based addressing 142------------------------------------------- 143 144GCC version 6 and newer provide support for FS/GS based addressing via 145Named Address Spaces. GCC implements the following address space 146identifiers for x86: 147 148 ========= ==================================== 149 __seg_fs Variable is addressed relative to FS 150 __seg_gs Variable is addressed relative to GS 151 ========= ==================================== 152 153The preprocessor symbols __SEG_FS and __SEG_GS are defined when these 154address spaces are supported. Code which implements fallback modes should 155check whether these symbols are defined. Usage example:: 156 157 #ifdef __SEG_GS 158 159 long data0 = 0; 160 long data1 = 1; 161 162 long __seg_gs *ptr; 163 164 /* Check whether FSGSBASE is enabled by the kernel (HWCAP2_FSGSBASE) */ 165 .... 166 167 /* Set GS base to point to data0 */ 168 _writegsbase_u64(&data0); 169 170 /* Access offset 0 of GS */ 171 ptr = 0; 172 printf("data0 = %ld\n", *ptr); 173 174 /* Set GS base to point to data1 */ 175 _writegsbase_u64(&data1); 176 /* ptr still addresses offset 0! */ 177 printf("data1 = %ld\n", *ptr); 178 179 180Clang does not provide the GCC address space identifiers, but it provides 181address spaces via an attribute based mechanism in Clang 2.6 and newer 182versions: 183 184 ==================================== ===================================== 185 __attribute__((address_space(256)) Variable is addressed relative to GS 186 __attribute__((address_space(257)) Variable is addressed relative to FS 187 ==================================== ===================================== 188 189FS/GS based addressing with inline assembly 190------------------------------------------- 191 192In case the compiler does not support address spaces, inline assembly can 193be used for FS/GS based addressing mode:: 194 195 mov %fs:offset, %reg 196 mov %gs:offset, %reg 197 198 mov %reg, %fs:offset 199 mov %reg, %gs:offset 200