xref: /linux/arch/s390/include/asm/irqflags.h (revision f057b57270c2a17d3f45c177e9434fa5745caa48)
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 #ifdef CONFIG_KMSAN
41 #define arch_local_irq_attributes noinline notrace __no_sanitize_memory __maybe_unused
42 #else
43 #define arch_local_irq_attributes __always_inline
44 #endif
45 
46 static arch_local_irq_attributes unsigned long arch_local_save_flags(void)
47 {
48 	return __arch_local_irq_stnsm(0xff);
49 }
50 
51 static arch_local_irq_attributes unsigned long arch_local_irq_save(void)
52 {
53 	return __arch_local_irq_stnsm(0xfc);
54 }
55 
56 static __always_inline void arch_local_irq_disable(void)
57 {
58 	arch_local_irq_save();
59 }
60 
61 static arch_local_irq_attributes void arch_local_irq_enable_external(void)
62 {
63 	__arch_local_irq_stosm(0x01);
64 }
65 
66 static arch_local_irq_attributes void arch_local_irq_enable(void)
67 {
68 	__arch_local_irq_stosm(0x03);
69 }
70 
71 /* This only restores external and I/O interrupt state */
72 static __always_inline void arch_local_irq_restore(unsigned long flags)
73 {
74 	/* only disabled->disabled and disabled->enabled is valid */
75 	if (flags & ARCH_IRQ_ENABLED)
76 		arch_local_irq_enable();
77 }
78 
79 static __always_inline bool arch_irqs_disabled_flags(unsigned long flags)
80 {
81 	return !(flags & ARCH_IRQ_ENABLED);
82 }
83 
84 static __always_inline bool arch_irqs_disabled(void)
85 {
86 	return arch_irqs_disabled_flags(arch_local_save_flags());
87 }
88 
89 #endif /* __ASM_IRQFLAGS_H */
90