All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH][2.6.11-mm3] perfctr API update 8/9: cpu_control access, ppc32
@ 2005-03-12 23:24 Mikael Pettersson
  0 siblings, 0 replies; only message in thread
From: Mikael Pettersson @ 2005-03-12 23:24 UTC (permalink / raw)
  To: akpm; +Cc: linux-kernel

- Implement perfctr_cpu_control_write()/read() in-kernel API.
  Only handle PERFCTR_DOMAIN_CPU_REGS, as the other domains will be
  handled in generic code.
- Implement get_reg_offset() via a static table. The ppc32 SPR numbers
  we use don't form a nice dense range, alas.

This depends on the physical-indexing patch for ppc32, and on the
common part of the cpu_control access patch.

Signed-off-by: Mikael Pettersson <mikpe@csd.uu.se>

/Mikael

 drivers/perfctr/ppc.c     |   70 ++++++++++++++++++++++++++++++++++++++++++++++
 include/asm-ppc/perfctr.h |   11 +++++++
 2 files changed, 81 insertions(+)

diff -rupN linux-2.6.11-mm3.perfctr-cpu_control_header/drivers/perfctr/ppc.c linux-2.6.11-mm3.perfctr-cpu_control-access/drivers/perfctr/ppc.c
--- linux-2.6.11-mm3.perfctr-cpu_control_header/drivers/perfctr/ppc.c	2005-03-12 19:58:15.000000000 +0100
+++ linux-2.6.11-mm3.perfctr-cpu_control-access/drivers/perfctr/ppc.c	2005-03-12 20:01:39.000000000 +0100
@@ -636,6 +636,76 @@ int perfctr_cpu_update_control(struct pe
 	return 0;
 }
 
+/*
+ * get_reg_offset() maps SPR numbers to offsets into struct perfctr_cpu_control,
+ * suitable for accessing control data of type unsigned int.
+ */
+static const struct {
+	unsigned int spr;
+	unsigned int offset;
+} reg_offsets[] = {
+	{ SPRN_MMCR0, offsetof(struct perfctr_cpu_control, mmcr0) },
+	{ SPRN_MMCR1, offsetof(struct perfctr_cpu_control, mmcr1) },
+	{ SPRN_MMCR2, offsetof(struct perfctr_cpu_control, mmcr2) },
+	{ SPRN_PMC1,  offsetof(struct perfctr_cpu_control, ireset[1-1]) },
+	{ SPRN_PMC2,  offsetof(struct perfctr_cpu_control, ireset[2-1]) },
+	{ SPRN_PMC3,  offsetof(struct perfctr_cpu_control, ireset[3-1]) },
+	{ SPRN_PMC4,  offsetof(struct perfctr_cpu_control, ireset[4-1]) },
+	{ SPRN_PMC5,  offsetof(struct perfctr_cpu_control, ireset[5-1]) },
+	{ SPRN_PMC6,  offsetof(struct perfctr_cpu_control, ireset[6-1]) },
+};
+
+static int get_reg_offset(unsigned int spr)
+{
+	unsigned int i;
+
+	for(i = 0; i < ARRAY_SIZE(reg_offsets); ++i)
+		if (spr == reg_offsets[i].spr)
+			return reg_offsets[i].offset;
+	return -1;
+}
+
+static int access_regs(struct perfctr_cpu_control *control,
+		       void *argp, unsigned int argbytes, int do_write)
+{
+	struct perfctr_cpu_reg *regs;
+	unsigned int i, nr_regs, *where;
+	int offset;
+
+	if (argbytes & (sizeof(struct perfctr_cpu_reg) - 1))
+		return -EINVAL;
+	regs = (struct perfctr_cpu_reg*)argp;
+	nr_regs = argbytes / sizeof(struct perfctr_cpu_reg);
+
+	for(i = 0; i < nr_regs; ++i) {
+		offset = get_reg_offset(regs[i].nr);
+		if (offset < 0)
+			return -EINVAL;
+		where = (unsigned int*)((char*)control + offset);
+		if (do_write)
+			*where = regs[i].value;
+		else
+			regs[i].value = *where;
+	}
+	return argbytes;
+}
+
+int perfctr_cpu_control_write(struct perfctr_cpu_control *control, unsigned int domain,
+			      const void *srcp, unsigned int srcbytes)
+{
+	if (domain != PERFCTR_DOMAIN_CPU_REGS)
+		return -EINVAL;
+	return access_regs(control, (void*)srcp, srcbytes, 1);
+}
+
+int perfctr_cpu_control_read(const struct perfctr_cpu_control *control, unsigned int domain,
+			     void *dstp, unsigned int dstbytes)
+{
+	if (domain != PERFCTR_DOMAIN_CPU_REGS)
+		return -EINVAL;
+	return access_regs((struct perfctr_cpu_control*)control, dstp, dstbytes, 0);
+}
+
 void perfctr_cpu_suspend(struct perfctr_cpu_state *state)
 {
 	unsigned int i, cstatus, nractrs;
diff -rupN linux-2.6.11-mm3.perfctr-cpu_control_header/include/asm-ppc/perfctr.h linux-2.6.11-mm3.perfctr-cpu_control-access/include/asm-ppc/perfctr.h
--- linux-2.6.11-mm3.perfctr-cpu_control_header/include/asm-ppc/perfctr.h	2005-03-12 19:58:15.000000000 +0100
+++ linux-2.6.11-mm3.perfctr-cpu_control-access/include/asm-ppc/perfctr.h	2005-03-12 20:01:39.000000000 +0100
@@ -133,6 +133,17 @@ extern void perfctr_cpu_release(const ch
    Returns a negative error code if the control data is invalid. */
 extern int perfctr_cpu_update_control(struct perfctr_cpu_state *state, int is_global);
 
+/* Parse and update control for the given domain. */
+extern int perfctr_cpu_control_write(struct perfctr_cpu_control *control,
+				     unsigned int domain,
+				     const void *srcp, unsigned int srcbytes);
+
+/* Retrieve and format control for the given domain.
+   Returns number of bytes written. */
+extern int perfctr_cpu_control_read(const struct perfctr_cpu_control *control,
+				    unsigned int domain,
+				    void *dstp, unsigned int dstbytes);
+
 /* Read a-mode counters. Subtract from start and accumulate into sums.
    Must be called with preemption disabled. */
 extern void perfctr_cpu_suspend(struct perfctr_cpu_state *state);

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2005-03-12 23:29 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2005-03-12 23:24 [PATCH][2.6.11-mm3] perfctr API update 8/9: cpu_control access, ppc32 Mikael Pettersson

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.