131
社区成员




在arch//include/asm/irqflags.h中操作CPU状态寄存器中的中断标志的体系结构特定代码应在实际中断控制和虚拟中断控制之间进行划分。真正的中断控制操作是从in-band(非实时)内核实现中继承的。虚拟的中断控制操作应该建立在中断管道核心提供的服务之上。
首先,原始的arch_local* 操作助手操作应该重命名为native_* 操作助手,这会影响CPU中的硬件中断状态。这个命名约定是由include/asm-generic/irq_pipeline.h中的通用助手强加给体系结构代码的。
示例:介绍ARM体系结构的原生中断状态访问
--- a/arch/arm/include/asm/irqflags.h
+++ b/arch/arm/include/asm/irqflags.h
#if __LINUX_ARM_ARCH__ >= 6
#define arch_local_irq_save arch_local_irq_save
-static inline unsigned long arch_local_irq_save(void)
+static inline unsigned long native_irq_save(void)
{
unsigned long flags;
asm volatile(
- " mrs %0, " IRQMASK_REG_NAME_R " @ arch_local_irq_save\n"
+ " mrs %0, " IRQMASK_REG_NAME_R " @ native_irq_save\n"
" cpsid i"
: "=r" (flags) : : "memory", "cc");
return flags;
}
#define arch_local_irq_enable arch_local_irq_enable
-static inline void arch_local_irq_enable(void)
+static inline void native_irq_enable(void)
{
asm volatile(
- " cpsie i @ arch_local_irq_enable"
+ " cpsie i @ native_irq_enable"
:
:
: "memory", "cc");
}
#define arch_local_irq_disable arch_local_irq_disable
-static inline void arch_local_irq_disable(void)
+static inline void native_irq_disable(void)
{
asm volatile(
- " cpsid i @ arch_local_irq_disable"
+ " cpsid i @ native_irq_disable"
:
:
: "memory", "cc");
@@ -69,12 +76,12 @@ static inline void arch_local_irq_disable(void)
* Save the current interrupt enable state & disable IRQs
*/
#define arch_local_irq_save arch_local_irq_save
-static inline unsigned long arch_local_irq_save(void)
+static inline unsigned long native_irq_save(void)
{
unsigned long flags, temp;
asm volatile(
- " mrs %0, cpsr @ arch_local_irq_save\n"
+ " mrs %0, cpsr @ native_irq_save\n"
" orr %1, %0, #128\n"
" msr cpsr_c, %1"
: "=r" (flags), "=r" (temp)
@@ -87,11 +94,11 @@ static inline unsigned long arch_local_irq_save(void)
* Enable IRQs
*/
#define arch_local_irq_enable arch_local_irq_enable
-static inline void arch_local_irq_enable(void)
+static inline void native_irq_enable(void)
{
unsigned long temp;
asm volatile(
- " mrs %0, cpsr @ arch_local_irq_enable\n"
+ " mrs %0, cpsr @ native_irq_enable\n"
" bic %0, %0, #128\n"
" msr cpsr_c, %0"
: "=r" (temp)
@@ -103,11 +110,11 @@ static inline void arch_local_irq_enable(void)
* Disable IRQs
*/
#define arch_local_irq_disable arch_local_irq_disable
-static inline void arch_local_irq_disable(void)
+static inline void native_irq_disable(void)
{
unsigned long temp;
asm volatile(
- " mrs %0, cpsr @ arch_local_irq_disable\n"
+ " mrs %0, cpsr @ native_irq_disable\n"
" orr %0, %0, #128\n"
" msr cpsr_c, %0"
: "=r" (temp)
@@ -153,11 +160,11 @@ static inline void arch_local_irq_disable(void)
* Save the current interrupt enable state.
*/
#define arch_local_save_flags arch_local_save_flags
-static inline unsigned long arch_local_save_flags(void)
+static inline unsigned long native_save_flags(void)
{
unsigned long flags;
asm volatile(
- " mrs %0, " IRQMASK_REG_NAME_R " @ local_save_flags"
+ " mrs %0, " IRQMASK_REG_NAME_R " @ native_save_flags"
: "=r" (flags) : : "memory", "cc");
return flags;
}
@@ -166,21 +173,28 @@ static inline unsigned long arch_local_save_flags(void)
* restore saved IRQ & FIQ state
*/
#define arch_local_irq_restore arch_local_irq_restore
-static inline void arch_local_irq_restore(unsigned long flags)
+static inline void native_irq_restore(unsigned long flags)
{
asm volatile(
- " msr " IRQMASK_REG_NAME_W ", %0 @ local_irq_restore"
+ " msr " IRQMASK_REG_NAME_W ", %0 @ native_irq_restore"
:
: "r" (flags)
: "memory", "cc");
}
#define arch_irqs_disabled_flags arch_irqs_disabled_flags
-static inline int arch_irqs_disabled_flags(unsigned long flags)
+static inline int native_irqs_disabled_flags(unsigned long flags)
{
return flags & IRQMASK_I_BIT;
}
+static inline bool native_irqs_disabled(void)
+{
+ unsigned long flags = native_save_flags();
+ return native_irqs_disabled_flags(flags);
+}
+
+#include <asm/irq_pipeline.h>
#include <asm-generic/irqflags.h>
#endif /* ifdef __KERNEL__ */
最后,应该提供一组新的arch_local*操作助手,这些操作助手影响由管道核心实现的虚拟中断禁用标志,以控制in-band(非实时)阶段对中断的保护。最好在由<asm/irq_pipeline.h>中包含的单独文件中实现此助手操作集合。
示例:为ARM体系结构提供虚拟中断状态访问
--- /dev/null
+++ b/arch/arm/include/asm/irq_pipeline.h
@@ -0,0 +1,138 @@
+#ifndef _ASM_ARM_IRQ_PIPELINE_H
+#define _ASM_ARM_IRQ_PIPELINE_H
+
+#include <asm-generic/irq_pipeline.h>
+
+#ifdef CONFIG_IRQ_PIPELINE
+
+static inline notrace unsigned long arch_local_irq_save(void)
+{
+ int stalled = inband_irq_save();
+ barrier();
+ return arch_irqs_virtual_to_native_flags(stalled);
+}
+
+static inline notrace void arch_local_irq_enable(void)
+{
+ barrier();
+ inband_irq_enable();
+}
+
+static inline notrace void arch_local_irq_disable(void)
+{
+ inband_irq_disable();
+ barrier();
+}
+
+static inline notrace unsigned long arch_local_save_flags(void)
+{
+ int stalled = inband_irqs_disabled();
+ barrier();
+ return arch_irqs_virtual_to_native_flags(stalled);
+}
+
+static inline int arch_irqs_disabled_flags(unsigned long flags)
+{
+ return native_irqs_disabled_flags(flags);
+}
+
+static inline notrace void arch_local_irq_restore(unsigned long flags)
+{
+ if (!arch_irqs_disabled_flags(flags))
+ __inband_irq_enable();
+ barrier();
+}
+
+#else /* !CONFIG_IRQ_PIPELINE */
+
+static inline unsigned long arch_local_irq_save(void)
+{
+ return native_irq_save();
+}
+
+static inline void arch_local_irq_enable(void)
+{
+ native_irq_enable();
+}
+
+static inline void arch_local_irq_disable(void)
+{
+ native_irq_disable();
+}
+
+static inline unsigned long arch_local_save_flags(void)
+{
+ return native_save_flags();
+}
+
+static inline void arch_local_irq_restore(unsigned long flags)
+{
+ native_irq_restore(flags);
+}
+
+static inline int arch_irqs_disabled_flags(unsigned long flags)
+{
+ return native_irqs_disabled_flags(flags);
+}
+
+#endif /* !CONFIG_IRQ_PIPELINE */
+
+#endif /* _ASM_ARM_IRQ_PIPELINE_H */
注意:
这个新文件应该尽早包含<asm-generic/irq_pipeline.h>,以便访问所需的管道声明。这种包含应该是无条件的,即使内核是在CONFIG_IRQ_PIPELINE被禁用的情况下构建的。