File Index
Files and directories
Sign in
FILE

coredump.c

File preview with syntax highlighting.

linux-6.19.14/arch/powerpc/platforms/cell/spufs/coredump.c C
  1// SPDX-License-Identifier: GPL-2.0-or-later
  2/*
  3 * SPU core dump code
  4 *
  5 * (C) Copyright 2006 IBM Corp.
  6 *
  7 * Author: Dwayne Grant McConnell <decimal@us.ibm.com>
  8 */
  9
 10#include <linux/elf.h>
 11#include <linux/file.h>
 12#include <linux/fdtable.h>
 13#include <linux/fs.h>
 14#include <linux/gfp.h>
 15#include <linux/list.h>
 16#include <linux/syscalls.h>
 17#include <linux/coredump.h>
 18#include <linux/binfmts.h>
 19
 20#include <linux/uaccess.h>
 21
 22#include "spufs.h"
 23
 24static int spufs_ctx_note_size(struct spu_context *ctx, int dfd)
 25{
 26	int i, sz, total = 0;
 27	char *name;
 28	char fullname[80];
 29
 30	for (i = 0; spufs_coredump_read[i].name != NULL; i++) {
 31		name = spufs_coredump_read[i].name;
 32		sz = spufs_coredump_read[i].size;
 33
 34		sprintf(fullname, "SPU/%d/%s", dfd, name);
 35
 36		total += sizeof(struct elf_note);
 37		total += roundup(strlen(fullname) + 1, 4);
 38		total += roundup(sz, 4);
 39	}
 40
 41	return total;
 42}
 43
 44static int match_context(const void *v, struct file *file, unsigned fd)
 45{
 46	struct spu_context *ctx;
 47	if (file->f_op != &spufs_context_fops)
 48		return 0;
 49	ctx = SPUFS_I(file_inode(file))->i_ctx;
 50	if (ctx->flags & SPU_CREATE_NOSCHED)
 51		return 0;
 52	return fd + 1;
 53}
 54
 55/*
 56 * The additional architecture-specific notes for Cell are various
 57 * context files in the spu context.
 58 *
 59 * This function iterates over all open file descriptors and sees
 60 * if they are a directory in spufs.  In that case we use spufs
 61 * internal functionality to dump them without needing to actually
 62 * open the files.
 63 */
 64/*
 65 * descriptor table is not shared, so files can't change or go away.
 66 */
 67static struct spu_context *coredump_next_context(int *fd)
 68{
 69	struct spu_context *ctx = NULL;
 70	struct file *file;
 71	int n = iterate_fd(current->files, *fd, match_context, NULL);
 72	if (!n)
 73		return NULL;
 74	*fd = n - 1;
 75
 76	file = fget_raw(*fd);
 77	if (file) {
 78		ctx = SPUFS_I(file_inode(file))->i_ctx;
 79		get_spu_context(ctx);
 80		fput(file);
 81	}
 82
 83	return ctx;
 84}
 85
 86int spufs_coredump_extra_notes_size(void)
 87{
 88	struct spu_context *ctx;
 89	int size = 0, rc, fd;
 90
 91	fd = 0;
 92	while ((ctx = coredump_next_context(&fd)) != NULL) {
 93		rc = spu_acquire_saved(ctx);
 94		if (rc) {
 95			put_spu_context(ctx);
 96			break;
 97		}
 98
 99		rc = spufs_ctx_note_size(ctx, fd);
100		spu_release_saved(ctx);
101		if (rc < 0) {
102			put_spu_context(ctx);
103			break;
104		}
105
106		size += rc;
107
108		/* start searching the next fd next time */
109		fd++;
110		put_spu_context(ctx);
111	}
112
113	return size;
114}
115
116static int spufs_arch_write_note(struct spu_context *ctx, int i,
117				  struct coredump_params *cprm, int dfd)
118{
119	size_t sz = spufs_coredump_read[i].size;
120	char fullname[80];
121	struct elf_note en;
122	int ret;
123
124	sprintf(fullname, "SPU/%d/%s", dfd, spufs_coredump_read[i].name);
125	en.n_namesz = strlen(fullname) + 1;
126	en.n_descsz = sz;
127	en.n_type = NT_SPU;
128
129	if (!dump_emit(cprm, &en, sizeof(en)))
130		return -EIO;
131	if (!dump_emit(cprm, fullname, en.n_namesz))
132		return -EIO;
133	if (!dump_align(cprm, 4))
134		return -EIO;
135
136	if (spufs_coredump_read[i].dump) {
137		ret = spufs_coredump_read[i].dump(ctx, cprm);
138		if (ret < 0)
139			return ret;
140	} else {
141		char buf[32];
142
143		ret = snprintf(buf, sizeof(buf), "0x%.16llx",
144			       spufs_coredump_read[i].get(ctx));
145		if (ret >= sizeof(buf))
146			return sizeof(buf);
147
148		/* count trailing the NULL: */
149		if (!dump_emit(cprm, buf, ret + 1))
150			return -EIO;
151	}
152
153	dump_skip_to(cprm, roundup(cprm->pos - ret + sz, 4));
154	return 0;
155}
156
157int spufs_coredump_extra_notes_write(struct coredump_params *cprm)
158{
159	struct spu_context *ctx;
160	int fd, j, rc;
161
162	fd = 0;
163	while ((ctx = coredump_next_context(&fd)) != NULL) {
164		rc = spu_acquire_saved(ctx);
165		if (rc)
166			return rc;
167
168		for (j = 0; spufs_coredump_read[j].name != NULL; j++) {
169			rc = spufs_arch_write_note(ctx, j, cprm, fd);
170			if (rc) {
171				spu_release_saved(ctx);
172				return rc;
173			}
174		}
175
176		spu_release_saved(ctx);
177
178		/* start searching the next fd next time */
179		fd++;
180	}
181
182	return 0;
183}
~/ Read-only file preview.