static int __spu_trap_invalid_dma(struct spu *spu)
 {
        pr_debug("%s\n", __FUNCTION__);
-       force_sig(SIGBUS, /* info, */ current);
+       spu->dma_callback(spu, SPE_EVENT_INVALID_DMA);
        return 0;
 }
 
 static int __spu_trap_dma_align(struct spu *spu)
 {
        pr_debug("%s\n", __FUNCTION__);
-       force_sig(SIGBUS, /* info, */ current);
+       spu->dma_callback(spu, SPE_EVENT_DMA_ALIGNMENT);
        return 0;
 }
 
 static int __spu_trap_error(struct spu *spu)
 {
        pr_debug("%s\n", __FUNCTION__);
-       force_sig(SIGILL, /* info, */ current);
+       spu->dma_callback(spu, SPE_EVENT_SPE_ERROR);
        return 0;
 }
 
 
 };
 
 static int
-spufs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
+spufs_mkdir(struct inode *dir, struct dentry *dentry, unsigned int flags,
+               int mode)
 {
        int ret;
        struct inode *inode;
        if (!ctx)
                goto out_iput;
 
+       ctx->flags = flags;
+
        inode->i_op = &spufs_dir_inode_operations;
        inode->i_fop = &simple_dir_operations;
        ret = spufs_fill_dir(dentry, spufs_dir_contents, mode, ctx);
                goto out;
 
        /* all flags are reserved */
-       if (flags)
+       if (flags & (~SPU_CREATE_FLAG_ALL))
                goto out;
 
        dentry = lookup_create(nd, 1);
                goto out_dput;
 
        mode &= ~current->fs->umask;
-       ret = spufs_mkdir(nd->dentry->d_inode, dentry, mode & S_IRWXUGO);
+       ret = spufs_mkdir(nd->dentry->d_inode, dentry, flags, mode & S_IRWXUGO);
        if (ret)
                goto out_dput;
 
 
        wake_up_all(&ctx->stop_wq);
 }
 
+void spufs_dma_callback(struct spu *spu, int type)
+{
+       struct spu_context *ctx = spu->ctx;
+
+       if (ctx->flags & SPU_CREATE_EVENTS_ENABLED) {
+               ctx->event_return |= type;
+               wake_up_all(&ctx->stop_wq);
+       } else {
+               switch (type) {
+               case SPE_EVENT_DMA_ALIGNMENT:
+               case SPE_EVENT_INVALID_DMA:
+                       force_sig(SIGBUS, /* info, */ current);
+                       break;
+               case SPE_EVENT_SPE_ERROR:
+                       force_sig(SIGILL, /* info */ current);
+                       break;
+               }
+       }
+}
+
 static inline int spu_stopped(struct spu_context *ctx, u32 * stat)
 {
        struct spu *spu;
        return (!(*stat & 0x1) || pte_fault || spu->class_0_pending) ? 1 : 0;
 }
 
-static inline int spu_run_init(struct spu_context *ctx, u32 * npc,
-                              u32 * status)
+static inline int spu_run_init(struct spu_context *ctx, u32 * npc)
 {
        int ret;
 
                       SPU_STATUS_STOPPED_BY_HALT)) {
                return *status;
        }
