LCOV - code coverage report
Current view: top level - arch/x86/events/intel - knc.c (source / functions) Hit Total Coverage
Test: landlock.info Lines: 0 78 0.0 %
Date: 2021-04-22 12:43:58 Functions: 0 12 0.0 %

          Line data    Source code
       1             : // SPDX-License-Identifier: GPL-2.0
       2             : /* Driver for Intel Xeon Phi "Knights Corner" PMU */
       3             : 
       4             : #include <linux/perf_event.h>
       5             : #include <linux/types.h>
       6             : 
       7             : #include <asm/hardirq.h>
       8             : 
       9             : #include "../perf_event.h"
      10             : 
      11             : static const u64 knc_perfmon_event_map[] =
      12             : {
      13             :   [PERF_COUNT_HW_CPU_CYCLES]            = 0x002a,
      14             :   [PERF_COUNT_HW_INSTRUCTIONS]          = 0x0016,
      15             :   [PERF_COUNT_HW_CACHE_REFERENCES]      = 0x0028,
      16             :   [PERF_COUNT_HW_CACHE_MISSES]          = 0x0029,
      17             :   [PERF_COUNT_HW_BRANCH_INSTRUCTIONS]   = 0x0012,
      18             :   [PERF_COUNT_HW_BRANCH_MISSES]         = 0x002b,
      19             : };
      20             : 
      21             : static const u64 __initconst knc_hw_cache_event_ids
      22             :                                 [PERF_COUNT_HW_CACHE_MAX]
      23             :                                 [PERF_COUNT_HW_CACHE_OP_MAX]
      24             :                                 [PERF_COUNT_HW_CACHE_RESULT_MAX] =
      25             : {
      26             :  [ C(L1D) ] = {
      27             :         [ C(OP_READ) ] = {
      28             :                 /* On Xeon Phi event "0" is a valid DATA_READ          */
      29             :                 /*   (L1 Data Cache Reads) Instruction.                */
      30             :                 /* We code this as ARCH_PERFMON_EVENTSEL_INT as this   */
      31             :                 /* bit will always be set in x86_pmu_hw_config().      */
      32             :                 [ C(RESULT_ACCESS) ] = ARCH_PERFMON_EVENTSEL_INT,
      33             :                                                 /* DATA_READ           */
      34             :                 [ C(RESULT_MISS)   ] = 0x0003,  /* DATA_READ_MISS      */
      35             :         },
      36             :         [ C(OP_WRITE) ] = {
      37             :                 [ C(RESULT_ACCESS) ] = 0x0001,  /* DATA_WRITE          */
      38             :                 [ C(RESULT_MISS)   ] = 0x0004,  /* DATA_WRITE_MISS     */
      39             :         },
      40             :         [ C(OP_PREFETCH) ] = {
      41             :                 [ C(RESULT_ACCESS) ] = 0x0011,  /* L1_DATA_PF1         */
      42             :                 [ C(RESULT_MISS)   ] = 0x001c,  /* L1_DATA_PF1_MISS    */
      43             :         },
      44             :  },
      45             :  [ C(L1I ) ] = {
      46             :         [ C(OP_READ) ] = {
      47             :                 [ C(RESULT_ACCESS) ] = 0x000c,  /* CODE_READ          */
      48             :                 [ C(RESULT_MISS)   ] = 0x000e,  /* CODE_CACHE_MISS    */
      49             :         },
      50             :         [ C(OP_WRITE) ] = {
      51             :                 [ C(RESULT_ACCESS) ] = -1,
      52             :                 [ C(RESULT_MISS)   ] = -1,
      53             :         },
      54             :         [ C(OP_PREFETCH) ] = {
      55             :                 [ C(RESULT_ACCESS) ] = 0x0,
      56             :                 [ C(RESULT_MISS)   ] = 0x0,
      57             :         },
      58             :  },
      59             :  [ C(LL  ) ] = {
      60             :         [ C(OP_READ) ] = {
      61             :                 [ C(RESULT_ACCESS) ] = 0,
      62             :                 [ C(RESULT_MISS)   ] = 0x10cb,  /* L2_READ_MISS */
      63             :         },
      64             :         [ C(OP_WRITE) ] = {
      65             :                 [ C(RESULT_ACCESS) ] = 0x10cc,  /* L2_WRITE_HIT */
      66             :                 [ C(RESULT_MISS)   ] = 0,
      67             :         },
      68             :         [ C(OP_PREFETCH) ] = {
      69             :                 [ C(RESULT_ACCESS) ] = 0x10fc,  /* L2_DATA_PF2      */
      70             :                 [ C(RESULT_MISS)   ] = 0x10fe,  /* L2_DATA_PF2_MISS */
      71             :         },
      72             :  },
      73             :  [ C(DTLB) ] = {
      74             :         [ C(OP_READ) ] = {
      75             :                 [ C(RESULT_ACCESS) ] = ARCH_PERFMON_EVENTSEL_INT,
      76             :                                                 /* DATA_READ */
      77             :                                                 /* see note on L1 OP_READ */
      78             :                 [ C(RESULT_MISS)   ] = 0x0002,  /* DATA_PAGE_WALK */
      79             :         },
      80             :         [ C(OP_WRITE) ] = {
      81             :                 [ C(RESULT_ACCESS) ] = 0x0001,  /* DATA_WRITE */
      82             :                 [ C(RESULT_MISS)   ] = 0x0002,  /* DATA_PAGE_WALK */
      83             :         },
      84             :         [ C(OP_PREFETCH) ] = {
      85             :                 [ C(RESULT_ACCESS) ] = 0x0,
      86             :                 [ C(RESULT_MISS)   ] = 0x0,
      87             :         },
      88             :  },
      89             :  [ C(ITLB) ] = {
      90             :         [ C(OP_READ) ] = {
      91             :                 [ C(RESULT_ACCESS) ] = 0x000c,  /* CODE_READ */
      92             :                 [ C(RESULT_MISS)   ] = 0x000d,  /* CODE_PAGE_WALK */
      93             :         },
      94             :         [ C(OP_WRITE) ] = {
      95             :                 [ C(RESULT_ACCESS) ] = -1,
      96             :                 [ C(RESULT_MISS)   ] = -1,
      97             :         },
      98             :         [ C(OP_PREFETCH) ] = {
      99             :                 [ C(RESULT_ACCESS) ] = -1,
     100             :                 [ C(RESULT_MISS)   ] = -1,
     101             :         },
     102             :  },
     103             :  [ C(BPU ) ] = {
     104             :         [ C(OP_READ) ] = {
     105             :                 [ C(RESULT_ACCESS) ] = 0x0012,  /* BRANCHES */
     106             :                 [ C(RESULT_MISS)   ] = 0x002b,  /* BRANCHES_MISPREDICTED */
     107             :         },
     108             :         [ C(OP_WRITE) ] = {
     109             :                 [ C(RESULT_ACCESS) ] = -1,
     110             :                 [ C(RESULT_MISS)   ] = -1,
     111             :         },
     112             :         [ C(OP_PREFETCH) ] = {
     113             :                 [ C(RESULT_ACCESS) ] = -1,
     114             :                 [ C(RESULT_MISS)   ] = -1,
     115             :         },
     116             :  },
     117             : };
     118             : 
     119             : 
     120           0 : static u64 knc_pmu_event_map(int hw_event)
     121             : {
     122           0 :         return knc_perfmon_event_map[hw_event];
     123             : }
     124             : 
     125             : static struct event_constraint knc_event_constraints[] =
     126             : {
     127             :         INTEL_EVENT_CONSTRAINT(0xc3, 0x1),      /* HWP_L2HIT */
     128             :         INTEL_EVENT_CONSTRAINT(0xc4, 0x1),      /* HWP_L2MISS */
     129             :         INTEL_EVENT_CONSTRAINT(0xc8, 0x1),      /* L2_READ_HIT_E */
     130             :         INTEL_EVENT_CONSTRAINT(0xc9, 0x1),      /* L2_READ_HIT_M */
     131             :         INTEL_EVENT_CONSTRAINT(0xca, 0x1),      /* L2_READ_HIT_S */
     132             :         INTEL_EVENT_CONSTRAINT(0xcb, 0x1),      /* L2_READ_MISS */
     133             :         INTEL_EVENT_CONSTRAINT(0xcc, 0x1),      /* L2_WRITE_HIT */
     134             :         INTEL_EVENT_CONSTRAINT(0xce, 0x1),      /* L2_STRONGLY_ORDERED_STREAMING_VSTORES_MISS */
     135             :         INTEL_EVENT_CONSTRAINT(0xcf, 0x1),      /* L2_WEAKLY_ORDERED_STREAMING_VSTORE_MISS */
     136             :         INTEL_EVENT_CONSTRAINT(0xd7, 0x1),      /* L2_VICTIM_REQ_WITH_DATA */
     137             :         INTEL_EVENT_CONSTRAINT(0xe3, 0x1),      /* SNP_HITM_BUNIT */
     138             :         INTEL_EVENT_CONSTRAINT(0xe6, 0x1),      /* SNP_HIT_L2 */
     139             :         INTEL_EVENT_CONSTRAINT(0xe7, 0x1),      /* SNP_HITM_L2 */
     140             :         INTEL_EVENT_CONSTRAINT(0xf1, 0x1),      /* L2_DATA_READ_MISS_CACHE_FILL */
     141             :         INTEL_EVENT_CONSTRAINT(0xf2, 0x1),      /* L2_DATA_WRITE_MISS_CACHE_FILL */
     142             :         INTEL_EVENT_CONSTRAINT(0xf6, 0x1),      /* L2_DATA_READ_MISS_MEM_FILL */
     143             :         INTEL_EVENT_CONSTRAINT(0xf7, 0x1),      /* L2_DATA_WRITE_MISS_MEM_FILL */
     144             :         INTEL_EVENT_CONSTRAINT(0xfc, 0x1),      /* L2_DATA_PF2 */
     145             :         INTEL_EVENT_CONSTRAINT(0xfd, 0x1),      /* L2_DATA_PF2_DROP */
     146             :         INTEL_EVENT_CONSTRAINT(0xfe, 0x1),      /* L2_DATA_PF2_MISS */
     147             :         INTEL_EVENT_CONSTRAINT(0xff, 0x1),      /* L2_DATA_HIT_INFLIGHT_PF2 */
     148             :         EVENT_CONSTRAINT_END
     149             : };
     150             : 
     151             : #define MSR_KNC_IA32_PERF_GLOBAL_STATUS         0x0000002d
     152             : #define MSR_KNC_IA32_PERF_GLOBAL_OVF_CONTROL    0x0000002e
     153             : #define MSR_KNC_IA32_PERF_GLOBAL_CTRL           0x0000002f
     154             : 
     155             : #define KNC_ENABLE_COUNTER0                     0x00000001
     156             : #define KNC_ENABLE_COUNTER1                     0x00000002
     157             : 
     158           0 : static void knc_pmu_disable_all(void)
     159             : {
     160           0 :         u64 val;
     161             : 
     162           0 :         rdmsrl(MSR_KNC_IA32_PERF_GLOBAL_CTRL, val);
     163           0 :         val &= ~(KNC_ENABLE_COUNTER0|KNC_ENABLE_COUNTER1);
     164           0 :         wrmsrl(MSR_KNC_IA32_PERF_GLOBAL_CTRL, val);
     165           0 : }
     166             : 
     167           0 : static void knc_pmu_enable_all(int added)
     168             : {
     169           0 :         u64 val;
     170             : 
     171           0 :         rdmsrl(MSR_KNC_IA32_PERF_GLOBAL_CTRL, val);
     172           0 :         val |= (KNC_ENABLE_COUNTER0|KNC_ENABLE_COUNTER1);
     173           0 :         wrmsrl(MSR_KNC_IA32_PERF_GLOBAL_CTRL, val);
     174           0 : }
     175             : 
     176             : static inline void
     177           0 : knc_pmu_disable_event(struct perf_event *event)
     178             : {
     179           0 :         struct hw_perf_event *hwc = &event->hw;
     180           0 :         u64 val;
     181             : 
     182           0 :         val = hwc->config;
     183           0 :         val &= ~ARCH_PERFMON_EVENTSEL_ENABLE;
     184             : 
     185           0 :         (void)wrmsrl_safe(hwc->config_base + hwc->idx, val);
     186           0 : }
     187             : 
     188           0 : static void knc_pmu_enable_event(struct perf_event *event)
     189             : {
     190           0 :         struct hw_perf_event *hwc = &event->hw;
     191           0 :         u64 val;
     192             : 
     193           0 :         val = hwc->config;
     194           0 :         val |= ARCH_PERFMON_EVENTSEL_ENABLE;
     195             : 
     196           0 :         (void)wrmsrl_safe(hwc->config_base + hwc->idx, val);
     197           0 : }
     198             : 
     199           0 : static inline u64 knc_pmu_get_status(void)
     200             : {
     201           0 :         u64 status;
     202             : 
     203           0 :         rdmsrl(MSR_KNC_IA32_PERF_GLOBAL_STATUS, status);
     204             : 
     205           0 :         return status;
     206             : }
     207             : 
     208           0 : static inline void knc_pmu_ack_status(u64 ack)
     209             : {
     210           0 :         wrmsrl(MSR_KNC_IA32_PERF_GLOBAL_OVF_CONTROL, ack);
     211             : }
     212             : 
     213           0 : static int knc_pmu_handle_irq(struct pt_regs *regs)
     214             : {
     215           0 :         struct perf_sample_data data;
     216           0 :         struct cpu_hw_events *cpuc;
     217           0 :         int handled = 0;
     218           0 :         int bit, loops;
     219           0 :         u64 status;
     220             : 
     221           0 :         cpuc = this_cpu_ptr(&cpu_hw_events);
     222             : 
     223           0 :         knc_pmu_disable_all();
     224             : 
     225           0 :         status = knc_pmu_get_status();
     226           0 :         if (!status) {
     227           0 :                 knc_pmu_enable_all(0);
     228           0 :                 return handled;
     229             :         }
     230             : 
     231             :         loops = 0;
     232           0 : again:
     233           0 :         knc_pmu_ack_status(status);
     234           0 :         if (++loops > 100) {
     235           0 :                 WARN_ONCE(1, "perf: irq loop stuck!\n");
     236           0 :                 perf_event_print_debug();
     237           0 :                 goto done;
     238             :         }
     239             : 
     240           0 :         inc_irq_stat(apic_perf_irqs);
     241             : 
     242           0 :         for_each_set_bit(bit, (unsigned long *)&status, X86_PMC_IDX_MAX) {
     243           0 :                 struct perf_event *event = cpuc->events[bit];
     244             : 
     245           0 :                 handled++;
     246             : 
     247           0 :                 if (!test_bit(bit, cpuc->active_mask))
     248           0 :                         continue;
     249             : 
     250           0 :                 if (!intel_pmu_save_and_restart(event))
     251           0 :                         continue;
     252             : 
     253           0 :                 perf_sample_data_init(&data, 0, event->hw.last_period);
     254             : 
     255           0 :                 if (perf_event_overflow(event, &data, regs))
     256           0 :                         x86_pmu_stop(event, 0);
     257             :         }
     258             : 
     259             :         /*
     260             :          * Repeat if there is more work to be done:
     261             :          */
     262           0 :         status = knc_pmu_get_status();
     263           0 :         if (status)
     264           0 :                 goto again;
     265             : 
     266           0 : done:
     267             :         /* Only restore PMU state when it's active. See x86_pmu_disable(). */
     268           0 :         if (cpuc->enabled)
     269           0 :                 knc_pmu_enable_all(0);
     270             : 
     271             :         return handled;
     272             : }
     273             : 
     274             : 
     275           0 : PMU_FORMAT_ATTR(event,  "config:0-7"  );
     276           0 : PMU_FORMAT_ATTR(umask,  "config:8-15" );
     277           0 : PMU_FORMAT_ATTR(edge,   "config:18"   );
     278           0 : PMU_FORMAT_ATTR(inv,    "config:23"   );
     279           0 : PMU_FORMAT_ATTR(cmask,  "config:24-31"        );
     280             : 
     281             : static struct attribute *intel_knc_formats_attr[] = {
     282             :         &format_attr_event.attr,
     283             :         &format_attr_umask.attr,
     284             :         &format_attr_edge.attr,
     285             :         &format_attr_inv.attr,
     286             :         &format_attr_cmask.attr,
     287             :         NULL,
     288             : };
     289             : 
     290             : static const struct x86_pmu knc_pmu __initconst = {
     291             :         .name                   = "knc",
     292             :         .handle_irq             = knc_pmu_handle_irq,
     293             :         .disable_all            = knc_pmu_disable_all,
     294             :         .enable_all             = knc_pmu_enable_all,
     295             :         .enable                 = knc_pmu_enable_event,
     296             :         .disable                = knc_pmu_disable_event,
     297             :         .hw_config              = x86_pmu_hw_config,
     298             :         .schedule_events        = x86_schedule_events,
     299             :         .eventsel               = MSR_KNC_EVNTSEL0,
     300             :         .perfctr                = MSR_KNC_PERFCTR0,
     301             :         .event_map              = knc_pmu_event_map,
     302             :         .max_events             = ARRAY_SIZE(knc_perfmon_event_map),
     303             :         .apic                   = 1,
     304             :         .max_period             = (1ULL << 39) - 1,
     305             :         .version                = 0,
     306             :         .num_counters           = 2,
     307             :         .cntval_bits            = 40,
     308             :         .cntval_mask            = (1ULL << 40) - 1,
     309             :         .get_event_constraints  = x86_get_event_constraints,
     310             :         .event_constraints      = knc_event_constraints,
     311             :         .format_attrs           = intel_knc_formats_attr,
     312             : };
     313             : 
     314           0 : __init int knc_pmu_init(void)
     315             : {
     316           0 :         x86_pmu = knc_pmu;
     317             : 
     318           0 :         memcpy(hw_cache_event_ids, knc_hw_cache_event_ids, 
     319             :                 sizeof(hw_cache_event_ids));
     320             : 
     321           0 :         return 0;
     322             : }

Generated by: LCOV version 1.14