Subject: spufs: replace recycle file with automated method It seems we don't need to use an explicit 'recycle' file if we simply rely on the initial secure application to exit secure mode correctly before loading the new kernel. This makes the interface much simpler and more consistant. The code may get even simpler if we move the initial isolated load into the spu_run instead of doing it behind the back of spu_create. Right now, this patch is completely untested, due to lack of the right simulator version for the isolation feature. The patch needs spufs-master-control.diff to be applied first. Please test this and report back on the success with it. Signed-off-by: Arnd Bergmann Index: linux-2.6/arch/powerpc/platforms/cell/spufs/file.c =================================================================== --- linux-2.6.orig/arch/powerpc/platforms/cell/spufs/file.c +++ linux-2.6/arch/powerpc/platforms/cell/spufs/file.c @@ -1357,37 +1357,6 @@ static struct file_operations spufs_mfc_ .mmap = spufs_mfc_mmap, }; - -static int spufs_recycle_open(struct inode *inode, struct file *file) -{ - file->private_data = SPUFS_I(inode)->i_ctx; - return nonseekable_open(inode, file); -} - -static ssize_t spufs_recycle_write(struct file *file, - const char __user *buffer, size_t size, loff_t *pos) -{ - struct spu_context *ctx = file->private_data; - int ret; - - if (!(ctx->flags & SPU_CREATE_ISOLATE)) - return -EINVAL; - - if (size < 1) - return -EINVAL; - - ret = spu_recycle_isolated(ctx); - - if (ret) - return ret; - return size; -} - -static struct file_operations spufs_recycle_fops = { - .open = spufs_recycle_open, - .write = spufs_recycle_write, -}; - static void spufs_npc_set(void *data, u64 val) { struct spu_context *ctx = data; @@ -1788,6 +1757,5 @@ struct tree_descr spufs_dir_nosched_cont { "psmap", &spufs_psmap_fops, 0666, }, { "phys-id", &spufs_id_ops, 0666, }, { "object-id", &spufs_object_id_ops, 0666, }, - { "recycle", &spufs_recycle_fops, 0222, }, {}, }; Index: linux-2.6/arch/powerpc/platforms/cell/spufs/inode.c =================================================================== --- linux-2.6.orig/arch/powerpc/platforms/cell/spufs/inode.c +++ linux-2.6/arch/powerpc/platforms/cell/spufs/inode.c @@ -236,7 +236,7 @@ struct file_operations spufs_context_fop .fsync = simple_sync_file, }; -static int spu_setup_isolated(struct spu_context *ctx) +int spu_setup_isolated(struct spu_context *ctx) { int ret; u64 __iomem *mfc_cntl; @@ -327,11 +327,6 @@ out: return ret; } -int spu_recycle_isolated(struct spu_context *ctx) -{ - return spu_setup_isolated(ctx); -} - static int spufs_mkdir(struct inode *dir, struct dentry *dentry, unsigned int flags, int mode) Index: linux-2.6/arch/powerpc/platforms/cell/spufs/run.c =================================================================== --- linux-2.6.orig/arch/powerpc/platforms/cell/spufs/run.c +++ linux-2.6/arch/powerpc/platforms/cell/spufs/run.c @@ -56,16 +56,37 @@ static inline int spu_run_init(struct sp int ret; unsigned long runcntl = SPU_RUNCNTL_RUNNABLE; - if ((ret = spu_acquire_runnable(ctx)) != 0) + ret = spu_acquire_runnable(ctx); + if (ret) return ret; - /* if we're in isolated mode, we would have started the SPU - * earlier, so don't do it again now. */ + /* + * if we're in isolated mode, we would have started the SPU + * earlier, so don't do it again now. + */ if (!(ctx->flags & SPU_CREATE_ISOLATE)) { ctx->ops->npc_write(ctx, *npc); ctx->ops->runcntl_write(ctx, runcntl); + } else { + /* + * When an isolated program has exited, we have to + * reload the secure kernel in order to continue + * running. + */ + if (ctx->ops->status_read(ctx) & + SPU_STATUS_ISOLATED_EXIT_STATUS) { + /* + * Need to release ctx, because + * spu_setup_isolated will acquire it + * exclusively. + */ + spu_release(ctx); + ret = spu_setup_isolated(ctx); + if (!ret) + ret = spu_acquire_runnable(ctx); + } } - return 0; + return ret; } static inline int spu_run_fini(struct spu_context *ctx, u32 * npc, Index: linux-2.6/arch/powerpc/platforms/cell/spufs/spufs.h =================================================================== --- linux-2.6.orig/arch/powerpc/platforms/cell/spufs/spufs.h +++ linux-2.6/arch/powerpc/platforms/cell/spufs/spufs.h @@ -182,7 +182,7 @@ void spu_yield(struct spu_context *ctx); int __init spu_sched_init(void); void __exit spu_sched_exit(void); -int spu_recycle_isolated(struct spu_context *ctx); +int spu_setup_isolated(struct spu_context *ctx); /* * spufs_wait * Same as wait_event_interruptible(), except that here