summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/powerpc/kernel/exceptions-64e.S9
-rw-r--r--arch/powerpc/kernel/head_fsl_booke.S10
-rw-r--r--arch/powerpc/kernel/idle.c3
-rw-r--r--arch/powerpc/kernel/time.c11
-rw-r--r--arch/powerpc/platforms/Kconfig.cputype42
-rw-r--r--drivers/watchdog/Kconfig2
6 files changed, 75 insertions, 2 deletions
diff --git a/arch/powerpc/kernel/exceptions-64e.S b/arch/powerpc/kernel/exceptions-64e.S
index 39308c7..5e6a242 100644
--- a/arch/powerpc/kernel/exceptions-64e.S
+++ b/arch/powerpc/kernel/exceptions-64e.S
@@ -444,6 +444,14 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
fixed_interval, .unknown_exception, ACK_FIT)
/* Watchdog Timer Interrupt */
+#ifdef CONFIG_FSL_ERRATUM_A_006184
+ START_EXCEPTION(watchdog)
+ mtspr SPRN_SPRG_CRIT_SCRATCH, r3
+ lis r3, TSR_WIS@h
+ mtspr SPRN_TSR, r3
+ mfspr r3, SPRN_SPRG_CRIT_SCRATCH
+ rfci
+#else
START_EXCEPTION(watchdog);
CRIT_EXCEPTION_PROLOG(0x9f0, BOOKE_INTERRUPT_WATCHDOG,
PROLOG_ADDITION_NONE)
@@ -454,6 +462,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
// bl .unknown_exception
// b ret_from_crit_except
b .
+#endif
/* System Call Interrupt */
START_EXCEPTION(system_call)
diff --git a/arch/powerpc/kernel/head_fsl_booke.S b/arch/powerpc/kernel/head_fsl_booke.S
index 58925b6..987a3f1 100644
--- a/arch/powerpc/kernel/head_fsl_booke.S
+++ b/arch/powerpc/kernel/head_fsl_booke.S
@@ -369,7 +369,15 @@ interrupt_base:
unknown_exception, EXC_XFER_EE)
/* Watchdog Timer Interrupt */
-#ifdef CONFIG_BOOKE_WDT
+#ifdef CONFIG_FSL_ERRATUM_A_006184
+ START_EXCEPTION(WatchdogTimer)
+ mtspr SPRN_SPRG_WSCRATCH_CRIT, r3
+ lis r3, TSR_WIS@h
+ mtspr SPRN_TSR, r3
+ /* use WSCRATCH to avoid any potential problems with KVM paravirt */
+ mfspr r3, SPRN_SPRG_WSCRATCH_CRIT
+ rfci
+#elif defined(CONFIG_BOOKE_WDT)
CRITICAL_EXCEPTION(0x3200, WATCHDOG, WatchdogTimer, WatchdogException)
#else
CRITICAL_EXCEPTION(0x3200, WATCHDOG, WatchdogTimer, unknown_exception)
diff --git a/arch/powerpc/kernel/idle.c b/arch/powerpc/kernel/idle.c
index ea78761..c6ac64b 100644
--- a/arch/powerpc/kernel/idle.c
+++ b/arch/powerpc/kernel/idle.c
@@ -102,6 +102,9 @@ void cpu_idle(void)
ppc64_runlatch_on();
rcu_idle_exit();
tick_nohz_idle_exit();
+#ifdef CONFIG_FSL_ERRATUM_A_006184
+ mtspr(SPRN_TSR, TSR_ENW);
+#endif
if (cpu_should_die()) {
sched_preempt_enable_no_resched();
cpu_die();
diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c
index 127361e..9a9112f 100644
--- a/arch/powerpc/kernel/time.c
+++ b/arch/powerpc/kernel/time.c
@@ -488,6 +488,9 @@ void timer_interrupt(struct pt_regs * regs)
struct clock_event_device *evt = &__get_cpu_var(decrementers);
u64 now;
+#ifdef CONFIG_FSL_ERRATUM_A_006184
+ mtspr(SPRN_TSR, TSR_ENW);
+#endif
/* Ensure a positive value is written to the decrementer, or else
* some CPUs will continue to take decrementer exceptions.
*/
@@ -638,7 +641,15 @@ void start_cpu_decrementer(void)
mtspr(SPRN_TSR, TSR_ENW | TSR_WIS | TSR_DIS | TSR_FIS);
/* Enable decrementer interrupt */
+#ifdef CONFIG_FSL_ERRATUM_A_006184
+#define WDTP(x) ((((x)&0x3)<<30)|(((x)&0x3c)<<15))
+ {
+ u32 period = WDTP(CONFIG_FSL_ERRATUM_A_006184_PERIOD);
+ mtspr(SPRN_TCR, TCR_DIE | TCR_WIE | period);
+ }
+#else
mtspr(SPRN_TCR, TCR_DIE);
+#endif
#endif /* defined(CONFIG_BOOKE) || defined(CONFIG_40x) */
}
diff --git a/arch/powerpc/platforms/Kconfig.cputype b/arch/powerpc/platforms/Kconfig.cputype
index 421bae9..550ceba 100644
--- a/arch/powerpc/platforms/Kconfig.cputype
+++ b/arch/powerpc/platforms/Kconfig.cputype
@@ -174,6 +174,48 @@ config PPC_E6500_REV1_BUGS
Do not define this if you are running on a simulator or rev2,
and want features like hardware tablewalk.
+config FSL_ERRATUM_A_006184
+ bool "Work around erratum A-006184"
+ help
+ Define this to work around erratum A-006184 ("Simultaneous
+ Instruction L1 MMU miss (due to eviction) and interrupt
+ servicing can cause a core hang"). This erratum affects
+ e500v1, e500v2, e500mc, and e5500. The workaround will
+ cause a watchdog interrupt to occur periodically. It will
+ not avoid the hang described by the erratum, but it will
+ recover from it when the next watchdog interrupt expires.
+
+ The normal watchdog functionality cannot be used when this
+ workaround is enabled.
+
+ If you are running Linux as the guest of a hypervisor, you
+ should enable this (or a similar workaround) in the host
+ instead.
+
+ Note that it is believed that it is unlikely that the hang
+ will be encountered in normal Linux operation. Running KVM
+ or using hugetlbfs could increase the chance of seeing the
+ hang.
+
+config FSL_ERRATUM_A_006184_PERIOD
+ int "Watchdog period for A-006184 workaround"
+ range 32 52
+ default 43
+ help
+ This is the watchdog period to be used for the A-006184
+ workaround. The watchdog will fire whenever the bit selected
+ transitions from 0 to 1 in the time base. The bits are
+ numbered with 0 starting at the most-signficant end --
+ larger numbers give a more frequent period.
+
+ The period must be set longer than the non-idle decrementer
+ period, to ensure that the watchdog interrupt only actually
+ happens when stuck -- but the longer the period, the worse the
+ latency will be if a hang does occur. Long decrementer
+ timeouts when idle due to CONFIG_NO_HZ should not be a problem,
+ since when idle we will always have just executed from the main
+ kernel mapping, so it should not be absent from the L1 I-MMU.
+
config FSL_ERRATUM_A_006198
bool "Work around e6500 rev1 erratum A-006198"
depends on PPC_E500MC
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index 19fa73a..391ee8c 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -1119,7 +1119,7 @@ config PIKA_WDT
config BOOKE_WDT
tristate "PowerPC Book-E Watchdog Timer"
- depends on BOOKE || 4xx
+ depends on (BOOKE || 4xx) && !FSL_ERRATUM_A_006184
---help---
Watchdog driver for PowerPC Book-E chips, such as the Freescale
MPC85xx SOCs and the IBM PowerPC 440.