aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2007-02-12 19:46:08 -0500
committerPaul Mackerras <paulus@samba.org>2007-02-12 23:35:54 -0500
commit17e0e27020d028a790d97699aff85a43af5be472 (patch)
treef3dd43243be6e840dc2b0386e91c4146a4f51620 /arch
parent44430e0d3916ab6aaf0451fdb811f4f1803b741e (diff)
[POWERPC] spufs: Fix bitrot of the SPU mmap facility
It looks like we've had some serious bitrot there mostly due to tracking of address_space's of mmap'ed files getting out of sync with the actual mmap code. The mfc, mss and psmap were not tracked properly and thus not invalidated on context switches (oops !) I also removed the various file->f_mapping = inode->i_mapping; assignments that were done in the other open() routines since that is already done for us by __dentry_open. One improvement we might want to do later is to assign the various ctx-> fields at mmap time instead of file open/close time so that we don't call unmap_mapping_range() on thing that have not been mmap'ed Finally, I added some smp_wmb's after assigning the ctx-> fields to make sure they are visible to other CPUs. I don't think this is really necessary as I suspect locking in the fs layer will make that happen anyway but better safe than sorry. Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch')
-rw-r--r--arch/powerpc/platforms/cell/spufs/context.c12
-rw-r--r--arch/powerpc/platforms/cell/spufs/file.c16
-rw-r--r--arch/powerpc/platforms/cell/spufs/spufs.h2
3 files changed, 22 insertions, 8 deletions
diff --git a/arch/powerpc/platforms/cell/spufs/context.c b/arch/powerpc/platforms/cell/spufs/context.c
index 0870009f56db..28c718ca3b51 100644
--- a/arch/powerpc/platforms/cell/spufs/context.c
+++ b/arch/powerpc/platforms/cell/spufs/context.c
@@ -111,13 +111,17 @@ void spu_unmap_mappings(struct spu_context *ctx)
111 if (ctx->local_store) 111 if (ctx->local_store)
112 unmap_mapping_range(ctx->local_store, 0, LS_SIZE, 1); 112 unmap_mapping_range(ctx->local_store, 0, LS_SIZE, 1);
113 if (ctx->mfc) 113 if (ctx->mfc)
114 unmap_mapping_range(ctx->mfc, 0, 0x4000, 1); 114 unmap_mapping_range(ctx->mfc, 0, 0x1000, 1);
115 if (ctx->cntl) 115 if (ctx->cntl)
116 unmap_mapping_range(ctx->cntl, 0, 0x4000, 1); 116 unmap_mapping_range(ctx->cntl, 0, 0x1000, 1);
117 if (ctx->signal1) 117 if (ctx->signal1)
118 unmap_mapping_range(ctx->signal1, 0, 0x4000, 1); 118 unmap_mapping_range(ctx->signal1, 0, PAGE_SIZE, 1);
119 if (ctx->signal2) 119 if (ctx->signal2)
120 unmap_mapping_range(ctx->signal2, 0, 0x4000, 1); 120 unmap_mapping_range(ctx->signal2, 0, PAGE_SIZE, 1);
121 if (ctx->mss)
122 unmap_mapping_range(ctx->mss, 0, 0x1000, 1);
123 if (ctx->psmap)
124 unmap_mapping_range(ctx->psmap, 0, 0x20000, 1);
121} 125}
122 126
123int spu_acquire_exclusive(struct spu_context *ctx) 127int spu_acquire_exclusive(struct spu_context *ctx)
diff --git a/arch/powerpc/platforms/cell/spufs/file.c b/arch/powerpc/platforms/cell/spufs/file.c
index 7fb9a6dc4f18..a528020baa18 100644
--- a/arch/powerpc/platforms/cell/spufs/file.c
+++ b/arch/powerpc/platforms/cell/spufs/file.c
@@ -45,8 +45,8 @@ spufs_mem_open(struct inode *inode, struct file *file)
45 struct spufs_inode_info *i = SPUFS_I(inode); 45 struct spufs_inode_info *i = SPUFS_I(inode);
46 struct spu_context *ctx = i->i_ctx; 46 struct spu_context *ctx = i->i_ctx;
47 file->private_data = ctx; 47 file->private_data = ctx;
48 file->f_mapping = inode->i_mapping;
49 ctx->local_store = inode->i_mapping; 48 ctx->local_store = inode->i_mapping;
49 smp_wmb();
50 return 0; 50 return 0;
51} 51}
52 52
@@ -232,8 +232,8 @@ static int spufs_cntl_open(struct inode *inode, struct file *file)
232 struct spu_context *ctx = i->i_ctx; 232 struct spu_context *ctx = i->i_ctx;
233 233
234 file->private_data = ctx; 234 file->private_data = ctx;
235 file->f_mapping = inode->i_mapping;
236 ctx->cntl = inode->i_mapping; 235 ctx->cntl = inode->i_mapping;
236 smp_wmb();
237 return simple_attr_open(inode, file, spufs_cntl_get, 237 return simple_attr_open(inode, file, spufs_cntl_get,
238 spufs_cntl_set, "0x%08lx"); 238 spufs_cntl_set, "0x%08lx");
239} 239}
@@ -717,8 +717,8 @@ static int spufs_signal1_open(struct inode *inode, struct file *file)
717 struct spufs_inode_info *i = SPUFS_I(inode); 717 struct spufs_inode_info *i = SPUFS_I(inode);
718 struct spu_context *ctx = i->i_ctx; 718 struct spu_context *ctx = i->i_ctx;
719 file->private_data = ctx; 719 file->private_data = ctx;
720 file->f_mapping = inode->i_mapping;
721 ctx->signal1 = inode->i_mapping; 720 ctx->signal1 = inode->i_mapping;
721 smp_wmb();
722 return nonseekable_open(inode, file); 722 return nonseekable_open(inode, file);
723} 723}
724 724
@@ -824,8 +824,8 @@ static int spufs_signal2_open(struct inode *inode, struct file *file)
824 struct spufs_inode_info *i = SPUFS_I(inode); 824 struct spufs_inode_info *i = SPUFS_I(inode);
825 struct spu_context *ctx = i->i_ctx; 825 struct spu_context *ctx = i->i_ctx;
826 file->private_data = ctx; 826 file->private_data = ctx;
827 file->f_mapping = inode->i_mapping;
828 ctx->signal2 = inode->i_mapping; 827 ctx->signal2 = inode->i_mapping;
828 smp_wmb();
829 return nonseekable_open(inode, file); 829 return nonseekable_open(inode, file);
830} 830}
831 831
@@ -1021,8 +1021,11 @@ static int spufs_mss_mmap(struct file *file, struct vm_area_struct *vma)
1021static int spufs_mss_open(struct inode *inode, struct file *file) 1021static int spufs_mss_open(struct inode *inode, struct file *file)
1022{ 1022{
1023 struct spufs_inode_info *i = SPUFS_I(inode); 1023 struct spufs_inode_info *i = SPUFS_I(inode);
1024 struct spu_context *ctx = i->i_ctx;
1024 1025
1025 file->private_data = i->i_ctx; 1026 file->private_data = i->i_ctx;
1027 ctx->mss = inode->i_mapping;
1028 smp_wmb();
1026 return nonseekable_open(inode, file); 1029 return nonseekable_open(inode, file);
1027} 1030}
1028 1031
@@ -1060,8 +1063,11 @@ static int spufs_psmap_mmap(struct file *file, struct vm_area_struct *vma)
1060static int spufs_psmap_open(struct inode *inode, struct file *file) 1063static int spufs_psmap_open(struct inode *inode, struct file *file)
1061{ 1064{
1062 struct spufs_inode_info *i = SPUFS_I(inode); 1065 struct spufs_inode_info *i = SPUFS_I(inode);
1066 struct spu_context *ctx = i->i_ctx;
1063 1067
1064 file->private_data = i->i_ctx; 1068 file->private_data = i->i_ctx;
1069 ctx->psmap = inode->i_mapping;
1070 smp_wmb();
1065 return nonseekable_open(inode, file); 1071 return nonseekable_open(inode, file);
1066} 1072}
1067 1073
@@ -1114,6 +1120,8 @@ static int spufs_mfc_open(struct inode *inode, struct file *file)
1114 return -EBUSY; 1120 return -EBUSY;
1115 1121
1116 file->private_data = ctx; 1122 file->private_data = ctx;
1123 ctx->mfc = inode->i_mapping;
1124 smp_wmb();
1117 return nonseekable_open(inode, file); 1125 return nonseekable_open(inode, file);
1118} 1126}
1119 1127
diff --git a/arch/powerpc/platforms/cell/spufs/spufs.h b/arch/powerpc/platforms/cell/spufs/spufs.h
index 56864469215e..0941c56df9b5 100644
--- a/arch/powerpc/platforms/cell/spufs/spufs.h
+++ b/arch/powerpc/platforms/cell/spufs/spufs.h
@@ -51,6 +51,8 @@ struct spu_context {
51 struct address_space *cntl; /* 'control' area mappings. */ 51 struct address_space *cntl; /* 'control' area mappings. */
52 struct address_space *signal1; /* 'signal1' area mappings. */ 52 struct address_space *signal1; /* 'signal1' area mappings. */
53 struct address_space *signal2; /* 'signal2' area mappings. */ 53 struct address_space *signal2; /* 'signal2' area mappings. */
54 struct address_space *mss; /* 'mss' area mappings. */
55 struct address_space *psmap; /* 'psmap' area mappings. */
54 u64 object_id; /* user space pointer for oprofile */ 56 u64 object_id; /* user space pointer for oprofile */
55 57
56 enum { SPU_STATE_RUNNABLE, SPU_STATE_SAVED } state; 58 enum { SPU_STATE_RUNNABLE, SPU_STATE_SAVED } state;