-       if ((ret = spu_run_init(ctx, npc, status)) != 0)
+       if ((ret = spu_run_init(ctx, npc)) != 0)
                return ret;
        return 0;
 }
 }
 
 long spufs_run_spu(struct file *file, struct spu_context *ctx,
-                  u32 * npc, u32 * status)
+                  u32 *npc, u32 *event)
 {
        int ret;
+       u32 status;
 
        if (down_interruptible(&ctx->run_sema))
                return -ERESTARTSYS;
 
-       ret = spu_run_init(ctx, npc, status);
+       ctx->event_return = 0;
+       ret = spu_run_init(ctx, npc);
        if (ret)
                goto out;
 
        do {
-               ret = spufs_wait(ctx->stop_wq, spu_stopped(ctx, status));
+               ret = spufs_wait(ctx->stop_wq, spu_stopped(ctx, &status));
                if (unlikely(ret))
                        break;
-               if ((*status & SPU_STATUS_STOPPED_BY_STOP) &&
-                   (*status >> SPU_STOP_STATUS_SHIFT == 0x2104)) {
+               if ((status & SPU_STATUS_STOPPED_BY_STOP) &&
+                   (status >> SPU_STOP_STATUS_SHIFT == 0x2104)) {
                        ret = spu_process_callback(ctx);
                        if (ret)
                                break;
-                       *status &= ~SPU_STATUS_STOPPED_BY_STOP;
+                       status &= ~SPU_STATUS_STOPPED_BY_STOP;
                }
                if (unlikely(ctx->state != SPU_STATE_RUNNABLE)) {
-                       ret = spu_reacquire_runnable(ctx, npc, status);
+                       ret = spu_reacquire_runnable(ctx, npc, &status);
                        if (ret)
                                goto out;
                        continue;
                }
                ret = spu_process_events(ctx);
 
-       } while (!ret && !(*status & (SPU_STATUS_STOPPED_BY_STOP |
+       } while (!ret && !(status & (SPU_STATUS_STOPPED_BY_STOP |
                                      SPU_STATUS_STOPPED_BY_HALT)));
 
        ctx->ops->runcntl_stop(ctx);
-       ret = spu_run_fini(ctx, npc, status);
+       ret = spu_run_fini(ctx, npc, &status);
        if (!ret)
-               ret = *status;
+               ret = status;
        spu_yield(ctx);
 
 out:
+       *event = ctx->event_return;
        up(&ctx->run_sema);
        return ret;
 }
 
                 spu->number, spu->node);
        spu->ctx = ctx;
        spu->flags = 0;
-       ctx->flags = 0;
        ctx->spu = spu;
        ctx->ops = &spu_hw_ops;
        spu->pid = current->pid;
        spu->wbox_callback = spufs_wbox_callback;
        spu->stop_callback = spufs_stop_callback;
        spu->mfc_callback = spufs_mfc_callback;
+       spu->dma_callback = spufs_dma_callback;
        mb();
        spu_unmap_mappings(ctx);
        spu_restore(&ctx->csa, spu);
        spu->wbox_callback = NULL;
        spu->stop_callback = NULL;
        spu->mfc_callback = NULL;
+       spu->dma_callback = NULL;
        spu->mm = NULL;
        spu->pid = 0;
        spu->prio = MAX_PRIO;
        ctx->ops = &spu_backing_ops;
        ctx->spu = NULL;
-       ctx->flags = 0;
        spu->flags = 0;
        spu->ctx = NULL;
 }
 
        u32 tagwait;
        struct spu_context_ops *ops;
        struct work_struct reap_work;
-       u64 flags;
+       unsigned long flags;
+       unsigned long event_return;
 };
 
 struct mfc_dma_command {
 void spufs_wbox_callback(struct spu *spu);
 void spufs_stop_callback(struct spu *spu);
 void spufs_mfc_callback(struct spu *spu);
+void spufs_dma_callback(struct spu *spu, int type);
 
 #endif
 
        u32 npc, status;
 
        ret = -EFAULT;
-       if (get_user(npc, unpc) || get_user(status, ustatus))
+       if (get_user(npc, unpc))
                goto out;
 
        /* check if this file was created by spu_create */
        i = SPUFS_I(filp->f_dentry->d_inode);
        ret = spufs_run_spu(filp, i->i_ctx, &npc, &status);
 
-       if (put_user(npc, unpc) || put_user(status, ustatus))
+       if (put_user(npc, unpc))
+               ret = -EFAULT;
+
+       if (ustatus && put_user(status, ustatus))
                ret = -EFAULT;
 out:
        return ret;
 
        void (* ibox_callback)(struct spu *spu);
        void (* stop_callback)(struct spu *spu);
        void (* mfc_callback)(struct spu *spu);
+       void (* dma_callback)(struct spu *spu, int type);
 
        char irq_c0[8];
        char irq_c1[8];
        struct module *owner;
 } spufs_calls;
 
+/* return status from spu_run, same as in libspe */
+#define SPE_EVENT_DMA_ALIGNMENT                0x0008  /*A DMA alignment error */
+#define SPE_EVENT_SPE_ERROR            0x0010  /*An illegal instruction error*/
+#define SPE_EVENT_SPE_DATA_SEGMENT     0x0020  /*A DMA segmentation error    */
+#define SPE_EVENT_SPE_DATA_STORAGE     0x0040  /*A DMA storage error */
+#define SPE_EVENT_INVALID_DMA          0x0800  /* Invalid MFC DMA */
+
+/*
+ * Flags for sys_spu_create.
+ */
+#define SPU_CREATE_EVENTS_ENABLED      0x0001
+#define SPU_CREATE_FLAG_ALL            0x0001 /* mask of all valid flags */
+
 #ifdef CONFIG_SPU_FS_MODULE
 int register_spu_syscalls(struct spufs_calls *calls);
 void unregister_spu_syscalls(struct spufs_calls *calls);