1 #define DEBUG 2 3 #include <linux/wait.h> 4 #include <linux/ptrace.h> 5 6 #include <asm/spu.h> 7 #include <asm/spu_priv1.h> 8 #include <asm/io.h> 9 #include <asm/unistd.h> 10 11 #include "spufs.h" 12 13 /* interrupt-level stop callback function. */ 14 void spufs_stop_callback(struct spu *spu) 15 { 16 struct spu_context *ctx = spu->ctx; 17 18 /* 19 * It should be impossible to preempt a context while an exception 20 * is being processed, since the context switch code is specially 21 * coded to deal with interrupts ... But, just in case, sanity check 22 * the context pointer. It is OK to return doing nothing since 23 * the exception will be regenerated when the context is resumed. 24 */ 25 if (ctx) { 26 /* Copy exception arguments into module specific structure */ 27 ctx->csa.class_0_pending = spu->class_0_pending; 28 ctx->csa.dsisr = spu->dsisr; 29 ctx->csa.dar = spu->dar; 30 31 /* ensure that the exception status has hit memory before a 32 * thread waiting on the context's stop queue is woken */ 33 smp_wmb(); 34 35 wake_up_all(&ctx->stop_wq); 36 } 37 38 /* Clear callback arguments from spu structure */ 39 spu->class_0_pending = 0; 40 spu->dsisr = 0; 41 spu->dar = 0; 42 } 43 44 int spu_stopped(struct spu_context *ctx, u32 *stat) 45 { 46 u64 dsisr; 47 u32 stopped; 48 49 *stat = ctx->ops->status_read(ctx); 50 51 if (test_bit(SPU_SCHED_NOTIFY_ACTIVE, &ctx->sched_flags)) 52 return 1; 53 54 stopped = SPU_STATUS_INVALID_INSTR | SPU_STATUS_SINGLE_STEP | 55 SPU_STATUS_STOPPED_BY_HALT | SPU_STATUS_STOPPED_BY_STOP; 56 if (*stat & stopped) 57 return 1; 58 59 dsisr = ctx->csa.dsisr; 60 if (dsisr & (MFC_DSISR_PTE_NOT_FOUND | MFC_DSISR_ACCESS_DENIED)) 61 return 1; 62 63 if (ctx->csa.class_0_pending) 64 return 1; 65 66 return 0; 67 } 68 69 static int spu_setup_isolated(struct spu_context *ctx) 70 { 71 int ret; 72 u64 __iomem *mfc_cntl; 73 u64 sr1; 74 u32 status; 75 unsigned long timeout; 76 const u32 status_loading = SPU_STATUS_RUNNING 77 | SPU_STATUS_ISOLATED_STATE | SPU_STATUS_ISOLATED_LOAD_STATUS; 78 79 ret = -ENODEV; 80 if (!isolated_loader) 81 goto out; 82 83 /* 84 * We need to exclude userspace access to the context. 85 * 86 * To protect against memory access we invalidate all ptes 87 * and make sure the pagefault handlers block on the mutex. 88 */ 89 spu_unmap_mappings(ctx); 90 91 mfc_cntl = &ctx->spu->priv2->mfc_control_RW; 92 93 /* purge the MFC DMA queue to ensure no spurious accesses before we 94 * enter kernel mode */ 95 timeout = jiffies + HZ; 96 out_be64(mfc_cntl, MFC_CNTL_PURGE_DMA_REQUEST); 97 while ((in_be64(mfc_cntl) & MFC_CNTL_PURGE_DMA_STATUS_MASK) 98 != MFC_CNTL_PURGE_DMA_COMPLETE) { 99 if (time_after(jiffies, timeout)) { 100 printk(KERN_ERR "%s: timeout flushing MFC DMA queue\n", 101 __FUNCTION__); 102 ret = -EIO; 103 goto out; 104 } 105 cond_resched(); 106 } 107 108 /* put the SPE in kernel mode to allow access to the loader */ 109 sr1 = spu_mfc_sr1_get(ctx->spu); 110 sr1 &= ~MFC_STATE1_PROBLEM_STATE_MASK; 111 spu_mfc_sr1_set(ctx->spu, sr1); 112 113 /* start the loader */ 114 ctx->ops->signal1_write(ctx, (unsigned long)isolated_loader >> 32); 115 ctx->ops->signal2_write(ctx, 116 (unsigned long)isolated_loader & 0xffffffff); 117 118 ctx->ops->runcntl_write(ctx, 119 SPU_RUNCNTL_RUNNABLE | SPU_RUNCNTL_ISOLATE); 120 121 ret = 0; 122 timeout = jiffies + HZ; 123 while (((status = ctx->ops->status_read(ctx)) & status_loading) == 124 status_loading) { 125 if (time_after(jiffies, timeout)) { 126 printk(KERN_ERR "%s: timeout waiting for loader\n", 127 __FUNCTION__); 128 ret = -EIO; 129 goto out_drop_priv; 130 } 131 cond_resched(); 132 } 133 134 if (!(status & SPU_STATUS_RUNNING)) { 135 /* If isolated LOAD has failed: run SPU, we will get a stop-and 136 * signal later. */ 137 pr_debug("%s: isolated LOAD failed\n", __FUNCTION__); 138 ctx->ops->runcntl_write(ctx, SPU_RUNCNTL_RUNNABLE); 139 ret = -EACCES; 140 goto out_drop_priv; 141 } 142 143 if (!(status & SPU_STATUS_ISOLATED_STATE)) { 144 /* This isn't allowed by the CBEA, but check anyway */ 145 pr_debug("%s: SPU fell out of isolated mode?\n", __FUNCTION__); 146 ctx->ops->runcntl_write(ctx, SPU_RUNCNTL_STOP); 147 ret = -EINVAL; 148 goto out_drop_priv; 149 } 150 151 out_drop_priv: 152 /* Finished accessing the loader. Drop kernel mode */ 153 sr1 |= MFC_STATE1_PROBLEM_STATE_MASK; 154 spu_mfc_sr1_set(ctx->spu, sr1); 155 156 out: 157 return ret; 158 } 159 160 static int spu_run_init(struct spu_context *ctx, u32 *npc) 161 { 162 unsigned long runcntl = SPU_RUNCNTL_RUNNABLE; 163 int ret; 164 165 spuctx_switch_state(ctx, SPU_UTIL_SYSTEM); 166 167 /* 168 * NOSCHED is synchronous scheduling with respect to the caller. 169 * The caller waits for the context to be loaded. 170 */ 171 if (ctx->flags & SPU_CREATE_NOSCHED) { 172 if (ctx->state == SPU_STATE_SAVED) { 173 ret = spu_activate(ctx, 0); 174 if (ret) 175 return ret; 176 } 177 } 178 179 /* 180 * Apply special setup as required. 181 */ 182 if (ctx->flags & SPU_CREATE_ISOLATE) { 183 if (!(ctx->ops->status_read(ctx) & SPU_STATUS_ISOLATED_STATE)) { 184 ret = spu_setup_isolated(ctx); 185 if (ret) 186 return ret; 187 } 188 189 /* 190 * If userspace has set the runcntrl register (eg, to 191 * issue an isolated exit), we need to re-set it here 192 */ 193 runcntl = ctx->ops->runcntl_read(ctx) & 194 (SPU_RUNCNTL_RUNNABLE | SPU_RUNCNTL_ISOLATE); 195 if (runcntl == 0) 196 runcntl = SPU_RUNCNTL_RUNNABLE; 197 } 198 199 if (ctx->flags & SPU_CREATE_NOSCHED) { 200 spuctx_switch_state(ctx, SPU_UTIL_USER); 201 ctx->ops->runcntl_write(ctx, runcntl); 202 } else { 203 unsigned long privcntl; 204 205 if (test_thread_flag(TIF_SINGLESTEP)) 206 privcntl = SPU_PRIVCNTL_MODE_SINGLE_STEP; 207 else 208 privcntl = SPU_PRIVCNTL_MODE_NORMAL; 209 210 ctx->ops->npc_write(ctx, *npc); 211 ctx->ops->privcntl_write(ctx, privcntl); 212 ctx->ops->runcntl_write(ctx, runcntl); 213 214 if (ctx->state == SPU_STATE_SAVED) { 215 ret = spu_activate(ctx, 0); 216 if (ret) 217 return ret; 218 } else { 219 spuctx_switch_state(ctx, SPU_UTIL_USER); 220 } 221 } 222 223 return 0; 224 } 225 226 static int spu_run_fini(struct spu_context *ctx, u32 *npc, 227 u32 *status) 228 { 229 int ret = 0; 230 231 spu_del_from_rq(ctx); 232 233 *status = ctx->ops->status_read(ctx); 234 *npc = ctx->ops->npc_read(ctx); 235 236 spuctx_switch_state(ctx, SPU_UTIL_IDLE_LOADED); 237 spu_release(ctx); 238 239 if (signal_pending(current)) 240 ret = -ERESTARTSYS; 241 242 return ret; 243 } 244 245 /* 246 * SPU syscall restarting is tricky because we violate the basic 247 * assumption that the signal handler is running on the interrupted 248 * thread. Here instead, the handler runs on PowerPC user space code, 249 * while the syscall was called from the SPU. 250 * This means we can only do a very rough approximation of POSIX 251 * signal semantics. 252 */ 253 static int spu_handle_restartsys(struct spu_context *ctx, long *spu_ret, 254 unsigned int *npc) 255 { 256 int ret; 257 258 switch (*spu_ret) { 259 case -ERESTARTSYS: 260 case -ERESTARTNOINTR: 261 /* 262 * Enter the regular syscall restarting for 263 * sys_spu_run, then restart the SPU syscall 264 * callback. 265 */ 266 *npc -= 8; 267 ret = -ERESTARTSYS; 268 break; 269 case -ERESTARTNOHAND: 270 case -ERESTART_RESTARTBLOCK: 271 /* 272 * Restart block is too hard for now, just return -EINTR 273 * to the SPU. 274 * ERESTARTNOHAND comes from sys_pause, we also return 275 * -EINTR from there. 276 * Assume that we need to be restarted ourselves though. 277 */ 278 *spu_ret = -EINTR; 279 ret = -ERESTARTSYS; 280 break; 281 default: 282 printk(KERN_WARNING "%s: unexpected return code %ld\n", 283 __FUNCTION__, *spu_ret); 284 ret = 0; 285 } 286 return ret; 287 } 288 289 static int spu_process_callback(struct spu_context *ctx) 290 { 291 struct spu_syscall_block s; 292 u32 ls_pointer, npc; 293 void __iomem *ls; 294 long spu_ret; 295 int ret, ret2; 296 297 /* get syscall block from local store */ 298 npc = ctx->ops->npc_read(ctx) & ~3; 299 ls = (void __iomem *)ctx->ops->get_ls(ctx); 300 ls_pointer = in_be32(ls + npc); 301 if (ls_pointer > (LS_SIZE - sizeof(s))) 302 return -EFAULT; 303 memcpy_fromio(&s, ls + ls_pointer, sizeof(s)); 304 305 /* do actual syscall without pinning the spu */ 306 ret = 0; 307 spu_ret = -ENOSYS; 308 npc += 4; 309 310 if (s.nr_ret < __NR_syscalls) { 311 spu_release(ctx); 312 /* do actual system call from here */ 313 spu_ret = spu_sys_callback(&s); 314 if (spu_ret <= -ERESTARTSYS) { 315 ret = spu_handle_restartsys(ctx, &spu_ret, &npc); 316 } 317 ret2 = spu_acquire(ctx); 318 if (ret == -ERESTARTSYS) 319 return ret; 320 if (ret2) 321 return -EINTR; 322 } 323 324 /* write result, jump over indirect pointer */ 325 memcpy_toio(ls + ls_pointer, &spu_ret, sizeof(spu_ret)); 326 ctx->ops->npc_write(ctx, npc); 327 ctx->ops->runcntl_write(ctx, SPU_RUNCNTL_RUNNABLE); 328 return ret; 329 } 330 331 long spufs_run_spu(struct spu_context *ctx, u32 *npc, u32 *event) 332 { 333 int ret; 334 struct spu *spu; 335 u32 status; 336 337 if (mutex_lock_interruptible(&ctx->run_mutex)) 338 return -ERESTARTSYS; 339 340 spu_enable_spu(ctx); 341 ctx->event_return = 0; 342 343 ret = spu_acquire(ctx); 344 if (ret) 345 goto out_unlock; 346 347 spu_update_sched_info(ctx); 348 349 ret = spu_run_init(ctx, npc); 350 if (ret) { 351 spu_release(ctx); 352 goto out; 353 } 354 355 do { 356 ret = spufs_wait(ctx->stop_wq, spu_stopped(ctx, &status)); 357 if (unlikely(ret)) 358 break; 359 spu = ctx->spu; 360 if (unlikely(test_and_clear_bit(SPU_SCHED_NOTIFY_ACTIVE, 361 &ctx->sched_flags))) { 362 if (!(status & SPU_STATUS_STOPPED_BY_STOP)) { 363 spu_switch_notify(spu, ctx); 364 continue; 365 } 366 } 367 368 spuctx_switch_state(ctx, SPU_UTIL_SYSTEM); 369 370 if ((status & SPU_STATUS_STOPPED_BY_STOP) && 371 (status >> SPU_STOP_STATUS_SHIFT == 0x2104)) { 372 ret = spu_process_callback(ctx); 373 if (ret) 374 break; 375 status &= ~SPU_STATUS_STOPPED_BY_STOP; 376 } 377 ret = spufs_handle_class1(ctx); 378 if (ret) 379 break; 380 381 ret = spufs_handle_class0(ctx); 382 if (ret) 383 break; 384 385 if (signal_pending(current)) 386 ret = -ERESTARTSYS; 387 } while (!ret && !(status & (SPU_STATUS_STOPPED_BY_STOP | 388 SPU_STATUS_STOPPED_BY_HALT | 389 SPU_STATUS_SINGLE_STEP))); 390 391 if ((status & SPU_STATUS_STOPPED_BY_STOP) && 392 (((status >> SPU_STOP_STATUS_SHIFT) & 0x3f00) == 0x2100) && 393 (ctx->state == SPU_STATE_RUNNABLE)) 394 ctx->stats.libassist++; 395 396 397 spu_disable_spu(ctx); 398 ret = spu_run_fini(ctx, npc, &status); 399 spu_yield(ctx); 400 401 if ((ret == 0) || 402 ((ret == -ERESTARTSYS) && 403 ((status & SPU_STATUS_STOPPED_BY_HALT) || 404 (status & SPU_STATUS_SINGLE_STEP) || 405 ((status & SPU_STATUS_STOPPED_BY_STOP) && 406 (status >> SPU_STOP_STATUS_SHIFT != 0x2104))))) 407 ret = status; 408 409 /* Note: we don't need to force_sig SIGTRAP on single-step 410 * since we have TIF_SINGLESTEP set, thus the kernel will do 411 * it upon return from the syscall anyawy 412 */ 413 if ((status & SPU_STATUS_STOPPED_BY_STOP) 414 && (status >> SPU_STOP_STATUS_SHIFT) == 0x3fff) { 415 force_sig(SIGTRAP, current); 416 ret = -ERESTARTSYS; 417 } 418 419 out: 420 *event = ctx->event_return; 421 out_unlock: 422 mutex_unlock(&ctx->run_mutex); 423 return ret; 424 } 425