aboutsummaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
Diffstat (limited to 'arch')
-rw-r--r--arch/powerpc/platforms/cell/spufs/context.c97
-rw-r--r--arch/powerpc/platforms/cell/spufs/run.c2
-rw-r--r--arch/powerpc/platforms/cell/spufs/spufs.h18
3 files changed, 64 insertions, 53 deletions
diff --git a/arch/powerpc/platforms/cell/spufs/context.c b/arch/powerpc/platforms/cell/spufs/context.c
index c9aab9b1cd8..f2630dc0db8 100644
--- a/arch/powerpc/platforms/cell/spufs/context.c
+++ b/arch/powerpc/platforms/cell/spufs/context.c
@@ -96,16 +96,6 @@ void spu_forget(struct spu_context *ctx)
spu_release(ctx);
}
-void spu_acquire(struct spu_context *ctx)
-{
- mutex_lock(&ctx->state_mutex);
-}
-
-void spu_release(struct spu_context *ctx)
-{
- mutex_unlock(&ctx->state_mutex);
-}
-
void spu_unmap_mappings(struct spu_context *ctx)
{
if (ctx->local_store)
@@ -124,66 +114,85 @@ void spu_unmap_mappings(struct spu_context *ctx)
unmap_mapping_range(ctx->psmap, 0, 0x20000, 1);
}
+/**
+ * spu_acquire_exclusive - lock spu contex and protect against userspace access
+ * @ctx: spu contex to lock
+ *
+ * Note:
+ * Returns 0 and with the context locked on success
+ * Returns negative error and with the context _unlocked_ on failure.
+ */
int spu_acquire_exclusive(struct spu_context *ctx)
{
- int ret = 0;
+ int ret = -EINVAL;
- mutex_lock(&ctx->state_mutex);
- /* ctx is about to be freed, can't acquire any more */
- if (!ctx->owner) {
- ret = -EINVAL;
- goto out;
- }
+ spu_acquire(ctx);
+ /*
+ * Context is about to be freed, so we can't acquire it anymore.
+ */
+ if (!ctx->owner)
+ goto out_unlock;
if (ctx->state == SPU_STATE_SAVED) {
ret = spu_activate(ctx, 0);
if (ret)
- goto out;
+ goto out_unlock;
} else {
- /* We need to exclude userspace access to the context. */
+ /*
+ * We need to exclude userspace access to the context.
+ *
+ * To protect against memory access we invalidate all ptes
+ * and make sure the pagefault handlers block on the mutex.
+ */
spu_unmap_mappings(ctx);
}
-out:
- if (ret)
- mutex_unlock(&ctx->state_mutex);
+ return 0;
+
+ out_unlock:
+ spu_release(ctx);
return ret;
}
+/**
+ * spu_acquire_runnable - lock spu contex and make sure it is in runnable state
+ * @ctx: spu contex to lock
+ *
+ * Note:
+ * Returns 0 and with the context locked on success
+ * Returns negative error and with the context _unlocked_ on failure.
+ */
int spu_acquire_runnable(struct spu_context *ctx)
{
- int ret = 0;
-
- mutex_lock(&ctx->state_mutex);
- if (ctx->state == SPU_STATE_RUNNABLE) {
- ctx->spu->prio = current->prio;
- return 0;
- }
-
- /* ctx is about to be freed, can't acquire any more */
- if (!ctx->owner) {
- ret = -EINVAL;
- goto out;
- }
+ int ret = -EINVAL;
+ spu_acquire(ctx);
if (ctx->state == SPU_STATE_SAVED) {
+ /*
+ * Context is about to be freed, so we can't acquire it anymore.
+ */
+ if (!ctx->owner)
+ goto out_unlock;
ret = spu_activate(ctx, 0);
if (ret)
- goto out;
- }
+ goto out_unlock;
+ } else
+ ctx->spu->prio = current->prio;
- /* On success, we return holding the lock */
- return ret;
-out:
- /* Release here, to simplify calling code. */
- mutex_unlock(&ctx->state_mutex);
+ return 0;
+ out_unlock:
+ spu_release(ctx);
return ret;
}
+/**
+ * spu_acquire_saved - lock spu contex and make sure it is in saved state
+ * @ctx: spu contex to lock
+ */
void spu_acquire_saved(struct spu_context *ctx)
{
- mutex_lock(&ctx->state_mutex);
- if (ctx->state == SPU_STATE_RUNNABLE)
+ spu_acquire(ctx);
+ if (ctx->state != SPU_STATE_SAVED)
spu_deactivate(ctx);
}
diff --git a/arch/powerpc/platforms/cell/spufs/run.c b/arch/powerpc/platforms/cell/spufs/run.c
index 51b78da2f0d..e1647311044 100644
--- a/arch/powerpc/platforms/cell/spufs/run.c
+++ b/arch/powerpc/platforms/cell/spufs/run.c
@@ -133,7 +133,7 @@ out_drop_priv:
spu_mfc_sr1_set(ctx->spu, sr1);
out_unlock:
- spu_release_exclusive(ctx);
+ spu_release(ctx);
out:
return ret;
}
diff --git a/arch/powerpc/platforms/cell/spufs/spufs.h b/arch/powerpc/platforms/cell/spufs/spufs.h
index de2401afb22..fa07ec2e2c1 100644
--- a/arch/powerpc/platforms/cell/spufs/spufs.h
+++ b/arch/powerpc/platforms/cell/spufs/spufs.h
@@ -158,6 +158,16 @@ void spu_gang_remove_ctx(struct spu_gang *gang, struct spu_context *ctx);
void spu_gang_add_ctx(struct spu_gang *gang, struct spu_context *ctx);
/* context management */
+static inline void spu_acquire(struct spu_context *ctx)
+{
+ mutex_lock(&ctx->state_mutex);
+}
+
+static inline void spu_release(struct spu_context *ctx)
+{
+ mutex_unlock(&ctx->state_mutex);
+}
+
struct spu_context * alloc_spu_context(struct spu_gang *gang);
void destroy_spu_context(struct kref *kref);
struct spu_context * get_spu_context(struct spu_context *ctx);
@@ -165,17 +175,9 @@ int put_spu_context(struct spu_context *ctx);
void spu_unmap_mappings(struct spu_context *ctx);
void spu_forget(struct spu_context *ctx);
-void spu_acquire(struct spu_context *ctx);
-void spu_release(struct spu_context *ctx);
int spu_acquire_runnable(struct spu_context *ctx);
void spu_acquire_saved(struct spu_context *ctx);
int spu_acquire_exclusive(struct spu_context *ctx);
-
-static inline void spu_release_exclusive(struct spu_context *ctx)
-{
- mutex_unlock(&ctx->state_mutex);
-}
-
int spu_activate(struct spu_context *ctx, u64 flags);
void spu_deactivate(struct spu_context *ctx);
void spu_yield(struct spu_context *ctx);