[POWERPC] spufs: add infrastructure for finding elf objects

This adds an 'object-id' file that the spe library can
use to store a pointer to its ELF object. This was
originally meant for use by oprofile, but is now
also used by the GNU debugger, if available.

In order for oprofile to find the location in an spu-elf
binary where an event counter triggered, we need a way
to identify the binary in the first place.

Unfortunately, that binary itself can be embedded in a
powerpc ELF binary. Since we can assume it is mapped into
the effective address space of the running process,
have that one write the pointer value into a new spufs
file.

When a context switch occurs, pass the user value to
the profiler so that can look at the mapped file (with
some care).

Signed-off-by: Arnd Bergmann <arnd.bergmann@de.ibm.com>
Signed-off-by: Paul Mackerras <paulus@samba.org>

authored by Arnd Bergmann and committed by Paul Mackerras 86767277 7650f2f2

+58 -1
+17 -1
arch/powerpc/platforms/cell/spufs/file.c
··· 1487 1487 } 1488 1488 DEFINE_SIMPLE_ATTRIBUTE(spufs_id_ops, spufs_id_get, NULL, "0x%llx\n") 1489 1489 1490 + static u64 spufs_object_id_get(void *data) 1491 + { 1492 + struct spu_context *ctx = data; 1493 + return ctx->object_id; 1494 + } 1495 + 1496 + static void spufs_object_id_set(void *data, u64 id) 1497 + { 1498 + struct spu_context *ctx = data; 1499 + ctx->object_id = id; 1500 + } 1501 + 1502 + DEFINE_SIMPLE_ATTRIBUTE(spufs_object_id_ops, spufs_object_id_get, 1503 + spufs_object_id_set, "0x%llx\n"); 1504 + 1490 1505 struct tree_descr spufs_dir_contents[] = { 1491 1506 { "mem", &spufs_mem_fops, 0666, }, 1492 1507 { "regs", &spufs_regs_fops, 0666, }, ··· 1525 1510 { "spu_tag_mask", &spufs_spu_tag_mask_ops, 0666, }, 1526 1511 { "event_mask", &spufs_event_mask_ops, 0666, }, 1527 1512 { "srr0", &spufs_srr0_ops, 0666, }, 1528 - { "phys-id", &spufs_id_ops, 0666, }, 1529 1513 { "psmap", &spufs_psmap_fops, 0666, }, 1514 + { "phys-id", &spufs_id_ops, 0666, }, 1515 + { "object-id", &spufs_object_id_ops, 0666, }, 1530 1516 {}, 1531 1517 };
+22
arch/powerpc/platforms/cell/spufs/sched.c
··· 35 35 #include <linux/unistd.h> 36 36 #include <linux/numa.h> 37 37 #include <linux/mutex.h> 38 + #include <linux/notifier.h> 38 39 39 40 #include <asm/io.h> 40 41 #include <asm/mmu_context.h> ··· 76 75 __cpus_setall(&mm->cpu_vm_mask, nr); 77 76 } 78 77 78 + static BLOCKING_NOTIFIER_HEAD(spu_switch_notifier); 79 + 80 + static void spu_switch_notify(struct spu *spu, struct spu_context *ctx) 81 + { 82 + blocking_notifier_call_chain(&spu_switch_notifier, 83 + ctx ? ctx->object_id : 0, spu); 84 + } 85 + 86 + int spu_switch_event_register(struct notifier_block * n) 87 + { 88 + return blocking_notifier_chain_register(&spu_switch_notifier, n); 89 + } 90 + 91 + int spu_switch_event_unregister(struct notifier_block * n) 92 + { 93 + return blocking_notifier_chain_unregister(&spu_switch_notifier, n); 94 + } 95 + 96 + 79 97 static inline void bind_context(struct spu *spu, struct spu_context *ctx) 80 98 { 81 99 pr_debug("%s: pid=%d SPU=%d NODE=%d\n", __FUNCTION__, current->pid, ··· 117 97 spu_restore(&ctx->csa, spu); 118 98 spu->timestamp = jiffies; 119 99 spu_cpu_affinity_set(spu, raw_smp_processor_id()); 100 + spu_switch_notify(spu, ctx); 120 101 } 121 102 122 103 static inline void unbind_context(struct spu *spu, struct spu_context *ctx) 123 104 { 124 105 pr_debug("%s: unbind pid=%d SPU=%d NODE=%d\n", __FUNCTION__, 125 106 spu->pid, spu->number, spu->node); 107 + spu_switch_notify(spu, NULL); 126 108 spu_unmap_mappings(ctx); 127 109 spu_save(&ctx->csa, spu); 128 110 spu->timestamp = jiffies;
+1
arch/powerpc/platforms/cell/spufs/spufs.h
··· 50 50 struct address_space *cntl; /* 'control' area mappings. */ 51 51 struct address_space *signal1; /* 'signal1' area mappings. */ 52 52 struct address_space *signal2; /* 'signal2' area mappings. */ 53 + u64 object_id; /* user space pointer for oprofile */ 53 54 54 55 enum { SPU_STATE_RUNNABLE, SPU_STATE_SAVED } state; 55 56 struct rw_semaphore state_sema;
+18
include/asm-powerpc/spu.h
··· 201 201 202 202 203 203 /* 204 + * Notifier blocks: 205 + * 206 + * oprofile can get notified when a context switch is performed 207 + * on an spe. The notifer function that gets called is passed 208 + * a pointer to the SPU structure as well as the object-id that 209 + * identifies the binary running on that SPU now. 210 + * 211 + * For a context save, the object-id that is passed is zero, 212 + * identifying that the kernel will run from that moment on. 213 + * 214 + * For a context restore, the object-id is the value written 215 + * to object-id spufs file from user space and the notifer 216 + * function can assume that spu->ctx is valid. 217 + */ 218 + int spu_switch_event_register(struct notifier_block * n); 219 + int spu_switch_event_unregister(struct notifier_block * n); 220 + 221 + /* 204 222 * This defines the Local Store, Problem Area and Privlege Area of an SPU. 205 223 */ 206 224