Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * Performance counter support for e500 family processors.
0004  *
0005  * Copyright 2008-2009 Paul Mackerras, IBM Corporation.
0006  * Copyright 2010 Freescale Semiconductor, Inc.
0007  */
0008 #include <linux/string.h>
0009 #include <linux/perf_event.h>
0010 #include <asm/reg.h>
0011 #include <asm/cputable.h>
0012 
0013 /*
0014  * Map of generic hardware event types to hardware events
0015  * Zero if unsupported
0016  */
0017 static int e500_generic_events[] = {
0018     [PERF_COUNT_HW_CPU_CYCLES] = 1,
0019     [PERF_COUNT_HW_INSTRUCTIONS] = 2,
0020     [PERF_COUNT_HW_CACHE_MISSES] = 41, /* Data L1 cache reloads */
0021     [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = 12,
0022     [PERF_COUNT_HW_BRANCH_MISSES] = 15,
0023     [PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] = 18,
0024     [PERF_COUNT_HW_STALLED_CYCLES_BACKEND] = 19,
0025 };
0026 
0027 #define C(x)    PERF_COUNT_HW_CACHE_##x
0028 
0029 /*
0030  * Table of generalized cache-related events.
0031  * 0 means not supported, -1 means nonsensical, other values
0032  * are event codes.
0033  */
0034 static int e500_cache_events[C(MAX)][C(OP_MAX)][C(RESULT_MAX)] = {
0035     /*
0036      * D-cache misses are not split into read/write/prefetch;
0037      * use raw event 41.
0038      */
0039     [C(L1D)] = {        /*  RESULT_ACCESS   RESULT_MISS */
0040         [C(OP_READ)] = {    27,     0   },
0041         [C(OP_WRITE)] = {   28,     0   },
0042         [C(OP_PREFETCH)] = {    29,     0   },
0043     },
0044     [C(L1I)] = {        /*  RESULT_ACCESS   RESULT_MISS */
0045         [C(OP_READ)] = {    2,      60  },
0046         [C(OP_WRITE)] = {   -1,     -1  },
0047         [C(OP_PREFETCH)] = {    0,      0   },
0048     },
0049     /*
0050      * Assuming LL means L2, it's not a good match for this model.
0051      * It allocates only on L1 castout or explicit prefetch, and
0052      * does not have separate read/write events (but it does have
0053      * separate instruction/data events).
0054      */
0055     [C(LL)] = {     /*  RESULT_ACCESS   RESULT_MISS */
0056         [C(OP_READ)] = {    0,      0   },
0057         [C(OP_WRITE)] = {   0,      0   },
0058         [C(OP_PREFETCH)] = {    0,      0   },
0059     },
0060     /*
0061      * There are data/instruction MMU misses, but that's a miss on
0062      * the chip's internal level-one TLB which is probably not
0063      * what the user wants.  Instead, unified level-two TLB misses
0064      * are reported here.
0065      */
0066     [C(DTLB)] = {       /*  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)] = {        /*  RESULT_ACCESS   RESULT_MISS */
0072         [C(OP_READ)] = {    12,     15  },
0073         [C(OP_WRITE)] = {   -1,     -1  },
0074         [C(OP_PREFETCH)] = {    -1,     -1  },
0075     },
0076     [C(NODE)] = {       /*  RESULT_ACCESS   RESULT_MISS */
0077         [C(OP_READ)] = {    -1,     -1  },
0078         [C(OP_WRITE)] = {   -1,     -1  },
0079         [C(OP_PREFETCH)] = {    -1,     -1  },
0080     },
0081 };
0082 
0083 static int num_events = 128;
0084 
0085 /* Upper half of event id is PMLCb, for threshold events */
0086 static u64 e500_xlate_event(u64 event_id)
0087 {
0088     u32 event_low = (u32)event_id;
0089     u64 ret;
0090 
0091     if (event_low >= num_events)
0092         return 0;
0093 
0094     ret = FSL_EMB_EVENT_VALID;
0095 
0096     if (event_low >= 76 && event_low <= 81) {
0097         ret |= FSL_EMB_EVENT_RESTRICTED;
0098         ret |= event_id &
0099                (FSL_EMB_EVENT_THRESHMUL | FSL_EMB_EVENT_THRESH);
0100     } else if (event_id &
0101                (FSL_EMB_EVENT_THRESHMUL | FSL_EMB_EVENT_THRESH)) {
0102         /* Threshold requested on non-threshold event */
0103         return 0;
0104     }
0105 
0106     return ret;
0107 }
0108 
0109 static struct fsl_emb_pmu e500_pmu = {
0110     .name           = "e500 family",
0111     .n_counter      = 4,
0112     .n_restricted       = 2,
0113     .xlate_event        = e500_xlate_event,
0114     .n_generic      = ARRAY_SIZE(e500_generic_events),
0115     .generic_events     = e500_generic_events,
0116     .cache_events       = &e500_cache_events,
0117 };
0118 
0119 static int init_e500_pmu(void)
0120 {
0121     unsigned int pvr = mfspr(SPRN_PVR);
0122 
0123     /* ec500mc */
0124     if (PVR_VER(pvr) == PVR_VER_E500MC || PVR_VER(pvr) == PVR_VER_E5500)
0125         num_events = 256;
0126     /* e500 */
0127     else if (PVR_VER(pvr) != PVR_VER_E500V1 && PVR_VER(pvr) != PVR_VER_E500V2)
0128         return -ENODEV;
0129 
0130     return register_fsl_emb_pmu(&e500_pmu);
0131 }
0132 
0133 early_initcall(init_e500_pmu);