perfctr ppc32 ABI update:
- <asm-ppc/perfctr.h>: In user-visible state, make start fields
  64 bits (for future-proofing the ABI). Remove map field from
  pmc[] array to avoid underutilised cache lines.
- ppc.c: retrieve mapping from ->control.pmc_map[].
- ppc32: Add sampling counter to user-visible state, and
  increment it in perfctr_cpu_resume() and perfctr_cpu_sample().

Signed-off-by: Mikael Pettersson <[EMAIL PROTECTED]>

 drivers/perfctr/ppc.c     |   16 ++++++++--------
 include/asm-ppc/perfctr.h |   15 +++++++++------
 2 files changed, 17 insertions(+), 14 deletions(-)

diff -rupN linux-2.6.12-rc2-mm2/drivers/perfctr/ppc.c 
linux-2.6.12-rc2-mm2.perfctr-ppc32-update/drivers/perfctr/ppc.c
--- linux-2.6.12-rc2-mm2/drivers/perfctr/ppc.c  2005-04-08 13:14:23.000000000 
+0200
+++ linux-2.6.12-rc2-mm2.perfctr-ppc32-update/drivers/perfctr/ppc.c     
2005-04-09 13:52:34.000000000 +0200
@@ -1,4 +1,4 @@
-/* $Id: ppc.c,v 1.35 2005/03/17 23:50:05 mikpe Exp $
+/* $Id: ppc.c,v 1.39 2005/04/08 14:36:49 mikpe Exp $
  * PPC32 performance-monitoring counters driver.
  *
  * Copyright (C) 2004-2005  Mikael Pettersson
@@ -237,7 +237,7 @@ static void ppc_read_counters(struct per
                ctrs->tsc = get_tbl();
        nrctrs = perfctr_cstatus_nractrs(cstatus);
        for(i = 0; i < nrctrs; ++i) {
-               unsigned int pmc = state->user.pmc[i].map;
+               unsigned int pmc = state->control.pmc_map[i];
                ctrs->pmc[i] = read_pmc(pmc);
        }
 }
@@ -299,7 +299,6 @@ static int ppc_check_control(struct perf
 
        for(i = 0; i < nrctrs; ++i) {
                pmc = state->control.pmc_map[i];
-               state->user.pmc[i].map = pmc;
                if (pmc >= nr_pmcs || (pmc_mask & (1<<pmc)))
                        return -EINVAL;
                pmc_mask |= (1<<pmc);
@@ -380,7 +379,7 @@ static void ppc_isuspend(struct perfctr_
        cstatus = state->user.cstatus;
        nrctrs = perfctr_cstatus_nrctrs(cstatus);
        for(i = perfctr_cstatus_nractrs(cstatus); i < nrctrs; ++i) {
-               unsigned int pmc = state->user.pmc[i].map;
+               unsigned int pmc = state->control.pmc_map[i];
                unsigned int now = read_pmc(pmc);
                state->user.pmc[i].sum += now - state->user.pmc[i].start;
                state->user.pmc[i].start = now;
@@ -420,7 +419,7 @@ static void ppc_iresume(const struct per
        cstatus = state->user.cstatus;
        nrctrs = perfctr_cstatus_nrctrs(cstatus);
        for(i = perfctr_cstatus_nractrs(cstatus); i < nrctrs; ++i)
-               pmc[state->user.pmc[i].map] = state->user.pmc[i].start;
+               pmc[state->control.pmc_map[i]] = state->user.pmc[i].start;
 
        switch (pm_type) {
        case PM_7450:
@@ -560,7 +559,7 @@ unsigned int perfctr_cpu_identify_overfl
        pmc_mask = 0;
        for(i = perfctr_cstatus_nractrs(cstatus); i < nrctrs; ++i) {
                if ((int)state->user.pmc[i].start < 0) { /* PPC-specific */
-                       unsigned int pmc = state->user.pmc[i].map;
+                       unsigned int pmc = state->control.pmc_map[i];
                        /* XXX: "+=" to correct for overshots */
                        state->user.pmc[i].start = state->control.ireset[pmc];
                        pmc_mask |= (1 << i);
@@ -578,7 +577,7 @@ static inline int check_ireset(struct pe
        i = state->control.header.nractrs;
        nrctrs = i + state->control.header.nrictrs;
        for(; i < nrctrs; ++i) {
-               unsigned int pmc = state->user.pmc[i].map;
+               unsigned int pmc = state->control.pmc_map[i];
                if ((int)state->control.ireset[pmc] < 0) /* PPC-specific */
                        return -EINVAL;
                state->user.pmc[i].start = state->control.ireset[pmc];
@@ -734,7 +733,7 @@ void perfctr_cpu_resume(struct perfctr_c
                for(i = 0; i < nrctrs; ++i)
                        state->user.pmc[i].start = now.pmc[i];
        }
-       /* XXX: if (SMP && start.tsc == now.tsc) ++now.tsc; */
+       ++state->user.samplecnt;
 }
 
 void perfctr_cpu_sample(struct perfctr_cpu_state *state)
@@ -753,6 +752,7 @@ void perfctr_cpu_sample(struct perfctr_c
                state->user.pmc[i].sum += now.pmc[i] - state->user.pmc[i].start;
                state->user.pmc[i].start = now.pmc[i];
        }
+       ++state->user.samplecnt;
 }
 
 static void perfctr_cpu_clear_counters(void)
diff -rupN linux-2.6.12-rc2-mm2/include/asm-ppc/perfctr.h 
linux-2.6.12-rc2-mm2.perfctr-ppc32-update/include/asm-ppc/perfctr.h
--- linux-2.6.12-rc2-mm2/include/asm-ppc/perfctr.h      2005-04-08 
13:14:24.000000000 +0200
+++ linux-2.6.12-rc2-mm2.perfctr-ppc32-update/include/asm-ppc/perfctr.h 
2005-04-09 13:52:34.000000000 +0200
@@ -1,4 +1,4 @@
-/* $Id: perfctr.h,v 1.16 2005/03/17 23:58:54 mikpe Exp $
+/* $Id: perfctr.h,v 1.19 2005/04/08 14:36:49 mikpe Exp $
  * PPC32 Performance-Monitoring Counters driver
  *
  * Copyright (C) 2004-2005  Mikael Pettersson
@@ -21,13 +21,16 @@ struct perfctr_cpu_control_header {
 
 struct perfctr_cpu_state_user {
        __u32 cstatus;
-       /* The two tsc fields must be inlined. Placing them in a
-          sub-struct causes unwanted internal padding on x86-64. */
-       __u32 tsc_start;
+       /* 'samplecnt' is incremented every time the 'start'
+          fields have been updated by a sampling operation.
+          Unfortunately the PPC timebase (tsc_start) has too
+          low frequency for it to be a reliable context-switch
+          indicator for user-space. */
+       __u32 samplecnt;
+       __u64 tsc_start;
        __u64 tsc_sum;
        struct {
-               __u32 map;
-               __u32 start;
+               __u64 start;
                __u64 sum;
        } pmc[8];       /* the size is not part of the user ABI */
 };
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to