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