aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc
diff options
context:
space:
mode:
authorArnd Bergmann <arnd@arndb.de>2006-10-04 11:26:21 -0400
committerPaul Mackerras <paulus@samba.org>2006-10-04 19:21:02 -0400
commit867672777964b9309e4e914fe097648c938b67b2 (patch)
treeef37d5252aa35497e96acf6b0e29e56894e6ab77 /arch/powerpc
parent7650f2f2c367242a2092908794b4486876baf6c7 (diff)
[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>
Diffstat (limited to 'arch/powerpc')
-rw-r--r--arch/powerpc/platforms/cell/spufs/file.c18
-rw-r--r--arch/powerpc/platforms/cell/spufs/sched.c22
-rw-r--r--arch/powerpc/platforms/cell/spufs/spufs.h1
3 files changed, 40 insertions, 1 deletions
diff --git a/arch/powerpc/platforms/cell/spufs/file.c b/arch/powerpc/platforms/cell/spufs/file.c
index e2c9d48a6804..e0d730045260 100644
--- a/arch/powerpc/platforms/cell/spufs/file.c
+++ b/arch/powerpc/platforms/cell/spufs/file.c
@@ -1487,6 +1487,21 @@ static u64 spufs_id_get(void *data)
1487} 1487}
1488DEFINE_SIMPLE_ATTRIBUTE(spufs_id_ops, spufs_id_get, NULL, "0x%llx\n") 1488DEFINE_SIMPLE_ATTRIBUTE(spufs_id_ops, spufs_id_get, NULL, "0x%llx\n")
1489 1489
1490static u64 spufs_object_id_get(void *data)
1491{
1492 struct spu_context *ctx = data;
1493 return ctx->object_id;
1494}
1495
1496static void spufs_object_id_set(void *data, u64 id)
1497{
1498 struct spu_context *ctx = data;
1499 ctx->object_id = id;
1500}
1501
1502DEFINE_SIMPLE_ATTRIBUTE(spufs_object_id_ops, spufs_object_id_get,
1503 spufs_object_id_set, "0x%llx\n");
1504
1490struct tree_descr spufs_dir_contents[] = { 1505struct tree_descr spufs_dir_contents[] = {
1491 { "mem", &spufs_mem_fops, 0666, }, 1506 { "mem", &spufs_mem_fops, 0666, },
1492 { "regs", &spufs_regs_fops, 0666, }, 1507 { "regs", &spufs_regs_fops, 0666, },
@@ -1510,7 +1525,8 @@ struct tree_descr spufs_dir_contents[] = {
1510 { "spu_tag_mask", &spufs_spu_tag_mask_ops, 0666, }, 1525 { "spu_tag_mask", &spufs_spu_tag_mask_ops, 0666, },
1511 { "event_mask", &spufs_event_mask_ops, 0666, }, 1526 { "event_mask", &spufs_event_mask_ops, 0666, },
1512 { "srr0", &spufs_srr0_ops, 0666, }, 1527 { "srr0", &spufs_srr0_ops, 0666, },
1513 { "phys-id", &spufs_id_ops, 0666, },
1514 { "psmap", &spufs_psmap_fops, 0666, }, 1528 { "psmap", &spufs_psmap_fops, 0666, },
1529 { "phys-id", &spufs_id_ops, 0666, },
1530 { "object-id", &spufs_object_id_ops, 0666, },
1515 {}, 1531 {},
1516}; 1532};
diff --git a/arch/powerpc/platforms/cell/spufs/sched.c b/arch/powerpc/platforms/cell/spufs/sched.c
index a824b6051164..bd6fe4b7a84b 100644
--- a/arch/powerpc/platforms/cell/spufs/sched.c
+++ b/arch/powerpc/platforms/cell/spufs/sched.c
@@ -35,6 +35,7 @@
35#include <linux/unistd.h> 35#include <linux/unistd.h>
36#include <linux/numa.h> 36#include <linux/numa.h>
37#include <linux/mutex.h> 37#include <linux/mutex.h>
38#include <linux/notifier.h>
38 39
39#include <asm/io.h> 40#include <asm/io.h>
40#include <asm/mmu_context.h> 41#include <asm/mmu_context.h>
@@ -75,6 +76,25 @@ static inline void mm_needs_global_tlbie(struct mm_struct *mm)
75 __cpus_setall(&mm->cpu_vm_mask, nr); 76 __cpus_setall(&mm->cpu_vm_mask, nr);
76} 77}
77 78
79static BLOCKING_NOTIFIER_HEAD(spu_switch_notifier);
80
81static void spu_switch_notify(struct spu *spu, struct spu_context *ctx)
82{
83 blocking_notifier_call_chain(&spu_switch_notifier,
84 ctx ? ctx->object_id : 0, spu);
85}
86
87int spu_switch_event_register(struct notifier_block * n)
88{
89 return blocking_notifier_chain_register(&spu_switch_notifier, n);
90}
91
92int spu_switch_event_unregister(struct notifier_block * n)
93{
94 return blocking_notifier_chain_unregister(&spu_switch_notifier, n);
95}
96
97
78static inline void bind_context(struct spu *spu, struct spu_context *ctx) 98static inline void bind_context(struct spu *spu, struct spu_context *ctx)
79{ 99{
80 pr_debug("%s: pid=%d SPU=%d NODE=%d\n", __FUNCTION__, current->pid, 100 pr_debug("%s: pid=%d SPU=%d NODE=%d\n", __FUNCTION__, current->pid,
@@ -97,12 +117,14 @@ static inline void bind_context(struct spu *spu, struct spu_context *ctx)
97 spu_restore(&ctx->csa, spu); 117 spu_restore(&ctx->csa, spu);
98 spu->timestamp = jiffies; 118 spu->timestamp = jiffies;
99 spu_cpu_affinity_set(spu, raw_smp_processor_id()); 119 spu_cpu_affinity_set(spu, raw_smp_processor_id());
120 spu_switch_notify(spu, ctx);
100} 121}
101 122
102static inline void unbind_context(struct spu *spu, struct spu_context *ctx) 123static inline void unbind_context(struct spu *spu, struct spu_context *ctx)
103{ 124{
104 pr_debug("%s: unbind pid=%d SPU=%d NODE=%d\n", __FUNCTION__, 125 pr_debug("%s: unbind pid=%d SPU=%d NODE=%d\n", __FUNCTION__,
105 spu->pid, spu->number, spu->node); 126 spu->pid, spu->number, spu->node);
127 spu_switch_notify(spu, NULL);
106 spu_unmap_mappings(ctx); 128 spu_unmap_mappings(ctx);
107 spu_save(&ctx->csa, spu); 129 spu_save(&ctx->csa, spu);
108 spu->timestamp = jiffies; 130 spu->timestamp = jiffies;
diff --git a/arch/powerpc/platforms/cell/spufs/spufs.h b/arch/powerpc/platforms/cell/spufs/spufs.h
index f6624ceedf70..a0f55ca2d488 100644
--- a/arch/powerpc/platforms/cell/spufs/spufs.h
+++ b/arch/powerpc/platforms/cell/spufs/spufs.h
@@ -50,6 +50,7 @@ struct spu_context {
50 struct address_space *cntl; /* 'control' area mappings. */ 50 struct address_space *cntl; /* 'control' area mappings. */
51 struct address_space *signal1; /* 'signal1' area mappings. */ 51 struct address_space *signal1; /* 'signal1' area mappings. */
52 struct address_space *signal2; /* 'signal2' area mappings. */ 52 struct address_space *signal2; /* 'signal2' area mappings. */
53 u64 object_id; /* user space pointer for oprofile */
53 54
54 enum { SPU_STATE_RUNNABLE, SPU_STATE_SAVED } state; 55 enum { SPU_STATE_RUNNABLE, SPU_STATE_SAVED } state;
55 struct rw_semaphore state_sema; 56 struct rw_semaphore state_sema;