* [PATCH 20/25] spufs: Add contents of npc file to SPU coredumps
2007-09-14 6:32 [PATCH 01/25] spufs: staticify file-internal functions & variables Jeremy Kerr
@ 2007-09-14 6:32 ` Jeremy Kerr
2007-09-14 6:32 ` [PATCH 05/25] spufs: fix race condition on gang->aff_ref_spu Jeremy Kerr
` (23 subsequent siblings)
24 siblings, 0 replies; 31+ messages in thread
From: Jeremy Kerr @ 2007-09-14 6:32 UTC (permalink / raw)
To: linuxppc-dev
From: Michael Ellerman <michael@ellerman.id.au>
Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
Signed-off-by: Jeremy Kerr <jk@ozlabs.org>
Acked-by: Arnd Bergmann <arnd.bergmann@de.ibm.com>
---
arch/powerpc/platforms/cell/spufs/file.c | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/arch/powerpc/platforms/cell/spufs/file.c b/arch/powerpc/platforms/cell/spufs/file.c
index 4cd34e5..985c86b 100644
--- a/arch/powerpc/platforms/cell/spufs/file.c
+++ b/arch/powerpc/platforms/cell/spufs/file.c
@@ -1606,12 +1606,17 @@ static void spufs_npc_set(void *data, u64 val)
spu_release(ctx);
}
+static u64 __spufs_npc_get(struct spu_context *ctx)
+{
+ return ctx->ops->npc_read(ctx);
+}
+
static u64 spufs_npc_get(void *data)
{
struct spu_context *ctx = data;
u64 ret;
spu_acquire(ctx);
- ret = ctx->ops->npc_read(ctx);
+ ret = __spufs_npc_get(ctx);
spu_release(ctx);
return ret;
}
@@ -2242,5 +2247,6 @@ struct spufs_coredump_reader spufs_coredump_read[] = {
{ "proxydma_info", __spufs_proxydma_info_read,
NULL, sizeof(struct spu_proxydma_info)},
{ "object-id", NULL, __spufs_object_id_get, 19 },
+ { "npc", NULL, __spufs_npc_get, 19 },
{ NULL },
};
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [PATCH 05/25] spufs: fix race condition on gang->aff_ref_spu
2007-09-14 6:32 [PATCH 01/25] spufs: staticify file-internal functions & variables Jeremy Kerr
2007-09-14 6:32 ` [PATCH 20/25] spufs: Add contents of npc file to SPU coredumps Jeremy Kerr
@ 2007-09-14 6:32 ` Jeremy Kerr
2007-09-14 6:32 ` [PATCH 08/25] Fix restore_decr_wrapped() to match CBE Handbook Jeremy Kerr
` (22 subsequent siblings)
24 siblings, 0 replies; 31+ messages in thread
From: Jeremy Kerr @ 2007-09-14 6:32 UTC (permalink / raw)
To: linuxppc-dev
From: Andre Detsch <adetsch@br.ibm.com>
Affinity reference point location (gang->aff_ref_spu) is reset
when the whole gang is descheduled. However, the last member of
a gang can be descheduled while we are trying to schedule another
member of the gang. This was leading to a race condition, and
the code was using gang->aff_ref_spu in an unsafe manner.
By holding the gang->aff_mutex a little bit longer, and increment
gang->aff_sched_count (which controls when gang->aff_ref_spu
should be reset) a little bit earlier, the problem is fixed.
Signed-off-by: Andre Detsch <adetsch@br.ibm.com>
Signed-off-by: Jeremy Kerr <jk@ozlabs.org>
---
arch/powerpc/platforms/cell/spufs/sched.c | 49 +++++++++++++++++++-----------
1 file changed, 32 insertions(+), 17 deletions(-)
diff --git a/arch/powerpc/platforms/cell/spufs/sched.c b/arch/powerpc/platforms/cell/spufs/sched.c
index c784edd..17806e0 100644
--- a/arch/powerpc/platforms/cell/spufs/sched.c
+++ b/arch/powerpc/platforms/cell/spufs/sched.c
@@ -230,8 +230,6 @@ static void spu_bind_context(struct spu *spu, struct spu_context *ctx)
if (ctx->flags & SPU_CREATE_NOSCHED)
atomic_inc(&cbe_spu_info[spu->node].reserved_spus);
- if (!list_empty(&ctx->aff_list))
- atomic_inc(&ctx->gang->aff_sched_count);
ctx->stats.slb_flt_base = spu->stats.slb_flt;
ctx->stats.class2_intr_base = spu->stats.class2_intr;
@@ -392,7 +390,6 @@ static int has_affinity(struct spu_context *ctx)
if (list_empty(&ctx->aff_list))
return 0;
- mutex_lock(&gang->aff_mutex);
if (!gang->aff_ref_spu) {
if (!(gang->aff_flags & AFF_MERGED))
aff_merge_remaining_ctxs(gang);
@@ -400,7 +397,6 @@ static int has_affinity(struct spu_context *ctx)
aff_set_offsets(gang);
aff_set_ref_point_location(gang);
}
- mutex_unlock(&gang->aff_mutex);
return gang->aff_ref_spu != NULL;
}
@@ -418,9 +414,16 @@ static void spu_unbind_context(struct spu *spu, struct spu_context *ctx)
if (spu->ctx->flags & SPU_CREATE_NOSCHED)
atomic_dec(&cbe_spu_info[spu->node].reserved_spus);
- if (!list_empty(&ctx->aff_list))
- if (atomic_dec_and_test(&ctx->gang->aff_sched_count))
- ctx->gang->aff_ref_spu = NULL;
+
+ if (ctx->gang){
+ mutex_lock(&ctx->gang->aff_mutex);
+ if (has_affinity(ctx)) {
+ if (atomic_dec_and_test(&ctx->gang->aff_sched_count))
+ ctx->gang->aff_ref_spu = NULL;
+ }
+ mutex_unlock(&ctx->gang->aff_mutex);
+ }
+
spu_switch_notify(spu, NULL);
spu_unmap_mappings(ctx);
spu_save(&ctx->csa, spu);
@@ -511,20 +514,32 @@ static void spu_prio_wait(struct spu_context *ctx)
static struct spu *spu_get_idle(struct spu_context *ctx)
{
- struct spu *spu;
+ struct spu *spu, *aff_ref_spu;
int node, n;
- if (has_affinity(ctx)) {
- node = ctx->gang->aff_ref_spu->node;
+ if (ctx->gang) {
+ mutex_lock(&ctx->gang->aff_mutex);
+ if (has_affinity(ctx)) {
+ aff_ref_spu = ctx->gang->aff_ref_spu;
+ atomic_inc(&ctx->gang->aff_sched_count);
+ mutex_unlock(&ctx->gang->aff_mutex);
+ node = aff_ref_spu->node;
- mutex_lock(&cbe_spu_info[node].list_mutex);
- spu = ctx_location(ctx->gang->aff_ref_spu, ctx->aff_offset, node);
- if (spu && spu->alloc_state == SPU_FREE)
- goto found;
- mutex_unlock(&cbe_spu_info[node].list_mutex);
- return NULL;
- }
+ mutex_lock(&cbe_spu_info[node].list_mutex);
+ spu = ctx_location(aff_ref_spu, ctx->aff_offset, node);
+ if (spu && spu->alloc_state == SPU_FREE)
+ goto found;
+ mutex_unlock(&cbe_spu_info[node].list_mutex);
+ mutex_lock(&ctx->gang->aff_mutex);
+ if (atomic_dec_and_test(&ctx->gang->aff_sched_count))
+ ctx->gang->aff_ref_spu = NULL;
+ mutex_unlock(&ctx->gang->aff_mutex);
+
+ return NULL;
+ }
+ mutex_unlock(&ctx->gang->aff_mutex);
+ }
node = cpu_to_node(raw_smp_processor_id());
for (n = 0; n < MAX_NUMNODES; n++, node++) {
node = (node < MAX_NUMNODES) ? node : 0;
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [PATCH 08/25] Fix restore_decr_wrapped() to match CBE Handbook
2007-09-14 6:32 [PATCH 01/25] spufs: staticify file-internal functions & variables Jeremy Kerr
2007-09-14 6:32 ` [PATCH 20/25] spufs: Add contents of npc file to SPU coredumps Jeremy Kerr
2007-09-14 6:32 ` [PATCH 05/25] spufs: fix race condition on gang->aff_ref_spu Jeremy Kerr
@ 2007-09-14 6:32 ` Jeremy Kerr
2007-09-14 6:32 ` [PATCH 18/25] spufs: Get rid of spufs_coredump_num_notes, it's not needed if we NULL terminate Jeremy Kerr
` (21 subsequent siblings)
24 siblings, 0 replies; 31+ messages in thread
From: Jeremy Kerr @ 2007-09-14 6:32 UTC (permalink / raw)
To: linuxppc-dev
Based on an original patch from Masato Noguchi
<Masato.Noguchi@jp.sony.com>.
We're currently not restoring the SPE decrementer as specified by the
CBE handbook. This change fixes our implementation to match, and makes
the function read more like the docs.
Signed-off-by: Jeremy Kerr <jk@ozlabs.org>
---
arch/powerpc/platforms/cell/spufs/switch.c | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/arch/powerpc/platforms/cell/spufs/switch.c b/arch/powerpc/platforms/cell/spufs/switch.c
index 2506619..de7e5ee 100644
--- a/arch/powerpc/platforms/cell/spufs/switch.c
+++ b/arch/powerpc/platforms/cell/spufs/switch.c
@@ -1559,15 +1559,15 @@ static inline void restore_decr_wrapped(struct spu_state *csa, struct spu *spu)
* "wrapped" flag is set, OR in a '1' to
* CSA.SPU_Event_Status[Tm].
*/
- if (csa->lscsa->decr_status.slot[0] & SPU_DECR_STATUS_WRAPPED) {
- csa->spu_chnldata_RW[0] |= 0x20;
- }
- if ((csa->lscsa->decr_status.slot[0] & SPU_DECR_STATUS_WRAPPED) &&
- (csa->spu_chnlcnt_RW[0] == 0 &&
- ((csa->spu_chnldata_RW[2] & 0x20) == 0x0) &&
- ((csa->spu_chnldata_RW[0] & 0x20) != 0x1))) {
+ if (!(csa->lscsa->decr_status.slot[0] & SPU_DECR_STATUS_WRAPPED))
+ return;
+
+ if ((csa->spu_chnlcnt_RW[0] == 0) &&
+ (csa->spu_chnldata_RW[1] & 0x20) &&
+ !(csa->spu_chnldata_RW[0] & 0x20))
csa->spu_chnlcnt_RW[0] = 1;
- }
+
+ csa->spu_chnldata_RW[0] |= 0x20;
}
static inline void restore_ch_part1(struct spu_state *csa, struct spu *spu)
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [PATCH 18/25] spufs: Get rid of spufs_coredump_num_notes, it's not needed if we NULL terminate
2007-09-14 6:32 [PATCH 01/25] spufs: staticify file-internal functions & variables Jeremy Kerr
` (2 preceding siblings ...)
2007-09-14 6:32 ` [PATCH 08/25] Fix restore_decr_wrapped() to match CBE Handbook Jeremy Kerr
@ 2007-09-14 6:32 ` Jeremy Kerr
2007-09-14 6:32 ` [PATCH 16/25] spufs: Correctly calculate the size of the local-store to dump Jeremy Kerr
` (20 subsequent siblings)
24 siblings, 0 replies; 31+ messages in thread
From: Jeremy Kerr @ 2007-09-14 6:32 UTC (permalink / raw)
To: linuxppc-dev
From: Michael Ellerman <michael@ellerman.id.au>
The spufs_coredump_read array is NULL terminated, and we also store the size.
We only need one or the other, and the other arrays in file.c are NULL
terminated, so do that.
Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
Signed-off-by: Jeremy Kerr <jk@ozlabs.org>
---
arch/powerpc/platforms/cell/spufs/coredump.c | 4 ++--
arch/powerpc/platforms/cell/spufs/file.c | 4 +---
2 files changed, 3 insertions(+), 5 deletions(-)
diff --git a/arch/powerpc/platforms/cell/spufs/coredump.c b/arch/powerpc/platforms/cell/spufs/coredump.c
index 52d6219..fc988fd 100644
--- a/arch/powerpc/platforms/cell/spufs/coredump.c
+++ b/arch/powerpc/platforms/cell/spufs/coredump.c
@@ -72,7 +72,7 @@ static int spufs_ctx_note_size(struct spu_context *ctx, int dfd)
char *name;
char fullname[80];
- for (i = 0; spufs_coredump_read[i].name; i++) {
+ for (i = 0; spufs_coredump_read[i].name != NULL; i++) {
name = spufs_coredump_read[i].name;
sz = spufs_coredump_read[i].size;
@@ -194,7 +194,7 @@ static void spufs_arch_write_notes(struct file *file)
while ((ctx = coredump_next_context(&fd)) != NULL) {
spu_acquire_saved(ctx);
- for (j = 0; j < spufs_coredump_num_notes; j++)
+ for (j = 0; spufs_coredump_read[j].name != NULL; j++)
spufs_arch_write_note(ctx, j, file, fd);
spu_release_saved(ctx);
diff --git a/arch/powerpc/platforms/cell/spufs/file.c b/arch/powerpc/platforms/cell/spufs/file.c
index 85edbec..6095fb1 100644
--- a/arch/powerpc/platforms/cell/spufs/file.c
+++ b/arch/powerpc/platforms/cell/spufs/file.c
@@ -2250,7 +2250,5 @@ struct spufs_coredump_reader spufs_coredump_read[] = {
{ "proxydma_info", __spufs_proxydma_info_read,
NULL, sizeof(struct spu_proxydma_info)},
{ "object-id", NULL, __spufs_object_id_get, 19 },
- { },
+ { NULL },
};
-int spufs_coredump_num_notes = ARRAY_SIZE(spufs_coredump_read) - 1;
-
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [PATCH 16/25] spufs: Correctly calculate the size of the local-store to dump
2007-09-14 6:32 [PATCH 01/25] spufs: staticify file-internal functions & variables Jeremy Kerr
` (3 preceding siblings ...)
2007-09-14 6:32 ` [PATCH 18/25] spufs: Get rid of spufs_coredump_num_notes, it's not needed if we NULL terminate Jeremy Kerr
@ 2007-09-14 6:32 ` Jeremy Kerr
2007-09-14 6:32 ` [PATCH 10/25] spusched: fix null pointer dereference in find_victim Jeremy Kerr
` (19 subsequent siblings)
24 siblings, 0 replies; 31+ messages in thread
From: Jeremy Kerr @ 2007-09-14 6:32 UTC (permalink / raw)
To: linuxppc-dev
From: Michael Ellerman <michael@ellerman.id.au>
The routine to dump the local store, __spufs_mem_read(), does not take the
spu_lslr_RW value into account - so we shouldn't check it when we're
calculating the size either.
Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
Signed-off-by: Jeremy Kerr <jk@ozlabs.org>
Acked-by: Arnd Bergmann <arnd.bergmann@de.ibm.com>
---
arch/powerpc/platforms/cell/spufs/coredump.c | 16 ++--------------
1 file changed, 2 insertions(+), 14 deletions(-)
diff --git a/arch/powerpc/platforms/cell/spufs/coredump.c b/arch/powerpc/platforms/cell/spufs/coredump.c
index c65b717..52d6219 100644
--- a/arch/powerpc/platforms/cell/spufs/coredump.c
+++ b/arch/powerpc/platforms/cell/spufs/coredump.c
@@ -66,11 +66,6 @@ static int spufs_dump_seek(struct file *file, loff_t off)
return 1;
}
-static u64 ctx_ls_size(struct spu_context *ctx)
-{
- return ctx->csa.priv2.spu_lslr_RW + 1;
-}
-
static int spufs_ctx_note_size(struct spu_context *ctx, int dfd)
{
int i, sz, total = 0;
@@ -85,10 +80,7 @@ static int spufs_ctx_note_size(struct spu_context *ctx, int dfd)
total += sizeof(struct elf_note);
total += roundup(strlen(fullname) + 1, 4);
- if (!strcmp(name, "mem"))
- total += roundup(ctx_ls_size(ctx), 4);
- else
- total += roundup(sz, 4);
+ total += roundup(sz, 4);
}
return total;
@@ -164,11 +156,7 @@ static void spufs_arch_write_note(struct spu_context *ctx, int i,
return;
name = spufs_coredump_read[i].name;
-
- if (!strcmp(name, "mem"))
- sz = ctx_ls_size(ctx);
- else
- sz = spufs_coredump_read[i].size;
+ sz = spufs_coredump_read[i].size;
sprintf(fullname, "SPU/%d/%s", dfd, name);
en.n_namesz = strlen(fullname) + 1;
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [PATCH 10/25] spusched: fix null pointer dereference in find_victim
2007-09-14 6:32 [PATCH 01/25] spufs: staticify file-internal functions & variables Jeremy Kerr
` (4 preceding siblings ...)
2007-09-14 6:32 ` [PATCH 16/25] spufs: Correctly calculate the size of the local-store to dump Jeremy Kerr
@ 2007-09-14 6:32 ` Jeremy Kerr
2007-09-14 7:44 ` Christoph Hellwig
2007-09-14 6:32 ` [PATCH 15/25] spufs: Write some SPU coredump values as ASCII Jeremy Kerr
` (18 subsequent siblings)
24 siblings, 1 reply; 31+ messages in thread
From: Jeremy Kerr @ 2007-09-14 6:32 UTC (permalink / raw)
To: linuxppc-dev
From: Christoph Hellwig <hch@lst.de>
find_victim can dereference a NULL pointer when iterating over the list
of victim spus because list_mutex only guarantees spu->ct to be stable,
but of course not to be non-NULL.
Also fix find_victim to not call spu_unbind_context without list_mutex
because that violates the above guarantee.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Arnd Bergmann <arnd.bergmann@de.ibm.com>
Signed-off-by: Jeremy Kerr <jk@ozlabs.org>
---
arch/powerpc/platforms/cell/spufs/sched.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/arch/powerpc/platforms/cell/spufs/sched.c b/arch/powerpc/platforms/cell/spufs/sched.c
index 17806e0..4d257b3 100644
--- a/arch/powerpc/platforms/cell/spufs/sched.c
+++ b/arch/powerpc/platforms/cell/spufs/sched.c
@@ -594,7 +594,7 @@ static struct spu *find_victim(struct spu_context *ctx)
list_for_each_entry(spu, &cbe_spu_info[node].spus, cbe_list) {
struct spu_context *tmp = spu->ctx;
- if (tmp->prio > ctx->prio &&
+ if (tmp && tmp->prio > ctx->prio &&
(!victim || tmp->prio > victim->prio))
victim = spu->ctx;
}
@@ -626,9 +626,9 @@ static struct spu *find_victim(struct spu_context *ctx)
mutex_lock(&cbe_spu_info[node].list_mutex);
cbe_spu_info[node].nr_active--;
+ spu_unbind_context(spu, victim);
mutex_unlock(&cbe_spu_info[node].list_mutex);
- spu_unbind_context(spu, victim);
victim->stats.invol_ctx_switch++;
spu->stats.invol_ctx_switch++;
mutex_unlock(&victim->state_mutex);
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [PATCH 15/25] spufs: Write some SPU coredump values as ASCII
2007-09-14 6:32 [PATCH 01/25] spufs: staticify file-internal functions & variables Jeremy Kerr
` (5 preceding siblings ...)
2007-09-14 6:32 ` [PATCH 10/25] spusched: fix null pointer dereference in find_victim Jeremy Kerr
@ 2007-09-14 6:32 ` Jeremy Kerr
2007-09-14 6:32 ` [PATCH 24/25] spufs: Respect RLIMIT_CORE in spu coredump code Jeremy Kerr
` (17 subsequent siblings)
24 siblings, 0 replies; 31+ messages in thread
From: Jeremy Kerr @ 2007-09-14 6:32 UTC (permalink / raw)
To: linuxppc-dev
From: Michael Ellerman <michael@ellerman.id.au>
Unfortunately GDB expects some of the SPU coredump values to be identical
in format to what is found in spufs. This means we need to dump some of
the values as ASCII strings, not the actual values.
Because we don't know what the values will be, we always print the values
with the format "0x%.16lx", that way we know the result will be 19 bytes.
do_coredump_read() doesn't take a __user buffer, so remove the annotation,
and because we know that it's safe to just snprintf() directly to it.
Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
Signed-off-by: Jeremy Kerr <jk@ozlabs.org>
---
arch/powerpc/platforms/cell/spufs/coredump.c | 8 +++++---
arch/powerpc/platforms/cell/spufs/file.c | 14 +++++++-------
2 files changed, 12 insertions(+), 10 deletions(-)
diff --git a/arch/powerpc/platforms/cell/spufs/coredump.c b/arch/powerpc/platforms/cell/spufs/coredump.c
index 21283f6..c65b717 100644
--- a/arch/powerpc/platforms/cell/spufs/coredump.c
+++ b/arch/powerpc/platforms/cell/spufs/coredump.c
@@ -31,7 +31,7 @@
#include "spufs.h"
-static ssize_t do_coredump_read(int num, struct spu_context *ctx, void __user *buffer,
+static ssize_t do_coredump_read(int num, struct spu_context *ctx, void *buffer,
size_t size, loff_t *off)
{
u64 data;
@@ -41,8 +41,10 @@ static ssize_t do_coredump_read(int num, struct spu_context *ctx, void __user *b
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;
+ ret = snprintf(buffer, size, "0x%.16lx", data);
+ if (ret >= size)
+ return size;
+ return ++ret; /* count trailing NULL */
}
/*
diff --git a/arch/powerpc/platforms/cell/spufs/file.c b/arch/powerpc/platforms/cell/spufs/file.c
index 18ddde8..85edbec 100644
--- a/arch/powerpc/platforms/cell/spufs/file.c
+++ b/arch/powerpc/platforms/cell/spufs/file.c
@@ -2233,16 +2233,16 @@ struct tree_descr spufs_dir_nosched_contents[] = {
struct spufs_coredump_reader spufs_coredump_read[] = {
{ "regs", __spufs_regs_read, NULL, sizeof(struct spu_reg128[128])},
{ "fpcr", __spufs_fpcr_read, NULL, sizeof(struct spu_reg128) },
- { "lslr", NULL, __spufs_lslr_get, 11 },
- { "decr", NULL, __spufs_decr_get, 11 },
- { "decr_status", NULL, __spufs_decr_status_get, 11 },
+ { "lslr", NULL, __spufs_lslr_get, 19 },
+ { "decr", NULL, __spufs_decr_get, 19 },
+ { "decr_status", NULL, __spufs_decr_status_get, 19 },
{ "mem", __spufs_mem_read, NULL, LS_SIZE, },
{ "signal1", __spufs_signal1_read, NULL, sizeof(u32) },
- { "signal1_type", NULL, __spufs_signal1_type_get, 2 },
+ { "signal1_type", NULL, __spufs_signal1_type_get, 19 },
{ "signal2", __spufs_signal2_read, NULL, sizeof(u32) },
- { "signal2_type", NULL, __spufs_signal2_type_get, 2 },
- { "event_mask", NULL, __spufs_event_mask_get, 8 },
- { "event_status", NULL, __spufs_event_status_get, 8 },
+ { "signal2_type", NULL, __spufs_signal2_type_get, 19 },
+ { "event_mask", NULL, __spufs_event_mask_get, 19 },
+ { "event_status", NULL, __spufs_event_status_get, 19 },
{ "mbox_info", __spufs_mbox_info_read, NULL, sizeof(u32) },
{ "ibox_info", __spufs_ibox_info_read, NULL, sizeof(u32) },
{ "wbox_info", __spufs_wbox_info_read, NULL, 4 * sizeof(u32)},
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [PATCH 24/25] spufs: Respect RLIMIT_CORE in spu coredump code
2007-09-14 6:32 [PATCH 01/25] spufs: staticify file-internal functions & variables Jeremy Kerr
` (6 preceding siblings ...)
2007-09-14 6:32 ` [PATCH 15/25] spufs: Write some SPU coredump values as ASCII Jeremy Kerr
@ 2007-09-14 6:32 ` Jeremy Kerr
2007-09-14 6:32 ` [PATCH 13/25] spufs: Call spu_acquire_saved() before calculating the SPU note sizes Jeremy Kerr
` (16 subsequent siblings)
24 siblings, 0 replies; 31+ messages in thread
From: Jeremy Kerr @ 2007-09-14 6:32 UTC (permalink / raw)
To: linuxppc-dev
From: Michael Ellerman <michael@ellerman.id.au>
Currently the spu coredump code doesn't respect the ulimit, it should.
Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
Signed-off-by: Jeremy Kerr <jk@ozlabs.org>
---
arch/powerpc/platforms/cell/spufs/coredump.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/arch/powerpc/platforms/cell/spufs/coredump.c b/arch/powerpc/platforms/cell/spufs/coredump.c
index 6b8aef6..80f6236 100644
--- a/arch/powerpc/platforms/cell/spufs/coredump.c
+++ b/arch/powerpc/platforms/cell/spufs/coredump.c
@@ -53,8 +53,12 @@ static ssize_t do_coredump_read(int num, struct spu_context *ctx, void *buffer,
*/
static int spufs_dump_write(struct file *file, const void *addr, int nr, loff_t *foffset)
{
+ unsigned long limit = current->signal->rlim[RLIMIT_CORE].rlim_cur;
ssize_t written;
+ if (*foffset + nr > limit)
+ return -EIO;
+
written = file->f_op->write(file, addr, nr, &file->f_pos);
*foffset += written;
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [PATCH 13/25] spufs: Call spu_acquire_saved() before calculating the SPU note sizes
2007-09-14 6:32 [PATCH 01/25] spufs: staticify file-internal functions & variables Jeremy Kerr
` (7 preceding siblings ...)
2007-09-14 6:32 ` [PATCH 24/25] spufs: Respect RLIMIT_CORE in spu coredump code Jeremy Kerr
@ 2007-09-14 6:32 ` Jeremy Kerr
2007-09-14 6:32 ` [PATCH 14/25] spufs: Use computed sizes/#defines rather than literals in SPU coredump code Jeremy Kerr
` (15 subsequent siblings)
24 siblings, 0 replies; 31+ messages in thread
From: Jeremy Kerr @ 2007-09-14 6:32 UTC (permalink / raw)
To: linuxppc-dev
From: Michael Ellerman <michael@ellerman.id.au>
It makes sense to stop the SPU processes as soon as possible. Also if we
dont acquire_saved() I think there's a possibility that the value in
csa.priv2.spu_lslr_RW won't be accurate.
Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
Signed-off-by: Jeremy Kerr <jk@ozlabs.org>
---
arch/powerpc/platforms/cell/spufs/coredump.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/arch/powerpc/platforms/cell/spufs/coredump.c b/arch/powerpc/platforms/cell/spufs/coredump.c
index 6663669..21283f6 100644
--- a/arch/powerpc/platforms/cell/spufs/coredump.c
+++ b/arch/powerpc/platforms/cell/spufs/coredump.c
@@ -135,7 +135,9 @@ static int spufs_arch_notes_size(void)
fd = 0;
while ((ctx = coredump_next_context(&fd)) != NULL) {
+ spu_acquire_saved(ctx);
rc = spufs_ctx_note_size(ctx, fd);
+ spu_release_saved(ctx);
if (rc < 0)
break;
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [PATCH 14/25] spufs: Use computed sizes/#defines rather than literals in SPU coredump code
2007-09-14 6:32 [PATCH 01/25] spufs: staticify file-internal functions & variables Jeremy Kerr
` (8 preceding siblings ...)
2007-09-14 6:32 ` [PATCH 13/25] spufs: Call spu_acquire_saved() before calculating the SPU note sizes Jeremy Kerr
@ 2007-09-14 6:32 ` Jeremy Kerr
2007-09-14 6:32 ` [PATCH 07/25] spufs: remove asmlinkage from spufs_calls Jeremy Kerr
` (14 subsequent siblings)
24 siblings, 0 replies; 31+ messages in thread
From: Jeremy Kerr @ 2007-09-14 6:32 UTC (permalink / raw)
To: linuxppc-dev
From: Michael Ellerman <michael@ellerman.id.au>
The spufs_coredump_reader array contains the size of the data that will be
returned by the read routine. Currently these are specified as literals, and
though some are obvious, sizeof(u32) == 4, others are not, 69 * 8 == ???
Instead, use sizeof() whatever type is returned by each routine, or in
the case of spufs_mem_read() the #define LS_SIZE.
Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
Signed-off-by: Jeremy Kerr <jk@ozlabs.org>
---
arch/powerpc/platforms/cell/spufs/file.c | 21 +++++++++++----------
1 file changed, 11 insertions(+), 10 deletions(-)
diff --git a/arch/powerpc/platforms/cell/spufs/file.c b/arch/powerpc/platforms/cell/spufs/file.c
index a4a8770..18ddde8 100644
--- a/arch/powerpc/platforms/cell/spufs/file.c
+++ b/arch/powerpc/platforms/cell/spufs/file.c
@@ -2231,23 +2231,24 @@ struct tree_descr spufs_dir_nosched_contents[] = {
};
struct spufs_coredump_reader spufs_coredump_read[] = {
- { "regs", __spufs_regs_read, NULL, 128 * 16 },
- { "fpcr", __spufs_fpcr_read, NULL, 16 },
+ { "regs", __spufs_regs_read, NULL, sizeof(struct spu_reg128[128])},
+ { "fpcr", __spufs_fpcr_read, NULL, sizeof(struct spu_reg128) },
{ "lslr", NULL, __spufs_lslr_get, 11 },
{ "decr", NULL, __spufs_decr_get, 11 },
{ "decr_status", NULL, __spufs_decr_status_get, 11 },
- { "mem", __spufs_mem_read, NULL, 256 * 1024, },
- { "signal1", __spufs_signal1_read, NULL, 4 },
+ { "mem", __spufs_mem_read, NULL, LS_SIZE, },
+ { "signal1", __spufs_signal1_read, NULL, sizeof(u32) },
{ "signal1_type", NULL, __spufs_signal1_type_get, 2 },
- { "signal2", __spufs_signal2_read, NULL, 4 },
+ { "signal2", __spufs_signal2_read, NULL, sizeof(u32) },
{ "signal2_type", NULL, __spufs_signal2_type_get, 2 },
{ "event_mask", NULL, __spufs_event_mask_get, 8 },
{ "event_status", NULL, __spufs_event_status_get, 8 },
- { "mbox_info", __spufs_mbox_info_read, NULL, 4 },
- { "ibox_info", __spufs_ibox_info_read, NULL, 4 },
- { "wbox_info", __spufs_wbox_info_read, NULL, 16 },
- { "dma_info", __spufs_dma_info_read, NULL, 69 * 8 },
- { "proxydma_info", __spufs_proxydma_info_read, NULL, 35 * 8 },
+ { "mbox_info", __spufs_mbox_info_read, NULL, sizeof(u32) },
+ { "ibox_info", __spufs_ibox_info_read, NULL, sizeof(u32) },
+ { "wbox_info", __spufs_wbox_info_read, NULL, 4 * sizeof(u32)},
+ { "dma_info", __spufs_dma_info_read, NULL, sizeof(struct spu_dma_info)},
+ { "proxydma_info", __spufs_proxydma_info_read,
+ NULL, sizeof(struct spu_proxydma_info)},
{ "object-id", NULL, __spufs_object_id_get, 19 },
{ },
};
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [PATCH 07/25] spufs: remove asmlinkage from spufs_calls
2007-09-14 6:32 [PATCH 01/25] spufs: staticify file-internal functions & variables Jeremy Kerr
` (9 preceding siblings ...)
2007-09-14 6:32 ` [PATCH 14/25] spufs: Use computed sizes/#defines rather than literals in SPU coredump code Jeremy Kerr
@ 2007-09-14 6:32 ` Jeremy Kerr
2007-09-14 6:32 ` [PATCH 04/25] spufs: make isolated loader properly aligned Jeremy Kerr
` (13 subsequent siblings)
24 siblings, 0 replies; 31+ messages in thread
From: Jeremy Kerr @ 2007-09-14 6:32 UTC (permalink / raw)
To: linuxppc-dev
spu_create and spu_run are wrapped by the cell syscall layer, so
we don't need the asmlinkage.
Signed-off-by: Jeremy Kerr <jk@ozlabs.org>
---
include/asm-powerpc/spu.h | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/include/asm-powerpc/spu.h b/include/asm-powerpc/spu.h
index 383ecfd..eb1159c 100644
--- a/include/asm-powerpc/spu.h
+++ b/include/asm-powerpc/spu.h
@@ -239,10 +239,10 @@ extern long spu_sys_callback(struct spu_syscall_block *s);
/* syscalls implemented in spufs */
struct file;
struct spufs_calls {
- asmlinkage long (*create_thread)(const char __user *name,
+ long (*create_thread)(const char __user *name,
unsigned int flags, mode_t mode,
struct file *neighbor);
- asmlinkage long (*spu_run)(struct file *filp, __u32 __user *unpc,
+ long (*spu_run)(struct file *filp, __u32 __user *unpc,
__u32 __user *ustatus);
struct module *owner;
};
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [PATCH 04/25] spufs: make isolated loader properly aligned
2007-09-14 6:32 [PATCH 01/25] spufs: staticify file-internal functions & variables Jeremy Kerr
` (10 preceding siblings ...)
2007-09-14 6:32 ` [PATCH 07/25] spufs: remove asmlinkage from spufs_calls Jeremy Kerr
@ 2007-09-14 6:32 ` Jeremy Kerr
2007-09-14 6:32 ` [PATCH 23/25] spufs: Handle errors in SPU coredump code, and support coredump to a pipe Jeremy Kerr
` (12 subsequent siblings)
24 siblings, 0 replies; 31+ messages in thread
From: Jeremy Kerr @ 2007-09-14 6:32 UTC (permalink / raw)
To: linuxppc-dev
From: Sebastian Siewior <cbe-oss-dev@ml.breakpoint.cc>
According to the comment in spufs_init_isolated_loader(), the isolated
loader should be aligned on a 16 byte boundary.
ARCH_{KMALLOC,SLAB}_MINALIGN is not defined so only 8 byte alignment is
guaranteed.
This patch enforces alignment via __get_free_pages.
Signed-off-by: Sebastian Siewior <sebastian@breakpoint.cc>
Signed-off-by: Jeremy Kerr <jk@ozlabs.org>
---
arch/powerpc/platforms/cell/spufs/inode.c | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/arch/powerpc/platforms/cell/spufs/inode.c b/arch/powerpc/platforms/cell/spufs/inode.c
index b3d0dd1..e210a4b 100644
--- a/arch/powerpc/platforms/cell/spufs/inode.c
+++ b/arch/powerpc/platforms/cell/spufs/inode.c
@@ -43,6 +43,7 @@
static struct kmem_cache *spufs_inode_cache;
char *isolated_loader;
+static int isolated_loader_size;
static struct inode *
spufs_alloc_inode(struct super_block *sb)
@@ -667,7 +668,8 @@ spufs_parse_options(char *options, struct inode *root)
static void spufs_exit_isolated_loader(void)
{
- kfree(isolated_loader);
+ free_pages((unsigned long) isolated_loader,
+ get_order(isolated_loader_size));
}
static void
@@ -685,11 +687,12 @@ spufs_init_isolated_loader(void)
if (!loader)
return;
- /* kmalloc should align on a 16 byte boundary..* */
- isolated_loader = kmalloc(size, GFP_KERNEL);
+ /* the loader must be align on a 16 byte boundary */
+ isolated_loader = (char *)__get_free_pages(GFP_KERNEL, get_order(size));
if (!isolated_loader)
return;
+ isolated_loader_size = size;
memcpy(isolated_loader, loader, size);
printk(KERN_INFO "spufs: SPU isolation mode enabled\n");
}
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [PATCH 23/25] spufs: Handle errors in SPU coredump code, and support coredump to a pipe
2007-09-14 6:32 [PATCH 01/25] spufs: staticify file-internal functions & variables Jeremy Kerr
` (11 preceding siblings ...)
2007-09-14 6:32 ` [PATCH 04/25] spufs: make isolated loader properly aligned Jeremy Kerr
@ 2007-09-14 6:32 ` Jeremy Kerr
2007-09-14 6:32 ` [PATCH 22/25] spufs: Cleanup ELF coredump extra notes logic Jeremy Kerr
` (11 subsequent siblings)
24 siblings, 0 replies; 31+ messages in thread
From: Jeremy Kerr @ 2007-09-14 6:32 UTC (permalink / raw)
To: linuxppc-dev
From: Michael Ellerman <michael@ellerman.id.au>
Rework spufs_coredump_extra_notes_write() to check for and return errors.
If we're coredumping to a pipe we can't trust file->f_pos, we need to
maintain the foffset value passed to us. The cleanest way to do this is
to have the low level write routine increment foffset when we've
successfully written.
Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
Signed-off-by: Jeremy Kerr <jk@ozlabs.org>
---
arch/powerpc/platforms/cell/spu_syscalls.c | 8 --
arch/powerpc/platforms/cell/spufs/coredump.c | 89 ++++++++++++++++++---------
arch/powerpc/platforms/cell/spufs/spufs.h | 2
include/asm-powerpc/spu.h | 2
4 files changed, 67 insertions(+), 34 deletions(-)
diff --git a/arch/powerpc/platforms/cell/spu_syscalls.c b/arch/powerpc/platforms/cell/spu_syscalls.c
index d9b2fd2..0b69107 100644
--- a/arch/powerpc/platforms/cell/spu_syscalls.c
+++ b/arch/powerpc/platforms/cell/spu_syscalls.c
@@ -129,19 +129,17 @@ int elf_coredump_extra_notes_size(void)
int elf_coredump_extra_notes_write(struct file *file, loff_t *foffset)
{
struct spufs_calls *calls;
+ int ret;
calls = spufs_calls_get();
if (!calls)
return 0;
- calls->coredump_extra_notes_write(file);
+ ret = calls->coredump_extra_notes_write(file, foffset);
spufs_calls_put(calls);
- /* Fudge foffset for now */
- *foffset = file->f_pos;
-
- return 0;
+ return ret;
}
int register_spu_syscalls(struct spufs_calls *calls)
diff --git a/arch/powerpc/platforms/cell/spufs/coredump.c b/arch/powerpc/platforms/cell/spufs/coredump.c
index 6c20e44..6b8aef6 100644
--- a/arch/powerpc/platforms/cell/spufs/coredump.c
+++ b/arch/powerpc/platforms/cell/spufs/coredump.c
@@ -51,19 +51,34 @@ static ssize_t do_coredump_read(int num, struct spu_context *ctx, void *buffer,
* 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 spufs_dump_write(struct file *file, const void *addr, int nr)
+static int spufs_dump_write(struct file *file, const void *addr, int nr, loff_t *foffset)
{
- return file->f_op->write(file, addr, nr, &file->f_pos) == nr;
+ ssize_t written;
+
+ written = file->f_op->write(file, addr, nr, &file->f_pos);
+ *foffset += written;
+
+ if (written != nr)
+ return -EIO;
+
+ return 0;
}
-static int spufs_dump_seek(struct file *file, loff_t off)
+static int spufs_dump_align(struct file *file, char *buf, loff_t new_off,
+ loff_t *foffset)
{
- if (file->f_op->llseek) {
- if (file->f_op->llseek(file, off, 0) != off)
- return 0;
- } else
- file->f_pos = off;
- return 1;
+ int rc, size;
+
+ size = min((loff_t)PAGE_SIZE, new_off - *foffset);
+ memset(buf, 0, size);
+
+ rc = 0;
+ while (rc == 0 && new_off > *foffset) {
+ size = min((loff_t)PAGE_SIZE, new_off - *foffset);
+ rc = spufs_dump_write(file, buf, size, foffset);
+ }
+
+ return rc;
}
static int spufs_ctx_note_size(struct spu_context *ctx, int dfd)
@@ -141,11 +156,11 @@ int spufs_coredump_extra_notes_size(void)
return size;
}
-static void spufs_arch_write_note(struct spu_context *ctx, int i,
- struct file *file, int dfd)
+static int spufs_arch_write_note(struct spu_context *ctx, int i,
+ struct file *file, int dfd, loff_t *foffset)
{
loff_t pos = 0;
- int sz, rc, total = 0;
+ int sz, rc, nread, total = 0;
const int bufsz = PAGE_SIZE;
char *name;
char fullname[80], *buf;
@@ -153,7 +168,7 @@ static void spufs_arch_write_note(struct spu_context *ctx, int i,
buf = (void *)get_zeroed_page(GFP_KERNEL);
if (!buf)
- return;
+ return -ENOMEM;
name = spufs_coredump_read[i].name;
sz = spufs_coredump_read[i].size;
@@ -163,40 +178,60 @@ static void spufs_arch_write_note(struct spu_context *ctx, int i,
en.n_descsz = sz;
en.n_type = NT_SPU;
- if (!spufs_dump_write(file, &en, sizeof(en)))
+ rc = spufs_dump_write(file, &en, sizeof(en), foffset);
+ if (rc)
goto out;
- if (!spufs_dump_write(file, fullname, en.n_namesz))
+
+ rc = spufs_dump_write(file, fullname, en.n_namesz, foffset);
+ if (rc)
goto out;
- if (!spufs_dump_seek(file, roundup((unsigned long)file->f_pos, 4)))
+
+ rc = spufs_dump_align(file, buf, roundup(*foffset, 4), foffset);
+ if (rc)
goto out;
do {
- rc = do_coredump_read(i, ctx, buf, bufsz, &pos);
- if (rc > 0) {
- if (!spufs_dump_write(file, buf, rc))
+ nread = do_coredump_read(i, ctx, buf, bufsz, &pos);
+ if (nread > 0) {
+ rc = spufs_dump_write(file, buf, nread, foffset);
+ if (rc)
goto out;
- total += rc;
+ total += nread;
}
- } while (rc == bufsz && total < sz);
+ } while (nread == bufsz && total < sz);
+
+ if (nread < 0) {
+ rc = nread;
+ goto out;
+ }
+
+ rc = spufs_dump_align(file, buf, roundup(*foffset - total + sz, 4),
+ foffset);
- spufs_dump_seek(file, roundup((unsigned long)file->f_pos
- - total + sz, 4));
out:
free_page((unsigned long)buf);
+ return rc;
}
-void spufs_coredump_extra_notes_write(struct file *file)
+int spufs_coredump_extra_notes_write(struct file *file, loff_t *foffset)
{
struct spu_context *ctx;
- int fd, j;
+ int fd, j, rc;
fd = 0;
while ((ctx = coredump_next_context(&fd)) != NULL) {
spu_acquire_saved(ctx);
- for (j = 0; spufs_coredump_read[j].name != NULL; j++)
- spufs_arch_write_note(ctx, j, file, fd);
+ for (j = 0; spufs_coredump_read[j].name != NULL; j++) {
+ rc = spufs_arch_write_note(ctx, j, file, fd, foffset);
+ if (rc) {
+ spu_release_saved(ctx);
+ return rc;
+ }
+ }
spu_release_saved(ctx);
}
+
+ return 0;
}
diff --git a/arch/powerpc/platforms/cell/spufs/spufs.h b/arch/powerpc/platforms/cell/spufs/spufs.h
index c7b4e03..ca47b99 100644
--- a/arch/powerpc/platforms/cell/spufs/spufs.h
+++ b/arch/powerpc/platforms/cell/spufs/spufs.h
@@ -206,7 +206,7 @@ long spufs_create(struct nameidata *nd, unsigned int flags,
mode_t mode, struct file *filp);
/* ELF coredump callbacks for writing SPU ELF notes */
extern int spufs_coredump_extra_notes_size(void);
-extern void spufs_coredump_extra_notes_write(struct file *file);
+extern int spufs_coredump_extra_notes_write(struct file *file, loff_t *foffset);
extern const struct file_operations spufs_context_fops;
diff --git a/include/asm-powerpc/spu.h b/include/asm-powerpc/spu.h
index f1b10a1..b1accce 100644
--- a/include/asm-powerpc/spu.h
+++ b/include/asm-powerpc/spu.h
@@ -245,7 +245,7 @@ struct spufs_calls {
long (*spu_run)(struct file *filp, __u32 __user *unpc,
__u32 __user *ustatus);
int (*coredump_extra_notes_size)(void);
- void (*coredump_extra_notes_write)(struct file *file);
+ int (*coredump_extra_notes_write)(struct file *file, loff_t *foffset);
struct module *owner;
};
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [PATCH 22/25] spufs: Cleanup ELF coredump extra notes logic
2007-09-14 6:32 [PATCH 01/25] spufs: staticify file-internal functions & variables Jeremy Kerr
` (12 preceding siblings ...)
2007-09-14 6:32 ` [PATCH 23/25] spufs: Handle errors in SPU coredump code, and support coredump to a pipe Jeremy Kerr
@ 2007-09-14 6:32 ` Jeremy Kerr
2007-09-14 6:32 ` [PATCH 21/25] spufs: Combine spufs_coredump_calls with spufs_calls Jeremy Kerr
` (10 subsequent siblings)
24 siblings, 0 replies; 31+ messages in thread
From: Jeremy Kerr @ 2007-09-14 6:32 UTC (permalink / raw)
To: linuxppc-dev
From: Michael Ellerman <michael@ellerman.id.au>
To start with, arch_notes_size() etc. is a little too ambiguous a name for
my liking, so change the function names to be more explicit.
Calling through macros is ugly, especially with hidden parameters, so don't
do that, call the routines directly.
Use ARCH_HAVE_EXTRA_ELF_NOTES as the only flag, and based on it decide
whether we want the extern declarations or the empty versions.
Since we have empty routines, actually use them in the coredump code to
save a few #ifdefs.
We want to change the handling of foffset so that the write routine updates
foffset as it goes, instead of using file->f_pos (so that writing to a pipe
works). So pass foffset to the write routine, and for now just set it to
file->f_pos at the end of writing.
It should also be possible for the write routine to fail, so change it to
return int and treat a non-zero return as failure.
Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
Signed-off-by: Jeremy Kerr <jk@ozlabs.org>
---
arch/powerpc/platforms/cell/spu_syscalls.c | 12 +++++++++---
fs/binfmt_elf.c | 14 +++-----------
include/asm-powerpc/elf.h | 9 ++-------
include/linux/elf.h | 14 ++++++++------
4 files changed, 22 insertions(+), 27 deletions(-)
diff --git a/arch/powerpc/platforms/cell/spu_syscalls.c b/arch/powerpc/platforms/cell/spu_syscalls.c
index cf00251..d9b2fd2 100644
--- a/arch/powerpc/platforms/cell/spu_syscalls.c
+++ b/arch/powerpc/platforms/cell/spu_syscalls.c
@@ -21,6 +21,7 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <linux/file.h>
+#include <linux/fs.h>
#include <linux/module.h>
#include <linux/syscalls.h>
#include <linux/mutex.h>
@@ -109,7 +110,7 @@ asmlinkage long sys_spu_run(int fd, __u32 __user *unpc, __u32 __user *ustatus)
return ret;
}
-int arch_notes_size(void)
+int elf_coredump_extra_notes_size(void)
{
struct spufs_calls *calls;
int ret;
@@ -125,17 +126,22 @@ int arch_notes_size(void)
return ret;
}
-void arch_write_notes(struct file *file)
+int elf_coredump_extra_notes_write(struct file *file, loff_t *foffset)
{
struct spufs_calls *calls;
calls = spufs_calls_get();
if (!calls)
- return;
+ return 0;
calls->coredump_extra_notes_write(file);
spufs_calls_put(calls);
+
+ /* Fudge foffset for now */
+ *foffset = file->f_pos;
+
+ return 0;
}
int register_spu_syscalls(struct spufs_calls *calls)
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index 4482a06..b1013f3 100644
--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -1514,9 +1514,6 @@ static int elf_core_dump(long signr, struct pt_regs *regs, struct file *file)
int thread_status_size = 0;
elf_addr_t *auxv;
unsigned long mm_flags;
-#ifdef ELF_CORE_WRITE_EXTRA_NOTES
- int extra_notes_size;
-#endif
/*
* We no longer stop all VM operations.
@@ -1645,10 +1642,7 @@ static int elf_core_dump(long signr, struct pt_regs *regs, struct file *file)
sz += thread_status_size;
-#ifdef ELF_CORE_WRITE_EXTRA_NOTES
- extra_notes_size = ELF_CORE_EXTRA_NOTES_SIZE;
- sz += extra_notes_size;
-#endif
+ sz += elf_coredump_extra_notes_size();
fill_elf_note_phdr(&phdr, sz, offset);
offset += sz;
@@ -1698,10 +1692,8 @@ static int elf_core_dump(long signr, struct pt_regs *regs, struct file *file)
if (!writenote(notes + i, file, &foffset))
goto end_coredump;
-#ifdef ELF_CORE_WRITE_EXTRA_NOTES
- ELF_CORE_WRITE_EXTRA_NOTES;
- foffset += extra_notes_size;
-#endif
+ if (elf_coredump_extra_notes_write(file, &foffset))
+ goto end_coredump;
/* write out the thread status notes section */
list_for_each(t, &thread_list) {
diff --git a/include/asm-powerpc/elf.h b/include/asm-powerpc/elf.h
index de50799..e42820d 100644
--- a/include/asm-powerpc/elf.h
+++ b/include/asm-powerpc/elf.h
@@ -413,13 +413,8 @@ do { \
/* Notes used in ET_CORE. Note name is "SPU/<fd>/<filename>". */
#define NT_SPU 1
-extern int arch_notes_size(void);
-extern void arch_write_notes(struct file *file);
-
-#define ELF_CORE_EXTRA_NOTES_SIZE arch_notes_size()
-#define ELF_CORE_WRITE_EXTRA_NOTES arch_write_notes(file)
-
#define ARCH_HAVE_EXTRA_ELF_NOTES
-#endif /* CONFIG_PPC_CELL */
+
+#endif /* CONFIG_SPU_BASE */
#endif /* _ASM_POWERPC_ELF_H */
diff --git a/include/linux/elf.h b/include/linux/elf.h
index 8b17ffe..d2da84a 100644
--- a/include/linux/elf.h
+++ b/include/linux/elf.h
@@ -389,12 +389,14 @@ extern Elf64_Dyn _DYNAMIC [];
#endif
+/* Optional callbacks to write extra ELF notes. */
#ifndef ARCH_HAVE_EXTRA_ELF_NOTES
-static inline int arch_notes_size(void) { return 0; }
-static inline void arch_write_notes(struct file *file) { }
-
-#define ELF_CORE_EXTRA_NOTES_SIZE arch_notes_size()
-#define ELF_CORE_WRITE_EXTRA_NOTES arch_write_notes(file)
-#endif /* ARCH_HAVE_EXTRA_ELF_NOTES */
+static inline int elf_coredump_extra_notes_size(void) { return 0; }
+static inline int elf_coredump_extra_notes_write(struct file *file,
+ loff_t *foffset) { return 0; }
+#else
+extern int elf_coredump_extra_notes_size(void);
+extern int elf_coredump_extra_notes_write(struct file *file, loff_t *foffset);
+#endif
#endif /* _LINUX_ELF_H */
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [PATCH 21/25] spufs: Combine spufs_coredump_calls with spufs_calls
2007-09-14 6:32 [PATCH 01/25] spufs: staticify file-internal functions & variables Jeremy Kerr
` (13 preceding siblings ...)
2007-09-14 6:32 ` [PATCH 22/25] spufs: Cleanup ELF coredump extra notes logic Jeremy Kerr
@ 2007-09-14 6:32 ` Jeremy Kerr
2007-09-14 6:32 ` [PATCH 03/25] spufs: remove spu_harvest Jeremy Kerr
` (9 subsequent siblings)
24 siblings, 0 replies; 31+ messages in thread
From: Jeremy Kerr @ 2007-09-14 6:32 UTC (permalink / raw)
To: linuxppc-dev
From: Michael Ellerman <michael@ellerman.id.au>
Because spufs might be built as a module, we can't have other parts of the
kernel calling directly into it, we need stub routines that check first if the
module is loaded.
Currently we have two structures which hold callbacks for these stubs, the
syscalls are in spufs_calls and the coredump calls are in spufs_coredump_calls.
In both cases the logic for registering/unregistering is essentially the same,
so we can simplify things by combining the two.
Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
Signed-off-by: Jeremy Kerr <jk@ozlabs.org>
Acked-by: Arnd Bergmann <arnd.bergmann@de.ibm.com>
---
arch/powerpc/platforms/cell/Makefile | 2
arch/powerpc/platforms/cell/spu_coredump.c | 83 ---------------------------
arch/powerpc/platforms/cell/spu_syscalls.c | 30 +++++++++
arch/powerpc/platforms/cell/spufs/coredump.c | 10 ---
arch/powerpc/platforms/cell/spufs/inode.c | 6 -
arch/powerpc/platforms/cell/spufs/spufs.h | 4 +
arch/powerpc/platforms/cell/spufs/syscalls.c | 2
include/asm-powerpc/spu.h | 12 ---
8 files changed, 41 insertions(+), 108 deletions(-)
diff --git a/arch/powerpc/platforms/cell/Makefile b/arch/powerpc/platforms/cell/Makefile
index 40f78e9..61d12f1 100644
--- a/arch/powerpc/platforms/cell/Makefile
+++ b/arch/powerpc/platforms/cell/Makefile
@@ -19,7 +19,7 @@ spu-manage-$(CONFIG_PPC_CELLEB) += spu_manage.o
spu-manage-$(CONFIG_PPC_CELL_NATIVE) += spu_manage.o
obj-$(CONFIG_SPU_BASE) += spu_callbacks.o spu_base.o \
- spu_coredump.o spu_syscalls.o \
+ spu_syscalls.o \
$(spu-priv1-y) \
$(spu-manage-y) \
spufs/
diff --git a/arch/powerpc/platforms/cell/spu_coredump.c b/arch/powerpc/platforms/cell/spu_coredump.c
deleted file mode 100644
index 656a8c5..0000000
--- a/arch/powerpc/platforms/cell/spu_coredump.c
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * SPU core dump code
- *
- * (C) Copyright 2006 IBM Corp.
- *
- * Author: Dwayne Grant McConnell <decimal@us.ibm.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <linux/file.h>
-#include <linux/module.h>
-#include <linux/syscalls.h>
-
-#include <asm/spu.h>
-
-static struct spu_coredump_calls *spu_coredump_calls;
-static DEFINE_MUTEX(spu_coredump_mutex);
-
-int arch_notes_size(void)
-{
- int ret;
-
- mutex_lock(&spu_coredump_mutex);
-
- if (spu_coredump_calls && try_module_get(spu_coredump_calls->owner)) {
- ret = spu_coredump_calls->arch_notes_size();
- module_put(spu_coredump_calls->owner);
- } else {
- ret = 0;
- }
-
- mutex_unlock(&spu_coredump_mutex);
-
- return ret;
-}
-
-void arch_write_notes(struct file *file)
-{
- mutex_lock(&spu_coredump_mutex);
- if (spu_coredump_calls && try_module_get(spu_coredump_calls->owner)) {
- spu_coredump_calls->arch_write_notes(file);
- module_put(spu_coredump_calls->owner);
- }
- mutex_unlock(&spu_coredump_mutex);
-}
-
-int register_arch_coredump_calls(struct spu_coredump_calls *calls)
-{
- int ret = 0;
-
-
- mutex_lock(&spu_coredump_mutex);
- if (spu_coredump_calls)
- ret = -EBUSY;
- else
- spu_coredump_calls = calls;
- mutex_unlock(&spu_coredump_mutex);
- return ret;
-}
-EXPORT_SYMBOL_GPL(register_arch_coredump_calls);
-
-void unregister_arch_coredump_calls(struct spu_coredump_calls *calls)
-{
- BUG_ON(spu_coredump_calls != calls);
-
- mutex_lock(&spu_coredump_mutex);
- spu_coredump_calls = NULL;
- mutex_unlock(&spu_coredump_mutex);
-}
-EXPORT_SYMBOL_GPL(unregister_arch_coredump_calls);
diff --git a/arch/powerpc/platforms/cell/spu_syscalls.c b/arch/powerpc/platforms/cell/spu_syscalls.c
index 76815c5..cf00251 100644
--- a/arch/powerpc/platforms/cell/spu_syscalls.c
+++ b/arch/powerpc/platforms/cell/spu_syscalls.c
@@ -2,6 +2,7 @@
* SPU file system -- system call stubs
*
* (C) Copyright IBM Deutschland Entwicklung GmbH 2005
+ * (C) Copyright 2006-2007, IBM Corporation
*
* Author: Arnd Bergmann <arndb@de.ibm.com>
*
@@ -108,6 +109,35 @@ asmlinkage long sys_spu_run(int fd, __u32 __user *unpc, __u32 __user *ustatus)
return ret;
}
+int arch_notes_size(void)
+{
+ struct spufs_calls *calls;
+ int ret;
+
+ calls = spufs_calls_get();
+ if (!calls)
+ return 0;
+
+ ret = calls->coredump_extra_notes_size();
+
+ spufs_calls_put(calls);
+
+ return ret;
+}
+
+void arch_write_notes(struct file *file)
+{
+ struct spufs_calls *calls;
+
+ calls = spufs_calls_get();
+ if (!calls)
+ return;
+
+ calls->coredump_extra_notes_write(file);
+
+ spufs_calls_put(calls);
+}
+
int register_spu_syscalls(struct spufs_calls *calls)
{
int ret = 0;
diff --git a/arch/powerpc/platforms/cell/spufs/coredump.c b/arch/powerpc/platforms/cell/spufs/coredump.c
index fc988fd..6c20e44 100644
--- a/arch/powerpc/platforms/cell/spufs/coredump.c
+++ b/arch/powerpc/platforms/cell/spufs/coredump.c
@@ -122,7 +122,7 @@ static struct spu_context *coredump_next_context(int *fd)
return ctx;
}
-static int spufs_arch_notes_size(void)
+int spufs_coredump_extra_notes_size(void)
{
struct spu_context *ctx;
int size = 0, rc, fd;
@@ -185,7 +185,7 @@ out:
free_page((unsigned long)buf);
}
-static void spufs_arch_write_notes(struct file *file)
+void spufs_coredump_extra_notes_write(struct file *file)
{
struct spu_context *ctx;
int fd, j;
@@ -200,9 +200,3 @@ static void spufs_arch_write_notes(struct file *file)
spu_release_saved(ctx);
}
}
-
-struct spu_coredump_calls spufs_coredump_calls = {
- .arch_notes_size = spufs_arch_notes_size,
- .arch_write_notes = spufs_arch_write_notes,
- .owner = THIS_MODULE,
-};
diff --git a/arch/powerpc/platforms/cell/spufs/inode.c b/arch/powerpc/platforms/cell/spufs/inode.c
index e210a4b..1109874 100644
--- a/arch/powerpc/platforms/cell/spufs/inode.c
+++ b/arch/powerpc/platforms/cell/spufs/inode.c
@@ -790,16 +790,11 @@ static int __init spufs_init(void)
ret = register_spu_syscalls(&spufs_calls);
if (ret)
goto out_fs;
- ret = register_arch_coredump_calls(&spufs_coredump_calls);
- if (ret)
- goto out_syscalls;
spufs_init_isolated_loader();
return 0;
-out_syscalls:
- unregister_spu_syscalls(&spufs_calls);
out_fs:
unregister_filesystem(&spufs_type);
out_sched:
@@ -815,7 +810,6 @@ static void __exit spufs_exit(void)
{
spu_sched_exit();
spufs_exit_isolated_loader();
- unregister_arch_coredump_calls(&spufs_coredump_calls);
unregister_spu_syscalls(&spufs_calls);
unregister_filesystem(&spufs_type);
kmem_cache_destroy(spufs_inode_cache);
diff --git a/arch/powerpc/platforms/cell/spufs/spufs.h b/arch/powerpc/platforms/cell/spufs/spufs.h
index f869a4b..c7b4e03 100644
--- a/arch/powerpc/platforms/cell/spufs/spufs.h
+++ b/arch/powerpc/platforms/cell/spufs/spufs.h
@@ -204,6 +204,10 @@ extern struct spufs_calls spufs_calls;
long spufs_run_spu(struct spu_context *ctx, u32 *npc, u32 *status);
long spufs_create(struct nameidata *nd, unsigned int flags,
mode_t mode, struct file *filp);
+/* ELF coredump callbacks for writing SPU ELF notes */
+extern int spufs_coredump_extra_notes_size(void);
+extern void spufs_coredump_extra_notes_write(struct file *file);
+
extern const struct file_operations spufs_context_fops;
/* gang management */
diff --git a/arch/powerpc/platforms/cell/spufs/syscalls.c b/arch/powerpc/platforms/cell/spufs/syscalls.c
index 22b138d..2c34f71 100644
--- a/arch/powerpc/platforms/cell/spufs/syscalls.c
+++ b/arch/powerpc/platforms/cell/spufs/syscalls.c
@@ -84,5 +84,7 @@ static long do_spu_create(const char __user *pathname, unsigned int flags,
struct spufs_calls spufs_calls = {
.create_thread = do_spu_create,
.spu_run = do_spu_run,
+ .coredump_extra_notes_size = spufs_coredump_extra_notes_size,
+ .coredump_extra_notes_write = spufs_coredump_extra_notes_write,
.owner = THIS_MODULE,
};
diff --git a/include/asm-powerpc/spu.h b/include/asm-powerpc/spu.h
index eb1159c..f1b10a1 100644
--- a/include/asm-powerpc/spu.h
+++ b/include/asm-powerpc/spu.h
@@ -244,13 +244,8 @@ struct spufs_calls {
struct file *neighbor);
long (*spu_run)(struct file *filp, __u32 __user *unpc,
__u32 __user *ustatus);
- struct module *owner;
-};
-
-/* coredump calls implemented in spufs */
-struct spu_coredump_calls {
- asmlinkage int (*arch_notes_size)(void);
- asmlinkage void (*arch_write_notes)(struct file *file);
+ int (*coredump_extra_notes_size)(void);
+ void (*coredump_extra_notes_write)(struct file *file);
struct module *owner;
};
@@ -277,9 +272,6 @@ struct spu_coredump_calls {
int register_spu_syscalls(struct spufs_calls *calls);
void unregister_spu_syscalls(struct spufs_calls *calls);
-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);
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [PATCH 03/25] spufs: remove spu_harvest
2007-09-14 6:32 [PATCH 01/25] spufs: staticify file-internal functions & variables Jeremy Kerr
` (14 preceding siblings ...)
2007-09-14 6:32 ` [PATCH 21/25] spufs: Combine spufs_coredump_calls with spufs_calls Jeremy Kerr
@ 2007-09-14 6:32 ` Jeremy Kerr
2007-09-14 6:32 ` [PATCH 12/25] spufs: Remove ctx_info and ctx_info_list Jeremy Kerr
` (8 subsequent siblings)
24 siblings, 0 replies; 31+ messages in thread
From: Jeremy Kerr @ 2007-09-14 6:32 UTC (permalink / raw)
To: linuxppc-dev
Based on an initial patch from Sebastian Siewior
<sebastian@breakpoint.cc>
spu_harvest isn't used, remove it.
Signed-off-by: Jeremy Kerr <jk@ozlabs.org>
---
arch/powerpc/platforms/cell/spufs/switch.c | 13 -------------
1 file changed, 13 deletions(-)
diff --git a/arch/powerpc/platforms/cell/spufs/switch.c b/arch/powerpc/platforms/cell/spufs/switch.c
index 27ffdae..2506619 100644
--- a/arch/powerpc/platforms/cell/spufs/switch.c
+++ b/arch/powerpc/platforms/cell/spufs/switch.c
@@ -2146,19 +2146,6 @@ int spu_restore(struct spu_state *new, struct spu *spu)
}
EXPORT_SYMBOL_GPL(spu_restore);
-/**
- * spu_harvest - SPU harvest (reset) operation
- * @spu: pointer to SPU iomem structure.
- *
- * Perform SPU harvest (reset) operation.
- */
-void spu_harvest(struct spu *spu)
-{
- acquire_spu_lock(spu);
- harvest(NULL, spu);
- release_spu_lock(spu);
-}
-
static void init_prob(struct spu_state *csa)
{
csa->spu_chnlcnt_RW[9] = 1;
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [PATCH 12/25] spufs: Remove ctx_info and ctx_info_list
2007-09-14 6:32 [PATCH 01/25] spufs: staticify file-internal functions & variables Jeremy Kerr
` (15 preceding siblings ...)
2007-09-14 6:32 ` [PATCH 03/25] spufs: remove spu_harvest Jeremy Kerr
@ 2007-09-14 6:32 ` Jeremy Kerr
2007-09-14 6:32 ` [PATCH 09/25] cell: remove DEBUG for spu callbacks Jeremy Kerr
` (7 subsequent siblings)
24 siblings, 0 replies; 31+ messages in thread
From: Jeremy Kerr @ 2007-09-14 6:32 UTC (permalink / raw)
To: linuxppc-dev
From: Michael Ellerman <michael@ellerman.id.au>
Remove the ctx_info struct entirely, and also the ctx_info_list. This fixes
a race where two processes can clobber each other's ctx_info structs.
Instead of using the list, we just repeat the search through the file
descriptor table.
Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
Signed-off-by: Jeremy Kerr <jk@ozlabs.org>
---
arch/powerpc/platforms/cell/spufs/coredump.c | 79 ++++++---------------------
1 file changed, 19 insertions(+), 60 deletions(-)
diff --git a/arch/powerpc/platforms/cell/spufs/coredump.c b/arch/powerpc/platforms/cell/spufs/coredump.c
index 99f8e0b..6663669 100644
--- a/arch/powerpc/platforms/cell/spufs/coredump.c
+++ b/arch/powerpc/platforms/cell/spufs/coredump.c
@@ -31,15 +31,6 @@
#include "spufs.h"
-struct spufs_ctx_info {
- struct list_head list;
- int dfd;
- int memsize; /* in bytes */
- struct spu_context *ctx;
-};
-
-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)
{
@@ -73,25 +64,17 @@ static int spufs_dump_seek(struct file *file, loff_t off)
return 1;
}
-static void spufs_fill_memsize(struct spufs_ctx_info *ctx_info)
+static u64 ctx_ls_size(struct spu_context *ctx)
{
- struct spu_context *ctx;
- unsigned long long lslr;
-
- ctx = ctx_info->ctx;
- lslr = ctx->csa.priv2.spu_lslr_RW;
- ctx_info->memsize = lslr + 1;
+ return ctx->csa.priv2.spu_lslr_RW + 1;
}
-static int spufs_ctx_note_size(struct spufs_ctx_info *ctx_info)
+static int spufs_ctx_note_size(struct spu_context *ctx, int dfd)
{
- int dfd, memsize, i, sz, total = 0;
+ int i, sz, total = 0;
char *name;
char fullname[80];
- dfd = ctx_info->dfd;
- memsize = ctx_info->memsize;
-
for (i = 0; spufs_coredump_read[i].name; i++) {
name = spufs_coredump_read[i].name;
sz = spufs_coredump_read[i].size;
@@ -101,7 +84,7 @@ static int spufs_ctx_note_size(struct spufs_ctx_info *ctx_info)
total += sizeof(struct elf_note);
total += roundup(strlen(fullname) + 1, 4);
if (!strcmp(name, "mem"))
- total += roundup(memsize, 4);
+ total += roundup(ctx_ls_size(ctx), 4);
else
total += roundup(sz, 4);
}
@@ -109,25 +92,6 @@ static int spufs_ctx_note_size(struct spufs_ctx_info *ctx_info)
return total;
}
-static int spufs_add_one_context(struct spu_context *ctx, int dfd)
-{
- struct spufs_ctx_info *ctx_info;
- int size;
-
- ctx_info = kzalloc(sizeof(*ctx_info), GFP_KERNEL);
- if (unlikely(!ctx_info))
- return -ENOMEM;
-
- ctx_info->dfd = dfd;
- ctx_info->ctx = ctx;
-
- spufs_fill_memsize(ctx_info);
-
- size = spufs_ctx_note_size(ctx_info);
- list_add(&ctx_info->list, &ctx_info_list);
- return size;
-}
-
/*
* The additional architecture-specific notes for Cell are various
* context files in the spu context.
@@ -171,7 +135,7 @@ static int spufs_arch_notes_size(void)
fd = 0;
while ((ctx = coredump_next_context(&fd)) != NULL) {
- rc = spufs_add_one_context(ctx, fd);
+ rc = spufs_ctx_note_size(ctx, fd);
if (rc < 0)
break;
@@ -181,12 +145,11 @@ static int spufs_arch_notes_size(void)
return size;
}
-static void spufs_arch_write_note(struct spufs_ctx_info *ctx_info, int i,
- struct file *file)
+static void spufs_arch_write_note(struct spu_context *ctx, int i,
+ struct file *file, int dfd)
{
- struct spu_context *ctx;
loff_t pos = 0;
- int sz, dfd, rc, total = 0;
+ int sz, rc, total = 0;
const int bufsz = PAGE_SIZE;
char *name;
char fullname[80], *buf;
@@ -196,18 +159,13 @@ static void spufs_arch_write_note(struct spufs_ctx_info *ctx_info, int i,
if (!buf)
return;
- dfd = ctx_info->dfd;
name = spufs_coredump_read[i].name;
if (!strcmp(name, "mem"))
- sz = ctx_info->memsize;
+ sz = ctx_ls_size(ctx);
else
sz = spufs_coredump_read[i].size;
- ctx = ctx_info->ctx;
- if (!ctx)
- goto out;
-
sprintf(fullname, "SPU/%d/%s", dfd, name);
en.n_namesz = strlen(fullname) + 1;
en.n_descsz = sz;
@@ -237,16 +195,17 @@ out:
static void spufs_arch_write_notes(struct file *file)
{
- int j;
- struct spufs_ctx_info *ctx_info, *next;
+ struct spu_context *ctx;
+ int fd, j;
+
+ fd = 0;
+ while ((ctx = coredump_next_context(&fd)) != NULL) {
+ spu_acquire_saved(ctx);
- list_for_each_entry_safe(ctx_info, next, &ctx_info_list, list) {
- spu_acquire_saved(ctx_info->ctx);
for (j = 0; j < spufs_coredump_num_notes; j++)
- spufs_arch_write_note(ctx_info, j, file);
- spu_release_saved(ctx_info->ctx);
- list_del(&ctx_info->list);
- kfree(ctx_info);
+ spufs_arch_write_note(ctx, j, file, fd);
+
+ spu_release_saved(ctx);
}
}
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [PATCH 09/25] cell: remove DEBUG for spu callbacks
2007-09-14 6:32 [PATCH 01/25] spufs: staticify file-internal functions & variables Jeremy Kerr
` (16 preceding siblings ...)
2007-09-14 6:32 ` [PATCH 12/25] spufs: Remove ctx_info and ctx_info_list Jeremy Kerr
@ 2007-09-14 6:32 ` Jeremy Kerr
2007-09-14 7:43 ` Christoph Hellwig
2007-09-14 6:32 ` [PATCH 19/25] spufs: Internal __spufs_get_foo() routines should take a spu_context * Jeremy Kerr
` (6 subsequent siblings)
24 siblings, 1 reply; 31+ messages in thread
From: Jeremy Kerr @ 2007-09-14 6:32 UTC (permalink / raw)
To: linuxppc-dev
We don't want SPE programs to be able to flood the kernel log by
invoking the SPE callback handler, so don't enable DEBUG for
spu_callbacks.c by default.
Signed-off-by: Jeremy Kerr <jk@ozlabs.org>
---
arch/powerpc/platforms/cell/spu_callbacks.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/powerpc/platforms/cell/spu_callbacks.c b/arch/powerpc/platforms/cell/spu_callbacks.c
index ab39e22..dceb8b6 100644
--- a/arch/powerpc/platforms/cell/spu_callbacks.c
+++ b/arch/powerpc/platforms/cell/spu_callbacks.c
@@ -2,7 +2,7 @@
* System call callback functions for SPUs
*/
-#define DEBUG
+#undef DEBUG
#include <linux/kallsyms.h>
#include <linux/module.h>
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [PATCH 19/25] spufs: Internal __spufs_get_foo() routines should take a spu_context *
2007-09-14 6:32 [PATCH 01/25] spufs: staticify file-internal functions & variables Jeremy Kerr
` (17 preceding siblings ...)
2007-09-14 6:32 ` [PATCH 09/25] cell: remove DEBUG for spu callbacks Jeremy Kerr
@ 2007-09-14 6:32 ` Jeremy Kerr
2007-09-14 7:43 ` Christoph Hellwig
2007-09-14 6:32 ` [PATCH 02/25] spufs: remove asmlinkage from do_spu_create Jeremy Kerr
` (5 subsequent siblings)
24 siblings, 1 reply; 31+ messages in thread
From: Jeremy Kerr @ 2007-09-14 6:32 UTC (permalink / raw)
To: linuxppc-dev
From: Michael Ellerman <michael@ellerman.id.au>
The SPUFS attribute get routines take a void * because the generic attribute
code doesn't know what sort of data it's passing around.
However our internal __spufs_get_foo() routines can take a spu_context *
directly, which saves plonking it in and out of a void * again.
Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
Signed-off-by: Jeremy Kerr <jk@ozlabs.org>
Acked-by: Arnd Bergmann <arnd.bergmann@de.ibm.com>
---
arch/powerpc/platforms/cell/spufs/file.c | 40 ++++++++++++------------------
arch/powerpc/platforms/cell/spufs/spufs.h | 2 -
2 files changed, 17 insertions(+), 25 deletions(-)
diff --git a/arch/powerpc/platforms/cell/spufs/file.c b/arch/powerpc/platforms/cell/spufs/file.c
index 6095fb1..4cd34e5 100644
--- a/arch/powerpc/platforms/cell/spufs/file.c
+++ b/arch/powerpc/platforms/cell/spufs/file.c
@@ -1085,9 +1085,8 @@ static void spufs_signal1_type_set(void *data, u64 val)
spu_release(ctx);
}
-static u64 __spufs_signal1_type_get(void *data)
+static u64 __spufs_signal1_type_get(struct spu_context *ctx)
{
- struct spu_context *ctx = data;
return ctx->ops->signal1_type_get(ctx);
}
@@ -1097,7 +1096,7 @@ static u64 spufs_signal1_type_get(void *data)
u64 ret;
spu_acquire(ctx);
- ret = __spufs_signal1_type_get(data);
+ ret = __spufs_signal1_type_get(ctx);
spu_release(ctx);
return ret;
@@ -1114,9 +1113,8 @@ static void spufs_signal2_type_set(void *data, u64 val)
spu_release(ctx);
}
-static u64 __spufs_signal2_type_get(void *data)
+static u64 __spufs_signal2_type_get(struct spu_context *ctx)
{
- struct spu_context *ctx = data;
return ctx->ops->signal2_type_get(ctx);
}
@@ -1126,7 +1124,7 @@ static u64 spufs_signal2_type_get(void *data)
u64 ret;
spu_acquire(ctx);
- ret = __spufs_signal2_type_get(data);
+ ret = __spufs_signal2_type_get(ctx);
spu_release(ctx);
return ret;
@@ -1629,9 +1627,8 @@ static void spufs_decr_set(void *data, u64 val)
spu_release_saved(ctx);
}
-static u64 __spufs_decr_get(void *data)
+static u64 __spufs_decr_get(struct spu_context *ctx)
{
- struct spu_context *ctx = data;
struct spu_lscsa *lscsa = ctx->csa.lscsa;
return lscsa->decr.slot[0];
}
@@ -1641,7 +1638,7 @@ static u64 spufs_decr_get(void *data)
struct spu_context *ctx = data;
u64 ret;
spu_acquire_saved(ctx);
- ret = __spufs_decr_get(data);
+ ret = __spufs_decr_get(ctx);
spu_release_saved(ctx);
return ret;
}
@@ -1659,9 +1656,8 @@ static void spufs_decr_status_set(void *data, u64 val)
spu_release_saved(ctx);
}
-static u64 __spufs_decr_status_get(void *data)
+static u64 __spufs_decr_status_get(struct spu_context *ctx)
{
- struct spu_context *ctx = data;
if (ctx->csa.priv2.mfc_control_RW & MFC_CNTL_DECREMENTER_RUNNING)
return SPU_DECR_STATUS_RUNNING;
else
@@ -1673,7 +1669,7 @@ static u64 spufs_decr_status_get(void *data)
struct spu_context *ctx = data;
u64 ret;
spu_acquire_saved(ctx);
- ret = __spufs_decr_status_get(data);
+ ret = __spufs_decr_status_get(ctx);
spu_release_saved(ctx);
return ret;
}
@@ -1689,9 +1685,8 @@ static void spufs_event_mask_set(void *data, u64 val)
spu_release_saved(ctx);
}
-static u64 __spufs_event_mask_get(void *data)
+static u64 __spufs_event_mask_get(struct spu_context *ctx)
{
- struct spu_context *ctx = data;
struct spu_lscsa *lscsa = ctx->csa.lscsa;
return lscsa->event_mask.slot[0];
}
@@ -1701,16 +1696,15 @@ static u64 spufs_event_mask_get(void *data)
struct spu_context *ctx = data;
u64 ret;
spu_acquire_saved(ctx);
- ret = __spufs_event_mask_get(data);
+ ret = __spufs_event_mask_get(ctx);
spu_release_saved(ctx);
return ret;
}
DEFINE_SIMPLE_ATTRIBUTE(spufs_event_mask_ops, spufs_event_mask_get,
spufs_event_mask_set, "0x%llx\n")
-static u64 __spufs_event_status_get(void *data)
+static u64 __spufs_event_status_get(struct spu_context *ctx)
{
- struct spu_context *ctx = data;
struct spu_state *state = &ctx->csa;
u64 stat;
stat = state->spu_chnlcnt_RW[0];
@@ -1725,7 +1719,7 @@ static u64 spufs_event_status_get(void *data)
u64 ret = 0;
spu_acquire_saved(ctx);
- ret = __spufs_event_status_get(data);
+ ret = __spufs_event_status_get(ctx);
spu_release_saved(ctx);
return ret;
}
@@ -1770,16 +1764,15 @@ static u64 spufs_id_get(void *data)
}
DEFINE_SIMPLE_ATTRIBUTE(spufs_id_ops, spufs_id_get, NULL, "0x%llx\n")
-static u64 __spufs_object_id_get(void *data)
+static u64 __spufs_object_id_get(struct spu_context *ctx)
{
- struct spu_context *ctx = data;
return ctx->object_id;
}
static u64 spufs_object_id_get(void *data)
{
/* FIXME: Should there really be no locking here? */
- return __spufs_object_id_get(data);
+ return __spufs_object_id_get((struct spu_context *)data);
}
static void spufs_object_id_set(void *data, u64 id)
@@ -1791,9 +1784,8 @@ static void spufs_object_id_set(void *data, u64 id)
DEFINE_SIMPLE_ATTRIBUTE(spufs_object_id_ops, spufs_object_id_get,
spufs_object_id_set, "0x%llx\n");
-static u64 __spufs_lslr_get(void *data)
+static u64 __spufs_lslr_get(struct spu_context *ctx)
{
- struct spu_context *ctx = data;
return ctx->csa.priv2.spu_lslr_RW;
}
@@ -1803,7 +1795,7 @@ static u64 spufs_lslr_get(void *data)
u64 ret;
spu_acquire_saved(ctx);
- ret = __spufs_lslr_get(data);
+ ret = __spufs_lslr_get(ctx);
spu_release_saved(ctx);
return ret;
diff --git a/arch/powerpc/platforms/cell/spufs/spufs.h b/arch/powerpc/platforms/cell/spufs/spufs.h
index 3dbffeb..f869a4b 100644
--- a/arch/powerpc/platforms/cell/spufs/spufs.h
+++ b/arch/powerpc/platforms/cell/spufs/spufs.h
@@ -296,7 +296,7 @@ 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);
+ u64 (*get)(struct spu_context *ctx);
size_t size;
};
extern struct spufs_coredump_reader spufs_coredump_read[];
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [PATCH 02/25] spufs: remove asmlinkage from do_spu_create
2007-09-14 6:32 [PATCH 01/25] spufs: staticify file-internal functions & variables Jeremy Kerr
` (18 preceding siblings ...)
2007-09-14 6:32 ` [PATCH 19/25] spufs: Internal __spufs_get_foo() routines should take a spu_context * Jeremy Kerr
@ 2007-09-14 6:32 ` Jeremy Kerr
2007-09-14 7:44 ` Christoph Hellwig
2007-09-14 6:32 ` [PATCH 06/25] cell: unify spufs syscall path Jeremy Kerr
` (4 subsequent siblings)
24 siblings, 1 reply; 31+ messages in thread
From: Jeremy Kerr @ 2007-09-14 6:32 UTC (permalink / raw)
To: linuxppc-dev
do_spu_create doesn't need the asmlinkage qualifier; remove it.
Signed-off-by: Jeremy Kerr <jk@ozlabs.org>
---
arch/powerpc/platforms/cell/spufs/syscalls.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/arch/powerpc/platforms/cell/spufs/syscalls.c b/arch/powerpc/platforms/cell/spufs/syscalls.c
index 3d8c328..936e0a8 100644
--- a/arch/powerpc/platforms/cell/spufs/syscalls.c
+++ b/arch/powerpc/platforms/cell/spufs/syscalls.c
@@ -76,8 +76,8 @@ asmlinkage long sys_spu_run(int fd, __u32 __user *unpc, __u32 __user *ustatus)
}
#endif
-static asmlinkage long do_spu_create(const char __user *pathname,
- unsigned int flags, mode_t mode, struct file *neighbor)
+static long do_spu_create(const char __user *pathname, unsigned int flags,
+ mode_t mode, struct file *neighbor)
{
char *tmp;
int ret;
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [PATCH 06/25] cell: unify spufs syscall path
2007-09-14 6:32 [PATCH 01/25] spufs: staticify file-internal functions & variables Jeremy Kerr
` (19 preceding siblings ...)
2007-09-14 6:32 ` [PATCH 02/25] spufs: remove asmlinkage from do_spu_create Jeremy Kerr
@ 2007-09-14 6:32 ` Jeremy Kerr
2007-09-14 6:32 ` [PATCH 17/25] spufs: Don't return -ENOSYS as extra notes size if spufs is not loaded Jeremy Kerr
` (3 subsequent siblings)
24 siblings, 0 replies; 31+ messages in thread
From: Jeremy Kerr @ 2007-09-14 6:32 UTC (permalink / raw)
To: linuxppc-dev
At present, a built-in spufs will not use the spufs_calls callbacks, but
directly call sys_spu_create. This saves us an indirect branch, but
means we have duplicated functions - one for CONFIG_SPU_FS=y and one for
=m.
This change unifies the spufs syscall path, and provides access to the
spufs_calls structure through a get/put pair. At present, the only user
of the spufs_calls structure is spu_syscalls.c, but this will facilitate
adding the coredump calls later. We also add a mutex to protect the
spufs_calls struct, so that accesses to the calls don't race with
{,un}register_spu_calls.
Everyone likes numbers, right? Here's a before/after comparison with
CONFIG_SPU_FS=y, doing spu_create(); close(); 64k times.
Before:
[jk@cell ~]$ time ./spu_create
performing 65536 spu_create calls
real 0m24.075s
user 0m0.146s
sys 0m23.925s
After:
[jk@cell ~]$ time ./spu_create
performing 65536 spu_create calls
real 0m24.777s
user 0m0.141s
sys 0m24.631s
So, we're adding around 11us per syscall, at the benefit of having
only one syscall path.
Signed-off-by: Jeremy Kerr <jk@ozlabs.org>
---
arch/powerpc/platforms/cell/Makefile | 4
arch/powerpc/platforms/cell/spu_syscalls.c | 117 +++++++++++++++++----------
arch/powerpc/platforms/cell/spufs/spufs.h | 1
arch/powerpc/platforms/cell/spufs/syscalls.c | 42 ---------
include/asm-powerpc/spu.h | 14 ---
5 files changed, 78 insertions(+), 100 deletions(-)
diff --git a/arch/powerpc/platforms/cell/Makefile b/arch/powerpc/platforms/cell/Makefile
index f88a7c7..40f78e9 100644
--- a/arch/powerpc/platforms/cell/Makefile
+++ b/arch/powerpc/platforms/cell/Makefile
@@ -13,15 +13,13 @@ obj-$(CONFIG_PPC_CELL_NATIVE) += smp.o
endif
# needed only when building loadable spufs.ko
-spufs-modular-$(CONFIG_SPU_FS) += spu_syscalls.o
spu-priv1-$(CONFIG_PPC_CELL_NATIVE) += spu_priv1_mmio.o
spu-manage-$(CONFIG_PPC_CELLEB) += spu_manage.o
spu-manage-$(CONFIG_PPC_CELL_NATIVE) += spu_manage.o
obj-$(CONFIG_SPU_BASE) += spu_callbacks.o spu_base.o \
- spu_coredump.o \
- $(spufs-modular-m) \
+ spu_coredump.o spu_syscalls.o \
$(spu-priv1-y) \
$(spu-manage-y) \
spufs/
diff --git a/arch/powerpc/platforms/cell/spu_syscalls.c b/arch/powerpc/platforms/cell/spu_syscalls.c
index 027ac32..76815c5 100644
--- a/arch/powerpc/platforms/cell/spu_syscalls.c
+++ b/arch/powerpc/platforms/cell/spu_syscalls.c
@@ -22,42 +22,67 @@
#include <linux/file.h>
#include <linux/module.h>
#include <linux/syscalls.h>
+#include <linux/mutex.h>
#include <asm/spu.h>
-struct spufs_calls spufs_calls = {
- .owner = NULL,
-};
+static struct spufs_calls *spufs_calls;
+DEFINE_MUTEX(spufs_calls_mutex);
-/* These stub syscalls are needed to have the actual implementation
- * within a loadable module. When spufs is built into the kernel,
- * this file is not used and the syscalls directly enter the fs code */
+#ifdef CONFIG_SPU_FS_MODULE
+
+static inline struct spufs_calls *spufs_calls_get(void)
+{
+ struct spufs_calls *calls = NULL;
+
+ mutex_lock(&spufs_calls_mutex);
+ if (spufs_calls && try_module_get(spufs_calls->owner))
+ calls = spufs_calls;
+ mutex_unlock(&spufs_calls_mutex);
+
+ return calls;
+}
+
+static inline void spufs_calls_put(struct spufs_calls *calls)
+{
+ BUG_ON(calls != spufs_calls);
+ module_put(calls->owner);
+}
+
+#else /* !defined CONFIG_SPU_FS_MODULE */
+
+static inline struct spufs_calls *spufs_calls_get(void)
+{
+ return spufs_calls;
+}
+
+static inline void spufs_calls_put(struct spufs_calls *calls) { }
+
+#endif /* CONFIG_SPU_FS_MODULE */
asmlinkage long sys_spu_create(const char __user *name,
unsigned int flags, mode_t mode, int neighbor_fd)
{
long ret;
- struct module *owner = spufs_calls.owner;
struct file *neighbor;
int fput_needed;
+ struct spufs_calls *calls;
- ret = -ENOSYS;
- if (owner && try_module_get(owner)) {
- if (flags & SPU_CREATE_AFFINITY_SPU) {
- neighbor = fget_light(neighbor_fd, &fput_needed);
- ret = -EBADF;
- if (neighbor) {
- ret = spufs_calls.create_thread(name, flags,
- mode, neighbor);
- fput_light(neighbor, fput_needed);
- }
- }
- else {
- ret = spufs_calls.create_thread(name, flags,
- mode, NULL);
+ calls = spufs_calls_get();
+ if (!calls)
+ return -ENOSYS;
+
+ if (flags & SPU_CREATE_AFFINITY_SPU) {
+ ret = -EBADF;
+ neighbor = fget_light(neighbor_fd, &fput_needed);
+ if (neighbor) {
+ ret = calls->create_thread(name, flags, mode, neighbor);
+ fput_light(neighbor, fput_needed);
}
- module_put(owner);
- }
+ } else
+ ret = calls->create_thread(name, flags, mode, NULL);
+
+ spufs_calls_put(calls);
return ret;
}
@@ -66,37 +91,43 @@ asmlinkage long sys_spu_run(int fd, __u32 __user *unpc, __u32 __user *ustatus)
long ret;
struct file *filp;
int fput_needed;
- struct module *owner = spufs_calls.owner;
+ struct spufs_calls *calls;
- ret = -ENOSYS;
- if (owner && try_module_get(owner)) {
- ret = -EBADF;
- filp = fget_light(fd, &fput_needed);
- if (filp) {
- ret = spufs_calls.spu_run(filp, unpc, ustatus);
- fput_light(filp, fput_needed);
- }
- module_put(owner);
+ calls = spufs_calls_get();
+ if (!calls)
+ return -ENOSYS;
+
+ ret = -EBADF;
+ filp = fget_light(fd, &fput_needed);
+ if (filp) {
+ ret = calls->spu_run(filp, unpc, ustatus);
+ fput_light(filp, fput_needed);
}
+
+ spufs_calls_put(calls);
return ret;
}
int register_spu_syscalls(struct spufs_calls *calls)
{
- if (spufs_calls.owner)
- return -EBUSY;
-
- spufs_calls.create_thread = calls->create_thread;
- spufs_calls.spu_run = calls->spu_run;
- smp_mb();
- spufs_calls.owner = calls->owner;
- return 0;
+ int ret = 0;
+
+ mutex_lock(&spufs_calls_mutex);
+ if (!spufs_calls)
+ spufs_calls = calls;
+ else
+ ret = -EBUSY;
+ mutex_unlock(&spufs_calls_mutex);
+
+ return ret;
}
EXPORT_SYMBOL_GPL(register_spu_syscalls);
void unregister_spu_syscalls(struct spufs_calls *calls)
{
- BUG_ON(spufs_calls.owner != calls->owner);
- spufs_calls.owner = NULL;
+ mutex_lock(&spufs_calls_mutex);
+ BUG_ON(spufs_calls->owner != calls->owner);
+ spufs_calls = NULL;
+ mutex_unlock(&spufs_calls_mutex);
}
EXPORT_SYMBOL_GPL(unregister_spu_syscalls);
diff --git a/arch/powerpc/platforms/cell/spufs/spufs.h b/arch/powerpc/platforms/cell/spufs/spufs.h
index 2bfdeb8..3dbffeb 100644
--- a/arch/powerpc/platforms/cell/spufs/spufs.h
+++ b/arch/powerpc/platforms/cell/spufs/spufs.h
@@ -200,6 +200,7 @@ extern struct tree_descr spufs_dir_contents[];
extern struct tree_descr spufs_dir_nosched_contents[];
/* system call implementation */
+extern struct spufs_calls spufs_calls;
long spufs_run_spu(struct spu_context *ctx, u32 *npc, u32 *status);
long spufs_create(struct nameidata *nd, unsigned int flags,
mode_t mode, struct file *filp);
diff --git a/arch/powerpc/platforms/cell/spufs/syscalls.c b/arch/powerpc/platforms/cell/spufs/syscalls.c
index 936e0a8..22b138d 100644
--- a/arch/powerpc/platforms/cell/spufs/syscalls.c
+++ b/arch/powerpc/platforms/cell/spufs/syscalls.c
@@ -58,24 +58,6 @@ out:
return ret;
}
-#ifndef MODULE
-asmlinkage long sys_spu_run(int fd, __u32 __user *unpc, __u32 __user *ustatus)
-{
- int fput_needed;
- struct file *filp;
- long ret;
-
- ret = -EBADF;
- filp = fget_light(fd, &fput_needed);
- if (filp) {
- ret = do_spu_run(filp, unpc, ustatus);
- fput_light(filp, fput_needed);
- }
-
- return ret;
-}
-#endif
-
static long do_spu_create(const char __user *pathname, unsigned int flags,
mode_t mode, struct file *neighbor)
{
@@ -99,30 +81,6 @@ static long do_spu_create(const char __user *pathname, unsigned int flags,
return ret;
}
-#ifndef MODULE
-asmlinkage long sys_spu_create(const char __user *pathname, unsigned int flags,
- mode_t mode, int neighbor_fd)
-{
- int fput_needed;
- struct file *neighbor;
- long ret;
-
- if (flags & SPU_CREATE_AFFINITY_SPU) {
- ret = -EBADF;
- neighbor = fget_light(neighbor_fd, &fput_needed);
- if (neighbor) {
- ret = do_spu_create(pathname, flags, mode, neighbor);
- fput_light(neighbor, fput_needed);
- }
- }
- else {
- ret = do_spu_create(pathname, flags, mode, NULL);
- }
-
- return ret;
-}
-#endif
-
struct spufs_calls spufs_calls = {
.create_thread = do_spu_create,
.spu_run = do_spu_run,
diff --git a/include/asm-powerpc/spu.h b/include/asm-powerpc/spu.h
index 5bde398..383ecfd 100644
--- a/include/asm-powerpc/spu.h
+++ b/include/asm-powerpc/spu.h
@@ -238,14 +238,14 @@ extern long spu_sys_callback(struct spu_syscall_block *s);
/* syscalls implemented in spufs */
struct file;
-extern struct spufs_calls {
+struct spufs_calls {
asmlinkage long (*create_thread)(const char __user *name,
unsigned int flags, mode_t mode,
struct file *neighbor);
asmlinkage long (*spu_run)(struct file *filp, __u32 __user *unpc,
__u32 __user *ustatus);
struct module *owner;
-} spufs_calls;
+};
/* coredump calls implemented in spufs */
struct spu_coredump_calls {
@@ -274,18 +274,8 @@ struct spu_coredump_calls {
#define SPU_CREATE_FLAG_ALL 0x003f /* mask of all valid flags */
-#ifdef CONFIG_SPU_FS_MODULE
int register_spu_syscalls(struct spufs_calls *calls);
void unregister_spu_syscalls(struct spufs_calls *calls);
-#else
-static inline int register_spu_syscalls(struct spufs_calls *calls)
-{
- return 0;
-}
-static inline void unregister_spu_syscalls(struct spufs_calls *calls)
-{
-}
-#endif /* MODULE */
int register_arch_coredump_calls(struct spu_coredump_calls *calls);
void unregister_arch_coredump_calls(struct spu_coredump_calls *calls);
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [PATCH 17/25] spufs: Don't return -ENOSYS as extra notes size if spufs is not loaded
2007-09-14 6:32 [PATCH 01/25] spufs: staticify file-internal functions & variables Jeremy Kerr
` (20 preceding siblings ...)
2007-09-14 6:32 ` [PATCH 06/25] cell: unify spufs syscall path Jeremy Kerr
@ 2007-09-14 6:32 ` Jeremy Kerr
2007-09-14 6:32 ` [PATCH 11/25] spufs: Extract the file descriptor search logic in SPU coredump code Jeremy Kerr
` (2 subsequent siblings)
24 siblings, 0 replies; 31+ messages in thread
From: Jeremy Kerr @ 2007-09-14 6:32 UTC (permalink / raw)
To: linuxppc-dev
From: Michael Ellerman <michael@ellerman.id.au>
Because the SPU coredump code might be built as part of a module (spufs),
we have a stub which is called by the coredump code, this routine then calls
into spufs if it's loaded.
Unfortunately the stub returns -ENOSYS if spufs is not loaded, which is
interpreted by the coredump code as an extra note size of -38 bytes. This
leads to a corrupt core dump.
If spufs is not loaded there will be no SPU ELF notes to write, and so the
extra notes size will be == 0.
Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
Signed-off-by: Jeremy Kerr <jk@ozlabs.org>
Acked-by: Arnd Bergmann <arnd.bergmann@de.ibm.com>
---
arch/powerpc/platforms/cell/spu_coredump.c | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/arch/powerpc/platforms/cell/spu_coredump.c b/arch/powerpc/platforms/cell/spu_coredump.c
index 4fd37ff..656a8c5 100644
--- a/arch/powerpc/platforms/cell/spu_coredump.c
+++ b/arch/powerpc/platforms/cell/spu_coredump.c
@@ -31,15 +31,19 @@ static DEFINE_MUTEX(spu_coredump_mutex);
int arch_notes_size(void)
{
- long ret;
+ int ret;
- ret = -ENOSYS;
mutex_lock(&spu_coredump_mutex);
+
if (spu_coredump_calls && try_module_get(spu_coredump_calls->owner)) {
ret = spu_coredump_calls->arch_notes_size();
module_put(spu_coredump_calls->owner);
+ } else {
+ ret = 0;
}
+
mutex_unlock(&spu_coredump_mutex);
+
return ret;
}
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [PATCH 11/25] spufs: Extract the file descriptor search logic in SPU coredump code
2007-09-14 6:32 [PATCH 01/25] spufs: staticify file-internal functions & variables Jeremy Kerr
` (21 preceding siblings ...)
2007-09-14 6:32 ` [PATCH 17/25] spufs: Don't return -ENOSYS as extra notes size if spufs is not loaded Jeremy Kerr
@ 2007-09-14 6:32 ` Jeremy Kerr
2007-09-14 6:32 ` [PATCH 25/25] spufs: Add DEFINE_SPUFS_ATTRIBUTE() Jeremy Kerr
2007-09-14 7:42 ` [PATCH 01/25] spufs: staticify file-internal functions & variables Christoph Hellwig
24 siblings, 0 replies; 31+ messages in thread
From: Jeremy Kerr @ 2007-09-14 6:32 UTC (permalink / raw)
To: linuxppc-dev
From: Michael Ellerman <michael@ellerman.id.au>
Extract the logic for searching through the file descriptors for spu contexts
into a separate routine, coredump_next_context(), so we can use it elsewhere
in future. In the process we flatten the for loop, and move the NOSCHED test
into coredump_next_context().
Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
Signed-off-by: Jeremy Kerr <jk@ozlabs.org>
---
arch/powerpc/platforms/cell/spufs/coredump.c | 58 +++++++++++++++++----------
1 file changed, 38 insertions(+), 20 deletions(-)
diff --git a/arch/powerpc/platforms/cell/spufs/coredump.c b/arch/powerpc/platforms/cell/spufs/coredump.c
index 5e31799..99f8e0b 100644
--- a/arch/powerpc/platforms/cell/spufs/coredump.c
+++ b/arch/powerpc/platforms/cell/spufs/coredump.c
@@ -109,16 +109,11 @@ static int spufs_ctx_note_size(struct spufs_ctx_info *ctx_info)
return total;
}
-static int spufs_add_one_context(struct file *file, int dfd)
+static int spufs_add_one_context(struct spu_context *ctx, int dfd)
{
- struct spu_context *ctx;
struct spufs_ctx_info *ctx_info;
int size;
- ctx = SPUFS_I(file->f_dentry->d_inode)->i_ctx;
- if (ctx->flags & SPU_CREATE_NOSCHED)
- return 0;
-
ctx_info = kzalloc(sizeof(*ctx_info), GFP_KERNEL);
if (unlikely(!ctx_info))
return -ENOMEM;
@@ -142,22 +137,45 @@ static int spufs_add_one_context(struct file *file, int dfd)
* internal functionality to dump them without needing to actually
* open the files.
*/
-static int spufs_arch_notes_size(void)
+static struct spu_context *coredump_next_context(int *fd)
{
struct fdtable *fdt = files_fdtable(current->files);
- int size = 0, fd;
-
- for (fd = 0; fd < fdt->max_fds; fd++) {
- if (FD_ISSET(fd, fdt->open_fds)) {
- struct file *file = fcheck(fd);
-
- if (file && file->f_op == &spufs_context_fops) {
- int rval = spufs_add_one_context(file, fd);
- if (rval < 0)
- break;
- size += rval;
- }
- }
+ struct file *file;
+ struct spu_context *ctx = NULL;
+
+ for (; *fd < fdt->max_fds; (*fd)++) {
+ if (!FD_ISSET(*fd, fdt->open_fds))
+ continue;
+
+ file = fcheck(*fd);
+
+ if (!file || file->f_op != &spufs_context_fops)
+ continue;
+
+ ctx = SPUFS_I(file->f_dentry->d_inode)->i_ctx;
+ if (ctx->flags & SPU_CREATE_NOSCHED)
+ continue;
+
+ /* start searching the next fd next time we're called */
+ (*fd)++;
+ break;
+ }
+
+ return ctx;
+}
+
+static int spufs_arch_notes_size(void)
+{
+ struct spu_context *ctx;
+ int size = 0, rc, fd;
+
+ fd = 0;
+ while ((ctx = coredump_next_context(&fd)) != NULL) {
+ rc = spufs_add_one_context(ctx, fd);
+ if (rc < 0)
+ break;
+
+ size += rc;
}
return size;
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [PATCH 25/25] spufs: Add DEFINE_SPUFS_ATTRIBUTE()
2007-09-14 6:32 [PATCH 01/25] spufs: staticify file-internal functions & variables Jeremy Kerr
` (22 preceding siblings ...)
2007-09-14 6:32 ` [PATCH 11/25] spufs: Extract the file descriptor search logic in SPU coredump code Jeremy Kerr
@ 2007-09-14 6:32 ` Jeremy Kerr
2007-09-14 7:42 ` [PATCH 01/25] spufs: staticify file-internal functions & variables Christoph Hellwig
24 siblings, 0 replies; 31+ messages in thread
From: Jeremy Kerr @ 2007-09-14 6:32 UTC (permalink / raw)
To: linuxppc-dev
From: Michael Ellerman <michael@ellerman.id.au>
This patch adds DEFINE_SPUFS_ATTRIBUTE(), a wraper around
DEFINE_SIMPLE_ATTRIBUTE which does the specified locking for the get
routine for us.
Unfortunately we need two get routines (a locked and unlocked version) to
support the coredump code. This patch hides one of those (the locked version)
inside the macro foo.
Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
Signed-off-by: Jeremy Kerr <jk@ozlabs.org>
---
arch/powerpc/platforms/cell/spufs/file.c | 216 ++++++++++---------------------
1 file changed, 76 insertions(+), 140 deletions(-)
diff --git a/arch/powerpc/platforms/cell/spufs/file.c b/arch/powerpc/platforms/cell/spufs/file.c
index 985c86b..b93a027 100644
--- a/arch/powerpc/platforms/cell/spufs/file.c
+++ b/arch/powerpc/platforms/cell/spufs/file.c
@@ -1076,6 +1076,36 @@ static const struct file_operations spufs_signal2_nosched_fops = {
.mmap = spufs_signal2_mmap,
};
+/*
+ * This is a wrapper around DEFINE_SIMPLE_ATTRIBUTE which does the
+ * work of acquiring (or not) the SPU context before calling through
+ * to the actual get routine. The set routine is called directly.
+ */
+#define SPU_ATTR_NOACQUIRE 0
+#define SPU_ATTR_ACQUIRE 1
+#define SPU_ATTR_ACQUIRE_SAVED 2
+
+#define DEFINE_SPUFS_ATTRIBUTE(__name, __get, __set, __fmt, __acquire) \
+static u64 __##__get(void *data) \
+{ \
+ struct spu_context *ctx = data; \
+ u64 ret; \
+ \
+ if (__acquire == SPU_ATTR_ACQUIRE) { \
+ spu_acquire(ctx); \
+ ret = __get(ctx); \
+ spu_release(ctx); \
+ } else if (__acquire == SPU_ATTR_ACQUIRE_SAVED) { \
+ spu_acquire_saved(ctx); \
+ ret = __get(ctx); \
+ spu_release_saved(ctx); \
+ } else \
+ ret = __get(ctx); \
+ \
+ return ret; \
+} \
+DEFINE_SIMPLE_ATTRIBUTE(__name, __##__get, __set, __fmt);
+
static void spufs_signal1_type_set(void *data, u64 val)
{
struct spu_context *ctx = data;
@@ -1085,24 +1115,13 @@ static void spufs_signal1_type_set(void *data, u64 val)
spu_release(ctx);
}
-static u64 __spufs_signal1_type_get(struct spu_context *ctx)
+static u64 spufs_signal1_type_get(struct spu_context *ctx)
{
return ctx->ops->signal1_type_get(ctx);
}
+DEFINE_SPUFS_ATTRIBUTE(spufs_signal1_type, spufs_signal1_type_get,
+ spufs_signal1_type_set, "%llu", SPU_ATTR_ACQUIRE);
-static u64 spufs_signal1_type_get(void *data)
-{
- struct spu_context *ctx = data;
- u64 ret;
-
- spu_acquire(ctx);
- ret = __spufs_signal1_type_get(ctx);
- spu_release(ctx);
-
- return ret;
-}
-DEFINE_SIMPLE_ATTRIBUTE(spufs_signal1_type, spufs_signal1_type_get,
- spufs_signal1_type_set, "%llu");
static void spufs_signal2_type_set(void *data, u64 val)
{
@@ -1113,24 +1132,12 @@ static void spufs_signal2_type_set(void *data, u64 val)
spu_release(ctx);
}
-static u64 __spufs_signal2_type_get(struct spu_context *ctx)
+static u64 spufs_signal2_type_get(struct spu_context *ctx)
{
return ctx->ops->signal2_type_get(ctx);
}
-
-static u64 spufs_signal2_type_get(void *data)
-{
- struct spu_context *ctx = data;
- u64 ret;
-
- spu_acquire(ctx);
- ret = __spufs_signal2_type_get(ctx);
- spu_release(ctx);
-
- return ret;
-}
-DEFINE_SIMPLE_ATTRIBUTE(spufs_signal2_type, spufs_signal2_type_get,
- spufs_signal2_type_set, "%llu");
+DEFINE_SPUFS_ATTRIBUTE(spufs_signal2_type, spufs_signal2_type_get,
+ spufs_signal2_type_set, "%llu", SPU_ATTR_ACQUIRE);
#if SPUFS_MMAP_4K
static unsigned long spufs_mss_mmap_nopfn(struct vm_area_struct *vma,
@@ -1606,22 +1613,12 @@ static void spufs_npc_set(void *data, u64 val)
spu_release(ctx);
}
-static u64 __spufs_npc_get(struct spu_context *ctx)
+static u64 spufs_npc_get(struct spu_context *ctx)
{
return ctx->ops->npc_read(ctx);
}
-
-static u64 spufs_npc_get(void *data)
-{
- struct spu_context *ctx = data;
- u64 ret;
- spu_acquire(ctx);
- ret = __spufs_npc_get(ctx);
- spu_release(ctx);
- return ret;
-}
-DEFINE_SIMPLE_ATTRIBUTE(spufs_npc_ops, spufs_npc_get, spufs_npc_set,
- "0x%llx\n")
+DEFINE_SPUFS_ATTRIBUTE(spufs_npc_ops, spufs_npc_get, spufs_npc_set,
+ "0x%llx\n", SPU_ATTR_ACQUIRE);
static void spufs_decr_set(void *data, u64 val)
{
@@ -1632,23 +1629,13 @@ static void spufs_decr_set(void *data, u64 val)
spu_release_saved(ctx);
}
-static u64 __spufs_decr_get(struct spu_context *ctx)
+static u64 spufs_decr_get(struct spu_context *ctx)
{
struct spu_lscsa *lscsa = ctx->csa.lscsa;
return lscsa->decr.slot[0];
}
-
-static u64 spufs_decr_get(void *data)
-{
- struct spu_context *ctx = data;
- u64 ret;
- spu_acquire_saved(ctx);
- ret = __spufs_decr_get(ctx);
- spu_release_saved(ctx);
- return ret;
-}
-DEFINE_SIMPLE_ATTRIBUTE(spufs_decr_ops, spufs_decr_get, spufs_decr_set,
- "0x%llx\n")
+DEFINE_SPUFS_ATTRIBUTE(spufs_decr_ops, spufs_decr_get, spufs_decr_set,
+ "0x%llx\n", SPU_ATTR_ACQUIRE_SAVED);
static void spufs_decr_status_set(void *data, u64 val)
{
@@ -1661,25 +1648,16 @@ static void spufs_decr_status_set(void *data, u64 val)
spu_release_saved(ctx);
}
-static u64 __spufs_decr_status_get(struct spu_context *ctx)
+static u64 spufs_decr_status_get(struct spu_context *ctx)
{
if (ctx->csa.priv2.mfc_control_RW & MFC_CNTL_DECREMENTER_RUNNING)
return SPU_DECR_STATUS_RUNNING;
else
return 0;
}
-
-static u64 spufs_decr_status_get(void *data)
-{
- struct spu_context *ctx = data;
- u64 ret;
- spu_acquire_saved(ctx);
- ret = __spufs_decr_status_get(ctx);
- spu_release_saved(ctx);
- return ret;
-}
-DEFINE_SIMPLE_ATTRIBUTE(spufs_decr_status_ops, spufs_decr_status_get,
- spufs_decr_status_set, "0x%llx\n")
+DEFINE_SPUFS_ATTRIBUTE(spufs_decr_status_ops, spufs_decr_status_get,
+ spufs_decr_status_set, "0x%llx\n",
+ SPU_ATTR_ACQUIRE_SAVED);
static void spufs_event_mask_set(void *data, u64 val)
{
@@ -1690,25 +1668,17 @@ static void spufs_event_mask_set(void *data, u64 val)
spu_release_saved(ctx);
}
-static u64 __spufs_event_mask_get(struct spu_context *ctx)
+static u64 spufs_event_mask_get(struct spu_context *ctx)
{
struct spu_lscsa *lscsa = ctx->csa.lscsa;
return lscsa->event_mask.slot[0];
}
-static u64 spufs_event_mask_get(void *data)
-{
- struct spu_context *ctx = data;
- u64 ret;
- spu_acquire_saved(ctx);
- ret = __spufs_event_mask_get(ctx);
- spu_release_saved(ctx);
- return ret;
-}
-DEFINE_SIMPLE_ATTRIBUTE(spufs_event_mask_ops, spufs_event_mask_get,
- spufs_event_mask_set, "0x%llx\n")
+DEFINE_SPUFS_ATTRIBUTE(spufs_event_mask_ops, spufs_event_mask_get,
+ spufs_event_mask_set, "0x%llx\n",
+ SPU_ATTR_ACQUIRE_SAVED);
-static u64 __spufs_event_status_get(struct spu_context *ctx)
+static u64 spufs_event_status_get(struct spu_context *ctx)
{
struct spu_state *state = &ctx->csa;
u64 stat;
@@ -1717,19 +1687,8 @@ static u64 __spufs_event_status_get(struct spu_context *ctx)
return state->spu_chnldata_RW[0];
return 0;
}
-
-static u64 spufs_event_status_get(void *data)
-{
- struct spu_context *ctx = data;
- u64 ret = 0;
-
- spu_acquire_saved(ctx);
- ret = __spufs_event_status_get(ctx);
- spu_release_saved(ctx);
- return ret;
-}
-DEFINE_SIMPLE_ATTRIBUTE(spufs_event_status_ops, spufs_event_status_get,
- NULL, "0x%llx\n")
+DEFINE_SPUFS_ATTRIBUTE(spufs_event_status_ops, spufs_event_status_get,
+ NULL, "0x%llx\n", SPU_ATTR_ACQUIRE_SAVED)
static void spufs_srr0_set(void *data, u64 val)
{
@@ -1740,44 +1699,32 @@ static void spufs_srr0_set(void *data, u64 val)
spu_release_saved(ctx);
}
-static u64 spufs_srr0_get(void *data)
+static u64 spufs_srr0_get(struct spu_context *ctx)
{
- struct spu_context *ctx = data;
struct spu_lscsa *lscsa = ctx->csa.lscsa;
- u64 ret;
- spu_acquire_saved(ctx);
- ret = lscsa->srr0.slot[0];
- spu_release_saved(ctx);
- return ret;
+ return lscsa->srr0.slot[0];
}
-DEFINE_SIMPLE_ATTRIBUTE(spufs_srr0_ops, spufs_srr0_get, spufs_srr0_set,
- "0x%llx\n")
+DEFINE_SPUFS_ATTRIBUTE(spufs_srr0_ops, spufs_srr0_get, spufs_srr0_set,
+ "0x%llx\n", SPU_ATTR_ACQUIRE_SAVED)
-static u64 spufs_id_get(void *data)
+static u64 spufs_id_get(struct spu_context *ctx)
{
- struct spu_context *ctx = data;
u64 num;
- spu_acquire(ctx);
if (ctx->state == SPU_STATE_RUNNABLE)
num = ctx->spu->number;
else
num = (unsigned int)-1;
- spu_release(ctx);
return num;
}
-DEFINE_SIMPLE_ATTRIBUTE(spufs_id_ops, spufs_id_get, NULL, "0x%llx\n")
+DEFINE_SPUFS_ATTRIBUTE(spufs_id_ops, spufs_id_get, NULL, "0x%llx\n",
+ SPU_ATTR_ACQUIRE)
-static u64 __spufs_object_id_get(struct spu_context *ctx)
-{
- return ctx->object_id;
-}
-
-static u64 spufs_object_id_get(void *data)
+static u64 spufs_object_id_get(struct spu_context *ctx)
{
/* FIXME: Should there really be no locking here? */
- return __spufs_object_id_get((struct spu_context *)data);
+ return ctx->object_id;
}
static void spufs_object_id_set(void *data, u64 id)
@@ -1786,26 +1733,15 @@ static void spufs_object_id_set(void *data, u64 id)
ctx->object_id = id;
}
-DEFINE_SIMPLE_ATTRIBUTE(spufs_object_id_ops, spufs_object_id_get,
- spufs_object_id_set, "0x%llx\n");
+DEFINE_SPUFS_ATTRIBUTE(spufs_object_id_ops, spufs_object_id_get,
+ spufs_object_id_set, "0x%llx\n", SPU_ATTR_NOACQUIRE);
-static u64 __spufs_lslr_get(struct spu_context *ctx)
+static u64 spufs_lslr_get(struct spu_context *ctx)
{
return ctx->csa.priv2.spu_lslr_RW;
}
-
-static u64 spufs_lslr_get(void *data)
-{
- struct spu_context *ctx = data;
- u64 ret;
-
- spu_acquire_saved(ctx);
- ret = __spufs_lslr_get(ctx);
- spu_release_saved(ctx);
-
- return ret;
-}
-DEFINE_SIMPLE_ATTRIBUTE(spufs_lslr_ops, spufs_lslr_get, NULL, "0x%llx\n")
+DEFINE_SPUFS_ATTRIBUTE(spufs_lslr_ops, spufs_lslr_get, NULL, "0x%llx\n",
+ SPU_ATTR_ACQUIRE_SAVED);
static int spufs_info_open(struct inode *inode, struct file *file)
{
@@ -2230,23 +2166,23 @@ struct tree_descr spufs_dir_nosched_contents[] = {
struct spufs_coredump_reader spufs_coredump_read[] = {
{ "regs", __spufs_regs_read, NULL, sizeof(struct spu_reg128[128])},
{ "fpcr", __spufs_fpcr_read, NULL, sizeof(struct spu_reg128) },
- { "lslr", NULL, __spufs_lslr_get, 19 },
- { "decr", NULL, __spufs_decr_get, 19 },
- { "decr_status", NULL, __spufs_decr_status_get, 19 },
+ { "lslr", NULL, spufs_lslr_get, 19 },
+ { "decr", NULL, spufs_decr_get, 19 },
+ { "decr_status", NULL, spufs_decr_status_get, 19 },
{ "mem", __spufs_mem_read, NULL, LS_SIZE, },
{ "signal1", __spufs_signal1_read, NULL, sizeof(u32) },
- { "signal1_type", NULL, __spufs_signal1_type_get, 19 },
+ { "signal1_type", NULL, spufs_signal1_type_get, 19 },
{ "signal2", __spufs_signal2_read, NULL, sizeof(u32) },
- { "signal2_type", NULL, __spufs_signal2_type_get, 19 },
- { "event_mask", NULL, __spufs_event_mask_get, 19 },
- { "event_status", NULL, __spufs_event_status_get, 19 },
+ { "signal2_type", NULL, spufs_signal2_type_get, 19 },
+ { "event_mask", NULL, spufs_event_mask_get, 19 },
+ { "event_status", NULL, spufs_event_status_get, 19 },
{ "mbox_info", __spufs_mbox_info_read, NULL, sizeof(u32) },
{ "ibox_info", __spufs_ibox_info_read, NULL, sizeof(u32) },
{ "wbox_info", __spufs_wbox_info_read, NULL, 4 * sizeof(u32)},
{ "dma_info", __spufs_dma_info_read, NULL, sizeof(struct spu_dma_info)},
{ "proxydma_info", __spufs_proxydma_info_read,
NULL, sizeof(struct spu_proxydma_info)},
- { "object-id", NULL, __spufs_object_id_get, 19 },
- { "npc", NULL, __spufs_npc_get, 19 },
+ { "object-id", NULL, spufs_object_id_get, 19 },
+ { "npc", NULL, spufs_npc_get, 19 },
{ NULL },
};
^ permalink raw reply related [flat|nested] 31+ messages in thread
* Re: [PATCH 01/25] spufs: staticify file-internal functions & variables
2007-09-14 6:32 [PATCH 01/25] spufs: staticify file-internal functions & variables Jeremy Kerr
` (23 preceding siblings ...)
2007-09-14 6:32 ` [PATCH 25/25] spufs: Add DEFINE_SPUFS_ATTRIBUTE() Jeremy Kerr
@ 2007-09-14 7:42 ` Christoph Hellwig
24 siblings, 0 replies; 31+ messages in thread
From: Christoph Hellwig @ 2007-09-14 7:42 UTC (permalink / raw)
To: Jeremy Kerr; +Cc: linuxppc-dev
On Fri, Sep 14, 2007 at 04:32:54PM +1000, Jeremy Kerr wrote:
> From: Sebastian Siewior <cbe-oss-dev@ml.breakpoint.cc>
>
> There are a few symbols used only in one file within spufs; this change
> makes them static where suitable.
>
> Signed-off-by: Sebastian Siewior <sebastian@breakpoint.cc>
> Signed-off-by: Jeremy Kerr <jk@ozlabs.org>
Looks good.
> +static asmlinkage long do_spu_create(const char __user *pathname,
> + unsigned int flags, mode_t mode, struct file *neighbor)
please drop the unessecary asmlinkage here, though.
^ permalink raw reply [flat|nested] 31+ messages in thread