~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/powerpc/platforms/cell/spufs/coredump.c

Version: ~ [ linux-5.3-rc5 ] ~ [ linux-5.2.9 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.67 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.139 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.189 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.189 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.140 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.72 ] ~ [ linux-3.15.10 ] ~ [ linux-3.14.79 ] ~ [ linux-3.13.11 ] ~ [ linux-3.12.74 ] ~ [ linux-3.11.10 ] ~ [ linux-3.10.108 ] ~ [ linux-3.9.11 ] ~ [ linux-3.8.13 ] ~ [ linux-3.7.10 ] ~ [ linux-3.6.11 ] ~ [ linux-3.5.7 ] ~ [ linux-3.4.113 ] ~ [ linux-3.3.8 ] ~ [ linux-3.2.102 ] ~ [ linux-3.1.10 ] ~ [ linux-3.0.101 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  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/fdtable.h>
 26 #include <linux/fs.h>
 27 #include <linux/gfp.h>
 28 #include <linux/list.h>
 29 #include <linux/syscalls.h>
 30 
 31 #include <asm/uaccess.h>
 32 
 33 #include "spufs.h"
 34 
 35 static ssize_t do_coredump_read(int num, struct spu_context *ctx, void *buffer,
 36                                 size_t size, loff_t *off)
 37 {
 38         u64 data;
 39         int ret;
 40 
 41         if (spufs_coredump_read[num].read)
 42                 return spufs_coredump_read[num].read(ctx, buffer, size, off);
 43 
 44         data = spufs_coredump_read[num].get(ctx);
 45         ret = snprintf(buffer, size, "0x%.16llx", data);
 46         if (ret >= size)
 47                 return size;
 48         return ++ret; /* count trailing NULL */
 49 }
 50 
 51 /*
 52  * These are the only things you should do on a core-file: use only these
 53  * functions to write out all the necessary info.
 54  */
 55 static int spufs_dump_write(struct file *file, const void *addr, int nr, loff_t *foffset)
 56 {
 57         unsigned long limit = rlimit(RLIMIT_CORE);
 58         ssize_t written;
 59 
 60         if (*foffset + nr > limit)
 61                 return -EIO;
 62 
 63         written = file->f_op->write(file, addr, nr, &file->f_pos);
 64         *foffset += written;
 65 
 66         if (written != nr)
 67                 return -EIO;
 68 
 69         return 0;
 70 }
 71 
 72 static int spufs_dump_align(struct file *file, char *buf, loff_t new_off,
 73                             loff_t *foffset)
 74 {
 75         int rc, size;
 76 
 77         size = min((loff_t)PAGE_SIZE, new_off - *foffset);
 78         memset(buf, 0, size);
 79 
 80         rc = 0;
 81         while (rc == 0 && new_off > *foffset) {
 82                 size = min((loff_t)PAGE_SIZE, new_off - *foffset);
 83                 rc = spufs_dump_write(file, buf, size, foffset);
 84         }
 85 
 86         return rc;
 87 }
 88 
 89 static int spufs_ctx_note_size(struct spu_context *ctx, int dfd)
 90 {
 91         int i, sz, total = 0;
 92         char *name;
 93         char fullname[80];
 94 
 95         for (i = 0; spufs_coredump_read[i].name != NULL; 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                 total += roundup(sz, 4);
104         }
105 
106         return total;
107 }
108 
109 static int match_context(const void *v, struct file *file, unsigned fd)
110 {
111         struct spu_context *ctx;
112         if (file->f_op != &spufs_context_fops)
113                 return 0;
114         ctx = SPUFS_I(file_inode(file))->i_ctx;
115         if (ctx->flags & SPU_CREATE_NOSCHED)
116                 return 0;
117         return fd + 1;
118 }
119 
120 /*
121  * The additional architecture-specific notes for Cell are various
122  * context files in the spu context.
123  *
124  * This function iterates over all open file descriptors and sees
125  * if they are a directory in spufs.  In that case we use spufs
126  * internal functionality to dump them without needing to actually
127  * open the files.
128  */
129 /*
130  * descriptor table is not shared, so files can't change or go away.
131  */
132 static struct spu_context *coredump_next_context(int *fd)
133 {
134         struct file *file;
135         int n = iterate_fd(current->files, *fd, match_context, NULL);
136         if (!n)
137                 return NULL;
138         *fd = n - 1;
139         file = fcheck(*fd);
140         return SPUFS_I(file_inode(file))->i_ctx;
141 }
142 
143 int spufs_coredump_extra_notes_size(void)
144 {
145         struct spu_context *ctx;
146         int size = 0, rc, fd;
147 
148         fd = 0;
149         while ((ctx = coredump_next_context(&fd)) != NULL) {
150                 rc = spu_acquire_saved(ctx);
151                 if (rc)
152                         break;
153                 rc = spufs_ctx_note_size(ctx, fd);
154                 spu_release_saved(ctx);
155                 if (rc < 0)
156                         break;
157 
158                 size += rc;
159 
160                 /* start searching the next fd next time */
161                 fd++;
162         }
163 
164         return size;
165 }
166 
167 static int spufs_arch_write_note(struct spu_context *ctx, int i,
168                                   struct file *file, int dfd, loff_t *foffset)
169 {
170         loff_t pos = 0;
171         int sz, rc, nread, total = 0;
172         const int bufsz = PAGE_SIZE;
173         char *name;
174         char fullname[80], *buf;
175         struct elf_note en;
176 
177         buf = (void *)get_zeroed_page(GFP_KERNEL);
178         if (!buf)
179                 return -ENOMEM;
180 
181         name = spufs_coredump_read[i].name;
182         sz = spufs_coredump_read[i].size;
183 
184         sprintf(fullname, "SPU/%d/%s", dfd, name);
185         en.n_namesz = strlen(fullname) + 1;
186         en.n_descsz = sz;
187         en.n_type = NT_SPU;
188 
189         rc = spufs_dump_write(file, &en, sizeof(en), foffset);
190         if (rc)
191                 goto out;
192 
193         rc = spufs_dump_write(file, fullname, en.n_namesz, foffset);
194         if (rc)
195                 goto out;
196 
197         rc = spufs_dump_align(file, buf, roundup(*foffset, 4), foffset);
198         if (rc)
199                 goto out;
200 
201         do {
202                 nread = do_coredump_read(i, ctx, buf, bufsz, &pos);
203                 if (nread > 0) {
204                         rc = spufs_dump_write(file, buf, nread, foffset);
205                         if (rc)
206                                 goto out;
207                         total += nread;
208                 }
209         } while (nread == bufsz && total < sz);
210 
211         if (nread < 0) {
212                 rc = nread;
213                 goto out;
214         }
215 
216         rc = spufs_dump_align(file, buf, roundup(*foffset - total + sz, 4),
217                               foffset);
218 
219 out:
220         free_page((unsigned long)buf);
221         return rc;
222 }
223 
224 int spufs_coredump_extra_notes_write(struct file *file, loff_t *foffset)
225 {
226         struct spu_context *ctx;
227         int fd, j, rc;
228 
229         fd = 0;
230         while ((ctx = coredump_next_context(&fd)) != NULL) {
231                 rc = spu_acquire_saved(ctx);
232                 if (rc)
233                         return rc;
234 
235                 for (j = 0; spufs_coredump_read[j].name != NULL; j++) {
236                         rc = spufs_arch_write_note(ctx, j, file, fd, foffset);
237                         if (rc) {
238                                 spu_release_saved(ctx);
239                                 return rc;
240                         }
241                 }
242 
243                 spu_release_saved(ctx);
244 
245                 /* start searching the next fd next time */
246                 fd++;
247         }
248 
249         return 0;
250 }
251 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp