From: Arnd Bergmann <arnd@arndb.de>
To: cbe-oss-dev@ozlabs.org
Cc: linuxppc-dev@ozlabs.org, Paul Mackerras <paulus@samba.org>,
linux-kernel@vger.kernel.org, Jeremy Kerr <jeremy@au1.ibm.com>,
Arnd Bergmann <arnd.bergmann@de.ibm.com>
Subject: [PATCH 16/22] spufs: load isolation kernel from spu_run
Date: Mon, 20 Nov 2006 18:45:10 +0100 [thread overview]
Message-ID: <20061120180526.009530000@arndb.de> (raw)
In-Reply-To: 20061120174454.067872000@arndb.de
From: Jeremy Kerr <jeremy@au1.ibm.com>
In order to fit with the "don't-run-spus-outside-of-spu_run" model, this
patch starts the isolated-mode loader in spu_run, rather than
spu_create. If spu_run is passed an isolated-mode context that isn't in
isolated mode state, it will run the loader.
This fixes potential races with the isolated SPE app doing a
stop-and-signal before the PPE has called spu_run: bugzilla #29111.
Also (in conjunction with a mambo patch), this addresses #28565, as we
always set the runcntrl register when entering spu_run.
It is up to libspe to ensure that isolated-mode apps are cleaned up
after running to completion - ie, put the app through the "ISOLATE EXIT"
state (see Ch11 of the CBEA).
Signed-off-by: Jeremy Kerr <jeremy@au1.ibm.com>
Signed-off-by: Arnd Bergmann <arnd.bergmann@de.ibm.com>
---
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
@@ -1358,37 +1358,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;
@@ -1789,6 +1758,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
@@ -34,8 +34,6 @@
#include <linux/parser.h>
#include <asm/prom.h>
-#include <asm/spu_priv1.h>
-#include <asm/io.h>
#include <asm/semaphore.h>
#include <asm/spu.h>
#include <asm/uaccess.h>
@@ -43,7 +41,7 @@
#include "spufs.h"
static kmem_cache_t *spufs_inode_cache;
-static char *isolated_loader;
+char *isolated_loader;
static struct inode *
spufs_alloc_inode(struct super_block *sb)
@@ -235,102 +233,6 @@ struct file_operations spufs_context_fop
.fsync = simple_sync_file,
};
-static int spu_setup_isolated(struct spu_context *ctx)
-{
- int ret;
- u64 __iomem *mfc_cntl;
- u64 sr1;
- u32 status;
- unsigned long timeout;
- const u32 status_loading = SPU_STATUS_RUNNING
- | SPU_STATUS_ISOLATED_STATE | SPU_STATUS_ISOLATED_LOAD_STATUS;
-
- if (!isolated_loader)
- return -ENODEV;
-
- /* prevent concurrent operation with spu_run */
- down(&ctx->run_sema);
- ctx->ops->master_start(ctx);
-
- ret = spu_acquire_exclusive(ctx);
- if (ret)
- goto out;
-
- mfc_cntl = &ctx->spu->priv2->mfc_control_RW;
-
- /* purge the MFC DMA queue to ensure no spurious accesses before we
- * enter kernel mode */
- timeout = jiffies + HZ;
- out_be64(mfc_cntl, MFC_CNTL_PURGE_DMA_REQUEST);
- while ((in_be64(mfc_cntl) & MFC_CNTL_PURGE_DMA_STATUS_MASK)
- != MFC_CNTL_PURGE_DMA_COMPLETE) {
- if (time_after(jiffies, timeout)) {
- printk(KERN_ERR "%s: timeout flushing MFC DMA queue\n",
- __FUNCTION__);
- ret = -EIO;
- goto out_unlock;
- }
- cond_resched();
- }
-
- /* put the SPE in kernel mode to allow access to the loader */
- sr1 = spu_mfc_sr1_get(ctx->spu);
- sr1 &= ~MFC_STATE1_PROBLEM_STATE_MASK;
- spu_mfc_sr1_set(ctx->spu, sr1);
-
- /* start the loader */
- ctx->ops->signal1_write(ctx, (unsigned long)isolated_loader >> 32);
- ctx->ops->signal2_write(ctx,
- (unsigned long)isolated_loader & 0xffffffff);
-
- ctx->ops->runcntl_write(ctx,
- SPU_RUNCNTL_RUNNABLE | SPU_RUNCNTL_ISOLATE);
-
- ret = 0;
- timeout = jiffies + HZ;
- while (((status = ctx->ops->status_read(ctx)) & status_loading) ==
- status_loading) {
- if (time_after(jiffies, timeout)) {
- printk(KERN_ERR "%s: timeout waiting for loader\n",
- __FUNCTION__);
- ret = -EIO;
- goto out_drop_priv;
- }
- cond_resched();
- }
-
- if (!(status & SPU_STATUS_RUNNING)) {
- /* If isolated LOAD has failed: run SPU, we will get a stop-and
- * signal later. */
- pr_debug("%s: isolated LOAD failed\n", __FUNCTION__);
- ctx->ops->runcntl_write(ctx, SPU_RUNCNTL_RUNNABLE);
- ret = -EACCES;
-
- } else if (!(status & SPU_STATUS_ISOLATED_STATE)) {
- /* This isn't allowed by the CBEA, but check anyway */
- pr_debug("%s: SPU fell out of isolated mode?\n", __FUNCTION__);
- ctx->ops->runcntl_write(ctx, SPU_RUNCNTL_STOP);
- ret = -EINVAL;
- }
-
-out_drop_priv:
- /* Finished accessing the loader. Drop kernel mode */
- sr1 |= MFC_STATE1_PROBLEM_STATE_MASK;
- spu_mfc_sr1_set(ctx->spu, sr1);
-
-out_unlock:
- spu_release_exclusive(ctx);
-out:
- ctx->ops->master_stop(ctx);
- up(&ctx->run_sema);
- 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)
@@ -439,15 +341,6 @@ static int spufs_create_context(struct i
out_unlock:
mutex_unlock(&inode->i_mutex);
out:
- if (ret >= 0 && (flags & SPU_CREATE_ISOLATE)) {
- int setup_err = spu_setup_isolated(
- SPUFS_I(dentry->d_inode)->i_ctx);
- /* FIXME: clean up context again on failure to avoid
- leak. */
- if (setup_err)
- ret = setup_err;
- }
-
dput(dentry);
return ret;
}
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
@@ -4,6 +4,8 @@
#include <linux/ptrace.h>
#include <asm/spu.h>
+#include <asm/spu_priv1.h>
+#include <asm/io.h>
#include <asm/unistd.h>
#include "spufs.h"
@@ -51,21 +53,122 @@ static inline int spu_stopped(struct spu
return (!(*stat & 0x1) || pte_fault || spu->class_0_pending) ? 1 : 0;
}
+static int spu_setup_isolated(struct spu_context *ctx)
+{
+ int ret;
+ u64 __iomem *mfc_cntl;
+ u64 sr1;
+ u32 status;
+ unsigned long timeout;
+ const u32 status_loading = SPU_STATUS_RUNNING
+ | SPU_STATUS_ISOLATED_STATE | SPU_STATUS_ISOLATED_LOAD_STATUS;
+
+ if (!isolated_loader)
+ return -ENODEV;
+
+ ret = spu_acquire_exclusive(ctx);
+ if (ret)
+ goto out;
+
+ mfc_cntl = &ctx->spu->priv2->mfc_control_RW;
+
+ /* purge the MFC DMA queue to ensure no spurious accesses before we
+ * enter kernel mode */
+ timeout = jiffies + HZ;
+ out_be64(mfc_cntl, MFC_CNTL_PURGE_DMA_REQUEST);
+ while ((in_be64(mfc_cntl) & MFC_CNTL_PURGE_DMA_STATUS_MASK)
+ != MFC_CNTL_PURGE_DMA_COMPLETE) {
+ if (time_after(jiffies, timeout)) {
+ printk(KERN_ERR "%s: timeout flushing MFC DMA queue\n",
+ __FUNCTION__);
+ ret = -EIO;
+ goto out_unlock;
+ }
+ cond_resched();
+ }
+
+ /* put the SPE in kernel mode to allow access to the loader */
+ sr1 = spu_mfc_sr1_get(ctx->spu);
+ sr1 &= ~MFC_STATE1_PROBLEM_STATE_MASK;
+ spu_mfc_sr1_set(ctx->spu, sr1);
+
+ /* start the loader */
+ ctx->ops->signal1_write(ctx, (unsigned long)isolated_loader >> 32);
+ ctx->ops->signal2_write(ctx,
+ (unsigned long)isolated_loader & 0xffffffff);
+
+ ctx->ops->runcntl_write(ctx,
+ SPU_RUNCNTL_RUNNABLE | SPU_RUNCNTL_ISOLATE);
+
+ ret = 0;
+ timeout = jiffies + HZ;
+ while (((status = ctx->ops->status_read(ctx)) & status_loading) ==
+ status_loading) {
+ if (time_after(jiffies, timeout)) {
+ printk(KERN_ERR "%s: timeout waiting for loader\n",
+ __FUNCTION__);
+ ret = -EIO;
+ goto out_drop_priv;
+ }
+ cond_resched();
+ }
+
+ if (!(status & SPU_STATUS_RUNNING)) {
+ /* If isolated LOAD has failed: run SPU, we will get a stop-and
+ * signal later. */
+ pr_debug("%s: isolated LOAD failed\n", __FUNCTION__);
+ ctx->ops->runcntl_write(ctx, SPU_RUNCNTL_RUNNABLE);
+ ret = -EACCES;
+
+ } else if (!(status & SPU_STATUS_ISOLATED_STATE)) {
+ /* This isn't allowed by the CBEA, but check anyway */
+ pr_debug("%s: SPU fell out of isolated mode?\n", __FUNCTION__);
+ ctx->ops->runcntl_write(ctx, SPU_RUNCNTL_STOP);
+ ret = -EINVAL;
+ }
+
+out_drop_priv:
+ /* Finished accessing the loader. Drop kernel mode */
+ sr1 |= MFC_STATE1_PROBLEM_STATE_MASK;
+ spu_mfc_sr1_set(ctx->spu, sr1);
+
+out_unlock:
+ spu_release_exclusive(ctx);
+out:
+ return ret;
+}
+
static inline int spu_run_init(struct spu_context *ctx, u32 * npc)
{
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 (!(ctx->flags & SPU_CREATE_ISOLATE)) {
+ if (ctx->flags & SPU_CREATE_ISOLATE) {
+ if (!(ctx->ops->status_read(ctx) & SPU_STATUS_ISOLATED_STATE)) {
+ /* 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);
+ }
+
+ /* if userspace has set the runcntrl register (eg, to issue an
+ * isolated exit), we need to re-set it here */
+ runcntl = ctx->ops->runcntl_read(ctx) &
+ (SPU_RUNCNTL_RUNNABLE | SPU_RUNCNTL_ISOLATE);
+ if (runcntl == 0)
+ runcntl = SPU_RUNCNTL_RUNNABLE;
+ } else
ctx->ops->npc_write(ctx, *npc);
- ctx->ops->runcntl_write(ctx, runcntl);
- }
- return 0;
+
+ ctx->ops->runcntl_write(ctx, runcntl);
+ 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
@@ -183,7 +183,8 @@ 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);
+extern char *isolated_loader;
+
/*
* spufs_wait
* Same as wait_event_interruptible(), except that here
--
WARNING: multiple messages have this Message-ID (diff)
From: Arnd Bergmann <arnd@arndb.de>
To: cbe-oss-dev@ozlabs.org
Cc: linuxppc-dev@ozlabs.org, linux-kernel@vger.kernel.org,
Paul Mackerras <paulus@samba.org>,
Jeremy Kerr <jeremy@au1.ibm.com>,
Arnd Bergmann <arnd.bergmann@de.ibm.com>
Subject: [PATCH 16/22] spufs: load isolation kernel from spu_run
Date: Mon, 20 Nov 2006 18:45:10 +0100 [thread overview]
Message-ID: <20061120180526.009530000@arndb.de> (raw)
In-Reply-To: 20061120174454.067872000@arndb.de
[-- Attachment #1: spufs-autorecycle-isolated-2.diff --]
[-- Type: text/plain, Size: 10655 bytes --]
From: Jeremy Kerr <jeremy@au1.ibm.com>
In order to fit with the "don't-run-spus-outside-of-spu_run" model, this
patch starts the isolated-mode loader in spu_run, rather than
spu_create. If spu_run is passed an isolated-mode context that isn't in
isolated mode state, it will run the loader.
This fixes potential races with the isolated SPE app doing a
stop-and-signal before the PPE has called spu_run: bugzilla #29111.
Also (in conjunction with a mambo patch), this addresses #28565, as we
always set the runcntrl register when entering spu_run.
It is up to libspe to ensure that isolated-mode apps are cleaned up
after running to completion - ie, put the app through the "ISOLATE EXIT"
state (see Ch11 of the CBEA).
Signed-off-by: Jeremy Kerr <jeremy@au1.ibm.com>
Signed-off-by: Arnd Bergmann <arnd.bergmann@de.ibm.com>
---
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
@@ -1358,37 +1358,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;
@@ -1789,6 +1758,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
@@ -34,8 +34,6 @@
#include <linux/parser.h>
#include <asm/prom.h>
-#include <asm/spu_priv1.h>
-#include <asm/io.h>
#include <asm/semaphore.h>
#include <asm/spu.h>
#include <asm/uaccess.h>
@@ -43,7 +41,7 @@
#include "spufs.h"
static kmem_cache_t *spufs_inode_cache;
-static char *isolated_loader;
+char *isolated_loader;
static struct inode *
spufs_alloc_inode(struct super_block *sb)
@@ -235,102 +233,6 @@ struct file_operations spufs_context_fop
.fsync = simple_sync_file,
};
-static int spu_setup_isolated(struct spu_context *ctx)
-{
- int ret;
- u64 __iomem *mfc_cntl;
- u64 sr1;
- u32 status;
- unsigned long timeout;
- const u32 status_loading = SPU_STATUS_RUNNING
- | SPU_STATUS_ISOLATED_STATE | SPU_STATUS_ISOLATED_LOAD_STATUS;
-
- if (!isolated_loader)
- return -ENODEV;
-
- /* prevent concurrent operation with spu_run */
- down(&ctx->run_sema);
- ctx->ops->master_start(ctx);
-
- ret = spu_acquire_exclusive(ctx);
- if (ret)
- goto out;
-
- mfc_cntl = &ctx->spu->priv2->mfc_control_RW;
-
- /* purge the MFC DMA queue to ensure no spurious accesses before we
- * enter kernel mode */
- timeout = jiffies + HZ;
- out_be64(mfc_cntl, MFC_CNTL_PURGE_DMA_REQUEST);
- while ((in_be64(mfc_cntl) & MFC_CNTL_PURGE_DMA_STATUS_MASK)
- != MFC_CNTL_PURGE_DMA_COMPLETE) {
- if (time_after(jiffies, timeout)) {
- printk(KERN_ERR "%s: timeout flushing MFC DMA queue\n",
- __FUNCTION__);
- ret = -EIO;
- goto out_unlock;
- }
- cond_resched();
- }
-
- /* put the SPE in kernel mode to allow access to the loader */
- sr1 = spu_mfc_sr1_get(ctx->spu);
- sr1 &= ~MFC_STATE1_PROBLEM_STATE_MASK;
- spu_mfc_sr1_set(ctx->spu, sr1);
-
- /* start the loader */
- ctx->ops->signal1_write(ctx, (unsigned long)isolated_loader >> 32);
- ctx->ops->signal2_write(ctx,
- (unsigned long)isolated_loader & 0xffffffff);
-
- ctx->ops->runcntl_write(ctx,
- SPU_RUNCNTL_RUNNABLE | SPU_RUNCNTL_ISOLATE);
-
- ret = 0;
- timeout = jiffies + HZ;
- while (((status = ctx->ops->status_read(ctx)) & status_loading) ==
- status_loading) {
- if (time_after(jiffies, timeout)) {
- printk(KERN_ERR "%s: timeout waiting for loader\n",
- __FUNCTION__);
- ret = -EIO;
- goto out_drop_priv;
- }
- cond_resched();
- }
-
- if (!(status & SPU_STATUS_RUNNING)) {
- /* If isolated LOAD has failed: run SPU, we will get a stop-and
- * signal later. */
- pr_debug("%s: isolated LOAD failed\n", __FUNCTION__);
- ctx->ops->runcntl_write(ctx, SPU_RUNCNTL_RUNNABLE);
- ret = -EACCES;
-
- } else if (!(status & SPU_STATUS_ISOLATED_STATE)) {
- /* This isn't allowed by the CBEA, but check anyway */
- pr_debug("%s: SPU fell out of isolated mode?\n", __FUNCTION__);
- ctx->ops->runcntl_write(ctx, SPU_RUNCNTL_STOP);
- ret = -EINVAL;
- }
-
-out_drop_priv:
- /* Finished accessing the loader. Drop kernel mode */
- sr1 |= MFC_STATE1_PROBLEM_STATE_MASK;
- spu_mfc_sr1_set(ctx->spu, sr1);
-
-out_unlock:
- spu_release_exclusive(ctx);
-out:
- ctx->ops->master_stop(ctx);
- up(&ctx->run_sema);
- 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)
@@ -439,15 +341,6 @@ static int spufs_create_context(struct i
out_unlock:
mutex_unlock(&inode->i_mutex);
out:
- if (ret >= 0 && (flags & SPU_CREATE_ISOLATE)) {
- int setup_err = spu_setup_isolated(
- SPUFS_I(dentry->d_inode)->i_ctx);
- /* FIXME: clean up context again on failure to avoid
- leak. */
- if (setup_err)
- ret = setup_err;
- }
-
dput(dentry);
return ret;
}
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
@@ -4,6 +4,8 @@
#include <linux/ptrace.h>
#include <asm/spu.h>
+#include <asm/spu_priv1.h>
+#include <asm/io.h>
#include <asm/unistd.h>
#include "spufs.h"
@@ -51,21 +53,122 @@ static inline int spu_stopped(struct spu
return (!(*stat & 0x1) || pte_fault || spu->class_0_pending) ? 1 : 0;
}
+static int spu_setup_isolated(struct spu_context *ctx)
+{
+ int ret;
+ u64 __iomem *mfc_cntl;
+ u64 sr1;
+ u32 status;
+ unsigned long timeout;
+ const u32 status_loading = SPU_STATUS_RUNNING
+ | SPU_STATUS_ISOLATED_STATE | SPU_STATUS_ISOLATED_LOAD_STATUS;
+
+ if (!isolated_loader)
+ return -ENODEV;
+
+ ret = spu_acquire_exclusive(ctx);
+ if (ret)
+ goto out;
+
+ mfc_cntl = &ctx->spu->priv2->mfc_control_RW;
+
+ /* purge the MFC DMA queue to ensure no spurious accesses before we
+ * enter kernel mode */
+ timeout = jiffies + HZ;
+ out_be64(mfc_cntl, MFC_CNTL_PURGE_DMA_REQUEST);
+ while ((in_be64(mfc_cntl) & MFC_CNTL_PURGE_DMA_STATUS_MASK)
+ != MFC_CNTL_PURGE_DMA_COMPLETE) {
+ if (time_after(jiffies, timeout)) {
+ printk(KERN_ERR "%s: timeout flushing MFC DMA queue\n",
+ __FUNCTION__);
+ ret = -EIO;
+ goto out_unlock;
+ }
+ cond_resched();
+ }
+
+ /* put the SPE in kernel mode to allow access to the loader */
+ sr1 = spu_mfc_sr1_get(ctx->spu);
+ sr1 &= ~MFC_STATE1_PROBLEM_STATE_MASK;
+ spu_mfc_sr1_set(ctx->spu, sr1);
+
+ /* start the loader */
+ ctx->ops->signal1_write(ctx, (unsigned long)isolated_loader >> 32);
+ ctx->ops->signal2_write(ctx,
+ (unsigned long)isolated_loader & 0xffffffff);
+
+ ctx->ops->runcntl_write(ctx,
+ SPU_RUNCNTL_RUNNABLE | SPU_RUNCNTL_ISOLATE);
+
+ ret = 0;
+ timeout = jiffies + HZ;
+ while (((status = ctx->ops->status_read(ctx)) & status_loading) ==
+ status_loading) {
+ if (time_after(jiffies, timeout)) {
+ printk(KERN_ERR "%s: timeout waiting for loader\n",
+ __FUNCTION__);
+ ret = -EIO;
+ goto out_drop_priv;
+ }
+ cond_resched();
+ }
+
+ if (!(status & SPU_STATUS_RUNNING)) {
+ /* If isolated LOAD has failed: run SPU, we will get a stop-and
+ * signal later. */
+ pr_debug("%s: isolated LOAD failed\n", __FUNCTION__);
+ ctx->ops->runcntl_write(ctx, SPU_RUNCNTL_RUNNABLE);
+ ret = -EACCES;
+
+ } else if (!(status & SPU_STATUS_ISOLATED_STATE)) {
+ /* This isn't allowed by the CBEA, but check anyway */
+ pr_debug("%s: SPU fell out of isolated mode?\n", __FUNCTION__);
+ ctx->ops->runcntl_write(ctx, SPU_RUNCNTL_STOP);
+ ret = -EINVAL;
+ }
+
+out_drop_priv:
+ /* Finished accessing the loader. Drop kernel mode */
+ sr1 |= MFC_STATE1_PROBLEM_STATE_MASK;
+ spu_mfc_sr1_set(ctx->spu, sr1);
+
+out_unlock:
+ spu_release_exclusive(ctx);
+out:
+ return ret;
+}
+
static inline int spu_run_init(struct spu_context *ctx, u32 * npc)
{
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 (!(ctx->flags & SPU_CREATE_ISOLATE)) {
+ if (ctx->flags & SPU_CREATE_ISOLATE) {
+ if (!(ctx->ops->status_read(ctx) & SPU_STATUS_ISOLATED_STATE)) {
+ /* 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);
+ }
+
+ /* if userspace has set the runcntrl register (eg, to issue an
+ * isolated exit), we need to re-set it here */
+ runcntl = ctx->ops->runcntl_read(ctx) &
+ (SPU_RUNCNTL_RUNNABLE | SPU_RUNCNTL_ISOLATE);
+ if (runcntl == 0)
+ runcntl = SPU_RUNCNTL_RUNNABLE;
+ } else
ctx->ops->npc_write(ctx, *npc);
- ctx->ops->runcntl_write(ctx, runcntl);
- }
- return 0;
+
+ ctx->ops->runcntl_write(ctx, runcntl);
+ 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
@@ -183,7 +183,8 @@ 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);
+extern char *isolated_loader;
+
/*
* spufs_wait
* Same as wait_event_interruptible(), except that here
--
next prev parent reply other threads:[~2006-11-20 17:45 UTC|newest]
Thread overview: 66+ messages / expand[flat|nested] mbox.gz Atom feed top
2006-11-20 17:44 [PATCH 00/22] Cell patches for 2.6.20 Arnd Bergmann
2006-11-20 17:44 ` Arnd Bergmann
2006-11-20 17:44 ` [PATCH 01/22] powerpc: convert idle_loop to use hard_irq_disable() Arnd Bergmann
2006-11-20 17:44 ` Arnd Bergmann
2006-11-20 21:59 ` Paul Mackerras
2006-11-20 21:59 ` Paul Mackerras
2006-11-21 0:53 ` Benjamin Herrenschmidt
2006-11-21 0:53 ` Benjamin Herrenschmidt
2006-11-21 10:14 ` Arnd Bergmann
2006-11-21 10:14 ` Arnd Bergmann
2006-11-21 16:58 ` Olof Johansson
2006-11-21 16:58 ` Olof Johansson
2006-11-20 17:44 ` [PATCH 02/22] powerpc: change ppc_rtas declaration to weak Arnd Bergmann
2006-11-20 17:44 ` Arnd Bergmann
2006-11-20 17:44 ` [PATCH 03/22] spufs: Change %llx to 0x%llx Arnd Bergmann
2006-11-20 17:44 ` Arnd Bergmann
2006-11-20 17:44 ` [PATCH 04/22] spufs: add /lslr, /dma_info and /proxydma files Arnd Bergmann
2006-11-20 17:44 ` Arnd Bergmann
2006-11-20 17:44 ` [PATCH 05/22] spufs: Remove /spu_tag_mask file Arnd Bergmann
2006-11-20 17:44 ` Arnd Bergmann
2006-11-20 17:45 ` [PATCH 06/22] spufs: implement /mbox_info, /ibox_info, and /wbox_info Arnd Bergmann
2006-11-20 17:45 ` Arnd Bergmann
2006-11-20 17:45 ` [PATCH 07/22] spufs: read from signal files only if data is there Arnd Bergmann
2006-11-20 17:45 ` Arnd Bergmann
2006-11-20 17:45 ` [PATCH 08/22] spufs: replace spu.nid with spu.node Arnd Bergmann
2006-11-20 17:45 ` Arnd Bergmann
2006-11-20 17:45 ` [PATCH 09/22] spufs: return correct event for data storage interrupt Arnd Bergmann
2006-11-20 17:45 ` Arnd Bergmann
2006-11-20 17:45 ` [PATCH 10/22] spufs: fix missing stop-and-signal Arnd Bergmann
2006-11-20 17:45 ` Arnd Bergmann
2006-11-20 17:45 ` [PATCH 11/22] spufs: avoid user-triggered oops in ptrace Arnd Bergmann
2006-11-20 17:45 ` Arnd Bergmann
2006-11-20 17:45 ` [PATCH 12/22] spufs: always map local store non-guarded Arnd Bergmann
2006-11-20 17:45 ` Arnd Bergmann
2006-11-20 17:45 ` [PATCH 13/22] spufs: fix return value of spufs_mfc_write Arnd Bergmann
2006-11-20 17:45 ` Arnd Bergmann
2006-11-20 17:45 ` [PATCH 14/22] spufs: use SPU master control to prevent wild SPU execution Arnd Bergmann
2006-11-20 17:45 ` Arnd Bergmann
2007-03-01 6:18 ` Michael Ellerman
2007-03-01 6:18 ` Michael Ellerman
2007-03-01 13:50 ` [Cbe-oss-dev] " Arnd Bergmann
2007-03-01 13:50 ` Arnd Bergmann
2007-03-02 10:13 ` Michael Ellerman
2007-03-02 10:13 ` Michael Ellerman
2007-03-05 1:02 ` Arnd Bergmann
2007-03-07 8:58 ` Michael Ellerman
2007-03-07 8:58 ` Michael Ellerman
2006-11-20 17:45 ` [PATCH 15/22] spufs: Add runcntrl read accessors Arnd Bergmann
2006-11-20 17:45 ` Arnd Bergmann
2006-11-20 17:45 ` Arnd Bergmann [this message]
2006-11-20 17:45 ` [PATCH 16/22] spufs: load isolation kernel from spu_run Arnd Bergmann
2006-11-20 17:45 ` [PATCH 17/22] coredump: Add SPU elf notes to coredump Arnd Bergmann
2006-11-20 17:45 ` Arnd Bergmann
2006-11-20 17:45 ` Arnd Bergmann
2006-11-21 5:38 ` Michael Ellerman
2006-11-21 5:38 ` Michael Ellerman
2006-11-20 17:45 ` [PATCH 18/22] cell: add symbol exports for oprofile Arnd Bergmann
2006-11-20 17:45 ` Arnd Bergmann
2006-11-20 17:45 ` [PATCH 19/22] cell: PMU register macros Arnd Bergmann
2006-11-20 17:45 ` Arnd Bergmann
2006-11-20 17:45 ` [PATCH 20/22] cell: Move PMU-related stuff to include/asm-powerpc/cell-pmu.h Arnd Bergmann
2006-11-20 17:45 ` Arnd Bergmann
2006-11-20 17:45 ` [PATCH 21/22] cell: add routines for managing PMU interrupts Arnd Bergmann
2006-11-20 17:45 ` Arnd Bergmann
2006-11-20 17:45 ` [PATCH 22/22] cell: add oprofile support Arnd Bergmann
2006-11-20 17:45 ` Arnd Bergmann
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20061120180526.009530000@arndb.de \
--to=arnd@arndb.de \
--cc=arnd.bergmann@de.ibm.com \
--cc=cbe-oss-dev@ozlabs.org \
--cc=jeremy@au1.ibm.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linuxppc-dev@ozlabs.org \
--cc=paulus@samba.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.