162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */ 262306a36Sopenharmony_ci#ifndef _ASM_X86_GSSEG_H 362306a36Sopenharmony_ci#define _ASM_X86_GSSEG_H 462306a36Sopenharmony_ci 562306a36Sopenharmony_ci#include <linux/types.h> 662306a36Sopenharmony_ci 762306a36Sopenharmony_ci#include <asm/asm.h> 862306a36Sopenharmony_ci#include <asm/cpufeature.h> 962306a36Sopenharmony_ci#include <asm/alternative.h> 1062306a36Sopenharmony_ci#include <asm/processor.h> 1162306a36Sopenharmony_ci#include <asm/nops.h> 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_ci#ifdef CONFIG_X86_64 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_ciextern asmlinkage void asm_load_gs_index(u16 selector); 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_ci/* Replace with "lkgs %di" once binutils support LKGS instruction */ 1862306a36Sopenharmony_ci#define LKGS_DI _ASM_BYTES(0xf2,0x0f,0x00,0xf7) 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_cistatic inline void native_lkgs(unsigned int selector) 2162306a36Sopenharmony_ci{ 2262306a36Sopenharmony_ci u16 sel = selector; 2362306a36Sopenharmony_ci asm_inline volatile("1: " LKGS_DI 2462306a36Sopenharmony_ci _ASM_EXTABLE_TYPE_REG(1b, 1b, EX_TYPE_ZERO_REG, %k[sel]) 2562306a36Sopenharmony_ci : [sel] "+D" (sel)); 2662306a36Sopenharmony_ci} 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_cistatic inline void native_load_gs_index(unsigned int selector) 2962306a36Sopenharmony_ci{ 3062306a36Sopenharmony_ci if (cpu_feature_enabled(X86_FEATURE_LKGS)) { 3162306a36Sopenharmony_ci native_lkgs(selector); 3262306a36Sopenharmony_ci } else { 3362306a36Sopenharmony_ci unsigned long flags; 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_ci local_irq_save(flags); 3662306a36Sopenharmony_ci asm_load_gs_index(selector); 3762306a36Sopenharmony_ci local_irq_restore(flags); 3862306a36Sopenharmony_ci } 3962306a36Sopenharmony_ci} 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_ci#endif /* CONFIG_X86_64 */ 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_cistatic inline void __init lkgs_init(void) 4462306a36Sopenharmony_ci{ 4562306a36Sopenharmony_ci#ifdef CONFIG_PARAVIRT_XXL 4662306a36Sopenharmony_ci#ifdef CONFIG_X86_64 4762306a36Sopenharmony_ci if (cpu_feature_enabled(X86_FEATURE_LKGS)) 4862306a36Sopenharmony_ci pv_ops.cpu.load_gs_index = native_lkgs; 4962306a36Sopenharmony_ci#endif 5062306a36Sopenharmony_ci#endif 5162306a36Sopenharmony_ci} 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_ci#ifndef CONFIG_PARAVIRT_XXL 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_cistatic inline void load_gs_index(unsigned int selector) 5662306a36Sopenharmony_ci{ 5762306a36Sopenharmony_ci#ifdef CONFIG_X86_64 5862306a36Sopenharmony_ci native_load_gs_index(selector); 5962306a36Sopenharmony_ci#else 6062306a36Sopenharmony_ci loadsegment(gs, selector); 6162306a36Sopenharmony_ci#endif 6262306a36Sopenharmony_ci} 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_ci#endif /* CONFIG_PARAVIRT_XXL */ 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_ci#endif /* _ASM_X86_GSSEG_H */ 67