xref: /linux/arch/s390/include/asm/irqflags.h (revision 3a2c4d55e32ad65efebdb6de44eef3bfa08bb49d)
1 /* SPDX-License-Identifier: GPL-2.0 */
2 /*
3  *    Copyright IBM Corp. 2006, 2010
4  *    Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>
5  */
6 
7 #ifndef __ASM_IRQFLAGS_H
8 #define __ASM_IRQFLAGS_H
9 
10 #include <linux/types.h>
11 
12 #define ARCH_IRQ_ENABLED	(3UL << (BITS_PER_LONG - 8))
13 
14 /* store then OR system mask. */
15 #define __arch_local_irq_stosm(__or)					\
16 ({									\
17 	unsigned long __mask;						\
18 	asm volatile(							\
19 		"	stosm	%0,%1"					\
20 		: "=Q" (__mask) : "i" (__or) : "memory");		\
21 	__mask;								\
22 })
23 
24 /* store then AND system mask. */
25 #define __arch_local_irq_stnsm(__and)					\
26 ({									\
27 	unsigned long __mask;						\
28 	asm volatile(							\
29 		"	stnsm	%0,%1"					\
30 		: "=Q" (__mask) : "i" (__and) : "memory");		\
31 	__mask;								\
32 })
33 
34 /* set system mask. */
35 static __always_inline void __arch_local_irq_ssm(unsigned long flags)
36 {
37 	asm volatile("ssm   %0" : : "Q" (flags) : "memory");
38 }
39 
40 #if defined(CONFIG_KMSAN) && !defined(__DECOMPRESSOR)
41 unsigned long arch_local_save_flags(void);
42 unsigned long arch_local_irq_save(void);
43 void arch_local_irq_enable_external(void);
44 void arch_local_irq_enable(void);
45 #else
46 #define arch_local_save_flags		__arch_local_save_flags
47 #define arch_local_irq_save		__arch_local_irq_save
48 #define arch_local_irq_enable_external	__arch_local_irq_enable_external
49 #define arch_local_irq_enable		__arch_local_irq_enable
50 #endif
51 
52 static __always_inline unsigned long __arch_local_save_flags(void)
53 {
54 	return __arch_local_irq_stnsm(0xff);
55 }
56 
57 static __always_inline unsigned long __arch_local_irq_save(void)
58 {
59 	return __arch_local_irq_stnsm(0xfc);
60 }
61 
62 static __always_inline void arch_local_irq_disable(void)
63 {
64 	arch_local_irq_save();
65 }
66 
67 static __always_inline void __arch_local_irq_enable_external(void)
68 {
69 	__arch_local_irq_stosm(0x01);
70 }
71 
72 static __always_inline void __arch_local_irq_enable(void)
73 {
74 	__arch_local_irq_stosm(0x03);
75 }
76 
77 /* This only restores external and I/O interrupt state */
78 static __always_inline void arch_local_irq_restore(unsigned long flags)
79 {
80 	/* only disabled->disabled and disabled->enabled is valid */
81 	if (flags & ARCH_IRQ_ENABLED)
82 		arch_local_irq_enable();
83 }
84 
85 static __always_inline bool arch_irqs_disabled_flags(unsigned long flags)
86 {
87 	return !(flags & ARCH_IRQ_ENABLED);
88 }
89 
90 static __always_inline bool arch_irqs_disabled(void)
91 {
92 	return arch_irqs_disabled_flags(arch_local_save_flags());
93 }
94 
95 #endif /* __ASM_IRQFLAGS_H */
96