diff options
Diffstat (limited to 'arch/powerpc/kernel')
-rw-r--r-- | arch/powerpc/kernel/entry_64.S | 21 | ||||
-rw-r--r-- | arch/powerpc/kernel/exceptions-64e.S | 10 | ||||
-rw-r--r-- | arch/powerpc/kernel/irq.c | 20 |
3 files changed, 32 insertions, 19 deletions
diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S index f8b32224dc11..51e4cc4dba4a 100644 --- a/arch/powerpc/kernel/entry_64.S +++ b/arch/powerpc/kernel/entry_64.S @@ -130,8 +130,7 @@ END_FW_FTR_SECTION_IFSET(FW_FEATURE_SPLPAR) */ #if defined(CONFIG_TRACE_IRQFLAGS) && defined(CONFIG_BUG) lbz r10,PACASOFTIRQEN(r13) - xori r10,r10,IRQS_ENABLED -1: tdnei r10,0 +1: tdnei r10,IRQS_ENABLED EMIT_BUG_ENTRY 1b,__FILE__,__LINE__,BUGFLAG_WARNING #endif @@ -741,10 +740,10 @@ resume_kernel: beq+ restore /* Check that preempt_count() == 0 and interrupts are enabled */ lwz r8,TI_PREEMPT(r9) - cmpwi cr1,r8,0 + cmpwi cr0,r8,0 + bne restore ld r0,SOFTE(r1) - cmpdi r0,IRQS_DISABLED - crandc eq,cr1*4+eq,eq + andi. r0,r0,IRQS_DISABLED bne restore /* @@ -783,11 +782,11 @@ restore: */ ld r5,SOFTE(r1) lbz r6,PACASOFTIRQEN(r13) - cmpwi cr0,r5,IRQS_DISABLED - beq .Lrestore_irq_off + andi. r5,r5,IRQS_DISABLED + bne .Lrestore_irq_off /* We are enabling, were we already enabled ? Yes, just return */ - cmpwi cr0,r6,IRQS_ENABLED + andi. r6,r6,IRQS_DISABLED beq cr0,.Ldo_restore /* @@ -1031,15 +1030,15 @@ _GLOBAL(enter_rtas) li r0,0 mtcr r0 -#ifdef CONFIG_BUG +#ifdef CONFIG_BUG /* There is no way it is acceptable to get here with interrupts enabled, * check it with the asm equivalent of WARN_ON */ lbz r0,PACASOFTIRQEN(r13) -1: tdnei r0,IRQS_DISABLED +1: tdeqi r0,IRQS_ENABLED EMIT_BUG_ENTRY 1b,__FILE__,__LINE__,BUGFLAG_WARNING #endif - + /* Hard-disable interrupts */ mfmsr r6 rldicl r7,r6,48,1 diff --git a/arch/powerpc/kernel/exceptions-64e.S b/arch/powerpc/kernel/exceptions-64e.S index 80cc91bbcf1a..9216ece7672c 100644 --- a/arch/powerpc/kernel/exceptions-64e.S +++ b/arch/powerpc/kernel/exceptions-64e.S @@ -210,10 +210,10 @@ END_FTR_SECTION_IFSET(CPU_FTR_EMB_HV) ld r5,SOFTE(r1) /* Interrupts had better not already be enabled... */ - twnei r6,IRQS_DISABLED + tweqi r6,IRQS_ENABLED - cmpwi cr0,r5,IRQS_DISABLED - beq 1f + andi. r6,r5,IRQS_DISABLED + bne 1f TRACE_ENABLE_INTS stb r5,PACASOFTIRQEN(r13) @@ -352,8 +352,8 @@ ret_from_mc_except: #define PROLOG_ADDITION_MASKABLE_GEN(n) \ lbz r10,PACASOFTIRQEN(r13); /* are irqs soft-disabled ? */ \ - cmpwi cr0,r10,IRQS_DISABLED; /* yes -> go out of line */ \ - beq masked_interrupt_book3e_##n + andi. r10,r10,IRQS_DISABLED; /* yes -> go out of line */ \ + bne masked_interrupt_book3e_##n #define PROLOG_ADDITION_2REGS_GEN(n) \ std r14,PACA_EXGEN+EX_R14(r13); \ diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c index 6c04e465caf5..406c4329b535 100644 --- a/arch/powerpc/kernel/irq.c +++ b/arch/powerpc/kernel/irq.c @@ -219,15 +219,29 @@ notrace unsigned int __check_irq_replay(void) return 0; } -notrace void arch_local_irq_restore(unsigned long en) +notrace void arch_local_irq_restore(unsigned long mask) { unsigned char irq_happened; unsigned int replay; /* Write the new soft-enabled value */ - soft_enabled_set(en); - if (en == IRQS_DISABLED) + soft_enabled_set(mask); + if (mask) { +#ifdef CONFIG_TRACE_IRQFLAGS + /* + * mask must always include LINUX bit if any + * are set, and interrupts don't get replayed until + * the Linux interrupt is unmasked. This could be + * changed to replay partial unmasks in future, + * which would allow Linux masks to nest inside + * other masks, among other things. For now, be very + * dumb and simple. + */ + WARN_ON(!(mask & IRQS_DISABLED)); +#endif return; + } + /* * From this point onward, we can take interrupts, preempt, * etc... unless we got hard-disabled. We check if an event |