1 /* SPDX-License-Identifier: GPL-2.0-only */ 2 #ifndef _ASM_X86_GSSEG_H 3 #define _ASM_X86_GSSEG_H 4 5 #include <linux/types.h> 6 7 #include <asm/asm.h> 8 #include <asm/cpufeature.h> 9 #include <asm/alternative.h> 10 #include <asm/processor.h> 11 #include <asm/nops.h> 12 13 #ifdef CONFIG_X86_64 14 15 extern asmlinkage void asm_load_gs_index(u16 selector); 16 17 /* Replace with "lkgs %di" once binutils support LKGS instruction */ 18 #define LKGS_DI _ASM_BYTES(0xf2,0x0f,0x00,0xf7) 19 20 static inline void native_lkgs(unsigned int selector) 21 { 22 u16 sel = selector; 23 asm_inline volatile("1: " LKGS_DI 24 _ASM_EXTABLE_TYPE_REG(1b, 1b, EX_TYPE_ZERO_REG, %k[sel]) 25 : [sel] "+D" (sel)); 26 } 27 28 static inline void native_load_gs_index(unsigned int selector) 29 { 30 if (cpu_feature_enabled(X86_FEATURE_LKGS)) { 31 native_lkgs(selector); 32 } else { 33 unsigned long flags; 34 35 local_irq_save(flags); 36 asm_load_gs_index(selector); 37 local_irq_restore(flags); 38 } 39 } 40 41 #endif /* CONFIG_X86_64 */ 42 43 static inline void __init lkgs_init(void) 44 { 45 #ifdef CONFIG_PARAVIRT_XXL 46 #ifdef CONFIG_X86_64 47 if (cpu_feature_enabled(X86_FEATURE_LKGS)) 48 pv_ops.cpu.load_gs_index = native_lkgs; 49 #endif 50 #endif 51 } 52 53 #ifndef CONFIG_PARAVIRT_XXL 54 55 static inline void load_gs_index(unsigned int selector) 56 { 57 #ifdef CONFIG_X86_64 58 native_load_gs_index(selector); 59 #else 60 loadsegment(gs, selector); 61 #endif 62 } 63 64 #endif /* CONFIG_PARAVIRT_XXL */ 65 66 #endif /* _ASM_X86_GSSEG_H */ 67