root/arch/sh/kernel/cpu/sh4/perf_event.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. sh7750_event_map
  2. sh7750_pmu_read
  3. sh7750_pmu_disable
  4. sh7750_pmu_enable
  5. sh7750_pmu_disable_all
  6. sh7750_pmu_enable_all
  7. sh7750_pmu_init

   1 // SPDX-License-Identifier: GPL-2.0
   2 /*
   3  * Performance events support for SH7750-style performance counters
   4  *
   5  *  Copyright (C) 2009  Paul Mundt
   6  */
   7 #include <linux/kernel.h>
   8 #include <linux/init.h>
   9 #include <linux/io.h>
  10 #include <linux/irq.h>
  11 #include <linux/perf_event.h>
  12 #include <asm/processor.h>
  13 
  14 #define PM_CR_BASE      0xff000084      /* 16-bit */
  15 #define PM_CTR_BASE     0xff100004      /* 32-bit */
  16 
  17 #define PMCR(n)         (PM_CR_BASE + ((n) * 0x04))
  18 #define PMCTRH(n)       (PM_CTR_BASE + 0x00 + ((n) * 0x08))
  19 #define PMCTRL(n)       (PM_CTR_BASE + 0x04 + ((n) * 0x08))
  20 
  21 #define PMCR_PMM_MASK   0x0000003f
  22 
  23 #define PMCR_CLKF       0x00000100
  24 #define PMCR_PMCLR      0x00002000
  25 #define PMCR_PMST       0x00004000
  26 #define PMCR_PMEN       0x00008000
  27 
  28 static struct sh_pmu sh7750_pmu;
  29 
  30 /*
  31  * There are a number of events supported by each counter (33 in total).
  32  * Since we have 2 counters, each counter will take the event code as it
  33  * corresponds to the PMCR PMM setting. Each counter can be configured
  34  * independently.
  35  *
  36  *      Event Code      Description
  37  *      ----------      -----------
  38  *
  39  *      0x01            Operand read access
  40  *      0x02            Operand write access
  41  *      0x03            UTLB miss
  42  *      0x04            Operand cache read miss
  43  *      0x05            Operand cache write miss
  44  *      0x06            Instruction fetch (w/ cache)
  45  *      0x07            Instruction TLB miss
  46  *      0x08            Instruction cache miss
  47  *      0x09            All operand accesses
  48  *      0x0a            All instruction accesses
  49  *      0x0b            OC RAM operand access
  50  *      0x0d            On-chip I/O space access
  51  *      0x0e            Operand access (r/w)
  52  *      0x0f            Operand cache miss (r/w)
  53  *      0x10            Branch instruction
  54  *      0x11            Branch taken
  55  *      0x12            BSR/BSRF/JSR
  56  *      0x13            Instruction execution
  57  *      0x14            Instruction execution in parallel
  58  *      0x15            FPU Instruction execution
  59  *      0x16            Interrupt
  60  *      0x17            NMI
  61  *      0x18            trapa instruction execution
  62  *      0x19            UBCA match
  63  *      0x1a            UBCB match
  64  *      0x21            Instruction cache fill
  65  *      0x22            Operand cache fill
  66  *      0x23            Elapsed time
  67  *      0x24            Pipeline freeze by I-cache miss
  68  *      0x25            Pipeline freeze by D-cache miss
  69  *      0x27            Pipeline freeze by branch instruction
  70  *      0x28            Pipeline freeze by CPU register
  71  *      0x29            Pipeline freeze by FPU
  72  */
  73 
  74 static const int sh7750_general_events[] = {
  75         [PERF_COUNT_HW_CPU_CYCLES]              = 0x0023,
  76         [PERF_COUNT_HW_INSTRUCTIONS]            = 0x000a,
  77         [PERF_COUNT_HW_CACHE_REFERENCES]        = 0x0006,       /* I-cache */
  78         [PERF_COUNT_HW_CACHE_MISSES]            = 0x0008,       /* I-cache */
  79         [PERF_COUNT_HW_BRANCH_INSTRUCTIONS]     = 0x0010,
  80         [PERF_COUNT_HW_BRANCH_MISSES]           = -1,
  81         [PERF_COUNT_HW_BUS_CYCLES]              = -1,
  82 };
  83 
  84 #define C(x)    PERF_COUNT_HW_CACHE_##x
  85 
  86 static const int sh7750_cache_events
  87                         [PERF_COUNT_HW_CACHE_MAX]
  88                         [PERF_COUNT_HW_CACHE_OP_MAX]
  89                         [PERF_COUNT_HW_CACHE_RESULT_MAX] =
  90 {
  91         [ C(L1D) ] = {
  92                 [ C(OP_READ) ] = {
  93                         [ C(RESULT_ACCESS) ] = 0x0001,
  94                         [ C(RESULT_MISS)   ] = 0x0004,
  95                 },
  96                 [ C(OP_WRITE) ] = {
  97                         [ C(RESULT_ACCESS) ] = 0x0002,
  98                         [ C(RESULT_MISS)   ] = 0x0005,
  99                 },
 100                 [ C(OP_PREFETCH) ] = {
 101                         [ C(RESULT_ACCESS) ] = 0,
 102                         [ C(RESULT_MISS)   ] = 0,
 103                 },
 104         },
 105 
 106         [ C(L1I) ] = {
 107                 [ C(OP_READ) ] = {
 108                         [ C(RESULT_ACCESS) ] = 0x0006,
 109                         [ C(RESULT_MISS)   ] = 0x0008,
 110                 },
 111                 [ C(OP_WRITE) ] = {
 112                         [ C(RESULT_ACCESS) ] = -1,
 113                         [ C(RESULT_MISS)   ] = -1,
 114                 },
 115                 [ C(OP_PREFETCH) ] = {
 116                         [ C(RESULT_ACCESS) ] = 0,
 117                         [ C(RESULT_MISS)   ] = 0,
 118                 },
 119         },
 120 
 121         [ C(LL) ] = {
 122                 [ C(OP_READ) ] = {
 123                         [ C(RESULT_ACCESS) ] = 0,
 124                         [ C(RESULT_MISS)   ] = 0,
 125                 },
 126                 [ C(OP_WRITE) ] = {
 127                         [ C(RESULT_ACCESS) ] = 0,
 128                         [ C(RESULT_MISS)   ] = 0,
 129                 },
 130                 [ C(OP_PREFETCH) ] = {
 131                         [ C(RESULT_ACCESS) ] = 0,
 132                         [ C(RESULT_MISS)   ] = 0,
 133                 },
 134         },
 135 
 136         [ C(DTLB) ] = {
 137                 [ C(OP_READ) ] = {
 138                         [ C(RESULT_ACCESS) ] = 0,
 139                         [ C(RESULT_MISS)   ] = 0x0003,
 140                 },
 141                 [ C(OP_WRITE) ] = {
 142                         [ C(RESULT_ACCESS) ] = 0,
 143                         [ C(RESULT_MISS)   ] = 0,
 144                 },
 145                 [ C(OP_PREFETCH) ] = {
 146                         [ C(RESULT_ACCESS) ] = 0,
 147                         [ C(RESULT_MISS)   ] = 0,
 148                 },
 149         },
 150 
 151         [ C(ITLB) ] = {
 152                 [ C(OP_READ) ] = {
 153                         [ C(RESULT_ACCESS) ] = 0,
 154                         [ C(RESULT_MISS)   ] = 0x0007,
 155                 },
 156                 [ C(OP_WRITE) ] = {
 157                         [ C(RESULT_ACCESS) ] = -1,
 158                         [ C(RESULT_MISS)   ] = -1,
 159                 },
 160                 [ C(OP_PREFETCH) ] = {
 161                         [ C(RESULT_ACCESS) ] = -1,
 162                         [ C(RESULT_MISS)   ] = -1,
 163                 },
 164         },
 165 
 166         [ C(BPU) ] = {
 167                 [ C(OP_READ) ] = {
 168                         [ C(RESULT_ACCESS) ] = -1,
 169                         [ C(RESULT_MISS)   ] = -1,
 170                 },
 171                 [ C(OP_WRITE) ] = {
 172                         [ C(RESULT_ACCESS) ] = -1,
 173                         [ C(RESULT_MISS)   ] = -1,
 174                 },
 175                 [ C(OP_PREFETCH) ] = {
 176                         [ C(RESULT_ACCESS) ] = -1,
 177                         [ C(RESULT_MISS)   ] = -1,
 178                 },
 179         },
 180 
 181         [ C(NODE) ] = {
 182                 [ C(OP_READ) ] = {
 183                         [ C(RESULT_ACCESS) ] = -1,
 184                         [ C(RESULT_MISS)   ] = -1,
 185                 },
 186                 [ C(OP_WRITE) ] = {
 187                         [ C(RESULT_ACCESS) ] = -1,
 188                         [ C(RESULT_MISS)   ] = -1,
 189                 },
 190                 [ C(OP_PREFETCH) ] = {
 191                         [ C(RESULT_ACCESS) ] = -1,
 192                         [ C(RESULT_MISS)   ] = -1,
 193                 },
 194         },
 195 };
 196 
 197 static int sh7750_event_map(int event)
 198 {
 199         return sh7750_general_events[event];
 200 }
 201 
 202 static u64 sh7750_pmu_read(int idx)
 203 {
 204         return (u64)((u64)(__raw_readl(PMCTRH(idx)) & 0xffff) << 32) |
 205                            __raw_readl(PMCTRL(idx));
 206 }
 207 
 208 static void sh7750_pmu_disable(struct hw_perf_event *hwc, int idx)
 209 {
 210         unsigned int tmp;
 211 
 212         tmp = __raw_readw(PMCR(idx));
 213         tmp &= ~(PMCR_PMM_MASK | PMCR_PMEN);
 214         __raw_writew(tmp, PMCR(idx));
 215 }
 216 
 217 static void sh7750_pmu_enable(struct hw_perf_event *hwc, int idx)
 218 {
 219         __raw_writew(__raw_readw(PMCR(idx)) | PMCR_PMCLR, PMCR(idx));
 220         __raw_writew(hwc->config | PMCR_PMEN | PMCR_PMST, PMCR(idx));
 221 }
 222 
 223 static void sh7750_pmu_disable_all(void)
 224 {
 225         int i;
 226 
 227         for (i = 0; i < sh7750_pmu.num_events; i++)
 228                 __raw_writew(__raw_readw(PMCR(i)) & ~PMCR_PMEN, PMCR(i));
 229 }
 230 
 231 static void sh7750_pmu_enable_all(void)
 232 {
 233         int i;
 234 
 235         for (i = 0; i < sh7750_pmu.num_events; i++)
 236                 __raw_writew(__raw_readw(PMCR(i)) | PMCR_PMEN, PMCR(i));
 237 }
 238 
 239 static struct sh_pmu sh7750_pmu = {
 240         .name           = "sh7750",
 241         .num_events     = 2,
 242         .event_map      = sh7750_event_map,
 243         .max_events     = ARRAY_SIZE(sh7750_general_events),
 244         .raw_event_mask = PMCR_PMM_MASK,
 245         .cache_events   = &sh7750_cache_events,
 246         .read           = sh7750_pmu_read,
 247         .disable        = sh7750_pmu_disable,
 248         .enable         = sh7750_pmu_enable,
 249         .disable_all    = sh7750_pmu_disable_all,
 250         .enable_all     = sh7750_pmu_enable_all,
 251 };
 252 
 253 static int __init sh7750_pmu_init(void)
 254 {
 255         /*
 256          * Make sure this CPU actually has perf counters.
 257          */
 258         if (!(boot_cpu_data.flags & CPU_HAS_PERF_COUNTER)) {
 259                 pr_notice("HW perf events unsupported, software events only.\n");
 260                 return -ENODEV;
 261         }
 262 
 263         return register_sh_pmu(&sh7750_pmu);
 264 }
 265 early_initcall(sh7750_pmu_init);

/* [<][>][^][v][top][bottom][index][help] */