Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * Performance counter support for e6500 family processors.
0004  *
0005  * Author: Priyanka Jain, Priyanka.Jain@freescale.com
0006  * Based on e500-pmu.c
0007  * Copyright 2013 Freescale Semiconductor, Inc.
0008  * Copyright 2008-2009 Paul Mackerras, IBM Corporation.
0009  */
0010 
0011 #include <linux/string.h>
0012 #include <linux/perf_event.h>
0013 #include <asm/reg.h>
0014 #include <asm/cputable.h>
0015 
0016 /*
0017  * Map of generic hardware event types to hardware events
0018  * Zero if unsupported
0019  */
0020 static int e6500_generic_events[] = {
0021     [PERF_COUNT_HW_CPU_CYCLES] = 1,
0022     [PERF_COUNT_HW_INSTRUCTIONS] = 2,
0023     [PERF_COUNT_HW_CACHE_MISSES] = 221,
0024     [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = 12,
0025     [PERF_COUNT_HW_BRANCH_MISSES] = 15,
0026 };
0027 
0028 #define C(x)    PERF_COUNT_HW_CACHE_##x
0029 
0030 /*
0031  * Table of generalized cache-related events.
0032  * 0 means not supported, -1 means nonsensical, other values
0033  * are event codes.
0034  */
0035 static int e6500_cache_events[C(MAX)][C(OP_MAX)][C(RESULT_MAX)] = {
0036     [C(L1D)] = {
0037                 /*RESULT_ACCESS     RESULT_MISS */
0038         [C(OP_READ)] = {    27,     222 },
0039         [C(OP_WRITE)] = {   28,     223 },
0040         [C(OP_PREFETCH)] = {    29,     0   },
0041     },
0042     [C(L1I)] = {
0043                 /*RESULT_ACCESS     RESULT_MISS */
0044         [C(OP_READ)] = {    2,      254 },
0045         [C(OP_WRITE)] = {   -1,     -1  },
0046         [C(OP_PREFETCH)] = {    37,     0   },
0047     },
0048     /*
0049      * Assuming LL means L2, it's not a good match for this model.
0050      * It does not have separate read/write events (but it does have
0051      * separate instruction/data events).
0052      */
0053     [C(LL)] = {
0054                 /*RESULT_ACCESS     RESULT_MISS */
0055         [C(OP_READ)] = {    0,      0   },
0056         [C(OP_WRITE)] = {   0,      0   },
0057         [C(OP_PREFETCH)] = {    0,      0   },
0058     },
0059     /*
0060      * There are data/instruction MMU misses, but that's a miss on
0061      * the chip's internal level-one TLB which is probably not
0062      * what the user wants.  Instead, unified level-two TLB misses
0063      * are reported here.
0064      */
0065     [C(DTLB)] = {
0066                 /*RESULT_ACCESS     RESULT_MISS */
0067         [C(OP_READ)] = {    26,     66  },
0068         [C(OP_WRITE)] = {   -1,     -1  },
0069         [C(OP_PREFETCH)] = {    -1,     -1  },
0070     },
0071     [C(BPU)] = {
0072                 /*RESULT_ACCESS     RESULT_MISS */
0073         [C(OP_READ)] = {    12,     15  },
0074         [C(OP_WRITE)] = {   -1,     -1  },
0075         [C(OP_PREFETCH)] = {    -1,     -1  },
0076     },
0077     [C(NODE)] = {
0078                 /* RESULT_ACCESS    RESULT_MISS */
0079         [C(OP_READ)] = {    -1,     -1  },
0080         [C(OP_WRITE)] = {   -1,     -1  },
0081         [C(OP_PREFETCH)] = {    -1,     -1  },
0082     },
0083 };
0084 
0085 static int num_events = 512;
0086 
0087 /* Upper half of event id is PMLCb, for threshold events */
0088 static u64 e6500_xlate_event(u64 event_id)
0089 {
0090     u32 event_low = (u32)event_id;
0091     if (event_low >= num_events ||
0092         (event_id & (FSL_EMB_EVENT_THRESHMUL | FSL_EMB_EVENT_THRESH)))
0093         return 0;
0094 
0095     return FSL_EMB_EVENT_VALID;
0096 }
0097 
0098 static struct fsl_emb_pmu e6500_pmu = {
0099     .name           = "e6500 family",
0100     .n_counter      = 6,
0101     .n_restricted       = 0,
0102     .xlate_event        = e6500_xlate_event,
0103     .n_generic      = ARRAY_SIZE(e6500_generic_events),
0104     .generic_events     = e6500_generic_events,
0105     .cache_events       = &e6500_cache_events,
0106 };
0107 
0108 static int init_e6500_pmu(void)
0109 {
0110     unsigned int pvr = mfspr(SPRN_PVR);
0111 
0112     if (PVR_VER(pvr) != PVR_VER_E6500)
0113         return -ENODEV;
0114 
0115     return register_fsl_emb_pmu(&e6500_pmu);
0116 }
0117 
0118 early_initcall(init_e6500_pmu);