diff options
-rw-r--r-- | arch/powerpc/platforms/cell/spufs/fault.c | 32 |
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 | ||
100 | static void spufs_handle_dma_error(struct spu_context *ctx, int type) | 100 | static 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 | ||
119 | void spufs_dma_callback(struct spu *spu, int type) | 137 | void 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 | } |
123 | EXPORT_SYMBOL_GPL(spufs_dma_callback); | 141 | EXPORT_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 | } |