summaryrefslogtreecommitdiffstats
path: root/sys/powerpc/ps3
diff options
context:
space:
mode:
authornwhitehorn <nwhitehorn@FreeBSD.org>2014-05-12 02:56:27 +0000
committernwhitehorn <nwhitehorn@FreeBSD.org>2014-05-12 02:56:27 +0000
commitb031f87ca09e2d76dd70b8a845ca699761273def (patch)
tree69a6029a74b163354c2a740fade253f1c3bfdc6c /sys/powerpc/ps3
parenteac3665246e4234610cc2a4c5a914b07e432139a (diff)
downloadFreeBSD-src-b031f87ca09e2d76dd70b8a845ca699761273def.zip
FreeBSD-src-b031f87ca09e2d76dd70b8a845ca699761273def.tar.gz
Repair some races in IPI handling:
1. Make sure IPI mask is set before sending the IPI 2. Operate atomically on PS3 PIC outstanding interrupt list 3. Make sure IPIs are EOI'ed before, not after, processing. Without this, a second IPI could be sent partway through processing the first one, get erroneously acknowledge by the EOI to the first, and be lost. In particular in the case of smp_rendezvous(), this can be fatal. In combination, this makes the PS3 boot SMP again. It probably also fixes some latent bugs elsewhere. MFC after: 2 weeks
Diffstat (limited to 'sys/powerpc/ps3')
-rw-r--r--sys/powerpc/ps3/ps3pic.c5
1 files changed, 3 insertions, 2 deletions
diff --git a/sys/powerpc/ps3/ps3pic.c b/sys/powerpc/ps3/ps3pic.c
index 9b40f6c..374d96e 100644
--- a/sys/powerpc/ps3/ps3pic.c
+++ b/sys/powerpc/ps3/ps3pic.c
@@ -166,12 +166,13 @@ ps3pic_dispatch(device_t dev, struct trapframe *tf)
sc = device_get_softc(dev);
if (PCPU_GET(cpuid) == 0) {
- bitmap = sc->bitmap_thread0[0];
+ bitmap = atomic_readandclear_64(&sc->bitmap_thread0[0]);
mask = sc->mask_thread0[0];
} else {
- bitmap = sc->bitmap_thread1[0];
+ bitmap = atomic_readandclear_64(&sc->bitmap_thread1[0]);
mask = sc->mask_thread1[0];
}
+ powerpc_sync();
while ((irq = ffsl(bitmap & mask) - 1) != -1) {
bitmap &= ~(1UL << irq);
OpenPOWER on IntegriCloud