Skip to content

Commit

Permalink
[POWERPC] spufs: clear mapping pointers after last close
Browse files Browse the repository at this point in the history
Make sure the pointers to various mappings are cleared once the last
user stopped using them.  This avoids accessing freed memory when
tearing down the gang directory aswell as optimizing away
pte invalidations if no one uses these.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Arnd Bergmann <arnd.bergmann@de.ibm.com>
  • Loading branch information
Christoph Hellwig authored and Arnd Bergmann committed Apr 23, 2007
1 parent 0887309 commit 43c2bbd
Show file tree
Hide file tree
Showing 4 changed files with 148 additions and 13 deletions.
1 change: 1 addition & 0 deletions arch/powerpc/platforms/cell/spufs/context.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ struct spu_context *alloc_spu_context(struct spu_gang *gang)
goto out_free;
}
spin_lock_init(&ctx->mmio_lock);
spin_lock_init(&ctx->mapping_lock);
kref_init(&ctx->kref);
mutex_init(&ctx->state_mutex);
init_MUTEX(&ctx->run_sema);
Expand Down
147 changes: 139 additions & 8 deletions arch/powerpc/platforms/cell/spufs/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,26 @@ spufs_mem_open(struct inode *inode, struct file *file)
{
struct spufs_inode_info *i = SPUFS_I(inode);
struct spu_context *ctx = i->i_ctx;

spin_lock(&ctx->mapping_lock);
file->private_data = ctx;
ctx->local_store = inode->i_mapping;
if (!i->i_openers++)
ctx->local_store = inode->i_mapping;
spin_unlock(&ctx->mapping_lock);
smp_wmb();
return 0;
}

static int
spufs_mem_release(struct inode *inode, struct file *file)
{
struct spufs_inode_info *i = SPUFS_I(inode);
struct spu_context *ctx = i->i_ctx;

spin_lock(&ctx->mapping_lock);
if (!--i->i_openers)
ctx->local_store = NULL;
spin_unlock(&ctx->mapping_lock);
smp_wmb();
return 0;
}
Expand Down Expand Up @@ -149,6 +167,7 @@ spufs_mem_mmap(struct file *file, struct vm_area_struct *vma)

static const struct file_operations spufs_mem_fops = {
.open = spufs_mem_open,
.release = spufs_mem_release,
.read = spufs_mem_read,
.write = spufs_mem_write,
.llseek = generic_file_llseek,
Expand Down Expand Up @@ -238,16 +257,35 @@ static int spufs_cntl_open(struct inode *inode, struct file *file)
struct spufs_inode_info *i = SPUFS_I(inode);
struct spu_context *ctx = i->i_ctx;

spin_lock(&ctx->mapping_lock);
file->private_data = ctx;
ctx->cntl = inode->i_mapping;
if (!i->i_openers++)
ctx->cntl = inode->i_mapping;
spin_unlock(&ctx->mapping_lock);
smp_wmb();
return simple_attr_open(inode, file, spufs_cntl_get,
spufs_cntl_set, "0x%08lx");
}

static int
spufs_cntl_release(struct inode *inode, struct file *file)
{
struct spufs_inode_info *i = SPUFS_I(inode);
struct spu_context *ctx = i->i_ctx;

simple_attr_close(inode, file);

spin_lock(&ctx->mapping_lock);
if (!--i->i_openers)
ctx->cntl = NULL;
spin_unlock(&ctx->mapping_lock);
smp_wmb();
return 0;
}

