aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2006-10-04 11:26:11 -0400
committerPaul Mackerras <paulus@samba.org>2006-10-04 19:21:00 -0400
commit27d5bf2a35c0762f1358e9ef39776733cd942121 (patch)
tree059292c3cee05c27a0fbf57333b6a7e634bc68cf
parent3bdc9d0b408e01c4e556daba0035ba37f603e920 (diff)
[POWERPC] spufs: cell spu problem state mapping updates
This patch adds a new "psmap" file to spufs that allows mmap of all of the problem state mapping of SPEs. It is compatible with 64k pages. In addition, it removes mmap ability of individual files when using 64k pages, with the exception of signal1 and signal2 which will both map the entire 64k page holding both registers. It also removes CONFIG_SPUFS_MMAP as there is no point in not building mmap support in spufs. It goes along a separate patch to libspe implementing usage of that new file to access problem state registers. Another patch will follow up to fix races opened up by accessing the 'runcntl' register directly, which is made possible with this patch. Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> Signed-off-by: Arnd Bergmann <arnd.bergmann@de.ibm.com> Signed-off-by: Paul Mackerras <paulus@samba.org>
-rw-r--r--arch/powerpc/platforms/cell/Kconfig5
-rw-r--r--arch/powerpc/platforms/cell/spufs/file.c130
2 files changed, 84 insertions, 51 deletions
diff --git a/arch/powerpc/platforms/cell/Kconfig b/arch/powerpc/platforms/cell/Kconfig
index 0c8c7b6ab897..3e430b489bb7 100644
--- a/arch/powerpc/platforms/cell/Kconfig
+++ b/arch/powerpc/platforms/cell/Kconfig
@@ -16,11 +16,6 @@ config SPU_BASE
16 bool 16 bool
17 default n 17 default n
18 18
19config SPUFS_MMAP
20 bool
21 depends on SPU_FS && SPARSEMEM
22 default y
23
24config CBE_RAS 19config CBE_RAS
25 bool "RAS features for bare metal Cell BE" 20 bool "RAS features for bare metal Cell BE"
26 default y 21 default y
diff --git a/arch/powerpc/platforms/cell/spufs/file.c b/arch/powerpc/platforms/cell/spufs/file.c
index 51fd197ab5dd..64f8b0a9b9e1 100644
--- a/arch/powerpc/platforms/cell/spufs/file.c
+++ b/arch/powerpc/platforms/cell/spufs/file.c
@@ -36,6 +36,8 @@
36 36
37#include "spufs.h" 37#include "spufs.h"
38 38
39#define SPUFS_MMAP_4K (PAGE_SIZE == 0x1000)
40
39 41
40static int 42static int
41spufs_mem_open(struct inode *inode, struct file *file) 43spufs_mem_open(struct inode *inode, struct file *file)
@@ -88,7 +90,6 @@ spufs_mem_write(struct file *file, const char __user *buffer,
88 return ret; 90 return ret;
89} 91}
90 92
91#ifdef CONFIG_SPUFS_MMAP
92static struct page * 93static struct page *
93spufs_mem_mmap_nopage(struct vm_area_struct *vma, 94spufs_mem_mmap_nopage(struct vm_area_struct *vma,
94 unsigned long address, int *type) 95 unsigned long address, int *type)
@@ -133,22 +134,19 @@ spufs_mem_mmap(struct file *file, struct vm_area_struct *vma)
133 vma->vm_ops = &spufs_mem_mmap_vmops; 134 vma->vm_ops = &spufs_mem_mmap_vmops;
134 return 0; 135 return 0;
135} 136}
136#endif
137 137
138static struct file_operations spufs_mem_fops = { 138static struct file_operations spufs_mem_fops = {
139 .open = spufs_mem_open, 139 .open = spufs_mem_open,
140 .read = spufs_mem_read, 140 .read = spufs_mem_read,
141 .write = spufs_mem_write, 141 .write = spufs_mem_write,
142 .llseek = generic_file_llseek, 142 .llseek = generic_file_llseek,
143#ifdef CONFIG_SPUFS_MMAP
144 .mmap = spufs_mem_mmap, 143 .mmap = spufs_mem_mmap,
145#endif
146}; 144};
147 145
148#ifdef CONFIG_SPUFS_MMAP
149static struct page *spufs_ps_nopage(struct vm_area_struct *vma, 146static struct page *spufs_ps_nopage(struct vm_area_struct *vma,
150 unsigned long address, 147 unsigned long address,
151 int *type, unsigned long ps_offs) 148 int *type, unsigned long ps_offs,
149 unsigned long ps_size)
152{ 150{
153 struct page *page = NOPAGE_SIGBUS; 151 struct page *page = NOPAGE_SIGBUS;
154 int fault_type = VM_FAULT_SIGBUS; 152 int fault_type = VM_FAULT_SIGBUS;
@@ -158,7 +156,7 @@ static struct page *spufs_ps_nopage(struct vm_area_struct *vma,
158 int ret; 156 int ret;
159 157
160 offset += vma->vm_pgoff << PAGE_SHIFT; 158 offset += vma->vm_pgoff << PAGE_SHIFT;
161 if (offset >= 0x4000) 159 if (offset >= ps_size)
162 goto out; 160 goto out;
163 161
164 ret = spu_acquire_runnable(ctx); 162 ret = spu_acquire_runnable(ctx);
@@ -179,10 +177,11 @@ static struct page *spufs_ps_nopage(struct vm_area_struct *vma,
179 return page; 177 return page;
180} 178}
181 179
180#if SPUFS_MMAP_4K
182static struct page *spufs_cntl_mmap_nopage(struct vm_area_struct *vma, 181static struct page *spufs_cntl_mmap_nopage(struct vm_area_struct *vma,
183 unsigned long address, int *type) 182 unsigned long address, int *type)
184{ 183{
185 return spufs_ps_nopage(vma, address, type, 0x4000); 184 return spufs_ps_nopage(vma, address, type, 0x4000, 0x1000);
186} 185}
187 186
188static struct vm_operations_struct spufs_cntl_mmap_vmops = { 187static struct vm_operations_struct spufs_cntl_mmap_vmops = {
@@ -191,17 +190,12 @@ static struct vm_operations_struct spufs_cntl_mmap_vmops = {
191 190
192/* 191/*
193 * mmap support for problem state control area [0x4000 - 0x4fff]. 192 * mmap support for problem state control area [0x4000 - 0x4fff].
194 * Mapping this area requires that the application have CAP_SYS_RAWIO,
195 * as these registers require special care when read/writing.
196 */ 193 */
197static int spufs_cntl_mmap(struct file *file, struct vm_area_struct *vma) 194static int spufs_cntl_mmap(struct file *file, struct vm_area_struct *vma)
198{ 195{
199 if (!(vma->vm_flags & VM_SHARED)) 196 if (!(vma->vm_flags & VM_SHARED))
200 return -EINVAL; 197 return -EINVAL;
201 198
202 if (!capable(CAP_SYS_RAWIO))
203 return -EPERM;
204
205 vma->vm_flags |= VM_RESERVED; 199 vma->vm_flags |= VM_RESERVED;
206 vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot) 200 vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot)
207 | _PAGE_NO_CACHE | _PAGE_GUARDED); 201 | _PAGE_NO_CACHE | _PAGE_GUARDED);
@@ -209,7 +203,9 @@ static int spufs_cntl_mmap(struct file *file, struct vm_area_struct *vma)
209 vma->vm_ops = &spufs_cntl_mmap_vmops; 203 vma->vm_ops = &spufs_cntl_mmap_vmops;
210 return 0; 204 return 0;
211} 205}
212#endif 206#else /* SPUFS_MMAP_4K */
207#define spufs_cntl_mmap NULL
208#endif /* !SPUFS_MMAP_4K */
213 209
214static int spufs_cntl_open(struct inode *inode, struct file *file) 210static int spufs_cntl_open(struct inode *inode, struct file *file)
215{ 211{
@@ -242,9 +238,7 @@ static struct file_operations spufs_cntl_fops = {
242 .open = spufs_cntl_open, 238 .open = spufs_cntl_open,
243 .read = spufs_cntl_read, 239 .read = spufs_cntl_read,
244 .write = spufs_cntl_write, 240 .write = spufs_cntl_write,
245#ifdef CONFIG_SPUFS_MMAP
246 .mmap = spufs_cntl_mmap, 241 .mmap = spufs_cntl_mmap,
247#endif
248}; 242};
249 243
250static int 244static int
@@ -657,11 +651,19 @@ static ssize_t spufs_signal1_write(struct file *file, const char __user *buf,
657 return 4; 651 return 4;
658} 652}
659 653
660#ifdef CONFIG_SPUFS_MMAP
661static struct page *spufs_signal1_mmap_nopage(struct vm_area_struct *vma, 654static struct page *spufs_signal1_mmap_nopage(struct vm_area_struct *vma,
662 unsigned long address, int *type) 655 unsigned long address, int *type)
663{ 656{
664 return spufs_ps_nopage(vma, address, type, 0x14000); 657#if PAGE_SIZE == 0x1000
658 return spufs_ps_nopage(vma, address, type, 0x14000, 0x1000);
659#elif PAGE_SIZE == 0x10000
660 /* For 64k pages, both signal1 and signal2 can be used to mmap the whole
661 * signal 1 and 2 area
662 */
663 return spufs_ps_nopage(vma, address, type, 0x10000, 0x10000);
664#else
665#error unsupported page size
666#endif
665} 667}
666 668
667static struct vm_operations_struct spufs_signal1_mmap_vmops = { 669static struct vm_operations_struct spufs_signal1_mmap_vmops = {
@@ -680,15 +682,12 @@ static int spufs_signal1_mmap(struct file *file, struct vm_area_struct *vma)
680 vma->vm_ops = &spufs_signal1_mmap_vmops; 682 vma->vm_ops = &spufs_signal1_mmap_vmops;
681 return 0; 683 return 0;
682} 684}
683#endif
684 685
685static struct file_operations spufs_signal1_fops = { 686static struct file_operations spufs_signal1_fops = {
686 .open = spufs_signal1_open, 687 .open = spufs_signal1_open,
687 .read = spufs_signal1_read, 688 .read = spufs_signal1_read,
688 .write = spufs_signal1_write, 689 .write = spufs_signal1_write,
689#ifdef CONFIG_SPUFS_MMAP
690 .mmap = spufs_signal1_mmap, 690 .mmap = spufs_signal1_mmap,
691#endif
692}; 691};
693 692
694static int spufs_signal2_open(struct inode *inode, struct file *file) 693static int spufs_signal2_open(struct inode *inode, struct file *file)
@@ -743,11 +742,20 @@ static ssize_t spufs_signal2_write(struct file *file, const char __user *buf,
743 return 4; 742 return 4;
744} 743}
745 744
746#ifdef CONFIG_SPUFS_MMAP 745#if SPUFS_MMAP_4K
747static struct page *spufs_signal2_mmap_nopage(struct vm_area_struct *vma, 746static struct page *spufs_signal2_mmap_nopage(struct vm_area_struct *vma,
748 unsigned long address, int *type) 747 unsigned long address, int *type)
749{ 748{
750 return spufs_ps_nopage(vma, address, type, 0x1c000); 749#if PAGE_SIZE == 0x1000
750 return spufs_ps_nopage(vma, address, type, 0x1c000, 0x1000);
751#elif PAGE_SIZE == 0x10000
752 /* For 64k pages, both signal1 and signal2 can be used to mmap the whole
753 * signal 1 and 2 area
754 */
755 return spufs_ps_nopage(vma, address, type, 0x10000, 0x10000);
756#else
757#error unsupported page size
758#endif
751} 759}
752 760
753static struct vm_operations_struct spufs_signal2_mmap_vmops = { 761static struct vm_operations_struct spufs_signal2_mmap_vmops = {
@@ -767,15 +775,15 @@ static int spufs_signal2_mmap(struct file *file, struct vm_area_struct *vma)
767 vma->vm_ops = &spufs_signal2_mmap_vmops; 775 vma->vm_ops = &spufs_signal2_mmap_vmops;
768 return 0; 776 return 0;
769} 777}
770#endif 778#else /* SPUFS_MMAP_4K */
779#define spufs_signal2_mmap NULL
780#endif /* !SPUFS_MMAP_4K */
771 781
772static struct file_operations spufs_signal2_fops = { 782static struct file_operations spufs_signal2_fops = {
773 .open = spufs_signal2_open, 783 .open = spufs_signal2_open,
774 .read = spufs_signal2_read, 784 .read = spufs_signal2_read,
775 .write = spufs_signal2_write, 785 .write = spufs_signal2_write,
776#ifdef CONFIG_SPUFS_MMAP
777 .mmap = spufs_signal2_mmap, 786 .mmap = spufs_signal2_mmap,
778#endif
779}; 787};
780 788
781static void spufs_signal1_type_set(void *data, u64 val) 789static void spufs_signal1_type_set(void *data, u64 val)
@@ -824,11 +832,11 @@ static u64 spufs_signal2_type_get(void *data)
824DEFINE_SIMPLE_ATTRIBUTE(spufs_signal2_type, spufs_signal2_type_get, 832DEFINE_SIMPLE_ATTRIBUTE(spufs_signal2_type, spufs_signal2_type_get,
825 spufs_signal2_type_set, "%llu"); 833 spufs_signal2_type_set, "%llu");
826 834
827#ifdef CONFIG_SPUFS_MMAP 835#if SPUFS_MMAP_4K
828static struct page *spufs_mss_mmap_nopage(struct vm_area_struct *vma, 836static struct page *spufs_mss_mmap_nopage(struct vm_area_struct *vma,
829 unsigned long address, int *type) 837 unsigned long address, int *type)
830{ 838{
831 return spufs_ps_nopage(vma, address, type, 0x0000); 839 return spufs_ps_nopage(vma, address, type, 0x0000, 0x1000);
832} 840}
833 841
834static struct vm_operations_struct spufs_mss_mmap_vmops = { 842static struct vm_operations_struct spufs_mss_mmap_vmops = {
@@ -837,17 +845,12 @@ static struct vm_operations_struct spufs_mss_mmap_vmops = {
837 845
838/* 846/*
839 * mmap support for problem state MFC DMA area [0x0000 - 0x0fff]. 847 * mmap support for problem state MFC DMA area [0x0000 - 0x0fff].
840 * Mapping this area requires that the application have CAP_SYS_RAWIO,
841 * as these registers require special care when read/writing.
842 */ 848 */
843static int spufs_mss_mmap(struct file *file, struct vm_area_struct *vma) 849static int spufs_mss_mmap(struct file *file, struct vm_area_struct *vma)
844{ 850{
845 if (!(vma->vm_flags & VM_SHARED)) 851 if (!(vma->vm_flags & VM_SHARED))
846 return -EINVAL; 852 return -EINVAL;
847 853
848 if (!capable(CAP_SYS_RAWIO))
849 return -EPERM;
850
851 vma->vm_flags |= VM_RESERVED; 854 vma->vm_flags |= VM_RESERVED;
852 vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot) 855 vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot)
853 | _PAGE_NO_CACHE | _PAGE_GUARDED); 856 | _PAGE_NO_CACHE | _PAGE_GUARDED);
@@ -855,7 +858,9 @@ static int spufs_mss_mmap(struct file *file, struct vm_area_struct *vma)
855 vma->vm_ops = &spufs_mss_mmap_vmops; 858 vma->vm_ops = &spufs_mss_mmap_vmops;
856 return 0; 859 return 0;
857} 860}
858#endif 861#else /* SPUFS_MMAP_4K */
862#define spufs_mss_mmap NULL
863#endif /* !SPUFS_MMAP_4K */
859 864
860static int spufs_mss_open(struct inode *inode, struct file *file) 865static int spufs_mss_open(struct inode *inode, struct file *file)
861{ 866{
@@ -867,17 +872,54 @@ static int spufs_mss_open(struct inode *inode, struct file *file)
867 872
868static struct file_operations spufs_mss_fops = { 873static struct file_operations spufs_mss_fops = {
869 .open = spufs_mss_open, 874 .open = spufs_mss_open,
870#ifdef CONFIG_SPUFS_MMAP
871 .mmap = spufs_mss_mmap, 875 .mmap = spufs_mss_mmap,
872#endif 876};
877
878static struct page *spufs_psmap_mmap_nopage(struct vm_area_struct *vma,
879 unsigned long address, int *type)
880{
881 return spufs_ps_nopage(vma, address, type, 0x0000, 0x20000);
882}
883
884static struct vm_operations_struct spufs_psmap_mmap_vmops = {
885 .nopage = spufs_psmap_mmap_nopage,
886};
887
888/*
889 * mmap support for full problem state area [0x00000 - 0x1ffff].
890 */
891static int spufs_psmap_mmap(struct file *file, struct vm_area_struct *vma)
892{
893 if (!(vma->vm_flags & VM_SHARED))
894 return -EINVAL;
895
896 vma->vm_flags |= VM_RESERVED;
897 vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot)
898 | _PAGE_NO_CACHE | _PAGE_GUARDED);
899
900 vma->vm_ops = &spufs_psmap_mmap_vmops;
901 return 0;
902}
903
904static int spufs_psmap_open(struct inode *inode, struct file *file)
905{
906 struct spufs_inode_info *i = SPUFS_I(inode);
907
908 file->private_data = i->i_ctx;
909 return nonseekable_open(inode, file);
910}
911
912static struct file_operations spufs_psmap_fops = {
913 .open = spufs_psmap_open,
914 .mmap = spufs_psmap_mmap,
873}; 915};
874 916
875 917
876#ifdef CONFIG_SPUFS_MMAP 918#if SPUFS_MMAP_4K
877static struct page *spufs_mfc_mmap_nopage(struct vm_area_struct *vma, 919static struct page *spufs_mfc_mmap_nopage(struct vm_area_struct *vma,
878 unsigned long address, int *type) 920 unsigned long address, int *type)
879{ 921{
880 return spufs_ps_nopage(vma, address, type, 0x3000); 922 return spufs_ps_nopage(vma, address, type, 0x3000, 0x1000);
881} 923}
882 924
883static struct vm_operations_struct spufs_mfc_mmap_vmops = { 925static struct vm_operations_struct spufs_mfc_mmap_vmops = {
@@ -886,17 +928,12 @@ static struct vm_operations_struct spufs_mfc_mmap_vmops = {
886 928
887/* 929/*
888 * mmap support for problem state MFC DMA area [0x0000 - 0x0fff]. 930 * mmap support for problem state MFC DMA area [0x0000 - 0x0fff].
889 * Mapping this area requires that the application have CAP_SYS_RAWIO,
890 * as these registers require special care when read/writing.
891 */ 931 */
892static int spufs_mfc_mmap(struct file *file, struct vm_area_struct *vma) 932static int spufs_mfc_mmap(struct file *file, struct vm_area_struct *vma)
893{ 933{
894 if (!(vma->vm_flags & VM_SHARED)) 934 if (!(vma->vm_flags & VM_SHARED))
895 return -EINVAL; 935 return -EINVAL;
896 936
897 if (!capable(CAP_SYS_RAWIO))
898 return -EPERM;
899
900 vma->vm_flags |= VM_RESERVED; 937 vma->vm_flags |= VM_RESERVED;
901 vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot) 938 vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot)
902 | _PAGE_NO_CACHE | _PAGE_GUARDED); 939 | _PAGE_NO_CACHE | _PAGE_GUARDED);
@@ -904,7 +941,9 @@ static int spufs_mfc_mmap(struct file *file, struct vm_area_struct *vma)
904 vma->vm_ops = &spufs_mfc_mmap_vmops; 941 vma->vm_ops = &spufs_mfc_mmap_vmops;
905 return 0; 942 return 0;
906} 943}
907#endif 944#else /* SPUFS_MMAP_4K */
945#define spufs_mfc_mmap NULL
946#endif /* !SPUFS_MMAP_4K */
908 947
909static int spufs_mfc_open(struct inode *inode, struct file *file) 948static int spufs_mfc_open(struct inode *inode, struct file *file)
910{ 949{
@@ -1194,9 +1233,7 @@ static struct file_operations spufs_mfc_fops = {
1194 .flush = spufs_mfc_flush, 1233 .flush = spufs_mfc_flush,
1195 .fsync = spufs_mfc_fsync, 1234 .fsync = spufs_mfc_fsync,
1196 .fasync = spufs_mfc_fasync, 1235 .fasync = spufs_mfc_fasync,
1197#ifdef CONFIG_SPUFS_MMAP
1198 .mmap = spufs_mfc_mmap, 1236 .mmap = spufs_mfc_mmap,
1199#endif
1200}; 1237};
1201 1238
1202static void spufs_npc_set(void *data, u64 val) 1239static void spufs_npc_set(void *data, u64 val)
@@ -1368,5 +1405,6 @@ struct tree_descr spufs_dir_contents[] = {
1368 { "event_mask", &spufs_event_mask_ops, 0666, }, 1405 { "event_mask", &spufs_event_mask_ops, 0666, },
1369 { "srr0", &spufs_srr0_ops, 0666, }, 1406 { "srr0", &spufs_srr0_ops, 0666, },
1370 { "phys-id", &spufs_id_ops, 0666, }, 1407 { "phys-id", &spufs_id_ops, 0666, },
1408 { "psmap", &spufs_psmap_fops, 0666, },
1371 {}, 1409 {},
1372}; 1410};