linux/arch/powerpc/perf/e6500-pmu.c
Rashmica Gupta ec3eb9d941 powerpc/perf: Use PVR rather than oprofile field to determine CPU version
Currently the perf CPU backend drivers detect what CPU they're on using
cur_cpu_spec->oprofile_cpu_type.

Although that works, it's a bit crufty to be using oprofile related fields,
especially seeing as oprofile is more or less unused these days.

It also means perf is reliant on the fragile logic in setup_cpu_spec()
which detects when we're using a logical PVR and copies back the PMU
related fields from the raw CPU entry. So lets check the PVR directly.

Suggested-by: Michael Ellerman <mpe@ellerman.id.au>
Signed-off-by: Rashmica Gupta <rashmica.g@gmail.com>
Signed-off-by: Christophe Leroy <christophe.leroy@csgroup.eu>
Reviewed-by: Madhavan Srinivasan <maddy@linux.vnet.ibm.com>
[chleroy: Added power10 and fixed checkpatch issues]
Reviewed-and-tested-by: Athira Rajeev <atrajeev@linux.vnet.ibm.com>
Reviewed-and-tested-By: Kajol Jain <kjain@linux.ibm.com> [For 24x7 side changes]
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/20c0ee7f99dbf0dbf8658df6b39f84753e6db1ef.1657204631.git.christophe.leroy@csgroup.eu
2022-07-27 21:36:05 +10:00

119 lines
3.0 KiB
C

// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Performance counter support for e6500 family processors.
*
* Author: Priyanka Jain, Priyanka.Jain@freescale.com
* Based on e500-pmu.c
* Copyright 2013 Freescale Semiconductor, Inc.
* Copyright 2008-2009 Paul Mackerras, IBM Corporation.
*/
#include <linux/string.h>
#include <linux/perf_event.h>
#include <asm/reg.h>
#include <asm/cputable.h>
/*
* Map of generic hardware event types to hardware events
* Zero if unsupported
*/
static int e6500_generic_events[] = {
[PERF_COUNT_HW_CPU_CYCLES] = 1,
[PERF_COUNT_HW_INSTRUCTIONS] = 2,
[PERF_COUNT_HW_CACHE_MISSES] = 221,
[PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = 12,
[PERF_COUNT_HW_BRANCH_MISSES] = 15,
};
#define C(x) PERF_COUNT_HW_CACHE_##x
/*
* Table of generalized cache-related events.
* 0 means not supported, -1 means nonsensical, other values
* are event codes.
*/
static int e6500_cache_events[C(MAX)][C(OP_MAX)][C(RESULT_MAX)] = {
[C(L1D)] = {
/*RESULT_ACCESS RESULT_MISS */
[C(OP_READ)] = { 27, 222 },
[C(OP_WRITE)] = { 28, 223 },
[C(OP_PREFETCH)] = { 29, 0 },
},
[C(L1I)] = {
/*RESULT_ACCESS RESULT_MISS */
[C(OP_READ)] = { 2, 254 },
[C(OP_WRITE)] = { -1, -1 },
[C(OP_PREFETCH)] = { 37, 0 },
},
/*
* Assuming LL means L2, it's not a good match for this model.
* It does not have separate read/write events (but it does have
* separate instruction/data events).
*/
[C(LL)] = {
/*RESULT_ACCESS RESULT_MISS */
[C(OP_READ)] = { 0, 0 },
[C(OP_WRITE)] = { 0, 0 },
[C(OP_PREFETCH)] = { 0, 0 },
},
/*
* There are data/instruction MMU misses, but that's a miss on
* the chip's internal level-one TLB which is probably not
* what the user wants. Instead, unified level-two TLB misses
* are reported here.
*/
[C(DTLB)] = {
/*RESULT_ACCESS RESULT_MISS */
[C(OP_READ)] = { 26, 66 },
[C(OP_WRITE)] = { -1, -1 },
[C(OP_PREFETCH)] = { -1, -1 },
},
[C(BPU)] = {
/*RESULT_ACCESS RESULT_MISS */
[C(OP_READ)] = { 12, 15 },
[C(OP_WRITE)] = { -1, -1 },
[C(OP_PREFETCH)] = { -1, -1 },
},
[C(NODE)] = {
/* RESULT_ACCESS RESULT_MISS */
[C(OP_READ)] = { -1, -1 },
[C(OP_WRITE)] = { -1, -1 },
[C(OP_PREFETCH)] = { -1, -1 },
},
};
static int num_events = 512;
/* Upper half of event id is PMLCb, for threshold events */
static u64 e6500_xlate_event(u64 event_id)
{
u32 event_low = (u32)event_id;
if (event_low >= num_events ||
(event_id & (FSL_EMB_EVENT_THRESHMUL | FSL_EMB_EVENT_THRESH)))
return 0;
return FSL_EMB_EVENT_VALID;
}
static struct fsl_emb_pmu e6500_pmu = {
.name = "e6500 family",
.n_counter = 6,
.n_restricted = 0,
.xlate_event = e6500_xlate_event,
.n_generic = ARRAY_SIZE(e6500_generic_events),
.generic_events = e6500_generic_events,
.cache_events = &e6500_cache_events,
};
static int init_e6500_pmu(void)
{
unsigned int pvr = mfspr(SPRN_PVR);
if (PVR_VER(pvr) != PVR_VER_E6500)
return -ENODEV;
return register_fsl_emb_pmu(&e6500_pmu);
}
early_initcall(init_e6500_pmu);