aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@lst.de>2007-04-23 15:08:07 -0400
committerArnd Bergmann <arnd@klappe.arndb.de>2007-04-23 15:18:53 -0400
commit43c2bbd932b66403688f3d812065d82f8fb8f4b3 (patch)
treea58ad5bb76d65cc8e04f5c7dd1e55460a9cb052b /arch
parent0887309589824fb1c3744c69a330c99c369124a0 (diff)
[POWERPC] spufs: clear mapping pointers after last close
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>
Diffstat (limited to 'arch')
-rw-r--r--arch/powerpc/platforms/cell/spufs/context.c1
-rw-r--r--arch/powerpc/platforms/cell/spufs/file.c147
-rw-r--r--arch/powerpc/platforms/cell/spufs/inode.c1
-rw-r--r--arch/powerpc/platforms/cell/spufs/spufs.h12
4 files changed, 148 insertions, 13 deletions
diff --git a/arch/powerpc/platforms/cell/spufs/context.c b/arch/powerpc/platforms/cell/spufs/context.c
index 04ad2e364e97..b3954aba424e 100644
--- a/arch/powerpc/platforms/cell/spufs/context.c
+++ b/arch/powerpc/platforms/cell/spufs/context.c
@@ -41,6 +41,7 @@ struct spu_context *alloc_spu_context(struct spu_gang *gang)
41 goto out_free; 41 goto out_free;
42 } 42 }
43 spin_lock_init(&ctx->mmio_lock); 43 spin_lock_init(&ctx->mmio_lock);
44 spin_lock_init(&ctx->mapping_lock);
44 kref_init(&ctx->kref); 45 kref_init(&ctx->kref);
45 mutex_init(&ctx->state_mutex); 46 mutex_init(&ctx->state_mutex);
46 init_MUTEX(&ctx->run_sema); 47 init_MUTEX(&ctx->run_sema);
diff --git a/arch/powerpc/platforms/cell/spufs/file.c b/arch/powerpc/platforms/cell/spufs/file.c
index 505266a568d4..deb340e6e0ae 100644
--- a/arch/powerpc/platforms/cell/spufs/file.c
+++ b/arch/powerpc/platforms/cell/spufs/file.c
@@ -44,8 +44,26 @@ spufs_mem_open(struct inode *inode, struct file *file)
44{ 44{
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
48 spin_lock(&ctx->mapping_lock);
47 file->private_data = ctx; 49 file->private_data = ctx;
48 ctx->local_store = inode->i_mapping; 50 if (!i->i_openers++)
51 ctx->local_store = inode->i_mapping;
52 spin_unlock(&ctx->mapping_lock);
53 smp_wmb();
54 return 0;
55}
56
57static int
58spufs_mem_release(struct inode *inode, struct file *file)
59{
60 struct spufs_inode_info *i = SPUFS_I(inode);
61 struct spu_context *ctx = i->i_ctx;
62
63 spin_lock(&ctx->mapping_lock);
64 if (!--i->i_openers)
65 ctx->local_store = NULL;
66 spin_unlock(&ctx->mapping_lock);
49 smp_wmb(); 67 smp_wmb();
50 return 0; 68 return 0;
51} 69}
@@ -149,6 +167,7 @@ spufs_mem_mmap(struct file *file, struct vm_area_struct *vma)
149 167
150static const struct file_operations spufs_mem_fops = { 168static const struct file_operations spufs_mem_fops = {
151 .open = spufs_mem_open, 169 .open = spufs_mem_open,
170 .release = spufs_mem_release,
152 .read = spufs_mem_read, 171 .read = spufs_mem_read,
153 .write = spufs_mem_write, 172 .write = spufs_mem_write,
154 .llseek = generic_file_llseek, 173 .llseek = generic_file_llseek,
@@ -238,16 +257,35 @@ static int spufs_cntl_open(struct inode *inode, struct file *file)
238 struct spufs_inode_info *i = SPUFS_I(inode); 257 struct spufs_inode_info *i = SPUFS_I(inode);
239 struct spu_context *ctx = i->i_ctx; 258 struct spu_context *ctx = i->i_ctx;
240 259
260 spin_lock(&ctx->mapping_lock);
241 file->private_data = ctx; 261 file->private_data = ctx;
242 ctx->cntl = inode->i_mapping; 262 if (!i->i_openers++)
263 ctx->cntl = inode->i_mapping;
264 spin_unlock(&ctx->mapping_lock);
243 smp_wmb(); 265 smp_wmb();
244 return simple_attr_open(inode, file, spufs_cntl_get, 266 return simple_attr_open(inode, file, spufs_cntl_get,
245 spufs_cntl_set, "0x%08lx"); 267 spufs_cntl_set, "0x%08lx");
246} 268}
247 269
270static int
271spufs_cntl_release(struct inode *inode, struct file *file)
272{
273 struct spufs_inode_info *i = SPUFS_I(inode);
274 struct spu_context *ctx = i->i_ctx;
275
276 simple_attr_close(inode, file);
277
278 spin_lock(&ctx->mapping_lock);
279 if (!--i->i_openers)
280 ctx->cntl = NULL;
281 spin_unlock(&ctx->mapping_lock);
282 smp_wmb();
283 return 0;
284}
285
248static const struct file_operations spufs_cntl_fops = { 286static const struct file_operations spufs_cntl_fops = {
249 .open = spufs_cntl_open, 287 .open = spufs_cntl_open,
250 .release = simple_attr_close, 288 .release = spufs_cntl_release,
251 .read = simple_attr_read, 289 .read = simple_attr_read,
252 .write = simple_attr_write, 290 .write = simple_attr_write,
253 .mmap = spufs_cntl_mmap, 291 .mmap = spufs_cntl_mmap,
@@ -723,12 +761,30 @@ static int spufs_signal1_open(struct inode *inode, struct file *file)
723{ 761{
724 struct spufs_inode_info *i = SPUFS_I(inode); 762 struct spufs_inode_info *i = SPUFS_I(inode);
725 struct spu_context *ctx = i->i_ctx; 763 struct spu_context *ctx = i->i_ctx;
764
765 spin_lock(&ctx->mapping_lock);
726 file->private_data = ctx; 766 file->private_data = ctx;
727 ctx->signal1 = inode->i_mapping; 767 if (!i->i_openers++)
768 ctx->signal1 = inode->i_mapping;
769 spin_unlock(&ctx->mapping_lock);
728 smp_wmb(); 770 smp_wmb();
729 return nonseekable_open(inode, file); 771 return nonseekable_open(inode, file);
730} 772}
731 773
774static int
775spufs_signal1_release(struct inode *inode, struct file *file)
776{
777 struct spufs_inode_info *i = SPUFS_I(inode);
778 struct spu_context *ctx = i->i_ctx;
779
780 spin_lock(&ctx->mapping_lock);
781 if (!--i->i_openers)
782 ctx->signal1 = NULL;
783 spin_unlock(&ctx->mapping_lock);
784 smp_wmb();
785 return 0;
786}
787
732static ssize_t __spufs_signal1_read(struct spu_context *ctx, char __user *buf, 788static ssize_t __spufs_signal1_read(struct spu_context *ctx, char __user *buf,
733 size_t len, loff_t *pos) 789 size_t len, loff_t *pos)
734{ 790{
@@ -821,6 +877,7 @@ static int spufs_signal1_mmap(struct file *file, struct vm_area_struct *vma)
821 877
822static const struct file_operations spufs_signal1_fops = { 878static const struct file_operations spufs_signal1_fops = {
823 .open = spufs_signal1_open, 879 .open = spufs_signal1_open,
880 .release = spufs_signal1_release,
824 .read = spufs_signal1_read, 881 .read = spufs_signal1_read,
825 .write = spufs_signal1_write, 882 .write = spufs_signal1_write,
826 .mmap = spufs_signal1_mmap, 883 .mmap = spufs_signal1_mmap,
@@ -830,12 +887,30 @@ static int spufs_signal2_open(struct inode *inode, struct file *file)
830{ 887{
831 struct spufs_inode_info *i = SPUFS_I(inode); 888 struct spufs_inode_info *i = SPUFS_I(inode);
832 struct spu_context *ctx = i->i_ctx; 889 struct spu_context *ctx = i->i_ctx;
890
891 spin_lock(&ctx->mapping_lock);
833 file->private_data = ctx; 892 file->private_data = ctx;
834 ctx->signal2 = inode->i_mapping; 893 if (!i->i_openers++)
894 ctx->signal2 = inode->i_mapping;
895 spin_unlock(&ctx->mapping_lock);
835 smp_wmb(); 896 smp_wmb();
836 return nonseekable_open(inode, file); 897 return nonseekable_open(inode, file);
837} 898}
838 899
900static int
901spufs_signal2_release(struct inode *inode, struct file *file)
902{
903 struct spufs_inode_info *i = SPUFS_I(inode);
904 struct spu_context *ctx = i->i_ctx;
905
906 spin_lock(&ctx->mapping_lock);
907 if (!--i->i_openers)
908 ctx->signal2 = NULL;
909 spin_unlock(&ctx->mapping_lock);
910 smp_wmb();
911 return 0;
912}
913
839static ssize_t __spufs_signal2_read(struct spu_context *ctx, char __user *buf, 914static ssize_t __spufs_signal2_read(struct spu_context *ctx, char __user *buf,
840 size_t len, loff_t *pos) 915 size_t len, loff_t *pos)
841{ 916{
@@ -932,6 +1007,7 @@ static int spufs_signal2_mmap(struct file *file, struct vm_area_struct *vma)
932 1007
933static const struct file_operations spufs_signal2_fops = { 1008static const struct file_operations spufs_signal2_fops = {
934 .open = spufs_signal2_open, 1009 .open = spufs_signal2_open,
1010 .release = spufs_signal2_release,
935 .read = spufs_signal2_read, 1011 .read = spufs_signal2_read,
936 .write = spufs_signal2_write, 1012 .write = spufs_signal2_write,
937 .mmap = spufs_signal2_mmap, 1013 .mmap = spufs_signal2_mmap,
@@ -1031,13 +1107,32 @@ static int spufs_mss_open(struct inode *inode, struct file *file)
1031 struct spu_context *ctx = i->i_ctx; 1107 struct spu_context *ctx = i->i_ctx;
1032 1108
1033 file->private_data = i->i_ctx; 1109 file->private_data = i->i_ctx;
1034 ctx->mss = inode->i_mapping; 1110
1111 spin_lock(&ctx->mapping_lock);
1112 if (!i->i_openers++)
1113 ctx->mss = inode->i_mapping;
1114 spin_unlock(&ctx->mapping_lock);
1035 smp_wmb(); 1115 smp_wmb();
1036 return nonseekable_open(inode, file); 1116 return nonseekable_open(inode, file);
1037} 1117}
1038 1118
1119static int
1120spufs_mss_release(struct inode *inode, struct file *file)
1121{
1122 struct spufs_inode_info *i = SPUFS_I(inode);
1123 struct spu_context *ctx = i->i_ctx;
1124
1125 spin_lock(&ctx->mapping_lock);
1126 if (!--i->i_openers)
1127 ctx->mss = NULL;
1128 spin_unlock(&ctx->mapping_lock);
1129 smp_wmb();
1130 return 0;
1131}
1132
1039static const struct file_operations spufs_mss_fops = { 1133static const struct file_operations spufs_mss_fops = {
1040 .open = spufs_mss_open, 1134 .open = spufs_mss_open,
1135 .release = spufs_mss_release,
1041 .mmap = spufs_mss_mmap, 1136 .mmap = spufs_mss_mmap,
1042}; 1137};
1043 1138
@@ -1072,14 +1167,32 @@ static int spufs_psmap_open(struct inode *inode, struct file *file)
1072 struct spufs_inode_info *i = SPUFS_I(inode); 1167 struct spufs_inode_info *i = SPUFS_I(inode);
1073 struct spu_context *ctx = i->i_ctx; 1168 struct spu_context *ctx = i->i_ctx;
1074 1169
1170 spin_lock(&ctx->mapping_lock);
1075 file->private_data = i->i_ctx; 1171 file->private_data = i->i_ctx;
1076 ctx->psmap = inode->i_mapping; 1172 if (!i->i_openers++)
1173 ctx->psmap = inode->i_mapping;
1174 spin_unlock(&ctx->mapping_lock);
1077 smp_wmb(); 1175 smp_wmb();
1078 return nonseekable_open(inode, file); 1176 return nonseekable_open(inode, file);
1079} 1177}
1080 1178
1179static int
1180spufs_psmap_release(struct inode *inode, struct file *file)
1181{
1182 struct spufs_inode_info *i = SPUFS_I(inode);
1183 struct spu_context *ctx = i->i_ctx;
1184
1185 spin_lock(&ctx->mapping_lock);
1186 if (!--i->i_openers)
1187 ctx->psmap = NULL;
1188 spin_unlock(&ctx->mapping_lock);
1189 smp_wmb();
1190 return 0;
1191}
1192
1081static const struct file_operations spufs_psmap_fops = { 1193static const struct file_operations spufs_psmap_fops = {
1082 .open = spufs_psmap_open, 1194 .open = spufs_psmap_open,
1195 .release = spufs_psmap_release,
1083 .mmap = spufs_psmap_mmap, 1196 .mmap = spufs_psmap_mmap,
1084}; 1197};
1085 1198
@@ -1126,12 +1239,29 @@ static int spufs_mfc_open(struct inode *inode, struct file *file)
1126 if (atomic_read(&inode->i_count) != 1) 1239 if (atomic_read(&inode->i_count) != 1)
1127 return -EBUSY; 1240 return -EBUSY;
1128 1241
1242 spin_lock(&ctx->mapping_lock);
1129 file->private_data = ctx; 1243 file->private_data = ctx;
1130 ctx->mfc = inode->i_mapping; 1244 if (!i->i_openers++)
1245 ctx->mfc = inode->i_mapping;
1246 spin_unlock(&ctx->mapping_lock);
1131 smp_wmb(); 1247 smp_wmb();
1132 return nonseekable_open(inode, file); 1248 return nonseekable_open(inode, file);
1133} 1249}
1134 1250
1251static int
1252spufs_mfc_release(struct inode *inode, struct file *file)
1253{
1254 struct spufs_inode_info *i = SPUFS_I(inode);
1255 struct spu_context *ctx = i->i_ctx;
1256
1257 spin_lock(&ctx->mapping_lock);
1258 if (!--i->i_openers)
1259 ctx->mfc = NULL;
1260 spin_unlock(&ctx->mapping_lock);
1261 smp_wmb();
1262 return 0;
1263}
1264
1135/* interrupt-level mfc callback function. */ 1265/* interrupt-level mfc callback function. */
1136void spufs_mfc_callback(struct spu *spu) 1266void spufs_mfc_callback(struct spu *spu)
1137{ 1267{
@@ -1399,6 +1529,7 @@ static int spufs_mfc_fasync(int fd, struct file *file, int on)
1399 1529
1400static const struct file_operations spufs_mfc_fops = { 1530static const struct file_operations spufs_mfc_fops = {
1401 .open = spufs_mfc_open, 1531 .open = spufs_mfc_open,
1532 .release = spufs_mfc_release,
1402 .read = spufs_mfc_read, 1533 .read = spufs_mfc_read,
1403 .write = spufs_mfc_write, 1534 .write = spufs_mfc_write,
1404 .poll = spufs_mfc_poll, 1535 .poll = spufs_mfc_poll,
diff --git a/arch/powerpc/platforms/cell/spufs/inode.c b/arch/powerpc/platforms/cell/spufs/inode.c
index e3f4ee97c913..423596a6b995 100644
--- a/arch/powerpc/platforms/cell/spufs/inode.c
+++ b/arch/powerpc/platforms/cell/spufs/inode.c
@@ -54,6 +54,7 @@ spufs_alloc_inode(struct super_block *sb)
54 54
55 ei->i_gang = NULL; 55 ei->i_gang = NULL;
56 ei->i_ctx = NULL; 56 ei->i_ctx = NULL;
57 ei->i_openers = 0;
57 58
58 return &ei->vfs_inode; 59 return &ei->vfs_inode;
59} 60}
diff --git a/arch/powerpc/platforms/cell/spufs/spufs.h b/arch/powerpc/platforms/cell/spufs/spufs.h
index f418378abdff..0fb366d9d257 100644
--- a/arch/powerpc/platforms/cell/spufs/spufs.h
+++ b/arch/powerpc/platforms/cell/spufs/spufs.h
@@ -50,11 +50,12 @@ struct spu_context {
50 spinlock_t mmio_lock; /* protects mmio access */ 50 spinlock_t mmio_lock; /* protects mmio access */
51 struct address_space *local_store; /* local store mapping. */ 51 struct address_space *local_store; /* local store mapping. */
52 struct address_space *mfc; /* 'mfc' area mappings. */ 52 struct address_space *mfc; /* 'mfc' area mappings. */
53 struct address_space *cntl; /* 'control' area mappings. */ 53 struct address_space *cntl; /* 'control' area mappings. */
54 struct address_space *signal1; /* 'signal1' area mappings. */ 54 struct address_space *signal1; /* 'signal1' area mappings. */
55 struct address_space *signal2; /* 'signal2' area mappings. */ 55 struct address_space *signal2; /* 'signal2' area mappings. */
56 struct address_space *mss; /* 'mss' area mappings. */ 56 struct address_space *mss; /* 'mss' area mappings. */
57 struct address_space *psmap; /* 'psmap' area mappings. */ 57 struct address_space *psmap; /* 'psmap' area mappings. */
58 spinlock_t mapping_lock;
58 u64 object_id; /* user space pointer for oprofile */ 59 u64 object_id; /* user space pointer for oprofile */
59 60
60 enum { SPU_STATE_RUNNABLE, SPU_STATE_SAVED } state; 61 enum { SPU_STATE_RUNNABLE, SPU_STATE_SAVED } state;
@@ -149,6 +150,7 @@ struct spufs_inode_info {
149 struct spu_context *i_ctx; 150 struct spu_context *i_ctx;
150 struct spu_gang *i_gang; 151 struct spu_gang *i_gang;
151 struct inode vfs_inode; 152 struct inode vfs_inode;
153 int i_openers;
152}; 154};
153#define SPUFS_I(inode) \ 155#define SPUFS_I(inode) \
154 container_of(inode, struct spufs_inode_info, vfs_inode) 156 container_of(inode, struct spufs_inode_info, vfs_inode)