diff options
author | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2008-04-02 00:58:40 -0400 |
---|---|---|
committer | Paul Mackerras <paulus@samba.org> | 2008-04-03 07:10:34 -0400 |
commit | ff3da2e0938bae36d10d69c22bce0177b067a9e2 (patch) | |
tree | 4df635b6bc9298fbf455ab2be23aaec04324c3f0 /arch | |
parent | 025306f30948836a743eb68a7cbaf4ab0bfb5f47 (diff) |
[POWERPC] Fix iSeries hard irq enabling regression
A subtle bug sneaked into iSeries recently. On this platform, we must
not normally clear MSR:EE (the hardware external interrupt enable)
except for short periods of time. Taking an interrupt while
soft-disabled doesn't cause us to clear it for example.
The iSeries kernel expects to mostly run with MSR:EE enabled at all
times except in a few exception entry/exit code paths. Thus
local_irq_enable() doesn't check if it needs to hard-enable as it
expects this to be unnecessary on iSeries.
However, hard_irq_disable() _does_ cause MSR:EE to be cleared,
including on iSeries. A call to it was recently added to the
context switch code, thus causing interrupts to become disabled
for a long periods of time, causing the iSeries watchdog to kick
in under some circumstances and other nasty things.
This patch fixes it by making local_irq_enable() properly re-enable
MSR:EE on iSeries. It basically removes a return statement here
to make iSeries use the same code path as everybody else. That does
mean that we might occasionally get spurious decrementer interrupts
but I don't think that matters.
Another option would have been to make hard_irq_disable() a nop
on iSeries but I didn't like it much, in case we have good reasons
to hard-disable.
Part of the patch is fixes to make sure the hard_enabled PACA field
is properly set on iSeries as it used not to be before, since it
was mostly unused.
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/powerpc/kernel/head_64.S | 13 | ||||
-rw-r--r-- | arch/powerpc/kernel/irq.c | 1 |
2 files changed, 7 insertions, 7 deletions
diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S index 11b4f6d9ffce..d3aee08e6814 100644 --- a/arch/powerpc/kernel/head_64.S +++ b/arch/powerpc/kernel/head_64.S | |||
@@ -1387,12 +1387,14 @@ __secondary_start: | |||
1387 | #ifdef CONFIG_PPC_ISERIES | 1387 | #ifdef CONFIG_PPC_ISERIES |
1388 | BEGIN_FW_FTR_SECTION | 1388 | BEGIN_FW_FTR_SECTION |
1389 | ori r4,r4,MSR_EE | 1389 | ori r4,r4,MSR_EE |
1390 | li r8,1 | ||
1391 | stb r8,PACAHARDIRQEN(r13) | ||
1390 | END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES) | 1392 | END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES) |
1391 | #endif | 1393 | #endif |
1392 | BEGIN_FW_FTR_SECTION | 1394 | BEGIN_FW_FTR_SECTION |
1393 | stb r7,PACASOFTIRQEN(r13) | ||
1394 | stb r7,PACAHARDIRQEN(r13) | 1395 | stb r7,PACAHARDIRQEN(r13) |
1395 | END_FW_FTR_SECTION_IFCLR(FW_FEATURE_ISERIES) | 1396 | END_FW_FTR_SECTION_IFCLR(FW_FEATURE_ISERIES) |
1397 | stb r7,PACASOFTIRQEN(r13) | ||
1396 | 1398 | ||
1397 | mtspr SPRN_SRR0,r3 | 1399 | mtspr SPRN_SRR0,r3 |
1398 | mtspr SPRN_SRR1,r4 | 1400 | mtspr SPRN_SRR1,r4 |
@@ -1520,15 +1522,14 @@ _INIT_GLOBAL(start_here_common) | |||
1520 | #ifdef CONFIG_PPC_ISERIES | 1522 | #ifdef CONFIG_PPC_ISERIES |
1521 | BEGIN_FW_FTR_SECTION | 1523 | BEGIN_FW_FTR_SECTION |
1522 | mfmsr r5 | 1524 | mfmsr r5 |
1523 | ori r5,r5,MSR_EE /* Hard Enabled */ | 1525 | ori r5,r5,MSR_EE /* Hard Enabled on iSeries*/ |
1524 | mtmsrd r5 | 1526 | mtmsrd r5 |
1527 | li r5,1 | ||
1525 | END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES) | 1528 | END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES) |
1526 | #endif | 1529 | #endif |
1527 | BEGIN_FW_FTR_SECTION | 1530 | stb r5,PACAHARDIRQEN(r13) /* Hard Disabled on others */ |
1528 | stb r5,PACAHARDIRQEN(r13) | ||
1529 | END_FW_FTR_SECTION_IFCLR(FW_FEATURE_ISERIES) | ||
1530 | 1531 | ||
1531 | bl .start_kernel | 1532 | bl .start_kernel |
1532 | 1533 | ||
1533 | /* Not reached */ | 1534 | /* Not reached */ |
1534 | BUG_OPCODE | 1535 | BUG_OPCODE |
diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c index b0e5deb4274f..292163f5b39a 100644 --- a/arch/powerpc/kernel/irq.c +++ b/arch/powerpc/kernel/irq.c | |||
@@ -143,7 +143,6 @@ void local_irq_restore(unsigned long en) | |||
143 | */ | 143 | */ |
144 | if (local_paca->lppaca_ptr->int_dword.any_int) | 144 | if (local_paca->lppaca_ptr->int_dword.any_int) |
145 | iseries_handle_interrupts(); | 145 | iseries_handle_interrupts(); |
146 | return; | ||
147 | } | 146 | } |
148 | 147 | ||
149 | /* | 148 | /* |