Subject: clean up spu core dump patch * Use spu_ or spufs_ symbol prefixes where appropriate * Use a mutex around the new calls to protect against module unload * Make some symbols static and get rid of the optimization for builtin spufs * Open-code some macros * Don't attempt to dump unschedulable contexts Signed-off-by: Arnd Bergmann Index: linux-2.6/arch/powerpc/platforms/cell/spu_coredump.c =================================================================== --- linux-2.6.orig/arch/powerpc/platforms/cell/spu_coredump.c +++ linux-2.6/arch/powerpc/platforms/cell/spu_coredump.c @@ -26,49 +26,56 @@ #include -struct coredump_calls coredump_calls = { - .owner = NULL, -}; +static struct spu_coredump_calls spu_coredump_calls; +static DEFINE_MUTEX(spu_coredump_mutex); int arch_notes_size(void) { long ret; - struct module *owner = coredump_calls.owner; + struct module *owner = spu_coredump_calls.owner; ret = -ENOSYS; + mutex_lock(&spu_coredump_mutex); if (owner && try_module_get(owner)) { - ret = coredump_calls.arch_notes_size(); + ret = spu_coredump_calls.arch_notes_size(); module_put(owner); } + mutex_unlock(&spu_coredump_mutex); return ret; } void arch_write_notes(struct file *file) { - struct module *owner = coredump_calls.owner; + struct module *owner = spu_coredump_calls.owner; + mutex_lock(&spu_coredump_mutex); if (owner && try_module_get(owner)) { - coredump_calls.arch_write_notes(file); + spu_coredump_calls.arch_write_notes(file); module_put(owner); } + mutex_unlock(&spu_coredump_mutex); } -int register_arch_coredump_calls(struct coredump_calls *calls) +int register_arch_coredump_calls(struct spu_coredump_calls *calls) { - if (coredump_calls.owner) + if (spu_coredump_calls.owner) return -EBUSY; - coredump_calls.arch_notes_size = calls->arch_notes_size; - coredump_calls.arch_write_notes = calls->arch_write_notes; - smp_mb(); - coredump_calls.owner = calls->owner; + mutex_lock(&spu_coredump_mutex); + spu_coredump_calls.arch_notes_size = calls->arch_notes_size; + spu_coredump_calls.arch_write_notes = calls->arch_write_notes; + spu_coredump_calls.owner = calls->owner; + mutex_unlock(&spu_coredump_mutex); return 0; } EXPORT_SYMBOL_GPL(register_arch_coredump_calls); -void unregister_arch_coredump_calls(struct coredump_calls *calls) +void unregister_arch_coredump_calls(struct spu_coredump_calls *calls) { - BUG_ON(coredump_calls.owner != calls->owner); - coredump_calls.owner = NULL; + BUG_ON(spu_coredump_calls.owner != calls->owner); + + mutex_lock(&spu_coredump_mutex); + spu_coredump_calls.owner = NULL; + mutex_unlock(&spu_coredump_mutex); } EXPORT_SYMBOL_GPL(unregister_arch_coredump_calls); Index: linux-2.6/arch/powerpc/platforms/cell/spufs/coredump.c =================================================================== --- linux-2.6.orig/arch/powerpc/platforms/cell/spufs/coredump.c +++ linux-2.6/arch/powerpc/platforms/cell/spufs/coredump.c @@ -27,9 +27,11 @@ #include #include +#include + #include "spufs.h" -struct spu_ctx_info { +struct spufs_ctx_info { struct list_head list; int dfd; int memsize; /* in bytes */ @@ -38,16 +40,30 @@ struct spu_ctx_info { static LIST_HEAD(ctx_info_list); +static ssize_t do_coredump_read(int num, struct spu_context *ctx, void __user *buffer, + size_t size, loff_t *off) +{ + u64 data; + int ret; + + if (spufs_coredump_read[num].read) + return spufs_coredump_read[num].read(ctx, buffer, size, off); + + data = spufs_coredump_read[num].get(ctx); + ret = copy_to_user(buffer, &data, 8); + return ret ? -EFAULT : 8; +} + /* * These are the only things you should do on a core-file: use only these * functions to write out all the necessary info. */ -static int dump_write(struct file *file, const void *addr, int nr) +static int spufs_dump_write(struct file *file, const void *addr, int nr) { return file->f_op->write(file, addr, nr, &file->f_pos) == nr; } -static int dump_seek(struct file *file, loff_t off) +static int spufs_dump_seek(struct file *file, loff_t off) { if (file->f_op->llseek) { if (file->f_op->llseek(file, off, 0) != off) @@ -57,23 +73,17 @@ static int dump_seek(struct file *file, return 1; } -static void spu_fill_memsize(struct spu_ctx_info *ctx_info) +static void spufs_fill_memsize(struct spufs_ctx_info *ctx_info) { struct spu_context *ctx; - int rc; - loff_t pos = 0; unsigned long long lslr; - char buf[12]; ctx = ctx_info->ctx; - rc = COREDUMP_READ(COREDUMP_LSLR_READ, ctx, buf, 11, &pos); - if (rc < 0) - return; - lslr = (*(unsigned long long *)buf); + lslr = ctx->csa.priv2.spu_lslr_RW; ctx_info->memsize = lslr + 1; } -static int spu_ctx_note_size(struct spu_ctx_info *ctx_info) +static int spufs_ctx_note_size(struct spufs_ctx_info *ctx_info) { int dfd, memsize, i, sz, total = 0; char *name; @@ -82,9 +92,9 @@ static int spu_ctx_note_size(struct spu_ dfd = ctx_info->dfd; memsize = ctx_info->memsize; - for (i = 0; i < NUM_SPU_NOTES; i++) { - name = coredump_read[i].name; - sz = coredump_read[i].size; + for (i = 0; spufs_coredump_read[i].name; i++) { + name = spufs_coredump_read[i].name; + sz = spufs_coredump_read[i].size; sprintf(fullname, "SPU/%d/%s", dfd, name); @@ -99,7 +109,7 @@ static int spu_ctx_note_size(struct spu_ return total; } -int arch_notes_size(void) +static int spufs_arch_notes_size(void) { int i, j, sz = 0, error = 0; struct fdtable *fdt; @@ -121,8 +131,10 @@ int arch_notes_size(void) struct inode *ip = dp->d_inode; struct spufs_inode_info *sip = SPUFS_I(ip); if (S_ISDIR(ip->i_mode) && - (fp->f_op == &spufs_context_fops)) { - struct spu_ctx_info *ctx_info; + (fp->f_op == &spufs_context_fops) && + !(sip->i_ctx->flags & + SPU_CREATE_NOSCHED)) { + struct spufs_ctx_info *ctx_info; ctx_info = kzalloc(sizeof(*ctx_info), GFP_KERNEL); if (!ctx_info) { @@ -131,8 +143,8 @@ int arch_notes_size(void) } ctx_info->dfd = i; ctx_info->ctx = sip->i_ctx; - spu_fill_memsize(ctx_info); - sz += spu_ctx_note_size(ctx_info); + spufs_fill_memsize(ctx_info); + sz += spufs_ctx_note_size(ctx_info); list_add(&ctx_info->list, &ctx_info_list); } @@ -146,12 +158,7 @@ cleanup: return sz; } -#define DUMP_WRITE_RET(addr, nr) \ - do { if (!dump_write(file, (addr), (nr))) return; } while(0) -#define DUMP_SEEK_RET(off) \ - do { if (!dump_seek(file, (off))) return; } while(0) - -static void arch_write_note(struct spu_ctx_info *ctx_info, int i, +static void spufs_arch_write_note(struct spufs_ctx_info *ctx_info, int i, struct file *file) { struct spu_context *ctx; @@ -167,12 +174,12 @@ static void arch_write_note(struct spu_c return; dfd = ctx_info->dfd; - name = coredump_read[i].name; + name = spufs_coredump_read[i].name; if (!strcmp(name, "mem")) sz = ctx_info->memsize; else - sz = coredump_read[i].size; + sz = spufs_coredump_read[i].size; ctx = ctx_info->ctx; if (!ctx) { @@ -184,38 +191,43 @@ static void arch_write_note(struct spu_c en.n_descsz = sz; en.n_type = NT_SPU; - DUMP_WRITE_RET(&en, sizeof(en)); - DUMP_WRITE_RET(fullname, en.n_namesz); - DUMP_SEEK_RET(roundup((unsigned long)file->f_pos, 4)); + if (!spufs_dump_write(file, &en, sizeof(en))) + return; + if (!spufs_dump_write(file, fullname, en.n_namesz)) + return; + if (!spufs_dump_seek(file, roundup((unsigned long)file->f_pos, 4))) + return; do { - rc = COREDUMP_READ(i, ctx, buf, bufsz, &pos); + rc = do_coredump_read(i, ctx, buf, bufsz, &pos); if (rc > 0) { - DUMP_WRITE_RET(buf, rc); + if (!spufs_dump_write(file, buf, rc)) + return; total += rc; } } while (rc == bufsz && total < sz); - DUMP_SEEK_RET(roundup((unsigned long)file->f_pos - total + sz, 4)); + spufs_dump_seek(file, roundup((unsigned long)file->f_pos + - total + sz, 4)); } -void arch_write_notes(struct file *file) +static void spufs_arch_write_notes(struct file *file) { int j; - struct spu_ctx_info *ctx_info, *next; + struct spufs_ctx_info *ctx_info, *next; list_for_each_entry_safe(ctx_info, next, &ctx_info_list, list) { spu_acquire_saved(ctx_info->ctx); - for (j = 0; j < NUM_SPU_NOTES; j++) - arch_write_note(ctx_info, j, file); + for (j = 0; j < spufs_coredump_num_notes; j++) + spufs_arch_write_note(ctx_info, j, file); spu_release(ctx_info->ctx); list_del(&ctx_info->list); kfree(ctx_info); } } -struct coredump_calls coredump_calls = { - .arch_notes_size = arch_notes_size, - .arch_write_notes = arch_write_notes, +struct spu_coredump_calls spufs_coredump_calls = { + .arch_notes_size = spufs_arch_notes_size, + .arch_write_notes = spufs_arch_write_notes, .owner = THIS_MODULE, }; Index: linux-2.6/arch/powerpc/platforms/cell/spufs/file.c =================================================================== --- linux-2.6.orig/arch/powerpc/platforms/cell/spufs/file.c +++ linux-2.6/arch/powerpc/platforms/cell/spufs/file.c @@ -733,7 +733,7 @@ static int spufs_signal1_open(struct ino return nonseekable_open(inode, file); } -static ssize_t __spufs_signal1_read(struct spu_context *ctx, char *buf, +static ssize_t __spufs_signal1_read(struct spu_context *ctx, char __user *buf, size_t len, loff_t *pos) { int ret = 0; @@ -1891,7 +1891,7 @@ struct tree_descr spufs_dir_nosched_cont {}, }; -struct coredump_reader coredump_read[] = { +struct spufs_coredump_reader spufs_coredump_read[] = { { "regs", __spufs_regs_read, NULL, 128 * 16 }, { "fpcr", __spufs_fpcr_read, NULL, 16 }, { "lslr", NULL, __spufs_lslr_get, 11 }, @@ -1910,5 +1910,7 @@ struct coredump_reader coredump_read[] = { "dma_info", __spufs_dma_info_read, NULL, 69 * 8 }, { "proxydma_info", __spufs_proxydma_info_read, NULL, 35 * 8 }, { "object-id", NULL, __spufs_object_id_get, 19 }, + { }, }; +int spufs_coredump_num_notes = ARRAY_SIZE(spufs_coredump_read) - 1; Index: linux-2.6/arch/powerpc/platforms/cell/spufs/inode.c =================================================================== --- linux-2.6.orig/arch/powerpc/platforms/cell/spufs/inode.c +++ linux-2.6/arch/powerpc/platforms/cell/spufs/inode.c @@ -667,7 +667,7 @@ static int __init spufs_init(void) ret = register_spu_syscalls(&spufs_calls); if (ret) goto out_fs; - ret = register_arch_coredump_calls(&coredump_calls); + ret = register_arch_coredump_calls(&spufs_coredump_calls); if (ret) goto out_fs; @@ -686,7 +686,7 @@ module_init(spufs_init); static void __exit spufs_exit(void) { spu_sched_exit(); - unregister_arch_coredump_calls(&coredump_calls); + unregister_arch_coredump_calls(&spufs_coredump_calls); unregister_spu_syscalls(&spufs_calls); unregister_filesystem(&spufs_type); kmem_cache_destroy(spufs_inode_cache); Index: linux-2.6/arch/powerpc/platforms/cell/spufs/spufs.h =================================================================== --- linux-2.6.orig/arch/powerpc/platforms/cell/spufs/spufs.h +++ linux-2.6/arch/powerpc/platforms/cell/spufs/spufs.h @@ -223,25 +223,15 @@ void spufs_stop_callback(struct spu *spu void spufs_mfc_callback(struct spu *spu); void spufs_dma_callback(struct spu *spu, int type); -struct coredump_reader { +extern struct spu_coredump_calls spufs_coredump_calls; +struct spufs_coredump_reader { char *name; ssize_t (*read)(struct spu_context *ctx, char __user *buffer, size_t size, loff_t *pos); u64 (*get)(void *data); size_t size; }; -extern struct coredump_reader coredump_read[]; -#define NUM_SPU_NOTES 18 +extern struct spufs_coredump_reader spufs_coredump_read[]; +extern int spufs_coredump_num_notes; -/* Must be changed if elements are added before lslr in coredump_read[]. */ -#define COREDUMP_LSLR_READ 2 - -#define COREDUMP_READ(num, ctx, buffer, size, pos) \ - (coredump_read[num].read ? \ - coredump_read[num].read(ctx, buffer, size, pos) : \ - (coredump_read[num].get ? \ - (((*(u64 *)buffer) = \ - coredump_read[num].get(ctx)), 8) : \ - 0)) - #endif Index: linux-2.6/include/asm-powerpc/spu.h =================================================================== --- linux-2.6.orig/include/asm-powerpc/spu.h +++ linux-2.6/include/asm-powerpc/spu.h @@ -173,11 +173,11 @@ extern struct spufs_calls { } spufs_calls; /* coredump calls implemented in spufs */ -extern struct coredump_calls { +struct spu_coredump_calls { asmlinkage int (*arch_notes_size)(void); asmlinkage void (*arch_write_notes)(struct file *file); struct module *owner; -} coredump_calls; +}; /* return status from spu_run, same as in libspe */ #define SPE_EVENT_DMA_ALIGNMENT 0x0008 /*A DMA alignment error */ @@ -200,8 +200,6 @@ extern struct coredump_calls { #ifdef CONFIG_SPU_FS_MODULE int register_spu_syscalls(struct spufs_calls *calls); void unregister_spu_syscalls(struct spufs_calls *calls); -int register_arch_coredump_calls(struct coredump_calls *calls); -void unregister_arch_coredump_calls(struct coredump_calls *calls); #else static inline int register_spu_syscalls(struct spufs_calls *calls) { @@ -210,15 +208,11 @@ static inline int register_spu_syscalls( static inline void unregister_spu_syscalls(struct spufs_calls *calls) { } -static inline int register_arch_coredump_calls(struct coredump_calls *calls) -{ - return 0; -} -static inline void unregister_arch_coredump_calls(struct coredump_calls *calls) -{ -} #endif /* MODULE */ +int register_arch_coredump_calls(struct spu_coredump_calls *calls); +void unregister_arch_coredump_calls(struct spu_coredump_calls *calls); + int spu_add_sysdev_attr(struct sysdev_attribute *attr); void spu_remove_sysdev_attr(struct sysdev_attribute *attr);