aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc
diff options
context:
space:
mode:
authorMasato Noguchi <Masato.Noguchi@jp.sony.com>2006-11-20 12:45:04 -0500
committerPaul Mackerras <paulus@samba.org>2006-12-04 04:39:55 -0500
commit2ebb2477f9a61b436dd22b75189857df1a77e585 (patch)
treed0f9fbfd2f63c83adcf71ab316096d25c5f50433 /arch/powerpc
parent453d9f72a91d798c3e3c4b4bed26210926dfb57b (diff)
[POWERPC] spufs: Fix missing stop-and-signal
When there is pending signals, current spufs_run_spu() always returns -ERESTARTSYS and it is called again automatically. But, if spe already stopped by stop-and-signal or halt instruction, returning -ERESTARTSYS makes stop-and-signal/halt lost and spu run over the end-point. For your convenience, I attached a sample code to restage this bug. If there is no bug, printed NPC will be 0x4000. Signed-off-by: Masato Noguchi <Masato.Noguchi@jp.sony.com> Signed-off-by: Arnd Bergmann <arnd.bergmann@de.ibm.com> Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch/powerpc')
-rw-r--r--arch/powerpc/platforms/cell/spufs/run.c28
1 files changed, 18 insertions, 10 deletions
diff --git a/arch/powerpc/platforms/cell/spufs/run.c b/arch/powerpc/platforms/cell/spufs/run.c
index 88a41d83a79b..c88fd7f9ea74 100644
--- a/arch/powerpc/platforms/cell/spufs/run.c
+++ b/arch/powerpc/platforms/cell/spufs/run.c
@@ -79,13 +79,7 @@ static inline int spu_run_fini(struct spu_context *ctx, u32 * npc,
79 79
80 if (signal_pending(current)) 80 if (signal_pending(current))
81 ret = -ERESTARTSYS; 81 ret = -ERESTARTSYS;
82 if (unlikely(current->ptrace & PT_PTRACED)) { 82
83 if ((*status & SPU_STATUS_STOPPED_BY_STOP)
84 && (*status >> SPU_STOP_STATUS_SHIFT) == 0x3fff) {
85 force_sig(SIGTRAP, current);
86 ret = -ERESTARTSYS;
87 }
88 }
89 return ret; 83 return ret;
90} 84}
91 85
@@ -232,7 +226,7 @@ long spufs_run_spu(struct file *file, struct spu_context *ctx,
232 if (unlikely(ctx->state != SPU_STATE_RUNNABLE)) { 226 if (unlikely(ctx->state != SPU_STATE_RUNNABLE)) {
233 ret = spu_reacquire_runnable(ctx, npc, &status); 227 ret = spu_reacquire_runnable(ctx, npc, &status);
234 if (ret) 228 if (ret)
235 goto out; 229 goto out2;
236 continue; 230 continue;
237 } 231 }
238 ret = spu_process_events(ctx); 232 ret = spu_process_events(ctx);
@@ -242,10 +236,24 @@ long spufs_run_spu(struct file *file, struct spu_context *ctx,
242 236
243 ctx->ops->runcntl_stop(ctx); 237 ctx->ops->runcntl_stop(ctx);
244 ret = spu_run_fini(ctx, npc, &status); 238 ret = spu_run_fini(ctx, npc, &status);
245 if (!ret)
246 ret = status;
247 spu_yield(ctx); 239 spu_yield(ctx);
248 240
241out2:
242 if ((ret == 0) ||
243 ((ret == -ERESTARTSYS) &&
244 ((status & SPU_STATUS_STOPPED_BY_HALT) ||
245 ((status & SPU_STATUS_STOPPED_BY_STOP) &&
246 (status >> SPU_STOP_STATUS_SHIFT != 0x2104)))))
247 ret = status;
248
249 if (unlikely(current->ptrace & PT_PTRACED)) {
250 if ((status & SPU_STATUS_STOPPED_BY_STOP)
251 && (status >> SPU_STOP_STATUS_SHIFT) == 0x3fff) {
252 force_sig(SIGTRAP, current);
253 ret = -ERESTARTSYS;
254 }
255 }
256
249out: 257out:
250 *event = ctx->event_return; 258 *event = ctx->event_return;
251 up(&ctx->run_sema); 259 up(&ctx->run_sema);