diff options
-rw-r--r-- | arch/powerpc/platforms/cell/spufs/file.c | 18 | ||||
-rw-r--r-- | arch/powerpc/platforms/cell/spufs/sched.c | 22 | ||||
-rw-r--r-- | arch/powerpc/platforms/cell/spufs/spufs.h | 1 | ||||
-rw-r--r-- | include/asm-powerpc/spu.h | 18 |
4 files changed, 58 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 | } |
1488 | DEFINE_SIMPLE_ATTRIBUTE(spufs_id_ops, spufs_id_get, NULL, "0x%llx\n") | 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 | struct tree_descr spufs_dir_contents[] = { | 1505 | struct 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 | ||
79 | static BLOCKING_NOTIFIER_HEAD(spu_switch_notifier); | ||
80 | |||
81 | static 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 | |||
87 | int spu_switch_event_register(struct notifier_block * n) | ||
88 | { | ||
89 | return blocking_notifier_chain_register(&spu_switch_notifier, n); | ||
90 | } | ||
91 | |||
92 | int spu_switch_event_unregister(struct notifier_block * n) | ||
93 | { | ||
94 | return blocking_notifier_chain_unregister(&spu_switch_notifier, n); | ||
95 | } | ||
96 | |||
97 | |||
78 | static inline void bind_context(struct spu *spu, struct spu_context *ctx) | 98 | static 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 | ||
102 | static inline void unbind_context(struct spu *spu, struct spu_context *ctx) | 123 | static 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; |
diff --git a/include/asm-powerpc/spu.h b/include/asm-powerpc/spu.h index 83b6dae48efc..e73ea00efd8b 100644 --- a/include/asm-powerpc/spu.h +++ b/include/asm-powerpc/spu.h | |||
@@ -201,6 +201,24 @@ static inline void unregister_spu_syscalls(struct spufs_calls *calls) | |||
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 | * This defines the Local Store, Problem Area and Privlege Area of an SPU. | 222 | * This defines the Local Store, Problem Area and Privlege Area of an SPU. |
205 | */ | 223 | */ |
206 | 224 | ||