[Cbe-oss-dev] [PATCH v2] serialize SLB invalidation against SLB loading

Arnd Bergmann arnd at arndb.de
Thu Feb 28 16:06:30 EST 2008


Subject: serialize SLB invalidation against SLB loading

There is a potential race between flushes of the entire SLB
in the MFC and the point where new entries are being established.
The problem is that we might put a ESID entry into the MFC SLB
when the VSID entry has just been cleared by the global
flush.

This can be circumvented by holding the register_lock
throughout both the flushing and the creation of SLB entries.

Signed-off-by: Arnd Bergmann <arnd at arndb.de>
---
unlike the previous version, this one uses spin_lock_irqsave,
because some of the callers of spu_invalidate_slbs call it
with interrupts enabled, which could potentially deadlock
the first version of this patch.

Index: linux-2.6/arch/powerpc/platforms/cell/spu_base.c
===================================================================
--- linux-2.6.orig/arch/powerpc/platforms/cell/spu_base.c
+++ linux-2.6/arch/powerpc/platforms/cell/spu_base.c
@@ -81,9 +81,12 @@ struct spu_slb {
 void spu_invalidate_slbs(struct spu *spu)
 {
 	struct spu_priv2 __iomem *priv2 = spu->priv2;
+	unsigned long flags;
 
+	spin_lock_irqsave(&spu->register_lock, flags);
 	if (spu_mfc_sr1_get(spu) & MFC_STATE1_RELOCATE_MASK)
 		out_be64(&priv2->slb_invalidate_all_W, 0UL);
+	spin_unlock_irqrestore(&spu->register_lock, flags);
 }
 EXPORT_SYMBOL_GPL(spu_invalidate_slbs);
 
@@ -290,9 +293,11 @@ void spu_setup_kernel_slbs(struct spu *s
 		nr_slbs++;
 	}
 
+	spin_lock_irq(&spu->register_lock);
 	/* Add the set of SLBs */
 	for (i = 0; i < nr_slbs; i++)
 		spu_load_slb(spu, i, &slbs[i]);
+	spin_unlock_irq(&spu->register_lock);
 }
 EXPORT_SYMBOL_GPL(spu_setup_kernel_slbs);
 
@@ -337,13 +342,14 @@ spu_irq_class_1(int irq, void *data)
 	if (stat & CLASS1_STORAGE_FAULT_INTR)
 		spu_mfc_dsisr_set(spu, 0ul);
 	spu_int_stat_clear(spu, 1, stat);
-	spin_unlock(&spu->register_lock);
-	pr_debug("%s: %lx %lx %lx %lx\n", __FUNCTION__, mask, stat,
-			dar, dsisr);
 
 	if (stat & CLASS1_SEGMENT_FAULT_INTR)
 		__spu_trap_data_seg(spu, dar);
 
+	spin_unlock(&spu->register_lock);
+	pr_debug("%s: %lx %lx %lx %lx\n", __FUNCTION__, mask, stat,
+			dar, dsisr);
+
 	if (stat & CLASS1_STORAGE_FAULT_INTR)
 		__spu_trap_data_map(spu, dar, dsisr);
 



More information about the cbe-oss-dev mailing list