Commit c92a1acb authored by Arnd Bergmann's avatar Arnd Bergmann Committed by Jeremy Kerr

[POWERPC] spufs: 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: default avatarArnd Bergmann <arnd@arndb.de>
Signed-off-by: default avatarJeremy Kerr <jk@ozlabs.org>
parent cc4b7c18
...@@ -81,9 +81,12 @@ struct spu_slb { ...@@ -81,9 +81,12 @@ struct spu_slb {
void spu_invalidate_slbs(struct spu *spu) void spu_invalidate_slbs(struct spu *spu)
{ {
struct spu_priv2 __iomem *priv2 = spu->priv2; 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) if (spu_mfc_sr1_get(spu) & MFC_STATE1_RELOCATE_MASK)
out_be64(&priv2->slb_invalidate_all_W, 0UL); out_be64(&priv2->slb_invalidate_all_W, 0UL);
spin_unlock_irqrestore(&spu->register_lock, flags);
} }
EXPORT_SYMBOL_GPL(spu_invalidate_slbs); EXPORT_SYMBOL_GPL(spu_invalidate_slbs);
...@@ -294,9 +297,11 @@ void spu_setup_kernel_slbs(struct spu *spu, struct spu_lscsa *lscsa, ...@@ -294,9 +297,11 @@ void spu_setup_kernel_slbs(struct spu *spu, struct spu_lscsa *lscsa,
nr_slbs++; nr_slbs++;
} }
spin_lock_irq(&spu->register_lock);
/* Add the set of SLBs */ /* Add the set of SLBs */
for (i = 0; i < nr_slbs; i++) for (i = 0; i < nr_slbs; i++)
spu_load_slb(spu, i, &slbs[i]); spu_load_slb(spu, i, &slbs[i]);
spin_unlock_irq(&spu->register_lock);
} }
EXPORT_SYMBOL_GPL(spu_setup_kernel_slbs); EXPORT_SYMBOL_GPL(spu_setup_kernel_slbs);
...@@ -341,13 +346,14 @@ spu_irq_class_1(int irq, void *data) ...@@ -341,13 +346,14 @@ spu_irq_class_1(int irq, void *data)
if (stat & CLASS1_STORAGE_FAULT_INTR) if (stat & CLASS1_STORAGE_FAULT_INTR)
spu_mfc_dsisr_set(spu, 0ul); spu_mfc_dsisr_set(spu, 0ul);
spu_int_stat_clear(spu, 1, stat); 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) if (stat & CLASS1_SEGMENT_FAULT_INTR)
__spu_trap_data_seg(spu, dar); __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) if (stat & CLASS1_STORAGE_FAULT_INTR)
__spu_trap_data_map(spu, dar, dsisr); __spu_trap_data_map(spu, dar, dsisr);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment