162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 262306a36Sopenharmony_ci#ifndef _X86_IRQFLAGS_H_ 362306a36Sopenharmony_ci#define _X86_IRQFLAGS_H_ 462306a36Sopenharmony_ci 562306a36Sopenharmony_ci#include <asm/processor-flags.h> 662306a36Sopenharmony_ci 762306a36Sopenharmony_ci#ifndef __ASSEMBLY__ 862306a36Sopenharmony_ci 962306a36Sopenharmony_ci#include <asm/nospec-branch.h> 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ci/* 1262306a36Sopenharmony_ci * Interrupt control: 1362306a36Sopenharmony_ci */ 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_ci/* Declaration required for gcc < 4.9 to prevent -Werror=missing-prototypes */ 1662306a36Sopenharmony_ciextern inline unsigned long native_save_fl(void); 1762306a36Sopenharmony_ciextern __always_inline unsigned long native_save_fl(void) 1862306a36Sopenharmony_ci{ 1962306a36Sopenharmony_ci unsigned long flags; 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_ci /* 2262306a36Sopenharmony_ci * "=rm" is safe here, because "pop" adjusts the stack before 2362306a36Sopenharmony_ci * it evaluates its effective address -- this is part of the 2462306a36Sopenharmony_ci * documented behavior of the "pop" instruction. 2562306a36Sopenharmony_ci */ 2662306a36Sopenharmony_ci asm volatile("# __raw_save_flags\n\t" 2762306a36Sopenharmony_ci "pushf ; pop %0" 2862306a36Sopenharmony_ci : "=rm" (flags) 2962306a36Sopenharmony_ci : /* no input */ 3062306a36Sopenharmony_ci : "memory"); 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_ci return flags; 3362306a36Sopenharmony_ci} 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_cistatic __always_inline void native_irq_disable(void) 3662306a36Sopenharmony_ci{ 3762306a36Sopenharmony_ci asm volatile("cli": : :"memory"); 3862306a36Sopenharmony_ci} 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_cistatic __always_inline void native_irq_enable(void) 4162306a36Sopenharmony_ci{ 4262306a36Sopenharmony_ci asm volatile("sti": : :"memory"); 4362306a36Sopenharmony_ci} 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_cistatic __always_inline void native_safe_halt(void) 4662306a36Sopenharmony_ci{ 4762306a36Sopenharmony_ci mds_idle_clear_cpu_buffers(); 4862306a36Sopenharmony_ci asm volatile("sti; hlt": : :"memory"); 4962306a36Sopenharmony_ci} 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_cistatic __always_inline void native_halt(void) 5262306a36Sopenharmony_ci{ 5362306a36Sopenharmony_ci mds_idle_clear_cpu_buffers(); 5462306a36Sopenharmony_ci asm volatile("hlt": : :"memory"); 5562306a36Sopenharmony_ci} 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_ci#endif 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_ci#ifdef CONFIG_PARAVIRT_XXL 6062306a36Sopenharmony_ci#include <asm/paravirt.h> 6162306a36Sopenharmony_ci#else 6262306a36Sopenharmony_ci#ifndef __ASSEMBLY__ 6362306a36Sopenharmony_ci#include <linux/types.h> 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_cistatic __always_inline unsigned long arch_local_save_flags(void) 6662306a36Sopenharmony_ci{ 6762306a36Sopenharmony_ci return native_save_fl(); 6862306a36Sopenharmony_ci} 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_cistatic __always_inline void arch_local_irq_disable(void) 7162306a36Sopenharmony_ci{ 7262306a36Sopenharmony_ci native_irq_disable(); 7362306a36Sopenharmony_ci} 7462306a36Sopenharmony_ci 7562306a36Sopenharmony_cistatic __always_inline void arch_local_irq_enable(void) 7662306a36Sopenharmony_ci{ 7762306a36Sopenharmony_ci native_irq_enable(); 7862306a36Sopenharmony_ci} 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_ci/* 8162306a36Sopenharmony_ci * Used in the idle loop; sti takes one instruction cycle 8262306a36Sopenharmony_ci * to complete: 8362306a36Sopenharmony_ci */ 8462306a36Sopenharmony_cistatic __always_inline void arch_safe_halt(void) 8562306a36Sopenharmony_ci{ 8662306a36Sopenharmony_ci native_safe_halt(); 8762306a36Sopenharmony_ci} 8862306a36Sopenharmony_ci 8962306a36Sopenharmony_ci/* 9062306a36Sopenharmony_ci * Used when interrupts are already enabled or to 9162306a36Sopenharmony_ci * shutdown the processor: 9262306a36Sopenharmony_ci */ 9362306a36Sopenharmony_cistatic __always_inline void halt(void) 9462306a36Sopenharmony_ci{ 9562306a36Sopenharmony_ci native_halt(); 9662306a36Sopenharmony_ci} 9762306a36Sopenharmony_ci 9862306a36Sopenharmony_ci/* 9962306a36Sopenharmony_ci * For spinlocks, etc: 10062306a36Sopenharmony_ci */ 10162306a36Sopenharmony_cistatic __always_inline unsigned long arch_local_irq_save(void) 10262306a36Sopenharmony_ci{ 10362306a36Sopenharmony_ci unsigned long flags = arch_local_save_flags(); 10462306a36Sopenharmony_ci arch_local_irq_disable(); 10562306a36Sopenharmony_ci return flags; 10662306a36Sopenharmony_ci} 10762306a36Sopenharmony_ci#else 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_ci#ifdef CONFIG_X86_64 11062306a36Sopenharmony_ci#ifdef CONFIG_DEBUG_ENTRY 11162306a36Sopenharmony_ci#define SAVE_FLAGS pushfq; popq %rax 11262306a36Sopenharmony_ci#endif 11362306a36Sopenharmony_ci 11462306a36Sopenharmony_ci#endif 11562306a36Sopenharmony_ci 11662306a36Sopenharmony_ci#endif /* __ASSEMBLY__ */ 11762306a36Sopenharmony_ci#endif /* CONFIG_PARAVIRT_XXL */ 11862306a36Sopenharmony_ci 11962306a36Sopenharmony_ci#ifndef __ASSEMBLY__ 12062306a36Sopenharmony_cistatic __always_inline int arch_irqs_disabled_flags(unsigned long flags) 12162306a36Sopenharmony_ci{ 12262306a36Sopenharmony_ci return !(flags & X86_EFLAGS_IF); 12362306a36Sopenharmony_ci} 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_cistatic __always_inline int arch_irqs_disabled(void) 12662306a36Sopenharmony_ci{ 12762306a36Sopenharmony_ci unsigned long flags = arch_local_save_flags(); 12862306a36Sopenharmony_ci 12962306a36Sopenharmony_ci return arch_irqs_disabled_flags(flags); 13062306a36Sopenharmony_ci} 13162306a36Sopenharmony_ci 13262306a36Sopenharmony_cistatic __always_inline void arch_local_irq_restore(unsigned long flags) 13362306a36Sopenharmony_ci{ 13462306a36Sopenharmony_ci if (!arch_irqs_disabled_flags(flags)) 13562306a36Sopenharmony_ci arch_local_irq_enable(); 13662306a36Sopenharmony_ci} 13762306a36Sopenharmony_ci#endif /* !__ASSEMBLY__ */ 13862306a36Sopenharmony_ci 13962306a36Sopenharmony_ci#endif 140