summaryrefslogtreecommitdiffstats
path: root/include/asm-powerpc
diff options
context:
space:
mode:
authorHugh Dickins <hugh@veritas.com>2006-11-10 21:32:40 +0000
committerPaul Mackerras <paulus@samba.org>2006-12-04 20:39:20 +1100
commitef2b343e99e772e35f0f9d00f7db318b6629c16e (patch)
tree386f9b6b1376ab99a478ab5d394572fca720d0ef /include/asm-powerpc
parent56291e19e37cf3bb8fc701ebf3aa8ffbf59f73ef (diff)
[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>
Diffstat (limited to 'include/asm-powerpc')
-rw-r--r--include/asm-powerpc/hw_irq.h20
1 files changed, 15 insertions, 5 deletions
diff --git a/include/asm-powerpc/hw_irq.h b/include/asm-powerpc/hw_irq.h
index c4a1ab608f6..fd3f2a20627 100644
--- a/include/asm-powerpc/hw_irq.h
+++ b/include/asm-powerpc/hw_irq.h
@@ -18,15 +18,25 @@ extern void timer_interrupt(struct pt_regs *);
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);