hc
2024-05-10 10ebd8556b7990499c896a550e3d416b444211e6
kernel/arch/arm64/include/asm/irqflags.h
....@@ -1,24 +1,14 @@
1
+/* SPDX-License-Identifier: GPL-2.0-only */
12 /*
23 * Copyright (C) 2012 ARM Ltd.
3
- *
4
- * This program is free software; you can redistribute it and/or modify
5
- * it under the terms of the GNU General Public License version 2 as
6
- * published by the Free Software Foundation.
7
- *
8
- * This program is distributed in the hope that it will be useful,
9
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
10
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
- * GNU General Public License for more details.
12
- *
13
- * You should have received a copy of the GNU General Public License
14
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
154 */
165 #ifndef __ASM_IRQFLAGS_H
176 #define __ASM_IRQFLAGS_H
187
19
-#ifdef __KERNEL__
20
-
8
+#include <asm/alternative.h>
9
+#include <asm/barrier.h>
2110 #include <asm/ptrace.h>
11
+#include <asm/sysreg.h>
2212
2313 /*
2414 * Aarch64 has flags for masking: Debug, Asynchronous (serror), Interrupts and
....@@ -36,33 +26,39 @@
3626 /*
3727 * CPU interrupt mask handling.
3828 */
39
-static inline unsigned long arch_local_irq_save(void)
40
-{
41
- unsigned long flags;
42
- asm volatile(
43
- "mrs %0, daif // arch_local_irq_save\n"
44
- "msr daifset, #2"
45
- : "=r" (flags)
46
- :
47
- : "memory");
48
- return flags;
49
-}
50
-
5129 static inline void arch_local_irq_enable(void)
5230 {
53
- asm volatile(
54
- "msr daifclr, #2 // arch_local_irq_enable"
31
+ if (system_has_prio_mask_debugging()) {
32
+ u32 pmr = read_sysreg_s(SYS_ICC_PMR_EL1);
33
+
34
+ WARN_ON_ONCE(pmr != GIC_PRIO_IRQON && pmr != GIC_PRIO_IRQOFF);
35
+ }
36
+
37
+ asm volatile(ALTERNATIVE(
38
+ "msr daifclr, #2 // arch_local_irq_enable",
39
+ __msr_s(SYS_ICC_PMR_EL1, "%0"),
40
+ ARM64_HAS_IRQ_PRIO_MASKING)
5541 :
56
- :
42
+ : "r" ((unsigned long) GIC_PRIO_IRQON)
5743 : "memory");
44
+
45
+ pmr_sync();
5846 }
5947
6048 static inline void arch_local_irq_disable(void)
6149 {
62
- asm volatile(
63
- "msr daifset, #2 // arch_local_irq_disable"
50
+ if (system_has_prio_mask_debugging()) {
51
+ u32 pmr = read_sysreg_s(SYS_ICC_PMR_EL1);
52
+
53
+ WARN_ON_ONCE(pmr != GIC_PRIO_IRQON && pmr != GIC_PRIO_IRQOFF);
54
+ }
55
+
56
+ asm volatile(ALTERNATIVE(
57
+ "msr daifset, #2 // arch_local_irq_disable",
58
+ __msr_s(SYS_ICC_PMR_EL1, "%0"),
59
+ ARM64_HAS_IRQ_PRIO_MASKING)
6460 :
65
- :
61
+ : "r" ((unsigned long) GIC_PRIO_IRQOFF)
6662 : "memory");
6763 }
6864
....@@ -72,11 +68,51 @@
7268 static inline unsigned long arch_local_save_flags(void)
7369 {
7470 unsigned long flags;
75
- asm volatile(
76
- "mrs %0, daif // arch_local_save_flags"
77
- : "=r" (flags)
71
+
72
+ asm volatile(ALTERNATIVE(
73
+ "mrs %0, daif",
74
+ __mrs_s("%0", SYS_ICC_PMR_EL1),
75
+ ARM64_HAS_IRQ_PRIO_MASKING)
76
+ : "=&r" (flags)
7877 :
7978 : "memory");
79
+
80
+ return flags;
81
+}
82
+
83
+static inline int arch_irqs_disabled_flags(unsigned long flags)
84
+{
85
+ int res;
86
+
87
+ asm volatile(ALTERNATIVE(
88
+ "and %w0, %w1, #" __stringify(PSR_I_BIT),
89
+ "eor %w0, %w1, #" __stringify(GIC_PRIO_IRQON),
90
+ ARM64_HAS_IRQ_PRIO_MASKING)
91
+ : "=&r" (res)
92
+ : "r" ((int) flags)
93
+ : "memory");
94
+
95
+ return res;
96
+}
97
+
98
+static inline int arch_irqs_disabled(void)
99
+{
100
+ return arch_irqs_disabled_flags(arch_local_save_flags());
101
+}
102
+
103
+static inline unsigned long arch_local_irq_save(void)
104
+{
105
+ unsigned long flags;
106
+
107
+ flags = arch_local_save_flags();
108
+
109
+ /*
110
+ * There are too many states with IRQs disabled, just keep the current
111
+ * state if interrupts are already disabled/masked.
112
+ */
113
+ if (!arch_irqs_disabled_flags(flags))
114
+ arch_local_irq_disable();
115
+
80116 return flags;
81117 }
82118
....@@ -85,16 +121,15 @@
85121 */
86122 static inline void arch_local_irq_restore(unsigned long flags)
87123 {
88
- asm volatile(
89
- "msr daif, %0 // arch_local_irq_restore"
90
- :
91
- : "r" (flags)
92
- : "memory");
124
+ asm volatile(ALTERNATIVE(
125
+ "msr daif, %0",
126
+ __msr_s(SYS_ICC_PMR_EL1, "%0"),
127
+ ARM64_HAS_IRQ_PRIO_MASKING)
128
+ :
129
+ : "r" (flags)
130
+ : "memory");
131
+
132
+ pmr_sync();
93133 }
94134
95
-static inline int arch_irqs_disabled_flags(unsigned long flags)
96
-{
97
- return flags & PSR_I_BIT;
98
-}
99
-#endif
100
-#endif
135
+#endif /* __ASM_IRQFLAGS_H */