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