From: Mikael Pettersson perfctr ppc64 ABI update: - : 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. - ppc64.c: retrieve mapping from ->control.pmc_map[]. - ppc64: Add sampling counter to user-visible state, and increment it in perfctr_cpu_resume() and perfctr_cpu_sample(). Signed-off-by: Mikael Pettersson Signed-off-by: Andrew Morton --- 25-akpm/drivers/perfctr/ppc64.c | 16 ++++++++-------- 25-akpm/include/asm-ppc64/perfctr.h | 13 ++++++++----- 2 files changed, 16 insertions(+), 13 deletions(-) diff -puN drivers/perfctr/ppc64.c~perfctr-ppc64-abi-update drivers/perfctr/ppc64.c --- 25/drivers/perfctr/ppc64.c~perfctr-ppc64-abi-update 2005-04-10 15:11:11.000000000 -0700 +++ 25-akpm/drivers/perfctr/ppc64.c 2005-04-10 15:11:11.000000000 -0700 @@ -244,7 +244,7 @@ static void perfctr_cpu_read_counters(st ctrs->tsc = mftb() & 0xffffffff; for (i = 0; i < perfctr_cstatus_nractrs(cstatus); ++i) { - pmc = state->user.pmc[i].map; + pmc = state->control.pmc_map[i]; ctrs->pmc[i] = read_pmc(pmc); } } @@ -260,7 +260,7 @@ static void perfctr_cpu_isuspend(struct 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; @@ -299,7 +299,7 @@ static void perfctr_cpu_iresume(const st cstatus = state->user.cstatus; nrctrs = perfctr_cstatus_nrctrs(cstatus); for (i = perfctr_cstatus_nractrs(cstatus); i < nrctrs; ++i) { - write_pmc(state->user.pmc[i].map, state->user.pmc[i].start); + write_pmc(state->control.pmc_map[i], state->user.pmc[i].start); } } @@ -334,7 +334,7 @@ unsigned int perfctr_cpu_identify_overfl * amd unused PMCs as well as the ones we actually care * about. */ for (i = 0; i < nractrs; ++i) { - int pmc = state->user.pmc[i].map; + int pmc = state->control.pmc_map[i]; unsigned int val = read_pmc(pmc); /* For actrs, force a sample if they overflowed */ @@ -347,7 +347,7 @@ unsigned int perfctr_cpu_identify_overfl } for (; i < nrctrs; ++i) { if ((int)state->user.pmc[i].start < 0) { /* PPC64-specific */ - int pmc = state->user.pmc[i].map; + 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); @@ -376,7 +376,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) /* PPC64-specific */ return -EINVAL; state->user.pmc[i].start = state->control.ireset[pmc]; @@ -406,7 +406,6 @@ static int check_control(struct perfctr_ pmc_mask = 0; 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<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) @@ -590,6 +589,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 -puN include/asm-ppc64/perfctr.h~perfctr-ppc64-abi-update include/asm-ppc64/perfctr.h --- 25/include/asm-ppc64/perfctr.h~perfctr-ppc64-abi-update 2005-04-10 15:11:11.000000000 -0700 +++ 25-akpm/include/asm-ppc64/perfctr.h 2005-04-10 15:11:11.000000000 -0700 @@ -22,13 +22,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 */ }; _