[Cbe-oss-dev] [PATCH] spufs: provide siginfo for SPE faults

Jeremy Kerr jk at ozlabs.org
Mon Jan 8 17:18:29 EST 2007


This change populates a siginfo struct for SPE application exceptions
(ie, invalid DMAs and illegal instructions).

Tested on an IBM Cell Blade.

Signed-off-by: Jeremy Kerr <jk at ozlabs.org>
---

 spu_base.c  |   10 ++++++----
 spufs/run.c |   25 +++++++++++++++++++++----
 2 files changed, 27 insertions(+), 8 deletions(-)

diff --git a/arch/powerpc/platforms/cell/spu_base.c b/arch/powerpc/platforms/cell/spu_base.c
index bd7bffc..fb4e071 100644
--- a/arch/powerpc/platforms/cell/spu_base.c
+++ b/arch/powerpc/platforms/cell/spu_base.c
@@ -496,13 +496,15 @@ int spu_irq_class_1_bottom(struct spu *spu)
 		else
 			error &= ~CLASS1_ENABLE_STORAGE_FAULT_INTR;
 	}
+
+	if (error)
+		spu->dma_callback(spu, SPE_EVENT_SPE_DATA_STORAGE);
+
 	spu->dar = 0UL;
 	spu->dsisr = 0UL;
-	if (!error) {
+
+	if (!error)
 		spu_restart_dma(spu);
-	} else {
-		spu->dma_callback(spu, SPE_EVENT_SPE_DATA_STORAGE);
-	}
 	return ret;
 }
 
diff --git a/arch/powerpc/platforms/cell/spufs/run.c b/arch/powerpc/platforms/cell/spufs/run.c
index 1acc2ff..ff96ab7 100644
--- a/arch/powerpc/platforms/cell/spufs/run.c
+++ b/arch/powerpc/platforms/cell/spufs/run.c
@@ -26,16 +26,33 @@ void spufs_dma_callback(struct spu *spu, int type)
 		ctx->event_return |= type;
 		wake_up_all(&ctx->stop_wq);
 	} else {
+		siginfo_t info;
+		memset(&info, 0, sizeof(info));
+
 		switch (type) {
-		case SPE_EVENT_DMA_ALIGNMENT:
-		case SPE_EVENT_SPE_DATA_STORAGE:
 		case SPE_EVENT_INVALID_DMA:
-			force_sig(SIGBUS, /* info, */ current);
+			info.si_signo = SIGBUS;
+			info.si_code = BUS_OBJERR;
+			break;
+		case SPE_EVENT_SPE_DATA_STORAGE:
+			info.si_signo = SIGBUS;
+			info.si_addr = (void __user *)spu->dar;
+			info.si_code = BUS_ADRERR;
+			break;
+		case SPE_EVENT_DMA_ALIGNMENT:
+			info.si_signo = SIGBUS;
+			/* DAR isn't set for an alignment fault :( */
+			info.si_code = BUS_ADRALN;
 			break;
 		case SPE_EVENT_SPE_ERROR:
-			force_sig(SIGILL, /* info */ current);
+			info.si_signo = SIGILL;
+			info.si_addr = (void __user *)(unsigned long)
+				ctx->ops->npc_read(ctx) - 4;
+			info.si_code = ILL_ILLOPC;
 			break;
 		}
+		if (info.si_signo)
+			force_sig_info(info.si_signo, &info, current);
 	}
 }
 



More information about the cbe-oss-dev mailing list