aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc
diff options
context:
space:
mode:
authorJeremy Kerr <jk@ozlabs.org>2007-04-23 15:08:16 -0400
committerArnd Bergmann <arnd@klappe.arndb.de>2007-04-23 15:18:55 -0400
commitc8a1e9393a86f862ab9c8bc0db9b8a1822226f84 (patch)
tree9ff1d8d44d5b5caa98770457297ec26382e1c9f5 /arch/powerpc
parent57dace2391ba10135e38457904121e7ef34d0c83 (diff)
[POWERPC] spufs: provide siginfo for SPE faults
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@ozlabs.org> Signed-off-by: Arnd Bergmann <arnd.bergmann@de.ibm.com>
Diffstat (limited to 'arch/powerpc')
-rw-r--r--arch/powerpc/platforms/cell/spufs/fault.c32
1 files changed, 25 insertions, 7 deletions
diff --git a/arch/powerpc/platforms/cell/spufs/fault.c b/arch/powerpc/platforms/cell/spufs/fault.c
index 182dc914cbc9..0f75c07e29d8 100644
--- a/arch/powerpc/platforms/cell/spufs/fault.c
+++ b/arch/powerpc/platforms/cell/spufs/fault.c
@@ -97,28 +97,46 @@ bad_area:
97 return -EFAULT; 97 return -EFAULT;
98} 98}
99 99
100static void spufs_handle_dma_error(struct spu_context *ctx, int type) 100static void spufs_handle_dma_error(struct spu_context *ctx,
101 unsigned long ea, int type)
101{ 102{
102 if (ctx->flags & SPU_CREATE_EVENTS_ENABLED) { 103 if (ctx->flags & SPU_CREATE_EVENTS_ENABLED) {
103 ctx->event_return |= type; 104 ctx->event_return |= type;
104 wake_up_all(&ctx->stop_wq); 105 wake_up_all(&ctx->stop_wq);
105 } else { 106 } else {
107 siginfo_t info;
108 memset(&info, 0, sizeof(info));
109
106 switch (type) { 110 switch (type) {
107 case SPE_EVENT_DMA_ALIGNMENT:
108 case SPE_EVENT_SPE_DATA_STORAGE:
109 case SPE_EVENT_INVALID_DMA: 111 case SPE_EVENT_INVALID_DMA:
110 force_sig(SIGBUS, /* info, */ current); 112 info.si_signo = SIGBUS;
113 info.si_code = BUS_OBJERR;
114 break;
115 case SPE_EVENT_SPE_DATA_STORAGE:
116 info.si_signo = SIGBUS;
117 info.si_addr = (void __user *)ea;
118 info.si_code = BUS_ADRERR;
119 break;
120 case SPE_EVENT_DMA_ALIGNMENT:
121 info.si_signo = SIGBUS;
122 /* DAR isn't set for an alignment fault :( */
123 info.si_code = BUS_ADRALN;
111 break; 124 break;
112 case SPE_EVENT_SPE_ERROR: 125 case SPE_EVENT_SPE_ERROR:
113 force_sig(SIGILL, /* info */ current); 126 info.si_signo = SIGILL;
127 info.si_addr = (void __user *)(unsigned long)
128 ctx->ops->npc_read(ctx) - 4;
129 info.si_code = ILL_ILLOPC;
114 break; 130 break;
115 } 131 }
132 if (info.si_signo)
133 force_sig_info(info.si_signo, &info, current);
116 } 134 }
117} 135}
118 136
119void spufs_dma_callback(struct spu *spu, int type) 137void spufs_dma_callback(struct spu *spu, int type)
120{ 138{
121 spufs_handle_dma_error(spu->ctx, type); 139 spufs_handle_dma_error(spu->ctx, spu->dar, type);
122} 140}
123EXPORT_SYMBOL_GPL(spufs_dma_callback); 141EXPORT_SYMBOL_GPL(spufs_dma_callback);
124 142
@@ -186,7 +204,7 @@ int spufs_handle_class1(struct spu_context *ctx)
186 if (ctx->spu) 204 if (ctx->spu)
187 ctx->ops->restart_dma(ctx); 205 ctx->ops->restart_dma(ctx);
188 } else 206 } else
189 spufs_handle_dma_error(ctx, SPE_EVENT_SPE_DATA_STORAGE); 207 spufs_handle_dma_error(ctx, ea, SPE_EVENT_SPE_DATA_STORAGE);
190 208
191 return ret; 209 return ret;
192} 210}