1/* SPDX-License-Identifier: GPL-2.0 */ 2#ifndef _X86_IRQFLAGS_H_ 3#define _X86_IRQFLAGS_H_ 4 5#include <asm/processor-flags.h> 6 7#ifndef __ASSEMBLY__ 8 9#include <asm/nospec-branch.h> 10 11/* 12 * Interrupt control: 13 */ 14 15/* Declaration required for gcc < 4.9 to prevent -Werror=missing-prototypes */ 16extern inline unsigned long native_save_fl(void); 17extern __always_inline unsigned long native_save_fl(void) 18{ 19 unsigned long flags; 20 21 /* 22 * "=rm" is safe here, because "pop" adjusts the stack before 23 * it evaluates its effective address -- this is part of the 24 * documented behavior of the "pop" instruction. 25 */ 26 asm volatile("# __raw_save_flags\n\t" 27 "pushf ; pop %0" 28 : "=rm" (flags) 29 : /* no input */ 30 : "memory"); 31 32 return flags; 33} 34 35static __always_inline void native_irq_disable(void) 36{ 37 asm volatile("cli": : :"memory"); 38} 39 40static __always_inline void native_irq_enable(void) 41{ 42 asm volatile("sti": : :"memory"); 43} 44 45static __always_inline void native_safe_halt(void) 46{ 47 mds_idle_clear_cpu_buffers(); 48 asm volatile("sti; hlt": : :"memory"); 49} 50 51static __always_inline void native_halt(void) 52{ 53 mds_idle_clear_cpu_buffers(); 54 asm volatile("hlt": : :"memory"); 55} 56 57#endif 58 59#ifdef CONFIG_PARAVIRT_XXL 60#include <asm/paravirt.h> 61#else 62#ifndef __ASSEMBLY__ 63#include <linux/types.h> 64 65static __always_inline unsigned long arch_local_save_flags(void) 66{ 67 return native_save_fl(); 68} 69 70static __always_inline void arch_local_irq_disable(void) 71{ 72 native_irq_disable(); 73} 74 75static __always_inline void arch_local_irq_enable(void) 76{ 77 native_irq_enable(); 78} 79 80/* 81 * Used in the idle loop; sti takes one instruction cycle 82 * to complete: 83 */ 84static __always_inline void arch_safe_halt(void) 85{ 86 native_safe_halt(); 87} 88 89/* 90 * Used when interrupts are already enabled or to 91 * shutdown the processor: 92 */ 93static __always_inline void halt(void) 94{ 95 native_halt(); 96} 97 98/* 99 * For spinlocks, etc: 100 */ 101static __always_inline unsigned long arch_local_irq_save(void) 102{ 103 unsigned long flags = arch_local_save_flags(); 104 arch_local_irq_disable(); 105 return flags; 106} 107#else 108 109#ifdef CONFIG_X86_64 110#ifdef CONFIG_DEBUG_ENTRY 111#define SAVE_FLAGS pushfq; popq %rax 112#endif 113 114#endif 115 116#endif /* __ASSEMBLY__ */ 117#endif /* CONFIG_PARAVIRT_XXL */ 118 119#ifndef __ASSEMBLY__ 120static __always_inline int arch_irqs_disabled_flags(unsigned long flags) 121{ 122 return !(flags & X86_EFLAGS_IF); 123} 124 125static __always_inline int arch_irqs_disabled(void) 126{ 127 unsigned long flags = arch_local_save_flags(); 128 129 return arch_irqs_disabled_flags(flags); 130} 131 132static __always_inline void arch_local_irq_restore(unsigned long flags) 133{ 134 if (!arch_irqs_disabled_flags(flags)) 135 arch_local_irq_enable(); 136} 137#endif /* !__ASSEMBLY__ */ 138 139#endif 140