From d52459ca3047435aa5d7957e50857fc7ba193411 Mon Sep 17 00:00:00 2001 From: Scott Wood Date: Tue, 23 Jul 2013 20:21:11 -0500 Subject: powerpc/fsl-booke: Work around erratum A-006958 Erratum A-006598 says that 64-bit mftb is not atomic -- it's subject to a similar race condition as doing mftbu/mftbl on 32-bit. The lower half of timebase is updated before the upper half; thus, we can share the workaround for a similar bug on Cell. This workaround involves looping if the lower half of timebase is zero, thus avoiding the need for a scratch register (other than CR0). This workaround must be avoided when the timebase is frozen, such as during the timebase sync code. This deals with kernel and vdso accesses, but other userspace accesses will of course need to be fixed elsewhere. Signed-off-by: Scott Wood --- arch/powerpc/platforms/85xx/smp.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) (limited to 'arch/powerpc/platforms/85xx/smp.c') diff --git a/arch/powerpc/platforms/85xx/smp.c b/arch/powerpc/platforms/85xx/smp.c index ea9c6269ead0..ea7e62910891 100644 --- a/arch/powerpc/platforms/85xx/smp.c +++ b/arch/powerpc/platforms/85xx/smp.c @@ -69,7 +69,30 @@ static void mpc85xx_give_timebase(void) tb_req = 0; mpc85xx_timebase_freeze(1); +#ifdef CONFIG_PPC64 + /* + * e5500/e6500 have a workaround for erratum A-006958 in place + * that will reread the timebase until TBL is non-zero. + * That would be a bad thing when the timebase is frozen. + * + * Thus, we read it manually, and instead of checking that + * TBL is non-zero, we ensure that TB does not change. We don't + * do that for the main mftb implementation, because it requires + * a scratch register + */ + { + u64 prev; + + asm volatile("mftb %0" : "=r" (timebase)); + + do { + prev = timebase; + asm volatile("mftb %0" : "=r" (timebase)); + } while (prev != timebase); + } +#else timebase = get_tb(); +#endif mb(); tb_valid = 1; -- cgit v1.2.3