相关文章推荐
  • Working with the kernel development community
  • Development tools for the kernel
  • How to write kernel documentation
  • Kernel Hacking Guides
  • Linux Tracing Technologies
  • Kernel Maintainer Handbook
  • fault-injection
  • Kernel Livepatching
  • The Linux driver implementer’s API guide
  • Core API Documentation
  • locking
  • Accounting
  • Block
  • cdrom
  • Linux CPUFreq - CPU frequency and voltage scaling code in the Linux(TM) kernel
  • Integrated Drive Electronics (IDE)
  • Frame Buffer
  • Human Interface Devices (HID)
  • I2C/SMBus Subsystem
  • Industrial I/O
  • InfiniBand
  • NetLabel
  • Linux Networking Documentation
  • pcmcia
  • Power Management
  • TCM Virtual Device
  • timers
  • Serial Peripheral Interface (SPI)
  • 1-Wire Subsystem
  • Linux Watchdog Support
  • Linux Virtualization Support
  • The Linux Input Documentation
  • Linux Hardware Monitoring
  • Linux GPU Driver Developer’s Guide
  • Security Documentation
  • Linux Sound Subsystem Documentation
  • Linux Kernel Crypto API
  • Filesystems in the Linux kernel
  • Linux Memory Management Documentation
  • BPF Documentation
  • USB support
  • Linux PCI Bus Subsystem
  • Linux SCSI Subsystem
  • Assorted Miscellaneous Devices Documentation
  • Linux Scheduler
  • Assembler Annotations
  • ARM Architecture
  • ARM64 Architecture
  • IA-64 Architecture
  • m68k Architecture
  • MIPS-specific Documentation
  • Linux on the Nios II architecture
  • OpenRISC Architecture
  • PA-RISC Architecture
  • powerpc
  • RISC-V architecture
  • s390 Architecture
  • SuperH Interfaces Guide
  • Sparc Architecture
  • x86-specific Documentation
    • 1. The Linux/x86 Boot Protocol
    • 2. x86 Topology
    • 3. Kernel level exception handling
    • 4. Kernel Stacks
    • 5. Kernel Entries
    • 6. Early Printk
    • 7. ORC unwinder
    • 8. Zero Page
    • 9. The TLB
    • 10. MTRR (Memory Type Range Register) control
    • 11. PAT (Page Attribute Table)
    • 12. Linux IOMMU Support
    • 13. Intel(R) TXT Overview
    • 14. AMD Memory Encryption
    • 15. Page Table Isolation (PTI)
    • 16. Microarchitectural Data Sampling (MDS) mitigation
    • 17. The Linux Microcode Loader
    • 18. User Interface for Resource Control feature
    • 19. TSX Async Abort (TAA) mitigation
    • 20. USB Legacy support
    • 21. i386 Support
    • 22. x86_64 Support
      • 22.1. AMD64 Specific Boot Options
      • 22.2. General note on [U]EFI x86_64 support
      • 22.3. Memory Management
      • 22.4. 5-level paging
      • 22.5. Fake NUMA For CPUSets
      • 22.6. Firmware support for CPU hotplug under Linux/x86-64
      • 22.7. Configurable sysfs parameters for the x86-64 machine check code
      • 22.8. Using FS and GS segments in user space applications
        • 22.8.1. Common FS and GS usage
        • 22.8.2. Reading and writing the FS/GS base address
        • 22.8.3. Accessing FS/GS base with arch_prctl()
        • 22.8.4. Accessing FS/GS base with the FSGSBASE instructions
        • 22.8.5. Compiler support for FS/GS based addressing
        • 22.8.6. FS/GS based addressing with inline assembly
        • 22.8. Using FS and GS segments in user space applications

          The x86 architecture supports segmentation. Instructions which access memory can use segment register based addressing mode. The following notation is used to address a byte within a segment:

          Segment-register:Byte-address

          The segment base address is added to the Byte-address to compute the resulting virtual address which is accessed. This allows to access multiple instances of data with the identical Byte-address, i.e. the same code. The selection of a particular instance is purely based on the base-address in the segment register.

          In 32-bit mode the CPU provides 6 segments, which also support segment limits. The limits can be used to enforce address space protections.

          In 64-bit mode the CS/SS/DS/ES segments are ignored and the base address is always 0 to provide a full 64bit address space. The FS and GS segments are still functional in 64-bit mode.

          22.8.1. Common FS and GS usage

          The FS segment is commonly used to address Thread Local Storage (TLS). FS is usually managed by runtime code or a threading library. Variables declared with the ‘__thread’ storage class specifier are instantiated per thread and the compiler emits the FS: address prefix for accesses to these variables. Each thread has its own FS base address so common code can be used without complex address offset calculations to access the per thread instances. Applications should not use FS for other purposes when they use runtimes or threading libraries which manage the per thread FS.

          The GS segment has no common use and can be used freely by applications. GCC and Clang support GS based addressing via address space identifiers.

          22.8.2. Reading and writing the FS/GS base address

          There exist two mechanisms to read and write the FS/GS base address:

        • the arch_prctl() system call
        • the FSGSBASE instruction family
        • 22.8.3. Accessing FS/GS base with arch_prctl()

          The arch_prctl(2) based mechanism is available on all 64-bit CPUs and all kernel versions.

          Reading the base:

          arch_prctl(ARCH_GET_FS, &fsbase); arch_prctl(ARCH_GET_GS, &gsbase);

          Writing the base:

          arch_prctl(ARCH_SET_FS, fsbase); arch_prctl(ARCH_SET_GS, gsbase);

          The ARCH_SET_GS prctl may be disabled depending on kernel configuration and security settings.

          22.8.4. Accessing FS/GS base with the FSGSBASE instructions

          With the Ivy Bridge CPU generation Intel introduced a new set of instructions to access the FS and GS base registers directly from user space. These instructions are also supported on AMD Family 17H CPUs. The following instructions are available:

          The instructions avoid the overhead of the arch_prctl() syscall and allow more flexible usage of the FS/GS addressing modes in user space applications. This does not prevent conflicts between threading libraries and runtimes which utilize FS and applications which want to use it for their own purpose.

          22.8.4.1. FSGSBASE instructions enablement

          The instructions are enumerated in CPUID leaf 7, bit 0 of EBX. If available /proc/cpuinfo shows ‘fsgsbase’ in the flag entry of the CPUs.

          The availability of the instructions does not enable them automatically. The kernel has to enable them explicitly in CR4. The reason for this is that older kernels make assumptions about the values in the GS register and enforce them when GS base is set via arch_prctl(). Allowing user space to write arbitrary values to GS base would violate these assumptions and cause malfunction.

          On kernels which do not enable FSGSBASE the execution of the FSGSBASE instructions will fault with a #UD exception.

          The kernel provides reliable information about the enabled state in the ELF AUX vector. If the HWCAP2_FSGSBASE bit is set in the AUX vector, the kernel has FSGSBASE instructions enabled and applications can use them. The following code example shows how this detection works:

          #include <sys/auxv.h>
          #include <elf.h>
          /* Will be eventually in asm/hwcap.h */
          #ifndef HWCAP2_FSGSBASE
          #define HWCAP2_FSGSBASE        (1 << 1)
          #endif
          unsigned val = getauxval(AT_HWCAP2);
          if (val & HWCAP2_FSGSBASE)
               printf("FSGSBASE enabled\n");
          

          22.8.4.2. FSGSBASE instructions compiler support

          GCC version 4.6.4 and newer provide instrinsics for the FSGSBASE instructions. Clang 5 supports them as well.

          22.8.5. Compiler support for FS/GS based addressing

          GCC version 6 and newer provide support for FS/GS based addressing via Named Address Spaces. GCC implements the following address space identifiers for x86:

          The preprocessor symbols __SEG_FS and __SEG_GS are defined when these address spaces are supported. Code which implements fallback modes should check whether these symbols are defined. Usage example:

          #ifdef __SEG_GS
          long data0 = 0;
          long data1 = 1;
          long __seg_gs *ptr;
          /* Check whether FSGSBASE is enabled by the kernel (HWCAP2_FSGSBASE) */
          /* Set GS base to point to data0 */
          _writegsbase_u64(&data0);
          /* Access offset 0 of GS */
          ptr = 0;
          printf("data0 = %ld\n", *ptr);
          /* Set GS base to point to data1 */
          _writegsbase_u64(&data1);
          /* ptr still addresses offset 0! */
          printf("data1 = %ld\n", *ptr);
          

          Clang does not provide the GCC address space identifiers, but it provides address spaces via an attribute based mechanism in Clang 2.6 and newer versions:

          22.8.6. FS/GS based addressing with inline assembly

          In case the compiler does not support address spaces, inline assembly can be used for FS/GS based addressing mode:

          mov %fs:offset, %reg
          mov %gs:offset, %reg
          mov %reg, %fs:offset
          mov %reg, %gs:offset
          
  •  
    推荐文章