diff options
Diffstat (limited to 'arch/powerpc/include')
-rw-r--r-- | arch/powerpc/include/asm/exception-64s.h | 34 | ||||
-rw-r--r-- | arch/powerpc/include/asm/hw_irq.h | 49 | ||||
-rw-r--r-- | arch/powerpc/include/asm/irqflags.h | 37 | ||||
-rw-r--r-- | arch/powerpc/include/asm/paca.h | 2 |
4 files changed, 78 insertions, 44 deletions
diff --git a/arch/powerpc/include/asm/exception-64s.h b/arch/powerpc/include/asm/exception-64s.h index 70354af0740e..548da3aa0a30 100644 --- a/arch/powerpc/include/asm/exception-64s.h +++ b/arch/powerpc/include/asm/exception-64s.h @@ -232,23 +232,30 @@ label##_hv: \ EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, label##_common, \ EXC_HV, KVMTEST, vec) -#define __SOFTEN_TEST(h) \ +/* This associate vector numbers with bits in paca->irq_happened */ +#define SOFTEN_VALUE_0x500 PACA_IRQ_EE +#define SOFTEN_VALUE_0x502 PACA_IRQ_EE +#define SOFTEN_VALUE_0x900 PACA_IRQ_DEC +#define SOFTEN_VALUE_0x982 PACA_IRQ_DEC + +#define __SOFTEN_TEST(h, vec) \ lbz r10,PACASOFTIRQEN(r13); \ cmpwi r10,0; \ + li r10,SOFTEN_VALUE_##vec; \ beq masked_##h##interrupt -#define _SOFTEN_TEST(h) __SOFTEN_TEST(h) +#define _SOFTEN_TEST(h, vec) __SOFTEN_TEST(h, vec) #define SOFTEN_TEST_PR(vec) \ KVMTEST_PR(vec); \ - _SOFTEN_TEST(EXC_STD) + _SOFTEN_TEST(EXC_STD, vec) #define SOFTEN_TEST_HV(vec) \ KVMTEST(vec); \ - _SOFTEN_TEST(EXC_HV) + _SOFTEN_TEST(EXC_HV, vec) #define SOFTEN_TEST_HV_201(vec) \ KVMTEST(vec); \ - _SOFTEN_TEST(EXC_STD) + _SOFTEN_TEST(EXC_STD, vec) #define __MASKABLE_EXCEPTION_PSERIES(vec, label, h, extra) \ HMT_MEDIUM; \ @@ -279,22 +286,7 @@ label##_hv: \ */ /* Exception addition: Hard disable interrupts */ -#ifdef CONFIG_TRACE_IRQFLAGS -#define DISABLE_INTS \ - lbz r10,PACASOFTIRQEN(r13); \ - li r11,0; \ - cmpwi cr0,r10,0; \ - stb r11,PACAHARDIRQEN(r13); \ - beq 44f; \ - stb r11,PACASOFTIRQEN(r13); \ - TRACE_DISABLE_INTS; \ -44: -#else -#define DISABLE_INTS \ - li r11,0; \ - stb r11,PACASOFTIRQEN(r13); \ - stb r11,PACAHARDIRQEN(r13) -#endif /* CONFIG_TRACE_IRQFLAGS */ +#define DISABLE_INTS SOFT_DISABLE_INTS(r10,r11) /* Exception addition: Keep interrupt state */ #define ENABLE_INTS \ diff --git a/arch/powerpc/include/asm/hw_irq.h b/arch/powerpc/include/asm/hw_irq.h index 6c6fa955baa7..51010bfc792e 100644 --- a/arch/powerpc/include/asm/hw_irq.h +++ b/arch/powerpc/include/asm/hw_irq.h @@ -11,6 +11,27 @@ #include <asm/ptrace.h> #include <asm/processor.h> +#ifdef CONFIG_PPC64 + +/* + * PACA flags in paca->irq_happened. + * + * This bits are set when interrupts occur while soft-disabled + * and allow a proper replay. Additionally, PACA_IRQ_HARD_DIS + * is set whenever we manually hard disable. + */ +#define PACA_IRQ_HARD_DIS 0x01 +#define PACA_IRQ_DBELL 0x02 +#define PACA_IRQ_EE 0x04 +#define PACA_IRQ_DEC 0x08 /* Or FIT */ +#define PACA_IRQ_EE_EDGE 0x10 /* BookE only */ + +#endif /* CONFIG_PPC64 */ + +#ifndef __ASSEMBLY__ + +extern void __replay_interrupt(unsigned int vector); + extern void timer_interrupt(struct pt_regs *); #ifdef CONFIG_PPC64 @@ -42,7 +63,6 @@ static inline unsigned long arch_local_irq_disable(void) } extern void arch_local_irq_restore(unsigned long); -extern void iseries_handle_interrupts(void); static inline void arch_local_irq_enable(void) { @@ -72,12 +92,24 @@ static inline bool arch_irqs_disabled(void) #define __hard_irq_disable() __mtmsrd(local_paca->kernel_msr, 1) #endif -#define hard_irq_disable() \ - do { \ - __hard_irq_disable(); \ - get_paca()->soft_enabled = 0; \ - get_paca()->hard_enabled = 0; \ - } while(0) +static inline void hard_irq_disable(void) +{ + __hard_irq_disable(); + get_paca()->soft_enabled = 0; + get_paca()->irq_happened |= PACA_IRQ_HARD_DIS; +} + +/* + * This is called by asynchronous interrupts to conditionally + * re-enable hard interrupts when soft-disabled after having + * cleared the source of the interrupt + */ +static inline void may_hard_irq_enable(void) +{ + get_paca()->irq_happened &= ~PACA_IRQ_HARD_DIS; + if (!(get_paca()->irq_happened & PACA_IRQ_EE)) + __hard_irq_enable(); +} static inline bool arch_irq_disabled_regs(struct pt_regs *regs) { @@ -149,6 +181,8 @@ static inline bool arch_irq_disabled_regs(struct pt_regs *regs) return !(regs->msr & MSR_EE); } +static inline void may_hard_irq_enable(void) { } + #endif /* CONFIG_PPC64 */ #define ARCH_IRQ_INIT_FLAGS IRQ_NOREQUEST @@ -159,5 +193,6 @@ static inline bool arch_irq_disabled_regs(struct pt_regs *regs) */ struct irq_chip; +#endif /* __ASSEMBLY__ */ #endif /* __KERNEL__ */ #endif /* _ASM_POWERPC_HW_IRQ_H */ diff --git a/arch/powerpc/include/asm/irqflags.h b/arch/powerpc/include/asm/irqflags.h index b0b06d85788d..6f9b6e23dc5a 100644 --- a/arch/powerpc/include/asm/irqflags.h +++ b/arch/powerpc/include/asm/irqflags.h @@ -39,24 +39,31 @@ #define TRACE_ENABLE_INTS TRACE_WITH_FRAME_BUFFER(.trace_hardirqs_on) #define TRACE_DISABLE_INTS TRACE_WITH_FRAME_BUFFER(.trace_hardirqs_off) -#define TRACE_AND_RESTORE_IRQ_PARTIAL(en,skip) \ - cmpdi en,0; \ - bne 95f; \ - stb en,PACASOFTIRQEN(r13); \ - TRACE_WITH_FRAME_BUFFER(.trace_hardirqs_off) \ - b skip; \ -95: TRACE_WITH_FRAME_BUFFER(.trace_hardirqs_on) \ - li en,1; -#define TRACE_AND_RESTORE_IRQ(en) \ - TRACE_AND_RESTORE_IRQ_PARTIAL(en,96f); \ - stb en,PACASOFTIRQEN(r13); \ -96: +/* + * This is used by assembly code to soft-disable interrupts + */ +#define SOFT_DISABLE_INTS(__rA, __rB) \ + lbz __rA,PACASOFTIRQEN(r13); \ + lbz __rB,PACAIRQHAPPENED(r13); \ + cmpwi cr0,__rA,0; \ + li __rA,0; \ + ori __rB,__rB,PACA_IRQ_HARD_DIS; \ + stb __rB,PACAIRQHAPPENED(r13); \ + beq 44f; \ + stb __rA,PACASOFTIRQEN(r13); \ + TRACE_DISABLE_INTS; \ +44: + #else #define TRACE_ENABLE_INTS #define TRACE_DISABLE_INTS -#define TRACE_AND_RESTORE_IRQ_PARTIAL(en,skip) -#define TRACE_AND_RESTORE_IRQ(en) \ - stb en,PACASOFTIRQEN(r13) + +#define SOFT_DISABLE_INTS(__rA, __rB) \ + lbz __rA,PACAIRQHAPPENED(r13); \ + li __rB,0; \ + ori __rA,__rA,PACA_IRQ_HARD_DIS; \ + stb __rB,PACASOFTIRQEN(r13); \ + stb __rA,PACAIRQHAPPENED(r13) #endif #endif diff --git a/arch/powerpc/include/asm/paca.h b/arch/powerpc/include/asm/paca.h index 269c05a36d91..daf813fea91f 100644 --- a/arch/powerpc/include/asm/paca.h +++ b/arch/powerpc/include/asm/paca.h @@ -132,7 +132,7 @@ struct paca_struct { u64 saved_msr; /* MSR saved here by enter_rtas */ u16 trap_save; /* Used when bad stack is encountered */ u8 soft_enabled; /* irq soft-enable flag */ - u8 hard_enabled; /* set if irqs are enabled in MSR */ + u8 irq_happened; /* irq happened while soft-disabled */ u8 io_sync; /* writel() needs spin_unlock sync */ u8 irq_work_pending; /* IRQ_WORK interrupt while soft-disable */ u8 nap_state_lost; /* NV GPR values lost in power7_idle */ |