Skip to content

Commit 82c0c7d

Browse files
committed
Documentation/x86/64: Add documentation for GS/FS addressing mode
Explain how the GS/FS based addressing can be utilized in user space applications along with the differences between the generic prctl() based GS/FS base control and the FSGSBASE version available on newer CPUs. Originally-by: Andi Kleen <[email protected]> Signed-off-by: Thomas Gleixner <[email protected]> Signed-off-by: Chang S. Bae <[email protected]> Signed-off-by: Sasha Levin <[email protected]> Signed-off-by: Thomas Gleixner <[email protected]> Reviewed-by: Tony Luck <[email protected]> Link: https://lkml.kernel.org/r/[email protected]
1 parent 742c45c commit 82c0c7d

File tree

2 files changed

+200
-0
lines changed

2 files changed

+200
-0
lines changed

Documentation/x86/x86_64/fsgs.rst

Lines changed: 199 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,199 @@
1+
.. SPDX-License-Identifier: GPL-2.0
2+
3+
Using FS and GS segments in user space applications
4+
===================================================
5+
6+
The x86 architecture supports segmentation. Instructions which access
7+
memory can use segment register based addressing mode. The following
8+
notation is used to address a byte within a segment:
9+
10+
Segment-register:Byte-address
11+
12+
The segment base address is added to the Byte-address to compute the
13+
resulting virtual address which is accessed. This allows to access multiple
14+
instances of data with the identical Byte-address, i.e. the same code. The
15+
selection of a particular instance is purely based on the base-address in
16+
the segment register.
17+
18+
In 32-bit mode the CPU provides 6 segments, which also support segment
19+
limits. The limits can be used to enforce address space protections.
20+
21+
In 64-bit mode the CS/SS/DS/ES segments are ignored and the base address is
22+
always 0 to provide a full 64bit address space. The FS and GS segments are
23+
still functional in 64-bit mode.
24+
25+
Common FS and GS usage
26+
------------------------------
27+
28+
The FS segment is commonly used to address Thread Local Storage (TLS). FS
29+
is usually managed by runtime code or a threading library. Variables
30+
declared with the '__thread' storage class specifier are instantiated per
31+
thread and the compiler emits the FS: address prefix for accesses to these
32+
variables. Each thread has its own FS base address so common code can be
33+
used without complex address offset calculations to access the per thread
34+
instances. Applications should not use FS for other purposes when they use
35+
runtimes or threading libraries which manage the per thread FS.
36+
37+
The GS segment has no common use and can be used freely by
38+
applications. GCC and Clang support GS based addressing via address space
39+
identifiers.
40+
41+
Reading and writing the FS/GS base address
42+
------------------------------------------
43+
44+
There 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+
50+
Accessing 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+
69+
Accessing 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+
90+
FSGSBASE 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+
125+
FSGSBASE instructions compiler support
126+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
127+
128+
GCC version 4.6.4 and newer provide instrinsics for the FSGSBASE
129+
instructions. 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+
138+
To utilize these instrinsics <immintrin.h> must be included in the source
139+
code and the compiler option -mfsgsbase has to be added.
140+
141+
Compiler support for FS/GS based addressing
142+
-------------------------------------------
143+
144+
GCC version 6 and newer provide support for FS/GS based addressing via
145+
Named Address Spaces. GCC implements the following address space
146+
identifiers for x86:
147+
148+
========= ====================================
149+
__seg_fs Variable is addressed relative to FS
150+
__seg_gs Variable is addressed relative to GS
151+
========= ====================================
152+
153+
The preprocessor symbols __SEG_FS and __SEG_GS are defined when these
154+
address spaces are supported. Code which implements fallback modes should
155+
check 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+
180+
Clang does not provide the GCC address space identifiers, but it provides
181+
address spaces via an attribute based mechanism in Clang 2.6 and newer
182+
versions:
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+
189+
FS/GS based addressing with inline assembly
190+
-------------------------------------------
191+
192+
In case the compiler does not support address spaces, inline assembly can
193+
be 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

Documentation/x86/x86_64/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,4 @@ x86_64 Support
1414
fake-numa-for-cpusets
1515
cpu-hotplug-spec
1616
machinecheck
17+
fsgs

0 commit comments

Comments
 (0)