diff options
Diffstat (limited to 'arch/powerpc/platforms/cell/spufs/inode.c')
-rw-r--r-- | arch/powerpc/platforms/cell/spufs/inode.c | 58 |
1 files changed, 55 insertions, 3 deletions
diff --git a/arch/powerpc/platforms/cell/spufs/inode.c b/arch/powerpc/platforms/cell/spufs/inode.c index 427d00a4f6a..c7d010749a1 100644 --- a/arch/powerpc/platforms/cell/spufs/inode.c +++ b/arch/powerpc/platforms/cell/spufs/inode.c | |||
@@ -33,7 +33,7 @@ | |||
33 | #include <linux/slab.h> | 33 | #include <linux/slab.h> |
34 | #include <linux/parser.h> | 34 | #include <linux/parser.h> |
35 | 35 | ||
36 | #include <asm/io.h> | 36 | #include <asm/prom.h> |
37 | #include <asm/semaphore.h> | 37 | #include <asm/semaphore.h> |
38 | #include <asm/spu.h> | 38 | #include <asm/spu.h> |
39 | #include <asm/uaccess.h> | 39 | #include <asm/uaccess.h> |
@@ -41,6 +41,7 @@ | |||
41 | #include "spufs.h" | 41 | #include "spufs.h" |
42 | 42 | ||
43 | static kmem_cache_t *spufs_inode_cache; | 43 | static kmem_cache_t *spufs_inode_cache; |
44 | char *isolated_loader; | ||
44 | 45 | ||
45 | static struct inode * | 46 | static struct inode * |
46 | spufs_alloc_inode(struct super_block *sb) | 47 | spufs_alloc_inode(struct super_block *sb) |
@@ -231,6 +232,7 @@ struct file_operations spufs_context_fops = { | |||
231 | .readdir = dcache_readdir, | 232 | .readdir = dcache_readdir, |
232 | .fsync = simple_sync_file, | 233 | .fsync = simple_sync_file, |
233 | }; | 234 | }; |
235 | EXPORT_SYMBOL_GPL(spufs_context_fops); | ||
234 | 236 | ||
235 | static int | 237 | static int |
236 | spufs_mkdir(struct inode *dir, struct dentry *dentry, unsigned int flags, | 238 | spufs_mkdir(struct inode *dir, struct dentry *dentry, unsigned int flags, |
@@ -255,10 +257,14 @@ spufs_mkdir(struct inode *dir, struct dentry *dentry, unsigned int flags, | |||
255 | goto out_iput; | 257 | goto out_iput; |
256 | 258 | ||
257 | ctx->flags = flags; | 259 | ctx->flags = flags; |
258 | |||
259 | inode->i_op = &spufs_dir_inode_operations; | 260 | inode->i_op = &spufs_dir_inode_operations; |
260 | inode->i_fop = &simple_dir_operations; | 261 | inode->i_fop = &simple_dir_operations; |
261 | ret = spufs_fill_dir(dentry, spufs_dir_contents, mode, ctx); | 262 | if (flags & SPU_CREATE_NOSCHED) |
263 | ret = spufs_fill_dir(dentry, spufs_dir_nosched_contents, | ||
264 | mode, ctx); | ||
265 | else | ||
266 | ret = spufs_fill_dir(dentry, spufs_dir_contents, mode, ctx); | ||
267 | |||
262 | if (ret) | 268 | if (ret) |
263 | goto out_free_ctx; | 269 | goto out_free_ctx; |
264 | 270 | ||
@@ -307,6 +313,20 @@ static int spufs_create_context(struct inode *inode, | |||
307 | { | 313 | { |
308 | int ret; | 314 | int ret; |
309 | 315 | ||
316 | ret = -EPERM; | ||
317 | if ((flags & SPU_CREATE_NOSCHED) && | ||
318 | !capable(CAP_SYS_NICE)) | ||
319 | goto out_unlock; | ||
320 | |||
321 | ret = -EINVAL; | ||
322 | if ((flags & (SPU_CREATE_NOSCHED | SPU_CREATE_ISOLATE)) | ||
323 | == SPU_CREATE_ISOLATE) | ||
324 | goto out_unlock; | ||
325 | |||
326 | ret = -ENODEV; | ||
327 | if ((flags & SPU_CREATE_ISOLATE) && !isolated_loader) | ||
328 | goto out_unlock; | ||
329 | |||
310 | ret = spufs_mkdir(inode, dentry, flags, mode & S_IRWXUGO); | 330 | ret = spufs_mkdir(inode, dentry, flags, mode & S_IRWXUGO); |
311 | if (ret) | 331 | if (ret) |
312 | goto out_unlock; | 332 | goto out_unlock; |
@@ -540,6 +560,30 @@ spufs_parse_options(char *options, struct inode *root) | |||
540 | return 1; | 560 | return 1; |
541 | } | 561 | } |
542 | 562 | ||
563 | static void | ||
564 | spufs_init_isolated_loader(void) | ||
565 | { | ||
566 | struct device_node *dn; | ||
567 | const char *loader; | ||
568 | int size; | ||
569 | |||
570 | dn = of_find_node_by_path("/spu-isolation"); | ||
571 | if (!dn) | ||
572 | return; | ||
573 | |||
574 | loader = get_property(dn, "loader", &size); | ||
575 | if (!loader) | ||
576 | return; | ||
577 | |||
578 | /* kmalloc should align on a 16 byte boundary..* */ | ||
579 | isolated_loader = kmalloc(size, GFP_KERNEL); | ||
580 | if (!isolated_loader) | ||
581 | return; | ||
582 | |||
583 | memcpy(isolated_loader, loader, size); | ||
584 | printk(KERN_INFO "spufs: SPU isolation mode enabled\n"); | ||
585 | } | ||
586 | |||
543 | static int | 587 | static int |
544 | spufs_create_root(struct super_block *sb, void *data) | 588 | spufs_create_root(struct super_block *sb, void *data) |
545 | { | 589 | { |
@@ -608,6 +652,7 @@ static struct file_system_type spufs_type = { | |||
608 | static int __init spufs_init(void) | 652 | static int __init spufs_init(void) |
609 | { | 653 | { |
610 | int ret; | 654 | int ret; |
655 | |||
611 | ret = -ENOMEM; | 656 | ret = -ENOMEM; |
612 | spufs_inode_cache = kmem_cache_create("spufs_inode_cache", | 657 | spufs_inode_cache = kmem_cache_create("spufs_inode_cache", |
613 | sizeof(struct spufs_inode_info), 0, | 658 | sizeof(struct spufs_inode_info), 0, |
@@ -625,6 +670,12 @@ static int __init spufs_init(void) | |||
625 | ret = register_spu_syscalls(&spufs_calls); | 670 | ret = register_spu_syscalls(&spufs_calls); |
626 | if (ret) | 671 | if (ret) |
627 | goto out_fs; | 672 | goto out_fs; |
673 | ret = register_arch_coredump_calls(&spufs_coredump_calls); | ||
674 | if (ret) | ||
675 | goto out_fs; | ||
676 | |||
677 | spufs_init_isolated_loader(); | ||
678 | |||
628 | return 0; | 679 | return 0; |
629 | out_fs: | 680 | out_fs: |
630 | unregister_filesystem(&spufs_type); | 681 | unregister_filesystem(&spufs_type); |
@@ -638,6 +689,7 @@ module_init(spufs_init); | |||
638 | static void __exit spufs_exit(void) | 689 | static void __exit spufs_exit(void) |
639 | { | 690 | { |
640 | spu_sched_exit(); | 691 | spu_sched_exit(); |
692 | unregister_arch_coredump_calls(&spufs_coredump_calls); | ||
641 | unregister_spu_syscalls(&spufs_calls); | 693 | unregister_spu_syscalls(&spufs_calls); |
642 | unregister_filesystem(&spufs_type); | 694 | unregister_filesystem(&spufs_type); |
643 | kmem_cache_destroy(spufs_inode_cache); | 695 | kmem_cache_destroy(spufs_inode_cache); |