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