aboutsummaryrefslogtreecommitdiffstats
path: root/include/asm-powerpc
diff options
context:
space:
mode:
authorHugh Dickins <hugh@veritas.com>2006-11-10 16:32:40 -0500
committerPaul Mackerras <paulus@samba.org>2006-12-04 04:39:20 -0500
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 c4a1ab608f6f..fd3f2a206271 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 *);
18 18
19static inline unsigned long local_get_flags(void) 19static inline unsigned long local_get_flags(void)
20{ 20{
21 return get_paca()->soft_enabled; 21 unsigned long flags;
22
23 __asm__ __volatile__("lbz %0,%1(13)"
24 : "=r" (flags)
25 : "i" (offsetof(struct paca_struct, soft_enabled)));
26
27 return flags;
22} 28}
23 29
24static inline unsigned long local_irq_disable(void) 30static inline unsigned long local_irq_disable(void)
25{ 31{
26 unsigned long flag = get_paca()->soft_enabled; 32 unsigned long flags, zero;
27 get_paca()->soft_enabled = 0; 33
28 barrier(); 34 __asm__ __volatile__("li %1,0; lbz %0,%2(13); stb %1,%2(13)"
29 return flag; 35 : "=r" (flags), "=&r" (zero)
36 : "i" (offsetof(struct paca_struct, soft_enabled))
37 : "memory");
38
39 return flags;
30} 40}
31 41
32extern void local_irq_restore(unsigned long); 42extern void local_irq_restore(unsigned long);