xref: /OK3568_Linux_fs/kernel/Documentation/x86/x86_64/fsgs.rst (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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