Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e9f8a0b6 authored by Christoph Hellwig's avatar Christoph Hellwig Committed by Paul Mackerras
Browse files

[POWERPC] spufs: Add stat file to spufs



Export per-context statistics in spufs.

Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
Signed-off-by: default avatarArnd Bergmann <arnd.bergmann@de.ibm.com>
Signed-off-by: default avatarJeremy Kerr <jk@ozlabs.org>
Signed-off-by: default avatarPaul Mackerras <paulus@samba.org>
parent 65de66f0
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -183,7 +183,7 @@ static int __spu_trap_data_seg(struct spu *spu, unsigned long ea)
		spu->slb_replace = 0;

	spu_restart_dma(spu);

	spu->stats.slb_flt++;
	return 0;
}

@@ -332,6 +332,7 @@ spu_irq_class_2(int irq, void *data)
	if (stat & 0x10) /* SPU mailbox threshold */
		spu->wbox_callback(spu);

	spu->stats.class2_intr++;
	return stat ? IRQ_HANDLED : IRQ_NONE;
}

+2 −0
Original line number Diff line number Diff line
@@ -59,6 +59,8 @@ struct spu_context *alloc_spu_context(struct spu_gang *gang)
		spu_gang_add_ctx(gang, ctx);
	ctx->cpus_allowed = current->cpus_allowed;
	spu_set_timeslice(ctx);
	ctx->stats.execution_state = SPUCTX_UTIL_USER;
	ctx->stats.tstamp = jiffies;

	atomic_inc(&nr_spu_contexts);
	goto out;
+16 −3
Original line number Diff line number Diff line
@@ -33,7 +33,8 @@
 * function. Currently, there are a few corner cases that we haven't had
 * to handle fortunately.
 */
