aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/powerpc/platforms/cell/Makefile1
-rw-r--r--arch/powerpc/platforms/cell/spu_coredump.c81
-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
-rw-r--r--fs/binfmt_elf.c8
-rw-r--r--include/asm-powerpc/elf.h13
-rw-r--r--include/asm-powerpc/spu.h10
-rw-r--r--include/linux/elf.h7
11 files changed, 618 insertions, 87 deletions
diff --git a/arch/powerpc/platforms/cell/Makefile b/arch/powerpc/platforms/cell/Makefile
index 62c011e80929..f90e8337796c 100644
--- a/arch/powerpc/platforms/cell/Makefile
+++ b/arch/powerpc/platforms/cell/Makefile
@@ -15,5 +15,6 @@ spufs-modular-$(CONFIG_SPU_FS) += spu_syscalls.o
15spu-priv1-$(CONFIG_PPC_CELL_NATIVE) += spu_priv1_mmio.o 15spu-priv1-$(CONFIG_PPC_CELL_NATIVE) += spu_priv1_mmio.o
16 16
17obj-$(CONFIG_SPU_BASE) += spu_callbacks.o spu_base.o \ 17obj-$(CONFIG_SPU_BASE) += spu_callbacks.o spu_base.o \
18 spu_coredump.o \
18 $(spufs-modular-m) \ 19 $(spufs-modular-m) \
19 $(spu-priv1-y) spufs/ 20 $(spu-priv1-y) spufs/
diff --git a/arch/powerpc/platforms/cell/spu_coredump.c b/arch/powerpc/platforms/cell/spu_coredump.c
new file mode 100644
index 000000000000..6915b418ee73
--- /dev/null
+++ b/arch/powerpc/platforms/cell/spu_coredump.c
@@ -0,0 +1,81 @@
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/file.h>
24#include <linux/module.h>
25#include <linux/syscalls.h>
26
27#include <asm/spu.h>
28
29static struct spu_coredump_calls spu_coredump_calls;
30static DEFINE_MUTEX(spu_coredump_mutex);
31
32int arch_notes_size(void)
33{
34 long ret;
35 struct module *owner = spu_coredump_calls.owner;
36
37 ret = -ENOSYS;
38 mutex_lock(&spu_coredump_mutex);
39 if (owner && try_module_get(owner)) {
40 ret = spu_coredump_calls.arch_notes_size();
41 module_put(owner);
42 }
43 mutex_unlock(&spu_coredump_mutex);
44 return ret;
45}
46
47void arch_write_notes(struct file *file)
48{
49 struct module *owner = spu_coredump_calls.owner;
50
51 mutex_lock(&spu_coredump_mutex);
52 if (owner && try_module_get(owner)) {
53 spu_coredump_calls.arch_write_notes(file);
54 module_put(owner);
55 }
56 mutex_unlock(&spu_coredump_mutex);
57}
58
59int register_arch_coredump_calls(struct spu_coredump_calls *calls)
60{
61 if (spu_coredump_calls.owner)
62 return -EBUSY;
63
64 mutex_lock(&spu_coredump_mutex);
65 spu_coredump_calls.arch_notes_size = calls->arch_notes_size;
66 spu_coredump_calls.arch_write_notes = calls->arch_write_notes;
67 spu_coredump_calls.owner = calls->owner;
68 mutex_unlock(&spu_coredump_mutex);
69 return 0;
70}
71EXPORT_SYMBOL_GPL(register_arch_coredump_calls);
72
73void unregister_arch_coredump_calls(struct spu_coredump_calls *calls)
74{
75 BUG_ON(spu_coredump_calls.owner != calls->owner);
76
77 mutex_lock(&spu_coredump_mutex);
78 spu_coredump_calls.owner = NULL;
79 mutex_unlock(&spu_coredump_mutex);
80}
81EXPORT_SYMBOL_GPL(unregister_arch_coredump_calls);
diff --git a/arch/powerpc/platforms/cell/spufs/Makefile b/arch/powerpc/platforms/cell/spufs/Makefile
index ecdfbb35f82e..472217d19faf 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 000000000000..26945c491f6b
--- /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 50e0afc46ad2..347eff56fcbd 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 d5f0a21a19d8..a3ca06bd0ca1 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 23d20f380560..70fb13395c04 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
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index 79b05a1a4365..cc72bb43061d 100644
--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -1582,6 +1582,10 @@ static int elf_core_dump(long signr, struct pt_regs *regs, struct file *file)
1582 1582
1583 sz += thread_status_size; 1583 sz += thread_status_size;
1584 1584
1585#ifdef ELF_CORE_WRITE_EXTRA_NOTES
1586 sz += ELF_CORE_EXTRA_NOTES_SIZE;
1587#endif
1588
1585 fill_elf_note_phdr(&phdr, sz, offset); 1589 fill_elf_note_phdr(&phdr, sz, offset);
1586 offset += sz; 1590 offset += sz;
1587 DUMP_WRITE(&phdr, sizeof(phdr)); 1591 DUMP_WRITE(&phdr, sizeof(phdr));
@@ -1622,6 +1626,10 @@ static int elf_core_dump(long signr, struct pt_regs *regs, struct file *file)
1622 if (!writenote(notes + i, file, &foffset)) 1626 if (!writenote(notes + i, file, &foffset))
1623 goto end_coredump; 1627 goto end_coredump;
1624 1628
1629#ifdef ELF_CORE_WRITE_EXTRA_NOTES
1630 ELF_CORE_WRITE_EXTRA_NOTES;
1631#endif
1632
1625 /* write out the thread status notes section */ 1633 /* write out the thread status notes section */
1626 list_for_each(t, &thread_list) { 1634 list_for_each(t, &thread_list) {
1627 struct elf_thread_status *tmp = 1635 struct elf_thread_status *tmp =
diff --git a/include/asm-powerpc/elf.h b/include/asm-powerpc/elf.h
index 9a83a987d396..4545aa682509 100644
--- a/include/asm-powerpc/elf.h
+++ b/include/asm-powerpc/elf.h
@@ -411,4 +411,17 @@ do { \
411/* Keep this the last entry. */ 411/* Keep this the last entry. */
412#define R_PPC64_NUM 107 412#define R_PPC64_NUM 107
413 413
414#ifdef CONFIG_PPC_CELL
415/* Notes used in ET_CORE. Note name is "SPU/<fd>/<filename>". */
416#define NT_SPU 1
417
418extern int arch_notes_size(void);
419extern void arch_write_notes(struct file *file);
420
421#define ELF_CORE_EXTRA_NOTES_SIZE arch_notes_size()
422#define ELF_CORE_WRITE_EXTRA_NOTES arch_write_notes(file)
423
424#define ARCH_HAVE_EXTRA_ELF_NOTES
425#endif /* CONFIG_PPC_CELL */
426
414#endif /* _ASM_POWERPC_ELF_H */ 427#endif /* _ASM_POWERPC_ELF_H */
diff --git a/include/asm-powerpc/spu.h b/include/asm-powerpc/spu.h
index ffa4df083609..f968f8697538 100644
--- a/include/asm-powerpc/spu.h
+++ b/include/asm-powerpc/spu.h
@@ -172,6 +172,13 @@ extern struct spufs_calls {
172 struct module *owner; 172 struct module *owner;
173} spufs_calls; 173} spufs_calls;
174 174
175/* coredump calls implemented in spufs */
176struct spu_coredump_calls {
177 asmlinkage int (*arch_notes_size)(void);
178 asmlinkage void (*arch_write_notes)(struct file *file);
179 struct module *owner;
180};
181
175/* return status from spu_run, same as in libspe */ 182/* return status from spu_run, same as in libspe */
176#define SPE_EVENT_DMA_ALIGNMENT 0x0008 /*A DMA alignment error */ 183#define SPE_EVENT_DMA_ALIGNMENT 0x0008 /*A DMA alignment error */
177#define SPE_EVENT_SPE_ERROR 0x0010 /*An illegal instruction error*/ 184#define SPE_EVENT_SPE_ERROR 0x0010 /*An illegal instruction error*/
@@ -203,6 +210,9 @@ static inline void unregister_spu_syscalls(struct spufs_calls *calls)
203} 210}
204#endif /* MODULE */ 211#endif /* MODULE */
205 212
213int register_arch_coredump_calls(struct spu_coredump_calls *calls);
214void unregister_arch_coredump_calls(struct spu_coredump_calls *calls);
215
206int spu_add_sysdev_attr(struct sysdev_attribute *attr); 216int spu_add_sysdev_attr(struct sysdev_attribute *attr);
207void spu_remove_sysdev_attr(struct sysdev_attribute *attr); 217void spu_remove_sysdev_attr(struct sysdev_attribute *attr);
208 218
diff --git a/include/linux/elf.h b/include/linux/elf.h
index b70d1d2c8d28..743d5c8e6d36 100644
--- a/include/linux/elf.h
+++ b/include/linux/elf.h
@@ -368,5 +368,12 @@ extern Elf64_Dyn _DYNAMIC [];
368 368
369#endif 369#endif
370 370
371#ifndef ARCH_HAVE_EXTRA_ELF_NOTES
372static inline int arch_notes_size(void) { return 0; }
373static inline void arch_write_notes(struct file *file) { }
374
375#define ELF_CORE_EXTRA_NOTES_SIZE arch_notes_size()
376#define ELF_CORE_WRITE_EXTRA_NOTES arch_write_notes(file)
377#endif /* ARCH_HAVE_EXTRA_ELF_NOTES */
371 378
372#endif /* _LINUX_ELF_H */ 379#endif /* _LINUX_ELF_H */