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 15extern 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 20static 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 28static 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 43static 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 55static 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