static const struct file_operations spufs_cntl_fops = {
.open = spufs_cntl_open,
.release = simple_attr_close,
.release = spufs_cntl_release,
.read = simple_attr_read,
.write = simple_attr_write,
.mmap = spufs_cntl_mmap,
Expand Down Expand Up @@ -723,12 +761,30 @@ static int spufs_signal1_open(struct inode *inode, struct file *file)
{
struct spufs_inode_info *i = SPUFS_I(inode);
struct spu_context *ctx = i->i_ctx;

spin_lock(&ctx->mapping_lock);
file->private_data = ctx;
ctx->signal1 = inode->i_mapping;
if (!i->i_openers++)
ctx->signal1 = inode->i_mapping;
spin_unlock(&ctx->mapping_lock);
smp_wmb();
return nonseekable_open(inode, file);
}

static int
spufs_signal1_release(struct inode *inode, struct file *file)
{
struct spufs_inode_info *i = SPUFS_I(inode);
struct spu_context *ctx = i->i_ctx;

spin_lock(&ctx->mapping_lock);
if (!--i->i_openers)
ctx->signal1 = NULL;
spin_unlock(&ctx->mapping_lock);
smp_wmb();
return 0;
}

static ssize_t __spufs_signal1_read(struct spu_context *ctx, char __user *buf,
size_t len, loff_t *pos)
{
Expand Down Expand Up @@ -821,6 +877,7 @@ static int spufs_signal1_mmap(struct file *file, struct vm_area_struct *vma)

static const struct file_operations spufs_signal1_fops = {
.open = spufs_signal1_open,
.release = spufs_signal1_release,
.read = spufs_signal1_read,
.write = spufs_signal1_write,
.mmap = spufs_signal1_mmap,
Expand All @@ -830,12 +887,30 @@ static int spufs_signal2_open(struct inode *inode, struct file *file)
{
struct spufs_inode_info *i = SPUFS_I(inode);
struct spu_context *ctx = i->i_ctx;

spin_lock(&ctx->mapping_lock);
file->private_data = ctx;
ctx->signal2 = inode->i_mapping;
if (!i->i_openers++)
ctx->signal2 = inode->i_mapping;
spin_unlock(&ctx->mapping_lock);
smp_wmb();
return nonseekable_open(inode, file);
}

static int
spufs_signal2_release(struct inode *inode, struct file *file)
{
struct spufs_inode_info *i = SPUFS_I(inode);
struct spu_context *ctx = i->i_ctx;

spin_lock(&ctx->mapping_lock);
if (!--i->i_openers)
ctx->signal2 = NULL;
spin_unlock(&ctx->mapping_lock);
smp_wmb();
return 0;
}

static ssize_t __spufs_signal2_read(struct spu_context *ctx, char __user *buf,
size_t len, loff_t *pos)
{
Expand Down Expand Up @@ -932,6 +1007,7 @@ static int spufs_signal2_mmap(struct file *file, struct vm_area_struct *vma)

static const struct file_operations spufs_signal2_fops = {
.open = spufs_signal2_open,
.release = spufs_signal2_release,
.read = spufs_signal2_read,
.write = spufs_signal2_write,
.mmap = spufs_signal2_mmap,
Expand Down Expand Up @@ -1031,13 +1107,32 @@ static int spufs_mss_open(struct inode *inode, struct file *file)
struct spu_context *ctx = i->i_ctx;

file->private_data = i->i_ctx;
ctx->mss = inode->i_mapping;

spin_lock(&ctx->mapping_lock);
if (!i->i_openers++)
ctx->mss = inode->i_mapping;
spin_unlock(&ctx->mapping_lock);
smp_wmb();
return nonseekable_open(inode, file);
}

static int
spufs_mss_release(struct inode *inode, struct file *file)
{
struct spufs_inode_info *i = SPUFS_I(inode);
struct spu_context *ctx = i->i_ctx;

spin_lock(&ctx->mapping_lock);
if (!--i->i_openers)
ctx->mss = NULL;
spin_unlock(&ctx->mapping_lock);
smp_wmb();
return 0;
}

static const struct file_operations spufs_mss_fops = {
.open = spufs_mss_open,
.release = spufs_mss_release,
.mmap = spufs_mss_mmap,
};

Expand Down Expand Up @@ -1072,14 +1167,32 @@ static int spufs_psmap_open(struct inode *inode, struct file *file)
struct spufs_inode_info *i = SPUFS_I(inode);
struct spu_context *ctx = i->i_ctx;

spin_lock(&ctx->mapping_lock);
file->private_data = i->i_ctx;
ctx->psmap = inode->i_mapping;
if (!i->i_openers++)
ctx->psmap = inode->i_mapping;
spin_unlock(&ctx->mapping_lock);
smp_wmb();
return nonseekable_open(inode, file);
}

static int
spufs_psmap_release(struct inode *inode, struct file *file)
{
struct spufs_inode_info *i = SPUFS_I(inode);
struct spu_context *ctx = i->i_ctx;

spin_lock(&ctx->mapping_lock);
if (!--i->i_openers)
ctx->psmap = NULL;
spin_unlock(&ctx->mapping_lock);
smp_wmb();
return 0;
}

static const struct file_operations spufs_psmap_fops = {
.open = spufs_psmap_open,
.release = spufs_psmap_release,
.mmap = spufs_psmap_mmap,
};

Expand Down Expand Up @@ -1126,12 +1239,29 @@ static int spufs_mfc_open(struct inode *inode, struct file *file)
if (atomic_read(&inode->i_count) != 1)
return -EBUSY;

spin_lock(&ctx->mapping_lock);
file->private_data = ctx;
ctx->mfc = inode->i_mapping;
if (!i->i_openers++)
ctx->mfc = inode->i_mapping;
spin_unlock(&ctx->mapping_lock);
smp_wmb();
return nonseekable_open(inode, file);
}

static int
spufs_mfc_release(struct inode *inode, struct file *file)
{
struct spufs_inode_info *i = SPUFS_I(inode);
struct spu_context *ctx = i->i_ctx;

spin_lock(&ctx->mapping_lock);
if (!--i->i_openers)
ctx->mfc = NULL;
spin_unlock(&ctx->mapping_lock);
smp_wmb();
return 0;
}

/* interrupt-level mfc callback function. */
void spufs_mfc_callback(struct spu *spu)
{
Expand Down Expand Up @@ -1399,6 +1529,7 @@ static int spufs_mfc_fasync(int fd, struct file *file, int on)

static const struct file_operations spufs_mfc_fops = {
.open = spufs_mfc_open,
.release = spufs_mfc_release,
.read = spufs_mfc_read,
.write = spufs_mfc_write,
.poll = spufs_mfc_poll,
Expand Down
1 change: 1 addition & 0 deletions arch/powerpc/platforms/cell/spufs/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ spufs_alloc_inode(struct super_block *sb)

ei->i_gang = NULL;
ei->i_ctx = NULL;
ei->i_openers = 0;

return &ei->vfs_inode;
}
Expand Down
12 changes: 7 additions & 5 deletions arch/powerpc/platforms/cell/spufs/spufs.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,11 +50,12 @@ struct spu_context {
spinlock_t mmio_lock; /* protects mmio access */
struct address_space *local_store; /* local store mapping. */
struct address_space *mfc; /* 'mfc' area mappings. */
struct address_space *cntl; /* 'control' area mappings. */
struct address_space *signal1; /* 'signal1' area mappings. */
struct address_space *signal2; /* 'signal2' area mappings. */
struct address_space *mss; /* 'mss' area mappings. */
struct address_space *psmap; /* 'psmap' area mappings. */
struct address_space *cntl; /* 'control' area mappings. */
struct address_space *signal1; /* 'signal1' area mappings. */
struct address_space *signal2; /* 'signal2' area mappings. */
struct address_space *mss; /* 'mss' area mappings. */
struct address_space *psmap; /* 'psmap' area mappings. */
spinlock_t mapping_lock;
u64 object_id; /* user space pointer for oprofile */

enum { SPU_STATE_RUNNABLE, SPU_STATE_SAVED } state;
Expand Down Expand Up @@ -149,6 +150,7 @@ struct spufs_inode_info {
struct spu_context *i_ctx;
struct spu_gang *i_gang;
struct inode vfs_inode;
int i_openers;
};
#define SPUFS_I(inode) \
container_of(inode, struct spufs_inode_info, vfs_inode)
Expand Down

0 comments on commit 43c2bbd

Please sign in to comment.