static int spu_handle_mm_fault(struct mm_struct *mm, unsigned long ea, unsigned long dsisr)
static int spu_handle_mm_fault(struct mm_struct *mm, unsigned long ea,
		unsigned long dsisr, unsigned *flt)
{
	struct vm_area_struct *vma;
	unsigned long is_write;
@@ -73,7 +74,8 @@ static int spu_handle_mm_fault(struct mm_struct *mm, unsigned long ea, unsigned
			goto bad_area;
	}
	ret = 0;
	switch (handle_mm_fault(mm, vma, ea, is_write)) {
	*flt = handle_mm_fault(mm, vma, ea, is_write);
	switch (*flt) {
	case VM_FAULT_MINOR:
		current->min_flt++;
		break;
@@ -153,6 +155,7 @@ int spufs_handle_class1(struct spu_context *ctx)
{
	u64 ea, dsisr, access;
	unsigned long flags;
	unsigned flt = 0;
	int ret;

	/*
@@ -178,9 +181,13 @@ int spufs_handle_class1(struct spu_context *ctx)
	if (!(dsisr & (MFC_DSISR_PTE_NOT_FOUND | MFC_DSISR_ACCESS_DENIED)))
		return 0;

	spuctx_switch_state(ctx, SPUCTX_UTIL_IOWAIT);

	pr_debug("ctx %p: ea %016lx, dsisr %016lx state %d\n", ctx, ea,
		dsisr, ctx->state);

	ctx->stats.hash_flt++;

	/* we must not hold the lock when entering spu_handle_mm_fault */
	spu_release(ctx);

@@ -192,7 +199,7 @@ int spufs_handle_class1(struct spu_context *ctx)

	/* hashing failed, so try the actual fault handler */
	if (ret)
		ret = spu_handle_mm_fault(current->mm, ea, dsisr);
		ret = spu_handle_mm_fault(current->mm, ea, dsisr, &flt);

	spu_acquire(ctx);
	/*
@@ -201,11 +208,17 @@ int spufs_handle_class1(struct spu_context *ctx)
	 * In case of unhandled error report the problem to user space.
	 */
	if (!ret) {
		if (flt == VM_FAULT_MINOR)
			ctx->stats.min_flt++;
		else
			ctx->stats.maj_flt++;

		if (ctx->spu)
			ctx->ops->restart_dma(ctx);
	} else
		spufs_handle_dma_error(ctx, ea, SPE_EVENT_SPE_DATA_STORAGE);

	spuctx_switch_state(ctx, SPUCTX_UTIL_SYSTEM);
	return ret;
}
EXPORT_SYMBOL_GPL(spufs_handle_class1);
+79 −0
Original line number Diff line number Diff line
@@ -2059,6 +2059,83 @@ static const struct file_operations spufs_tid_fops = {
	.release	= single_release,
};

static const char *ctx_state_names[] = {
	"user", "system", "iowait", "loaded"
};

static unsigned long long spufs_acct_time(struct spu_context *ctx,
		enum spuctx_execution_state state)
{
	unsigned long time = ctx->stats.times[state];

	if (ctx->stats.execution_state == state)
		time += jiffies - ctx->stats.tstamp;

	return jiffies_to_msecs(time);
}

static unsigned long long spufs_slb_flts(struct spu_context *ctx)
{
	unsigned long long slb_flts = ctx->stats.slb_flt;

	if (ctx->state == SPU_STATE_RUNNABLE) {
		slb_flts += (ctx->spu->stats.slb_flt -
			     ctx->stats.slb_flt_base);
	}

	return slb_flts;
}

static unsigned long long spufs_class2_intrs(struct spu_context *ctx)
{
	unsigned long long class2_intrs = ctx->stats.class2_intr;

	if (ctx->state == SPU_STATE_RUNNABLE) {
		class2_intrs += (ctx->spu->stats.class2_intr -
				 ctx->stats.class2_intr_base);
	}

	return class2_intrs;
}


static int spufs_show_stat(struct seq_file *s, void *private)
{
	struct spu_context *ctx = s->private;

	spu_acquire(ctx);
	seq_printf(s, "%s %llu %llu %llu %llu "
		      "%llu %llu %llu %llu %llu %llu %llu %llu\n",
		ctx_state_names[ctx->stats.execution_state],
		spufs_acct_time(ctx, SPUCTX_UTIL_USER),
		spufs_acct_time(ctx, SPUCTX_UTIL_SYSTEM),
		spufs_acct_time(ctx, SPUCTX_UTIL_IOWAIT),
		spufs_acct_time(ctx, SPUCTX_UTIL_LOADED),
		ctx->stats.vol_ctx_switch,
		ctx->stats.invol_ctx_switch,
		spufs_slb_flts(ctx),
		ctx->stats.hash_flt,
		ctx->stats.min_flt,
		ctx->stats.maj_flt,
		spufs_class2_intrs(ctx),
		ctx->stats.libassist);
	spu_release(ctx);
	return 0;
}

static int spufs_stat_open(struct inode *inode, struct file *file)
{
	return single_open(file, spufs_show_stat, SPUFS_I(inode)->i_ctx);
}

static const struct file_operations spufs_stat_fops = {
	.open		= spufs_stat_open,
	.read		= seq_read,
	.llseek		= seq_lseek,
	.release	= single_release,
};


struct tree_descr spufs_dir_contents[] = {
	{ "capabilities", &spufs_caps_fops, 0444, },
	{ "mem",  &spufs_mem_fops,  0666, },
@@ -2093,6 +2170,7 @@ struct tree_descr spufs_dir_contents[] = {
	{ "dma_info", &spufs_dma_info_fops, 0444, },
	{ "proxydma_info", &spufs_proxydma_info_fops, 0444, },
	{ "tid", &spufs_tid_fops, 0444, },
	{ "stat", &spufs_stat_fops, 0444, },
	{},
};

@@ -2117,6 +2195,7 @@ struct tree_descr spufs_dir_nosched_contents[] = {
	{ "phys-id", &spufs_id_ops, 0666, },
	{ "object-id", &spufs_object_id_ops, 0666, },
	{ "tid", &spufs_tid_fops, 0444, },
	{ "stat", &spufs_stat_fops, 0444, },
	{},
};

+4 −0
Original line number Diff line number Diff line
@@ -351,6 +351,10 @@ long spufs_run_spu(struct file *file, struct spu_context *ctx,
				      SPU_STATUS_STOPPED_BY_HALT |
				       SPU_STATUS_SINGLE_STEP)));

	if ((status & SPU_STATUS_STOPPED_BY_STOP) &&
	    ((status >> SPU_STOP_STATUS_SHIFT) & 0x2100))
		ctx->stats.libassist++;

	ctx->ops->master_stop(ctx);
	ret = spu_run_fini(ctx, npc, &status);
	spu_yield(ctx);
Loading