diff mbox

44x _tlbie() ME/CE/DE disabling unnecessary?

Message ID fb412d760810301104s228a6036s50adba8605a13a98@mail.gmail.com (mailing list archive)
State Not Applicable, archived
Delegated to: Josh Boyer
Headers show

Commit Message

Hollis Blanchard Oct. 30, 2008, 6:04 p.m. UTC
Regarding this patch:

commit aa1cf632bd6f998cb4567ccf1a9d2e5daaa9fb44
Author: David Gibson <david@gibson.dropbear.id.au>
Date:   Tue Aug 7 14:20:50 2007 +1000

    [POWERPC] Fix small race in 44x tlbie function

    The 440 family of processors don't have a tlbie instruction.  So, we
    implement TLB invalidates by explicitly searching the TLB with tlbsx.,
    then clobbering the relevant entry, if any.  Unfortunately the PID for
    the search needs to be stored in the MMUCR register, which is also
    used by the TLB miss handler.  Interrupts were enabled in _tlbie(), so
    an interrupt between loading the MMUCR and the tlbsx could cause
    incorrect search results, and thus a failure to invalide TLB entries
    which needed to be invalidated.

    This fixes the problem in both arch/ppc and arch/powerpc by inhibiting
    interrupts (even critical and debug interrupts) across the relevant
    instructions.

    Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
    Acked-by: Josh Boyer <jwboyer@linux.vnet.ibm.com>
    Signed-off-by: Paul Mackerras <paulus@samba.org>


I don't think it's necessary at all to disable ME/CE/DE inside
_tlbie() on 440, because the interrupt handlers for those types save
and restore MMUCR (they're all the same code path; see
mcheck_transfer_to_handler in entry_32.S).

However, I think EE does need to be disabled, since the normal EE
handler doesn't deal with MMUCR. So instead of all these MSR
manipulations, I think a simple wrteei 0/1 pair should do the trick?
Or maybe mfmsr/wrteei/wrtee, in case _tlbie() happens to be called
with interrupts disabled already.

-Hollis

Comments

Benjamin Herrenschmidt Oct. 30, 2008, 8:14 p.m. UTC | #1
On Thu, 2008-10-30 at 13:04 -0500, Hollis Blanchard wrote:
> 
> I don't think it's necessary at all to disable ME/CE/DE inside
> _tlbie() on 440, because the interrupt handlers for those types save
> and restore MMUCR (they're all the same code path; see
> mcheck_transfer_to_handler in entry_32.S).

This was written before the saving of MMUCR was added I think.

> However, I think EE does need to be disabled, since the normal EE
> handler doesn't deal with MMUCR. So instead of all these MSR
> manipulations, I think a simple wrteei 0/1 pair should do the trick?
> Or maybe mfmsr/wrteei/wrtee, in case _tlbie() happens to be called
> with interrupts disabled already.

Yes.

Ben.
Josh Boyer Oct. 30, 2008, 8:36 p.m. UTC | #2
On Fri, 31 Oct 2008 07:14:00 +1100
Benjamin Herrenschmidt <benh@kernel.crashing.org> wrote:

> On Thu, 2008-10-30 at 13:04 -0500, Hollis Blanchard wrote:
> > 
> > I don't think it's necessary at all to disable ME/CE/DE inside
> > _tlbie() on 440, because the interrupt handlers for those types save
> > and restore MMUCR (they're all the same code path; see
> > mcheck_transfer_to_handler in entry_32.S).
> 
> This was written before the saving of MMUCR was added I think.

I was thinking that but git was being annoying.

> > However, I think EE does need to be disabled, since the normal EE
> > handler doesn't deal with MMUCR. So instead of all these MSR
> > manipulations, I think a simple wrteei 0/1 pair should do the trick?
> > Or maybe mfmsr/wrteei/wrtee, in case _tlbie() happens to be called
> > with interrupts disabled already.
> 
> Yes.

Agreed.  Hollis and I had this discussion on IRC and I pointed out that
the patch originally just started with wrteei's.

(And aren't you supposed to be on vacation...)

josh
Kumar Gala Oct. 30, 2008, 9:20 p.m. UTC | #3
On Oct 30, 2008, at 3:36 PM, Josh Boyer wrote:

>
> (And aren't you supposed to be on vacation...)

There is no vacation from the community.. you will be assimilated. :)

- k
diff mbox

Patch

diff --git a/arch/powerpc/kernel/misc_32.S b/arch/powerpc/kernel/misc_32.S
index e708ab7..8533de5 100644
--- a/arch/powerpc/kernel/misc_32.S
+++ b/arch/powerpc/kernel/misc_32.S
@@ -301,9 +301,19 @@  _GLOBAL(_tlbie)
 	mfspr	r4,SPRN_MMUCR
 	mfspr	r5,SPRN_PID			/* Get PID */
 	rlwimi	r4,r5,0,24,31			/* Set TID */
-	mtspr	SPRN_MMUCR,r4

+	/* We have to run the search with interrupts disabled, even critical
+	 * and debug interrupts (in fact the only critical exceptions we have
+	 * are debug and machine check).  Otherwise  an interrupt which causes
+	 * a TLB miss can clobber the MMUCR between the mtspr and the tlbsx. */
+	mfmsr	r5
+	lis	r6,(MSR_EE|MSR_CE|MSR_ME|MSR_DE)@ha
+	addi	r6,r6,(MSR_EE|MSR_CE|MSR_ME|MSR_DE)@l
+	andc	r6,r5,r6
+	mtmsr	r6
+	mtspr	SPRN_MMUCR,r4
 	tlbsx.	r3, 0, r3
+	mtmsr	r5
 	bne	10f
 	sync
 	/* There are only 64 TLB entries, so r3 < 64,
diff --git a/arch/ppc/kernel/misc.S b/arch/ppc/kernel/misc.S
index 0da5536..a22e1f4 100644
--- a/arch/ppc/kernel/misc.S
+++ b/arch/ppc/kernel/misc.S
@@ -237,9 +237,19 @@  _GLOBAL(_tlbie)
 	mfspr	r4,SPRN_MMUCR
 	mfspr	r5,SPRN_PID			/* Get PID */
 	rlwimi	r4,r5,0,24,31			/* Set TID */
-	mtspr	SPRN_MMUCR,r4

+	/* We have to run the search with interrupts disabled, even critical
+	 * and debug interrupts (in fact the only critical exceptions we have
+	 * are debug and machine check).  Otherwise  an interrupt which causes
+	 * a TLB miss can clobber the MMUCR between the mtspr and the tlbsx. */
+	mfmsr	r5
+	lis	r6,(MSR_EE|MSR_CE|MSR_ME|MSR_DE)@ha
+	addi	r6,r6,(MSR_EE|MSR_CE|MSR_ME|MSR_DE)@l
+	andc	r6,r5,r6
+	mtmsr	r6
+	mtspr	SPRN_MMUCR,r4
 	tlbsx.	r3, 0, r3
+	mtmsr	r5
 	bne	10f
 	sync
 	/* There are only 64 TLB entries, so r3 < 64,