[POWERPC] Make soft_enabled irqs preempt safe
Rewrite local_get_flags and local_irq_disable to use r13 explicitly,
to avoid the risk that gcc will split get_paca()->soft_enabled into a
sequence unsafe against preemption. Similar care in local_irq_restore.
Signed-off-by: Hugh Dickins <hugh@veritas.com>
Signed-off-by: Paul Mackerras <paulus@samba.org>
diff --git a/include/asm-powerpc/hw_irq.h b/include/asm-powerpc/hw_irq.h
index c4a1ab6..fd3f2a2 100644
--- a/include/asm-powerpc/hw_irq.h
+++ b/include/asm-powerpc/hw_irq.h
@@ -18,15 +18,25 @@
static inline unsigned long local_get_flags(void)
{
- return get_paca()->soft_enabled;
+ unsigned long flags;
+
+ __asm__ __volatile__("lbz %0,%1(13)"
+ : "=r" (flags)
+ : "i" (offsetof(struct paca_struct, soft_enabled)));
+
+ return flags;
}
static inline unsigned long local_irq_disable(void)
{
- unsigned long flag = get_paca()->soft_enabled;
- get_paca()->soft_enabled = 0;
- barrier();
- return flag;
+ unsigned long flags, zero;
+
+ __asm__ __volatile__("li %1,0; lbz %0,%2(13); stb %1,%2(13)"
+ : "=r" (flags), "=&r" (zero)
+ : "i" (offsetof(struct paca_struct, soft_enabled))
+ : "memory");
+
+ return flags;
}
extern void local_irq_restore(unsigned long);