aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/platforms/cell/spufs
diff options
context:
space:
mode:
authorDwayne Grant McConnell <decimal@us.ibm.com>2006-11-22 18:46:37 -0500
committerPaul Mackerras <paulus@samba.org>2006-12-04 04:40:19 -0500
commitbf1ab978be2318c5a564de9aa0f1a217b44170d4 (patch)
tree518a971f12a65c8a3ee54d75b6a8c33b68f54664 /arch/powerpc/platforms/cell/spufs
parent9309180f11f0107c9858a61a1ac2b04518a91080 (diff)
[POWERPC] coredump: Add SPU elf notes to coredump.
This patch adds SPU elf notes to the coredump. It creates a separate note for each of /regs, /fpcr, /lslr, /decr, /decr_status, /mem, /signal1, /signal1_type, /signal2, /signal2_type, /event_mask, /event_status, /mbox_info, /ibox_info, /wbox_info, /dma_info, /proxydma_info, /object-id. A new macro, ARCH_HAVE_EXTRA_NOTES, was created for architectures to specify they have extra elf core notes. A new macro, ELF_CORE_EXTRA_NOTES_SIZE, was created so the size of the additional notes could be calculated and added to the notes phdr entry. A new macro, ELF_CORE_WRITE_EXTRA_NOTES, was created so the new notes would be written after the existing notes. The SPU coredump code resides in spufs. Stub functions are provided in the kernel which are hooked into the spufs code which does the actual work via register_arch_coredump_calls(). A new set of __spufs_<file>_read/get() functions was provided to allow the coredump code to read from the spufs files without having to lock the SPU context for each file read from. Cc: <linux-arch@vger.kernel.org> Signed-off-by: Dwayne Grant McConnell <decimal@us.ibm.com> Signed-off-by: Arnd Bergmann <arnd.bergmann@de.ibm.com>
Diffstat (limited to 'arch/powerpc/platforms/cell/spufs')
-rw-r--r--arch/powerpc/platforms/cell/spufs/Makefile2
-rw-r--r--arch/powerpc/platforms/cell/spufs/coredump.c238
-rw-r--r--arch/powerpc/platforms/cell/spufs/file.c327
-rw-r--r--arch/powerpc/platforms/cell/spufs/inode.c7
-rw-r--r--arch/powerpc/platforms/cell/spufs/spufs.h11
5 files changed, 498 insertions, 87 deletions
diff --git a/arch/powerpc/platforms/cell/spufs/Makefile b/arch/powerpc/platforms/cell/spufs/Makefile
index ecdfbb35f82..472217d19fa 100644
--- a/arch/powerpc/platforms/cell/spufs/Makefile
+++ b/arch/powerpc/platforms/cell/spufs/Makefile
@@ -1,7 +1,7 @@
1obj-y += switch.o 1obj-y += switch.o
2 2
3obj-$(CONFIG_SPU_FS) += spufs.o 3obj-$(CONFIG_SPU_FS) += spufs.o
4spufs-y += inode.o file.o context.o syscalls.o 4spufs-y += inode.o file.o context.o syscalls.o coredump.o
5spufs-y += sched.o backing_ops.o hw_ops.o run.o gang.o 5spufs-y += sched.o backing_ops.o hw_ops.o run.o gang.o
6 6
7# Rules to build switch.o with the help of SPU tool chain 7# Rules to build switch.o with the help of SPU tool chain
diff --git a/arch/powerpc/platforms/cell/spufs/coredump.c b/arch/powerpc/platforms/cell/spufs/coredump.c
new file mode 100644
index 00000000000..26945c491f6
--- /dev/null
+++ b/arch/powerpc/platforms/cell/spufs/coredump.c
@@ -0,0 +1,238 @@
1/*
2 * SPU core dump code
3 *
4 * (C) Copyright 2006 IBM Corp.
5 *
6 * Author: Dwayne Grant McConnell <decimal@us.ibm.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2, or (at your option)
11 * any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 */
22
23#include <linux/elf.h>
24#include <linux/file.h>
25#include <linux/fs.h>
26#include <linux/list.h>
27#include <linux/module.h>
28#include <linux/syscalls.h>
29
30#include <asm/uaccess.h>
31
32#include "spufs.h"
33
34struct spufs_ctx_info {
35 struct list_head list;
36 int dfd;
37 int memsize; /* in bytes */
38 struct spu_context *ctx;
39};
40
41static LIST_HEAD(ctx_info_list);
42
43static ssize_t do_coredump_read(int num, struct spu_context *ctx, void __user *buffer,
44 size_t size, loff_t *off)
45{
46 u64 data;
47 int ret;
48
49 if (spufs_coredump_read[num].read)
50 return spufs_coredump_read[num].read(ctx, buffer, size, off);
51
52 data = spufs_coredump_read[num].get(ctx);
53 ret = copy_to_user(buffer, &data, 8);
54 return ret ? -EFAULT : 8;
55}
56
57/*
58 * These are the only things you should do on a core-file: use only these
59 * functions to write out all the necessary info.
60 */
61static int spufs_dump_write(struct file *file, const void *addr, int nr)
62{
63 return file->f_op->write(file, addr, nr, &file->f_pos) == nr;
64}
65
66static int spufs_dump_seek(struct file *file, loff_t off)
67{
68 if (file->f_op->llseek) {
69 if (file->f_op->llseek(file, off, 0) != off)
70 return 0;
71 } else
72 file->f_pos = off;
73 return 1;
74}
75
76static void spufs_fill_memsize(struct spufs_ctx_info *ctx_info)
77{
78 struct spu_context *ctx;
79 unsigned long long lslr;
80
81 ctx = ctx_info->ctx;
82 lslr = ctx->csa.priv2.spu_lslr_RW;
83 ctx_info->memsize = lslr + 1;
84}
85
86static int spufs_ctx_note_size(struct spufs_ctx_info *ctx_info)
87{
88 int dfd, memsize, i, sz, total = 0;
89 char *name;
90 char fullname[80];
91
92 dfd = ctx_info->dfd;
93 memsize = ctx_info->memsize;
94
95 for (i = 0; spufs_coredump_read[i].name; i++) {
96 name = spufs_coredump_read[i].name;
97 sz = spufs_coredump_read[i].size;
98
99 sprintf(fullname, "SPU/%d/%s", dfd, name);
100
101 total += sizeof(struct elf_note);
102 total += roundup(strlen(fullname) + 1, 4);
103 if (!strcmp(name, "mem"))
104 total += roundup(memsize, 4);
105 else
106 total += roundup(sz, 4);
107 }
108
109 return total;
110}
111
112static int spufs_add_one_context(struct file *file, int dfd)
113{
114 struct spu_context *ctx;
115 struct spufs_ctx_info *ctx_info;
116 int size;
117
118 ctx = SPUFS_I(file->f_dentry->d_inode)->i_ctx;
119 if (ctx->flags & SPU_CREATE_NOSCHED)
120 return 0;
121
122 ctx_info = kzalloc(sizeof(*ctx_info), GFP_KERNEL);
123 if (unlikely(!ctx_info))
124 return -ENOMEM;
125
126 ctx_info->dfd = dfd;
127 ctx_info->ctx = ctx;
128
129 spufs_fill_memsize(ctx_info);
130
131 size = spufs_ctx_note_size(ctx_info);
132 list_add(&ctx_info->list, &ctx_info_list);
133 return size;
134}
135
136/*
137 * The additional architecture-specific notes for Cell are various
138 * context files in the spu context.
139 *
140 * This function iterates over all open file descriptors and sees
141 * if they are a directory in spufs. In that case we use spufs
142 * internal functionality to dump them without needing to actually
143 * open the files.
144 */
145static int spufs_arch_notes_size(void)
146{
147 struct fdtable *fdt = files_fdtable(current->files);
148 int size = 0, fd;
149
150 for (fd = 0; fd < fdt->max_fdset && fd < fdt->max_fds; fd++) {
151 if (FD_ISSET(fd, fdt->open_fds)) {
152 struct file *file = fcheck(fd);
153
154 if (file && file->f_op == &spufs_context_fops) {
155 int rval = spufs_add_one_context(file, fd);
156 if (rval < 0)
157 break;
158 size += rval;
159 }
160 }
161 }
162
163 return size;
164}
165
166static void spufs_arch_write_note(struct spufs_ctx_info *ctx_info, int i,
167 struct file *file)
168{
169 struct spu_context *ctx;
170 loff_t pos = 0;
171 int sz, dfd, rc, total = 0;
172 const int bufsz = 4096;
173 char *name;
174 char fullname[80], *buf;
175 struct elf_note en;
176
177 buf = kmalloc(bufsz, GFP_KERNEL);
178 if (!buf)
179 return;
180
181 dfd = ctx_info->dfd;
182 name = spufs_coredump_read[i].name;
183
184 if (!strcmp(name, "mem"))
185 sz = ctx_info->memsize;
186 else
187 sz = spufs_coredump_read[i].size;
188
189 ctx = ctx_info->ctx;
190 if (!ctx) {
191 return;
192 }
193
194 sprintf(fullname, "SPU/%d/%s", dfd, name);
195 en.n_namesz = strlen(fullname) + 1;
196 en.n_descsz = sz;
197 en.n_type = NT_SPU;
198
199 if (!spufs_dump_write(file, &en, sizeof(en)))
200 return;
201 if (!spufs_dump_write(file, fullname, en.n_namesz))
202 return;
203 if (!spufs_dump_seek(file, roundup((unsigned long)file->f_pos, 4)))
204 return;
205
206 do {
207 rc = do_coredump_read(i, ctx, buf, bufsz, &pos);
208 if (rc > 0) {
209 if (!spufs_dump_write(file, buf, rc))
210 return;
211 total += rc;
212 }
213 } while (rc == bufsz && total < sz);
214
215 spufs_dump_seek(file, roundup((unsigned long)file->f_pos
216 - total + sz, 4));
217}
218
219static void spufs_arch_write_notes(struct file *file)
220{
221 int j;
222 struct spufs_ctx_info *ctx_info, *next;
223
224 list_for_each_entry_safe(ctx_info, next, &ctx_info_list, list) {
225 spu_acquire_saved(ctx_info->ctx);
226 for (j = 0; j < spufs_coredump_num_notes; j++)
227 spufs_arch_write_note(ctx_info, j, file);
228 spu_release(ctx_info->ctx);
229 list_del(&ctx_info->list);
230 kfree(ctx_info);
231 }
232}
233
234struct spu_coredump_calls spufs_coredump_calls = {
235 .arch_notes_size = spufs_arch_notes_size,
236 .arch_write_notes = spufs_arch_write_notes,
237 .owner = THIS_MODULE,
238};
diff --git a/arch/powerpc/platforms/cell/spufs/file.c b/arch/powerpc/platforms/cell/spufs/file.c
index 50e0afc46ad..347eff56fcb 100644
--- a/arch/powerpc/platforms/cell/spufs/file.c
+++ b/arch/powerpc/platforms/cell/spufs/file.c
@@ -39,7 +39,6 @@
39 39
40#define SPUFS_MMAP_4K (PAGE_SIZE == 0x1000) 40#define SPUFS_MMAP_4K (PAGE_SIZE == 0x1000)
41 41
42
43static int 42static int
44spufs_mem_open(struct inode *inode, struct file *file) 43spufs_mem_open(struct inode *inode, struct file *file)
45{ 44{
@@ -52,18 +51,23 @@ spufs_mem_open(struct inode *inode, struct file *file)
52} 51}
53 52
54static ssize_t 53static ssize_t
54__spufs_mem_read(struct spu_context *ctx, char __user *buffer,
55 size_t size, loff_t *pos)
56{
57 char *local_store = ctx->ops->get_ls(ctx);
58 return simple_read_from_buffer(buffer, size, pos, local_store,
59 LS_SIZE);
60}
61
62static ssize_t
55spufs_mem_read(struct file *file, char __user *buffer, 63spufs_mem_read(struct file *file, char __user *buffer,
56 size_t size, loff_t *pos) 64 size_t size, loff_t *pos)
57{ 65{
58 struct spu_context *ctx = file->private_data;
59 char *local_store;
60 int ret; 66 int ret;
67 struct spu_context *ctx = file->private_data;
61 68
62 spu_acquire(ctx); 69 spu_acquire(ctx);
63 70 ret = __spufs_mem_read(ctx, buffer, size, pos);
64 local_store = ctx->ops->get_ls(ctx);
65 ret = simple_read_from_buffer(buffer, size, pos, local_store, LS_SIZE);
66
67 spu_release(ctx); 71 spu_release(ctx);
68 return ret; 72 return ret;
69} 73}
@@ -262,18 +266,23 @@ spufs_regs_open(struct inode *inode, struct file *file)
262} 266}
263 267
264static ssize_t 268static ssize_t
269__spufs_regs_read(struct spu_context *ctx, char __user *buffer,
270 size_t size, loff_t *pos)
271{
272 struct spu_lscsa *lscsa = ctx->csa.lscsa;
273 return simple_read_from_buffer(buffer, size, pos,
274 lscsa->gprs, sizeof lscsa->gprs);
275}
276
277static ssize_t
265spufs_regs_read(struct file *file, char __user *buffer, 278spufs_regs_read(struct file *file, char __user *buffer,
266 size_t size, loff_t *pos) 279 size_t size, loff_t *pos)
267{ 280{
268 struct spu_context *ctx = file->private_data;
269 struct spu_lscsa *lscsa = ctx->csa.lscsa;
270 int ret; 281 int ret;
282 struct spu_context *ctx = file->private_data;
271 283
272 spu_acquire_saved(ctx); 284 spu_acquire_saved(ctx);
273 285 ret = __spufs_regs_read(ctx, buffer, size, pos);
274 ret = simple_read_from_buffer(buffer, size, pos,
275 lscsa->gprs, sizeof lscsa->gprs);
276
277 spu_release(ctx); 286 spu_release(ctx);
278 return ret; 287 return ret;
279} 288}
@@ -308,18 +317,23 @@ static struct file_operations spufs_regs_fops = {
308}; 317};
309 318
310static ssize_t 319static ssize_t
320__spufs_fpcr_read(struct spu_context *ctx, char __user * buffer,
321 size_t size, loff_t * pos)
322{
323 struct spu_lscsa *lscsa = ctx->csa.lscsa;
324 return simple_read_from_buffer(buffer, size, pos,
325 &lscsa->fpcr, sizeof(lscsa->fpcr));
326}
327
328static ssize_t
311spufs_fpcr_read(struct file *file, char __user * buffer, 329spufs_fpcr_read(struct file *file, char __user * buffer,
312 size_t size, loff_t * pos) 330 size_t size, loff_t * pos)
313{ 331{
314 struct spu_context *ctx = file->private_data;
315 struct spu_lscsa *lscsa = ctx->csa.lscsa;
316 int ret; 332 int ret;
333 struct spu_context *ctx = file->private_data;
317 334
318 spu_acquire_saved(ctx); 335 spu_acquire_saved(ctx);
319 336 ret = __spufs_fpcr_read(ctx, buffer, size, pos);
320 ret = simple_read_from_buffer(buffer, size, pos,
321 &lscsa->fpcr, sizeof(lscsa->fpcr));
322
323 spu_release(ctx); 337 spu_release(ctx);
324 return ret; 338 return ret;
325} 339}
@@ -719,22 +733,19 @@ static int spufs_signal1_open(struct inode *inode, struct file *file)
719 return nonseekable_open(inode, file); 733 return nonseekable_open(inode, file);
720} 734}
721 735
722static ssize_t spufs_signal1_read(struct file *file, char __user *buf, 736static ssize_t __spufs_signal1_read(struct spu_context *ctx, char __user *buf,
723 size_t len, loff_t *pos) 737 size_t len, loff_t *pos)
724{ 738{
725 struct spu_context *ctx = file->private_data;
726 int ret = 0; 739 int ret = 0;
727 u32 data; 740 u32 data;
728 741
729 if (len < 4) 742 if (len < 4)
730 return -EINVAL; 743 return -EINVAL;
731 744
732 spu_acquire_saved(ctx);
733 if (ctx->csa.spu_chnlcnt_RW[3]) { 745 if (ctx->csa.spu_chnlcnt_RW[3]) {
734 data = ctx->csa.spu_chnldata_RW[3]; 746 data = ctx->csa.spu_chnldata_RW[3];
735 ret = 4; 747 ret = 4;
736 } 748 }
737 spu_release(ctx);
738 749
739 if (!ret) 750 if (!ret)
740 goto out; 751 goto out;
@@ -746,6 +757,19 @@ out:
746 return ret; 757 return ret;
747} 758}
748 759
760static ssize_t spufs_signal1_read(struct file *file, char __user *buf,
761 size_t len, loff_t *pos)
762{
763 int ret;
764 struct spu_context *ctx = file->private_data;
765
766 spu_acquire_saved(ctx);
767 ret = __spufs_signal1_read(ctx, buf, len, pos);
768 spu_release(ctx);
769
770 return ret;
771}
772
749static ssize_t spufs_signal1_write(struct file *file, const char __user *buf, 773static ssize_t spufs_signal1_write(struct file *file, const char __user *buf,
750 size_t len, loff_t *pos) 774 size_t len, loff_t *pos)
751{ 775{
@@ -816,22 +840,19 @@ static int spufs_signal2_open(struct inode *inode, struct file *file)
816 return nonseekable_open(inode, file); 840 return nonseekable_open(inode, file);
817} 841}
818 842
819static ssize_t spufs_signal2_read(struct file *file, char __user *buf, 843static ssize_t __spufs_signal2_read(struct spu_context *ctx, char __user *buf,
820 size_t len, loff_t *pos) 844 size_t len, loff_t *pos)
821{ 845{
822 struct spu_context *ctx = file->private_data;
823 int ret = 0; 846 int ret = 0;
824 u32 data; 847 u32 data;
825 848
826 if (len < 4) 849 if (len < 4)
827 return -EINVAL; 850 return -EINVAL;
828 851
829 spu_acquire_saved(ctx);
830 if (ctx->csa.spu_chnlcnt_RW[4]) { 852 if (ctx->csa.spu_chnlcnt_RW[4]) {
831 data = ctx->csa.spu_chnldata_RW[4]; 853 data = ctx->csa.spu_chnldata_RW[4];
832 ret = 4; 854 ret = 4;
833 } 855 }
834 spu_release(ctx);
835 856
836 if (!ret) 857 if (!ret)
837 goto out; 858 goto out;
@@ -840,7 +861,20 @@ static ssize_t spufs_signal2_read(struct file *file, char __user *buf,
840 return -EFAULT; 861 return -EFAULT;
841 862
842out: 863out:
843 return 4; 864 return ret;
865}
866
867static ssize_t spufs_signal2_read(struct file *file, char __user *buf,
868 size_t len, loff_t *pos)
869{
870 struct spu_context *ctx = file->private_data;
871 int ret;
872
873 spu_acquire_saved(ctx);
874 ret = __spufs_signal2_read(ctx, buf, len, pos);
875 spu_release(ctx);
876
877 return ret;
844} 878}
845 879
846static ssize_t spufs_signal2_write(struct file *file, const char __user *buf, 880static ssize_t spufs_signal2_write(struct file *file, const char __user *buf,
@@ -916,13 +950,19 @@ static void spufs_signal1_type_set(void *data, u64 val)
916 spu_release(ctx); 950 spu_release(ctx);
917} 951}
918 952
953static u64 __spufs_signal1_type_get(void *data)
954{
955 struct spu_context *ctx = data;
956 return ctx->ops->signal1_type_get(ctx);
957}
958
919static u64 spufs_signal1_type_get(void *data) 959static u64 spufs_signal1_type_get(void *data)
920{ 960{
921 struct spu_context *ctx = data; 961 struct spu_context *ctx = data;
922 u64 ret; 962 u64 ret;
923 963
924 spu_acquire(ctx); 964 spu_acquire(ctx);
925 ret = ctx->ops->signal1_type_get(ctx); 965 ret = __spufs_signal1_type_get(data);
926 spu_release(ctx); 966 spu_release(ctx);
927 967
928 return ret; 968 return ret;
@@ -939,13 +979,19 @@ static void spufs_signal2_type_set(void *data, u64 val)
939 spu_release(ctx); 979 spu_release(ctx);
940} 980}
941 981
982static u64 __spufs_signal2_type_get(void *data)
983{
984 struct spu_context *ctx = data;
985 return ctx->ops->signal2_type_get(ctx);
986}
987
942static u64 spufs_signal2_type_get(void *data) 988static u64 spufs_signal2_type_get(void *data)
943{ 989{
944 struct spu_context *ctx = data; 990 struct spu_context *ctx = data;
945 u64 ret; 991 u64 ret;
946 992
947 spu_acquire(ctx); 993 spu_acquire(ctx);
948 ret = ctx->ops->signal2_type_get(ctx); 994 ret = __spufs_signal2_type_get(data);
949 spu_release(ctx); 995 spu_release(ctx);
950 996
951 return ret; 997 return ret;
@@ -1387,13 +1433,19 @@ static void spufs_decr_set(void *data, u64 val)
1387 spu_release(ctx); 1433 spu_release(ctx);
1388} 1434}
1389 1435
1390static u64 spufs_decr_get(void *data) 1436static u64 __spufs_decr_get(void *data)
1391{ 1437{
1392 struct spu_context *ctx = data; 1438 struct spu_context *ctx = data;
1393 struct spu_lscsa *lscsa = ctx->csa.lscsa; 1439 struct spu_lscsa *lscsa = ctx->csa.lscsa;
1440 return lscsa->decr.slot[0];
1441}
1442
1443static u64 spufs_decr_get(void *data)
1444{
1445 struct spu_context *ctx = data;
1394 u64 ret; 1446 u64 ret;
1395 spu_acquire_saved(ctx); 1447 spu_acquire_saved(ctx);
1396 ret = lscsa->decr.slot[0]; 1448 ret = __spufs_decr_get(data);
1397 spu_release(ctx); 1449 spu_release(ctx);
1398 return ret; 1450 return ret;
1399} 1451}
@@ -1409,13 +1461,19 @@ static void spufs_decr_status_set(void *data, u64 val)
1409 spu_release(ctx); 1461 spu_release(ctx);
1410} 1462}
1411 1463
1412static u64 spufs_decr_status_get(void *data) 1464static u64 __spufs_decr_status_get(void *data)
1413{ 1465{
1414 struct spu_context *ctx = data; 1466 struct spu_context *ctx = data;
1415 struct spu_lscsa *lscsa = ctx->csa.lscsa; 1467 struct spu_lscsa *lscsa = ctx->csa.lscsa;
1468 return lscsa->decr_status.slot[0];
1469}
1470
1471static u64 spufs_decr_status_get(void *data)
1472{
1473 struct spu_context *ctx = data;
1416 u64 ret; 1474 u64 ret;
1417 spu_acquire_saved(ctx); 1475 spu_acquire_saved(ctx);
1418 ret = lscsa->decr_status.slot[0]; 1476 ret = __spufs_decr_status_get(data);
1419 spu_release(ctx); 1477 spu_release(ctx);
1420 return ret; 1478 return ret;
1421} 1479}
@@ -1431,30 +1489,43 @@ static void spufs_event_mask_set(void *data, u64 val)
1431 spu_release(ctx); 1489 spu_release(ctx);
1432} 1490}
1433 1491
1434static u64 spufs_event_mask_get(void *data) 1492static u64 __spufs_event_mask_get(void *data)
1435{ 1493{
1436 struct spu_context *ctx = data; 1494 struct spu_context *ctx = data;
1437 struct spu_lscsa *lscsa = ctx->csa.lscsa; 1495 struct spu_lscsa *lscsa = ctx->csa.lscsa;
1496 return lscsa->event_mask.slot[0];
1497}
1498
1499static u64 spufs_event_mask_get(void *data)
1500{
1501 struct spu_context *ctx = data;
1438 u64 ret; 1502 u64 ret;
1439 spu_acquire_saved(ctx); 1503 spu_acquire_saved(ctx);
1440 ret = lscsa->event_mask.slot[0]; 1504 ret = __spufs_event_mask_get(data);
1441 spu_release(ctx); 1505 spu_release(ctx);
1442 return ret; 1506 return ret;
1443} 1507}
1444DEFINE_SIMPLE_ATTRIBUTE(spufs_event_mask_ops, spufs_event_mask_get, 1508DEFINE_SIMPLE_ATTRIBUTE(spufs_event_mask_ops, spufs_event_mask_get,
1445 spufs_event_mask_set, "0x%llx\n") 1509 spufs_event_mask_set, "0x%llx\n")
1446 1510
1447static u64 spufs_event_status_get(void *data) 1511static u64 __spufs_event_status_get(void *data)
1448{ 1512{
1449 struct spu_context *ctx = data; 1513 struct spu_context *ctx = data;
1450 struct spu_state *state = &ctx->csa; 1514 struct spu_state *state = &ctx->csa;
1451 u64 ret = 0;
1452 u64 stat; 1515 u64 stat;
1453
1454 spu_acquire_saved(ctx);
1455 stat = state->spu_chnlcnt_RW[0]; 1516 stat = state->spu_chnlcnt_RW[0];
1456 if (stat) 1517 if (stat)
1457 ret = state->spu_chnldata_RW[0]; 1518 return state->spu_chnldata_RW[0];
1519 return 0;
1520}
1521
1522static u64 spufs_event_status_get(void *data)
1523{
1524 struct spu_context *ctx = data;
1525 u64 ret = 0;
1526
1527 spu_acquire_saved(ctx);
1528 ret = __spufs_event_status_get(data);
1458 spu_release(ctx); 1529 spu_release(ctx);
1459 return ret; 1530 return ret;
1460} 1531}
@@ -1499,12 +1570,18 @@ static u64 spufs_id_get(void *data)
1499} 1570}
1500DEFINE_SIMPLE_ATTRIBUTE(spufs_id_ops, spufs_id_get, NULL, "0x%llx\n") 1571DEFINE_SIMPLE_ATTRIBUTE(spufs_id_ops, spufs_id_get, NULL, "0x%llx\n")
1501 1572
1502static u64 spufs_object_id_get(void *data) 1573static u64 __spufs_object_id_get(void *data)
1503{ 1574{
1504 struct spu_context *ctx = data; 1575 struct spu_context *ctx = data;
1505 return ctx->object_id; 1576 return ctx->object_id;
1506} 1577}
1507 1578
1579static u64 spufs_object_id_get(void *data)
1580{
1581 /* FIXME: Should there really be no locking here? */
1582 return __spufs_object_id_get(data);
1583}
1584
1508static void spufs_object_id_set(void *data, u64 id) 1585static void spufs_object_id_set(void *data, u64 id)
1509{ 1586{
1510 struct spu_context *ctx = data; 1587 struct spu_context *ctx = data;
@@ -1514,13 +1591,19 @@ static void spufs_object_id_set(void *data, u64 id)
1514DEFINE_SIMPLE_ATTRIBUTE(spufs_object_id_ops, spufs_object_id_get, 1591DEFINE_SIMPLE_ATTRIBUTE(spufs_object_id_ops, spufs_object_id_get,
1515 spufs_object_id_set, "0x%llx\n"); 1592 spufs_object_id_set, "0x%llx\n");
1516 1593
1594static u64 __spufs_lslr_get(void *data)
1595{
1596 struct spu_context *ctx = data;
1597 return ctx->csa.priv2.spu_lslr_RW;
1598}
1599
1517static u64 spufs_lslr_get(void *data) 1600static u64 spufs_lslr_get(void *data)
1518{ 1601{
1519 struct spu_context *ctx = data; 1602 struct spu_context *ctx = data;
1520 u64 ret; 1603 u64 ret;
1521 1604
1522 spu_acquire_saved(ctx); 1605 spu_acquire_saved(ctx);
1523 ret = ctx->csa.priv2.spu_lslr_RW; 1606 ret = __spufs_lslr_get(data);
1524 spu_release(ctx); 1607 spu_release(ctx);
1525 1608
1526 return ret; 1609 return ret;
@@ -1535,26 +1618,36 @@ static int spufs_info_open(struct inode *inode, struct file *file)
1535 return 0; 1618 return 0;
1536} 1619}
1537 1620
1621static ssize_t __spufs_mbox_info_read(struct spu_context *ctx,
1622 char __user *buf, size_t len, loff_t *pos)
1623{
1624 u32 mbox_stat;
1625 u32 data;
1626
1627 mbox_stat = ctx->csa.prob.mb_stat_R;
1628 if (mbox_stat & 0x0000ff) {
1629 data = ctx->csa.prob.pu_mb_R;
1630 }
1631
1632 return simple_read_from_buffer(buf, len, pos, &data, sizeof data);
1633}
1634
1538static ssize_t spufs_mbox_info_read(struct file *file, char __user *buf, 1635static ssize_t spufs_mbox_info_read(struct file *file, char __user *buf,
1539 size_t len, loff_t *pos) 1636 size_t len, loff_t *pos)
1540{ 1637{
1638 int ret;
1541 struct spu_context *ctx = file->private_data; 1639 struct spu_context *ctx = file->private_data;
1542 u32 mbox_stat;
1543 u32 data;
1544 1640
1545 if (!access_ok(VERIFY_WRITE, buf, len)) 1641 if (!access_ok(VERIFY_WRITE, buf, len))
1546 return -EFAULT; 1642 return -EFAULT;
1547 1643
1548 spu_acquire_saved(ctx); 1644 spu_acquire_saved(ctx);
1549 spin_lock(&ctx->csa.register_lock); 1645 spin_lock(&ctx->csa.register_lock);
1550 mbox_stat = ctx->csa.prob.mb_stat_R; 1646 ret = __spufs_mbox_info_read(ctx, buf, len, pos);
1551 if (mbox_stat & 0x0000ff) {
1552 data = ctx->csa.prob.pu_mb_R;
1553 }
1554 spin_unlock(&ctx->csa.register_lock); 1647 spin_unlock(&ctx->csa.register_lock);
1555 spu_release(ctx); 1648 spu_release(ctx);
1556 1649
1557 return simple_read_from_buffer(buf, len, pos, &data, sizeof data); 1650 return ret;
1558} 1651}
1559 1652
1560static struct file_operations spufs_mbox_info_fops = { 1653static struct file_operations spufs_mbox_info_fops = {
@@ -1563,26 +1656,36 @@ static struct file_operations spufs_mbox_info_fops = {
1563 .llseek = generic_file_llseek, 1656 .llseek = generic_file_llseek,
1564}; 1657};
1565 1658
1659static ssize_t __spufs_ibox_info_read(struct spu_context *ctx,
1660 char __user *buf, size_t len, loff_t *pos)
1661{
1662 u32 ibox_stat;
1663 u32 data;
1664
1665 ibox_stat = ctx->csa.prob.mb_stat_R;
1666 if (ibox_stat & 0xff0000) {
1667 data = ctx->csa.priv2.puint_mb_R;
1668 }
1669
1670 return simple_read_from_buffer(buf, len, pos, &data, sizeof data);
1671}
1672
1566static ssize_t spufs_ibox_info_read(struct file *file, char __user *buf, 1673static ssize_t spufs_ibox_info_read(struct file *file, char __user *buf,
1567 size_t len, loff_t *pos) 1674 size_t len, loff_t *pos)
1568{ 1675{
1569 struct spu_context *ctx = file->private_data; 1676 struct spu_context *ctx = file->private_data;
1570 u32 ibox_stat; 1677 int ret;
1571 u32 data;
1572 1678
1573 if (!access_ok(VERIFY_WRITE, buf, len)) 1679 if (!access_ok(VERIFY_WRITE, buf, len))
1574 return -EFAULT; 1680 return -EFAULT;
1575 1681
1576 spu_acquire_saved(ctx); 1682 spu_acquire_saved(ctx);
1577 spin_lock(&ctx->csa.register_lock); 1683 spin_lock(&ctx->csa.register_lock);
1578 ibox_stat = ctx->csa.prob.mb_stat_R; 1684 ret = __spufs_ibox_info_read(ctx, buf, len, pos);
1579 if (ibox_stat & 0xff0000) {
1580 data = ctx->csa.priv2.puint_mb_R;
1581 }
1582 spin_unlock(&ctx->csa.register_lock); 1685 spin_unlock(&ctx->csa.register_lock);
1583 spu_release(ctx); 1686 spu_release(ctx);
1584 1687
1585 return simple_read_from_buffer(buf, len, pos, &data, sizeof data); 1688 return ret;
1586} 1689}
1587 1690
1588static struct file_operations spufs_ibox_info_fops = { 1691static struct file_operations spufs_ibox_info_fops = {
@@ -1591,29 +1694,39 @@ static struct file_operations spufs_ibox_info_fops = {
1591 .llseek = generic_file_llseek, 1694 .llseek = generic_file_llseek,
1592}; 1695};
1593 1696
1594static ssize_t spufs_wbox_info_read(struct file *file, char __user *buf, 1697static ssize_t __spufs_wbox_info_read(struct spu_context *ctx,
1595 size_t len, loff_t *pos) 1698 char __user *buf, size_t len, loff_t *pos)
1596{ 1699{
1597 struct spu_context *ctx = file->private_data;
1598 int i, cnt; 1700 int i, cnt;
1599 u32 data[4]; 1701 u32 data[4];
1600 u32 wbox_stat; 1702 u32 wbox_stat;
1601 1703
1704 wbox_stat = ctx->csa.prob.mb_stat_R;
1705 cnt = 4 - ((wbox_stat & 0x00ff00) >> 8);
1706 for (i = 0; i < cnt; i++) {
1707 data[i] = ctx->csa.spu_mailbox_data[i];
1708 }
1709
1710 return simple_read_from_buffer(buf, len, pos, &data,
1711 cnt * sizeof(u32));
1712}
1713
1714static ssize_t spufs_wbox_info_read(struct file *file, char __user *buf,
1715 size_t len, loff_t *pos)
1716{
1717 struct spu_context *ctx = file->private_data;
1718 int ret;
1719
1602 if (!access_ok(VERIFY_WRITE, buf, len)) 1720 if (!access_ok(VERIFY_WRITE, buf, len))
1603 return -EFAULT; 1721 return -EFAULT;
1604 1722
1605 spu_acquire_saved(ctx); 1723 spu_acquire_saved(ctx);
1606 spin_lock(&ctx->csa.register_lock); 1724 spin_lock(&ctx->csa.register_lock);
1607 wbox_stat = ctx->csa.prob.mb_stat_R; 1725 ret = __spufs_wbox_info_read(ctx, buf, len, pos);
1608 cnt = (wbox_stat & 0x00ff00) >> 8;
1609 for (i = 0; i < cnt; i++) {
1610 data[i] = ctx->csa.spu_mailbox_data[i];
1611 }
1612 spin_unlock(&ctx->csa.register_lock); 1726 spin_unlock(&ctx->csa.register_lock);
1613 spu_release(ctx); 1727 spu_release(ctx);
1614 1728
1615 return simple_read_from_buffer(buf, len, pos, &data, 1729 return ret;
1616 cnt * sizeof(u32));
1617} 1730}
1618 1731
1619static struct file_operations spufs_wbox_info_fops = { 1732static struct file_operations spufs_wbox_info_fops = {
@@ -1622,19 +1735,13 @@ static struct file_operations spufs_wbox_info_fops = {
1622 .llseek = generic_file_llseek, 1735 .llseek = generic_file_llseek,
1623}; 1736};
1624 1737
1625static ssize_t spufs_dma_info_read(struct file *file, char __user *buf, 1738static ssize_t __spufs_dma_info_read(struct spu_context *ctx,
1626 size_t len, loff_t *pos) 1739 char __user *buf, size_t len, loff_t *pos)
1627{ 1740{
1628 struct spu_context *ctx = file->private_data;
1629 struct spu_dma_info info; 1741 struct spu_dma_info info;
1630 struct mfc_cq_sr *qp, *spuqp; 1742 struct mfc_cq_sr *qp, *spuqp;
1631 int i; 1743 int i;
1632 1744
1633 if (!access_ok(VERIFY_WRITE, buf, len))
1634 return -EFAULT;
1635
1636 spu_acquire_saved(ctx);
1637 spin_lock(&ctx->csa.register_lock);
1638 info.dma_info_type = ctx->csa.priv2.spu_tag_status_query_RW; 1745 info.dma_info_type = ctx->csa.priv2.spu_tag_status_query_RW;
1639 info.dma_info_mask = ctx->csa.lscsa->tag_mask.slot[0]; 1746 info.dma_info_mask = ctx->csa.lscsa->tag_mask.slot[0];
1640 info.dma_info_status = ctx->csa.spu_chnldata_RW[24]; 1747 info.dma_info_status = ctx->csa.spu_chnldata_RW[24];
@@ -1649,25 +1756,40 @@ static ssize_t spufs_dma_info_read(struct file *file, char __user *buf,
1649 qp->mfc_cq_data2_RW = spuqp->mfc_cq_data2_RW; 1756 qp->mfc_cq_data2_RW = spuqp->mfc_cq_data2_RW;
1650 qp->mfc_cq_data3_RW = spuqp->mfc_cq_data3_RW; 1757 qp->mfc_cq_data3_RW = spuqp->mfc_cq_data3_RW;
1651 } 1758 }
1652 spin_unlock(&ctx->csa.register_lock);
1653 spu_release(ctx);
1654 1759
1655 return simple_read_from_buffer(buf, len, pos, &info, 1760 return simple_read_from_buffer(buf, len, pos, &info,
1656 sizeof info); 1761 sizeof info);
1657} 1762}
1658 1763
1764static ssize_t spufs_dma_info_read(struct file *file, char __user *buf,
1765 size_t len, loff_t *pos)
1766{
1767 struct spu_context *ctx = file->private_data;
1768 int ret;
1769
1770 if (!access_ok(VERIFY_WRITE, buf, len))
1771 return -EFAULT;
1772
1773 spu_acquire_saved(ctx);
1774 spin_lock(&ctx->csa.register_lock);
1775 ret = __spufs_dma_info_read(ctx, buf, len, pos);
1776 spin_unlock(&ctx->csa.register_lock);
1777 spu_release(ctx);
1778
1779 return ret;
1780}
1781
1659static struct file_operations spufs_dma_info_fops = { 1782static struct file_operations spufs_dma_info_fops = {
1660 .open = spufs_info_open, 1783 .open = spufs_info_open,
1661 .read = spufs_dma_info_read, 1784 .read = spufs_dma_info_read,
1662}; 1785};
1663 1786
1664static ssize_t spufs_proxydma_info_read(struct file *file, char __user *buf, 1787static ssize_t __spufs_proxydma_info_read(struct spu_context *ctx,
1665 size_t len, loff_t *pos) 1788 char __user *buf, size_t len, loff_t *pos)
1666{ 1789{
1667 struct spu_context *ctx = file->private_data;
1668 struct spu_proxydma_info info; 1790 struct spu_proxydma_info info;
1669 int ret = sizeof info;
1670 struct mfc_cq_sr *qp, *puqp; 1791 struct mfc_cq_sr *qp, *puqp;
1792 int ret = sizeof info;
1671 int i; 1793 int i;
1672 1794
1673 if (len < ret) 1795 if (len < ret)
@@ -1676,8 +1798,6 @@ static ssize_t spufs_proxydma_info_read(struct file *file, char __user *buf,
1676 if (!access_ok(VERIFY_WRITE, buf, len)) 1798 if (!access_ok(VERIFY_WRITE, buf, len))
1677 return -EFAULT; 1799 return -EFAULT;
1678 1800
1679 spu_acquire_saved(ctx);
1680 spin_lock(&ctx->csa.register_lock);
1681 info.proxydma_info_type = ctx->csa.prob.dma_querytype_RW; 1801 info.proxydma_info_type = ctx->csa.prob.dma_querytype_RW;
1682 info.proxydma_info_mask = ctx->csa.prob.dma_querymask_RW; 1802 info.proxydma_info_mask = ctx->csa.prob.dma_querymask_RW;
1683 info.proxydma_info_status = ctx->csa.prob.dma_tagstatus_R; 1803 info.proxydma_info_status = ctx->csa.prob.dma_tagstatus_R;
@@ -1690,12 +1810,23 @@ static ssize_t spufs_proxydma_info_read(struct file *file, char __user *buf,
1690 qp->mfc_cq_data2_RW = puqp->mfc_cq_data2_RW; 1810 qp->mfc_cq_data2_RW = puqp->mfc_cq_data2_RW;
1691 qp->mfc_cq_data3_RW = puqp->mfc_cq_data3_RW; 1811 qp->mfc_cq_data3_RW = puqp->mfc_cq_data3_RW;
1692 } 1812 }
1813
1814 return simple_read_from_buffer(buf, len, pos, &info,
1815 sizeof info);
1816}
1817
1818static ssize_t spufs_proxydma_info_read(struct file *file, char __user *buf,
1819 size_t len, loff_t *pos)
1820{
1821 struct spu_context *ctx = file->private_data;
1822 int ret;
1823
1824 spu_acquire_saved(ctx);
1825 spin_lock(&ctx->csa.register_lock);
1826 ret = __spufs_proxydma_info_read(ctx, buf, len, pos);
1693 spin_unlock(&ctx->csa.register_lock); 1827 spin_unlock(&ctx->csa.register_lock);
1694 spu_release(ctx); 1828 spu_release(ctx);
1695 1829
1696 if (copy_to_user(buf, &info, sizeof info))
1697 ret = -EFAULT;
1698
1699 return ret; 1830 return ret;
1700} 1831}
1701 1832
@@ -1760,3 +1891,27 @@ struct tree_descr spufs_dir_nosched_contents[] = {
1760 { "object-id", &spufs_object_id_ops, 0666, }, 1891 { "object-id", &spufs_object_id_ops, 0666, },
1761 {}, 1892 {},
1762}; 1893};
1894
1895struct spufs_coredump_reader spufs_coredump_read[] = {
1896 { "regs", __spufs_regs_read, NULL, 128 * 16 },
1897 { "fpcr", __spufs_fpcr_read, NULL, 16 },
1898 { "lslr", NULL, __spufs_lslr_get, 11 },
1899 { "decr", NULL, __spufs_decr_get, 11 },
1900 { "decr_status", NULL, __spufs_decr_status_get, 11 },
1901 { "mem", __spufs_mem_read, NULL, 256 * 1024, },
1902 { "signal1", __spufs_signal1_read, NULL, 4 },
1903 { "signal1_type", NULL, __spufs_signal1_type_get, 2 },
1904 { "signal2", __spufs_signal2_read, NULL, 4 },
1905 { "signal2_type", NULL, __spufs_signal2_type_get, 2 },
1906 { "event_mask", NULL, __spufs_event_mask_get, 8 },
1907 { "event_status", NULL, __spufs_event_status_get, 8 },
1908 { "mbox_info", __spufs_mbox_info_read, NULL, 4 },
1909 { "ibox_info", __spufs_ibox_info_read, NULL, 4 },
1910 { "wbox_info", __spufs_wbox_info_read, NULL, 16 },
1911 { "dma_info", __spufs_dma_info_read, NULL, 69 * 8 },
1912 { "proxydma_info", __spufs_proxydma_info_read, NULL, 35 * 8 },
1913 { "object-id", NULL, __spufs_object_id_get, 19 },
1914 { },
1915};
1916int spufs_coredump_num_notes = ARRAY_SIZE(spufs_coredump_read) - 1;
1917
diff --git a/arch/powerpc/platforms/cell/spufs/inode.c b/arch/powerpc/platforms/cell/spufs/inode.c
index d5f0a21a19d..a3ca06bd0ca 100644
--- a/arch/powerpc/platforms/cell/spufs/inode.c
+++ b/arch/powerpc/platforms/cell/spufs/inode.c
@@ -232,6 +232,7 @@ struct file_operations spufs_context_fops = {
232 .readdir = dcache_readdir, 232 .readdir = dcache_readdir,
233 .fsync = simple_sync_file, 233 .fsync = simple_sync_file,
234}; 234};
235EXPORT_SYMBOL_GPL(spufs_context_fops);
235 236
236static int 237static int
237spufs_mkdir(struct inode *dir, struct dentry *dentry, unsigned int flags, 238spufs_mkdir(struct inode *dir, struct dentry *dentry, unsigned int flags,
@@ -647,6 +648,7 @@ static struct file_system_type spufs_type = {
647static int __init spufs_init(void) 648static int __init spufs_init(void)
648{ 649{
649 int ret; 650 int ret;
651
650 ret = -ENOMEM; 652 ret = -ENOMEM;
651 spufs_inode_cache = kmem_cache_create("spufs_inode_cache", 653 spufs_inode_cache = kmem_cache_create("spufs_inode_cache",
652 sizeof(struct spufs_inode_info), 0, 654 sizeof(struct spufs_inode_info), 0,
@@ -664,8 +666,12 @@ static int __init spufs_init(void)
664 ret = register_spu_syscalls(&spufs_calls); 666 ret = register_spu_syscalls(&spufs_calls);
665 if (ret) 667 if (ret)
666 goto out_fs; 668 goto out_fs;
669 ret = register_arch_coredump_calls(&spufs_coredump_calls);
670 if (ret)
671 goto out_fs;
667 672
668 spufs_init_isolated_loader(); 673 spufs_init_isolated_loader();
674
669 return 0; 675 return 0;
670out_fs: 676out_fs:
671 unregister_filesystem(&spufs_type); 677 unregister_filesystem(&spufs_type);
@@ -679,6 +685,7 @@ module_init(spufs_init);
679static void __exit spufs_exit(void) 685static void __exit spufs_exit(void)
680{ 686{
681 spu_sched_exit(); 687 spu_sched_exit();
688 unregister_arch_coredump_calls(&spufs_coredump_calls);
682 unregister_spu_syscalls(&spufs_calls); 689 unregister_spu_syscalls(&spufs_calls);
683 unregister_filesystem(&spufs_type); 690 unregister_filesystem(&spufs_type);
684 kmem_cache_destroy(spufs_inode_cache); 691 kmem_cache_destroy(spufs_inode_cache);
diff --git a/arch/powerpc/platforms/cell/spufs/spufs.h b/arch/powerpc/platforms/cell/spufs/spufs.h
index 23d20f38056..70fb13395c0 100644
--- a/arch/powerpc/platforms/cell/spufs/spufs.h
+++ b/arch/powerpc/platforms/cell/spufs/spufs.h
@@ -223,4 +223,15 @@ void spufs_stop_callback(struct spu *spu);
223void spufs_mfc_callback(struct spu *spu); 223void spufs_mfc_callback(struct spu *spu);
224void spufs_dma_callback(struct spu *spu, int type); 224void spufs_dma_callback(struct spu *spu, int type);
225 225
226extern struct spu_coredump_calls spufs_coredump_calls;
227struct spufs_coredump_reader {
228 char *name;
229 ssize_t (*read)(struct spu_context *ctx,
230 char __user *buffer, size_t size, loff_t *pos);
231 u64 (*get)(void *data);
232 size_t size;
233};
234extern struct spufs_coredump_reader spufs_coredump_read[];
235extern int spufs_coredump_num_notes;
236
226#endif 237#endif