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