1fd1c601cSBorislav Petkov /* 2fd1c601cSBorislav Petkov * Intel(R) Processor Trace PMU driver for perf 3fd1c601cSBorislav Petkov * Copyright (c) 2013-2014, Intel Corporation. 4fd1c601cSBorislav Petkov * 5fd1c601cSBorislav Petkov * This program is free software; you can redistribute it and/or modify it 6fd1c601cSBorislav Petkov * under the terms and conditions of the GNU General Public License, 7fd1c601cSBorislav Petkov * version 2, as published by the Free Software Foundation. 8fd1c601cSBorislav Petkov * 9fd1c601cSBorislav Petkov * This program is distributed in the hope it will be useful, but WITHOUT 10fd1c601cSBorislav Petkov * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11fd1c601cSBorislav Petkov * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 12fd1c601cSBorislav Petkov * more details. 13fd1c601cSBorislav Petkov * 14fd1c601cSBorislav Petkov * Intel PT is specified in the Intel Architecture Instruction Set Extensions 15fd1c601cSBorislav Petkov * Programming Reference: 16fd1c601cSBorislav Petkov * http://software.intel.com/en-us/intel-isa-extensions 17fd1c601cSBorislav Petkov */ 18fd1c601cSBorislav Petkov 19fd1c601cSBorislav Petkov #undef DEBUG 20fd1c601cSBorislav Petkov 21fd1c601cSBorislav Petkov #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 22fd1c601cSBorislav Petkov 23fd1c601cSBorislav Petkov #include <linux/types.h> 24fd1c601cSBorislav Petkov #include <linux/slab.h> 25fd1c601cSBorislav Petkov #include <linux/device.h> 26fd1c601cSBorislav Petkov 27fd1c601cSBorislav Petkov #include <asm/perf_event.h> 28fd1c601cSBorislav Petkov #include <asm/insn.h> 29fd1c601cSBorislav Petkov #include <asm/io.h> 30fd1c601cSBorislav Petkov #include <asm/intel_pt.h> 31*d35869baSAlexander Shishkin #include <asm/intel-family.h> 32fd1c601cSBorislav Petkov 3327f6d22bSBorislav Petkov #include "../perf_event.h" 34fd1c601cSBorislav Petkov #include "pt.h" 35fd1c601cSBorislav Petkov 36fd1c601cSBorislav Petkov static DEFINE_PER_CPU(struct pt, pt_ctx); 37fd1c601cSBorislav Petkov 38fd1c601cSBorislav Petkov static struct pt_pmu pt_pmu; 39fd1c601cSBorislav Petkov 40fd1c601cSBorislav Petkov /* 41fd1c601cSBorislav Petkov * Capabilities of Intel PT hardware, such as number of address bits or 42fd1c601cSBorislav Petkov * supported output schemes, are cached and exported to userspace as "caps" 43fd1c601cSBorislav Petkov * attribute group of pt pmu device 44fd1c601cSBorislav Petkov * (/sys/bus/event_source/devices/intel_pt/caps/) so that userspace can store 45fd1c601cSBorislav Petkov * relevant bits together with intel_pt traces. 46fd1c601cSBorislav Petkov * 47fd1c601cSBorislav Petkov * These are necessary for both trace decoding (payloads_lip, contains address 48fd1c601cSBorislav Petkov * width encoded in IP-related packets), and event configuration (bitmasks with 49fd1c601cSBorislav Petkov * permitted values for certain bit fields). 50fd1c601cSBorislav Petkov */ 51fd1c601cSBorislav Petkov #define PT_CAP(_n, _l, _r, _m) \ 52fd1c601cSBorislav Petkov [PT_CAP_ ## _n] = { .name = __stringify(_n), .leaf = _l, \ 53fd1c601cSBorislav Petkov .reg = _r, .mask = _m } 54fd1c601cSBorislav Petkov 55fd1c601cSBorislav Petkov static struct pt_cap_desc { 56fd1c601cSBorislav Petkov const char *name; 57fd1c601cSBorislav Petkov u32 leaf; 58fd1c601cSBorislav Petkov u8 reg; 59fd1c601cSBorislav Petkov u32 mask; 60fd1c601cSBorislav Petkov } pt_caps[] = { 6147f10a36SHe Chen PT_CAP(max_subleaf, 0, CPUID_EAX, 0xffffffff), 6247f10a36SHe Chen PT_CAP(cr3_filtering, 0, CPUID_EBX, BIT(0)), 6347f10a36SHe Chen PT_CAP(psb_cyc, 0, CPUID_EBX, BIT(1)), 6447f10a36SHe Chen PT_CAP(ip_filtering, 0, CPUID_EBX, BIT(2)), 6547f10a36SHe Chen PT_CAP(mtc, 0, CPUID_EBX, BIT(3)), 6647f10a36SHe Chen PT_CAP(ptwrite, 0, CPUID_EBX, BIT(4)), 6747f10a36SHe Chen PT_CAP(power_event_trace, 0, CPUID_EBX, BIT(5)), 6847f10a36SHe Chen PT_CAP(topa_output, 0, CPUID_ECX, BIT(0)), 6947f10a36SHe Chen PT_CAP(topa_multiple_entries, 0, CPUID_ECX, BIT(1)), 7047f10a36SHe Chen PT_CAP(single_range_output, 0, CPUID_ECX, BIT(2)), 7147f10a36SHe Chen PT_CAP(payloads_lip, 0, CPUID_ECX, BIT(31)), 7247f10a36SHe Chen PT_CAP(num_address_ranges, 1, CPUID_EAX, 0x3), 7347f10a36SHe Chen PT_CAP(mtc_periods, 1, CPUID_EAX, 0xffff0000), 7447f10a36SHe Chen PT_CAP(cycle_thresholds, 1, CPUID_EBX, 0xffff), 7547f10a36SHe Chen PT_CAP(psb_periods, 1, CPUID_EBX, 0xffff0000), 76fd1c601cSBorislav Petkov }; 77fd1c601cSBorislav Petkov 78fd1c601cSBorislav Petkov static u32 pt_cap_get(enum pt_capabilities cap) 79fd1c601cSBorislav Petkov { 80fd1c601cSBorislav Petkov struct pt_cap_desc *cd = &pt_caps[cap]; 81fd1c601cSBorislav Petkov u32 c = pt_pmu.caps[cd->leaf * PT_CPUID_REGS_NUM + cd->reg]; 82fd1c601cSBorislav Petkov unsigned int shift = __ffs(cd->mask); 83fd1c601cSBorislav Petkov 84fd1c601cSBorislav Petkov return (c & cd->mask) >> shift; 85fd1c601cSBorislav Petkov } 86fd1c601cSBorislav Petkov 87fd1c601cSBorislav Petkov static ssize_t pt_cap_show(struct device *cdev, 88fd1c601cSBorislav Petkov struct device_attribute *attr, 89fd1c601cSBorislav Petkov char *buf) 90fd1c601cSBorislav Petkov { 91fd1c601cSBorislav Petkov struct dev_ext_attribute *ea = 92fd1c601cSBorislav Petkov container_of(attr, struct dev_ext_attribute, attr); 93fd1c601cSBorislav Petkov enum pt_capabilities cap = (long)ea->var; 94fd1c601cSBorislav Petkov 95fd1c601cSBorislav Petkov return snprintf(buf, PAGE_SIZE, "%x\n", pt_cap_get(cap)); 96fd1c601cSBorislav Petkov } 97fd1c601cSBorislav Petkov 98fd1c601cSBorislav Petkov static struct attribute_group pt_cap_group = { 99fd1c601cSBorislav Petkov .name = "caps", 100fd1c601cSBorislav Petkov }; 101fd1c601cSBorislav Petkov 102*d35869baSAlexander Shishkin PMU_FORMAT_ATTR(pt, "config:0" ); 103fd1c601cSBorislav Petkov PMU_FORMAT_ATTR(cyc, "config:1" ); 1045443624bSAlexander Shishkin PMU_FORMAT_ATTR(pwr_evt, "config:4" ); 1055443624bSAlexander Shishkin PMU_FORMAT_ATTR(fup_on_ptw, "config:5" ); 106fd1c601cSBorislav Petkov PMU_FORMAT_ATTR(mtc, "config:9" ); 107fd1c601cSBorislav Petkov PMU_FORMAT_ATTR(tsc, "config:10" ); 108fd1c601cSBorislav Petkov PMU_FORMAT_ATTR(noretcomp, "config:11" ); 1095443624bSAlexander Shishkin PMU_FORMAT_ATTR(ptw, "config:12" ); 110*d35869baSAlexander Shishkin PMU_FORMAT_ATTR(branch, "config:13" ); 111fd1c601cSBorislav Petkov PMU_FORMAT_ATTR(mtc_period, "config:14-17" ); 112fd1c601cSBorislav Petkov PMU_FORMAT_ATTR(cyc_thresh, "config:19-22" ); 113fd1c601cSBorislav Petkov PMU_FORMAT_ATTR(psb_period, "config:24-27" ); 114fd1c601cSBorislav Petkov 115fd1c601cSBorislav Petkov static struct attribute *pt_formats_attr[] = { 116*d35869baSAlexander Shishkin &format_attr_pt.attr, 117fd1c601cSBorislav Petkov &format_attr_cyc.attr, 1185443624bSAlexander Shishkin &format_attr_pwr_evt.attr, 1195443624bSAlexander Shishkin &format_attr_fup_on_ptw.attr, 120fd1c601cSBorislav Petkov &format_attr_mtc.attr, 121fd1c601cSBorislav Petkov &format_attr_tsc.attr, 122fd1c601cSBorislav Petkov &format_attr_noretcomp.attr, 1235443624bSAlexander Shishkin &format_attr_ptw.attr, 124*d35869baSAlexander Shishkin &format_attr_branch.attr, 125fd1c601cSBorislav Petkov &format_attr_mtc_period.attr, 126fd1c601cSBorislav Petkov &format_attr_cyc_thresh.attr, 127fd1c601cSBorislav Petkov &format_attr_psb_period.attr, 128fd1c601cSBorislav Petkov NULL, 129fd1c601cSBorislav Petkov }; 130fd1c601cSBorislav Petkov 131fd1c601cSBorislav Petkov static struct attribute_group pt_format_group = { 132fd1c601cSBorislav Petkov .name = "format", 133fd1c601cSBorislav Petkov .attrs = pt_formats_attr, 134fd1c601cSBorislav Petkov }; 135fd1c601cSBorislav Petkov 13665c7e6f1SAlexander Shishkin static ssize_t 13765c7e6f1SAlexander Shishkin pt_timing_attr_show(struct device *dev, struct device_attribute *attr, 13865c7e6f1SAlexander Shishkin char *page) 13965c7e6f1SAlexander Shishkin { 14065c7e6f1SAlexander Shishkin struct perf_pmu_events_attr *pmu_attr = 14165c7e6f1SAlexander Shishkin container_of(attr, struct perf_pmu_events_attr, attr); 14265c7e6f1SAlexander Shishkin 14365c7e6f1SAlexander Shishkin switch (pmu_attr->id) { 14465c7e6f1SAlexander Shishkin case 0: 14565c7e6f1SAlexander Shishkin return sprintf(page, "%lu\n", pt_pmu.max_nonturbo_ratio); 14665c7e6f1SAlexander Shishkin case 1: 14765c7e6f1SAlexander Shishkin return sprintf(page, "%u:%u\n", 14865c7e6f1SAlexander Shishkin pt_pmu.tsc_art_num, 14965c7e6f1SAlexander Shishkin pt_pmu.tsc_art_den); 15065c7e6f1SAlexander Shishkin default: 15165c7e6f1SAlexander Shishkin break; 15265c7e6f1SAlexander Shishkin } 15365c7e6f1SAlexander Shishkin 15465c7e6f1SAlexander Shishkin return -EINVAL; 15565c7e6f1SAlexander Shishkin } 15665c7e6f1SAlexander Shishkin 15765c7e6f1SAlexander Shishkin PMU_EVENT_ATTR(max_nonturbo_ratio, timing_attr_max_nonturbo_ratio, 0, 15865c7e6f1SAlexander Shishkin pt_timing_attr_show); 15965c7e6f1SAlexander Shishkin PMU_EVENT_ATTR(tsc_art_ratio, timing_attr_tsc_art_ratio, 1, 16065c7e6f1SAlexander Shishkin pt_timing_attr_show); 16165c7e6f1SAlexander Shishkin 16265c7e6f1SAlexander Shishkin static struct attribute *pt_timing_attr[] = { 16365c7e6f1SAlexander Shishkin &timing_attr_max_nonturbo_ratio.attr.attr, 16465c7e6f1SAlexander Shishkin &timing_attr_tsc_art_ratio.attr.attr, 16565c7e6f1SAlexander Shishkin NULL, 16665c7e6f1SAlexander Shishkin }; 16765c7e6f1SAlexander Shishkin 16865c7e6f1SAlexander Shishkin static struct attribute_group pt_timing_group = { 16965c7e6f1SAlexander Shishkin .attrs = pt_timing_attr, 17065c7e6f1SAlexander Shishkin }; 17165c7e6f1SAlexander Shishkin 172fd1c601cSBorislav Petkov static const struct attribute_group *pt_attr_groups[] = { 173fd1c601cSBorislav Petkov &pt_cap_group, 174fd1c601cSBorislav Petkov &pt_format_group, 17565c7e6f1SAlexander Shishkin &pt_timing_group, 176fd1c601cSBorislav Petkov NULL, 177fd1c601cSBorislav Petkov }; 178fd1c601cSBorislav Petkov 179fd1c601cSBorislav Petkov static int __init pt_pmu_hw_init(void) 180fd1c601cSBorislav Petkov { 181fd1c601cSBorislav Petkov struct dev_ext_attribute *de_attrs; 182fd1c601cSBorislav Petkov struct attribute **attrs; 183fd1c601cSBorislav Petkov size_t size; 1841c5ac21aSAlexander Shishkin u64 reg; 185fd1c601cSBorislav Petkov int ret; 186fd1c601cSBorislav Petkov long i; 187fd1c601cSBorislav Petkov 18865c7e6f1SAlexander Shishkin rdmsrl(MSR_PLATFORM_INFO, reg); 18965c7e6f1SAlexander Shishkin pt_pmu.max_nonturbo_ratio = (reg & 0xff00) >> 8; 19065c7e6f1SAlexander Shishkin 19165c7e6f1SAlexander Shishkin /* 19265c7e6f1SAlexander Shishkin * if available, read in TSC to core crystal clock ratio, 19365c7e6f1SAlexander Shishkin * otherwise, zero for numerator stands for "not enumerated" 19465c7e6f1SAlexander Shishkin * as per SDM 19565c7e6f1SAlexander Shishkin */ 19665c7e6f1SAlexander Shishkin if (boot_cpu_data.cpuid_level >= CPUID_TSC_LEAF) { 19765c7e6f1SAlexander Shishkin u32 eax, ebx, ecx, edx; 19865c7e6f1SAlexander Shishkin 19965c7e6f1SAlexander Shishkin cpuid(CPUID_TSC_LEAF, &eax, &ebx, &ecx, &edx); 20065c7e6f1SAlexander Shishkin 20165c7e6f1SAlexander Shishkin pt_pmu.tsc_art_num = ebx; 20265c7e6f1SAlexander Shishkin pt_pmu.tsc_art_den = eax; 20365c7e6f1SAlexander Shishkin } 20465c7e6f1SAlexander Shishkin 205*d35869baSAlexander Shishkin /* model-specific quirks */ 206*d35869baSAlexander Shishkin switch (boot_cpu_data.x86_model) { 207*d35869baSAlexander Shishkin case INTEL_FAM6_BROADWELL_CORE: 208*d35869baSAlexander Shishkin case INTEL_FAM6_BROADWELL_XEON_D: 209*d35869baSAlexander Shishkin case INTEL_FAM6_BROADWELL_GT3E: 210*d35869baSAlexander Shishkin case INTEL_FAM6_BROADWELL_X: 211*d35869baSAlexander Shishkin /* not setting BRANCH_EN will #GP, erratum BDM106 */ 212*d35869baSAlexander Shishkin pt_pmu.branch_en_always_on = true; 213*d35869baSAlexander Shishkin break; 214*d35869baSAlexander Shishkin default: 215*d35869baSAlexander Shishkin break; 216*d35869baSAlexander Shishkin } 217*d35869baSAlexander Shishkin 2181c5ac21aSAlexander Shishkin if (boot_cpu_has(X86_FEATURE_VMX)) { 2191c5ac21aSAlexander Shishkin /* 2201c5ac21aSAlexander Shishkin * Intel SDM, 36.5 "Tracing post-VMXON" says that 2211c5ac21aSAlexander Shishkin * "IA32_VMX_MISC[bit 14]" being 1 means PT can trace 2221c5ac21aSAlexander Shishkin * post-VMXON. 2231c5ac21aSAlexander Shishkin */ 2241c5ac21aSAlexander Shishkin rdmsrl(MSR_IA32_VMX_MISC, reg); 2251c5ac21aSAlexander Shishkin if (reg & BIT(14)) 2261c5ac21aSAlexander Shishkin pt_pmu.vmx = true; 2271c5ac21aSAlexander Shishkin } 2281c5ac21aSAlexander Shishkin 229fd1c601cSBorislav Petkov attrs = NULL; 230fd1c601cSBorislav Petkov 231fd1c601cSBorislav Petkov for (i = 0; i < PT_CPUID_LEAVES; i++) { 232fd1c601cSBorislav Petkov cpuid_count(20, i, 23347f10a36SHe Chen &pt_pmu.caps[CPUID_EAX + i*PT_CPUID_REGS_NUM], 23447f10a36SHe Chen &pt_pmu.caps[CPUID_EBX + i*PT_CPUID_REGS_NUM], 23547f10a36SHe Chen &pt_pmu.caps[CPUID_ECX + i*PT_CPUID_REGS_NUM], 23647f10a36SHe Chen &pt_pmu.caps[CPUID_EDX + i*PT_CPUID_REGS_NUM]); 237fd1c601cSBorislav Petkov } 238fd1c601cSBorislav Petkov 239fd1c601cSBorislav Petkov ret = -ENOMEM; 240fd1c601cSBorislav Petkov size = sizeof(struct attribute *) * (ARRAY_SIZE(pt_caps)+1); 241fd1c601cSBorislav Petkov attrs = kzalloc(size, GFP_KERNEL); 242fd1c601cSBorislav Petkov if (!attrs) 243fd1c601cSBorislav Petkov goto fail; 244fd1c601cSBorislav Petkov 245fd1c601cSBorislav Petkov size = sizeof(struct dev_ext_attribute) * (ARRAY_SIZE(pt_caps)+1); 246fd1c601cSBorislav Petkov de_attrs = kzalloc(size, GFP_KERNEL); 247fd1c601cSBorislav Petkov if (!de_attrs) 248fd1c601cSBorislav Petkov goto fail; 249fd1c601cSBorislav Petkov 250fd1c601cSBorislav Petkov for (i = 0; i < ARRAY_SIZE(pt_caps); i++) { 251fd1c601cSBorislav Petkov struct dev_ext_attribute *de_attr = de_attrs + i; 252fd1c601cSBorislav Petkov 253fd1c601cSBorislav Petkov de_attr->attr.attr.name = pt_caps[i].name; 254fd1c601cSBorislav Petkov 255fd1c601cSBorislav Petkov sysfs_attr_init(&de_attr->attr.attr); 256fd1c601cSBorislav Petkov 257fd1c601cSBorislav Petkov de_attr->attr.attr.mode = S_IRUGO; 258fd1c601cSBorislav Petkov de_attr->attr.show = pt_cap_show; 259fd1c601cSBorislav Petkov de_attr->var = (void *)i; 260fd1c601cSBorislav Petkov 261fd1c601cSBorislav Petkov attrs[i] = &de_attr->attr.attr; 262fd1c601cSBorislav Petkov } 263fd1c601cSBorislav Petkov 264fd1c601cSBorislav Petkov pt_cap_group.attrs = attrs; 265fd1c601cSBorislav Petkov 266fd1c601cSBorislav Petkov return 0; 267fd1c601cSBorislav Petkov 268fd1c601cSBorislav Petkov fail: 269fd1c601cSBorislav Petkov kfree(attrs); 270fd1c601cSBorislav Petkov 271fd1c601cSBorislav Petkov return ret; 272fd1c601cSBorislav Petkov } 273fd1c601cSBorislav Petkov 274fd1c601cSBorislav Petkov #define RTIT_CTL_CYC_PSB (RTIT_CTL_CYCLEACC | \ 275fd1c601cSBorislav Petkov RTIT_CTL_CYC_THRESH | \ 276fd1c601cSBorislav Petkov RTIT_CTL_PSB_FREQ) 277fd1c601cSBorislav Petkov 278fd1c601cSBorislav Petkov #define RTIT_CTL_MTC (RTIT_CTL_MTC_EN | \ 279fd1c601cSBorislav Petkov RTIT_CTL_MTC_RANGE) 280fd1c601cSBorislav Petkov 2818ee83b2aSAlexander Shishkin #define RTIT_CTL_PTW (RTIT_CTL_PTW_EN | \ 2828ee83b2aSAlexander Shishkin RTIT_CTL_FUP_ON_PTW) 2838ee83b2aSAlexander Shishkin 284*d35869baSAlexander Shishkin /* 285*d35869baSAlexander Shishkin * Bit 0 (TraceEn) in the attr.config is meaningless as the 286*d35869baSAlexander Shishkin * corresponding bit in the RTIT_CTL can only be controlled 287*d35869baSAlexander Shishkin * by the driver; therefore, repurpose it to mean: pass 288*d35869baSAlexander Shishkin * through the bit that was previously assumed to be always 289*d35869baSAlexander Shishkin * on for PT, thereby allowing the user to *not* set it if 290*d35869baSAlexander Shishkin * they so wish. See also pt_event_valid() and pt_config(). 291*d35869baSAlexander Shishkin */ 292*d35869baSAlexander Shishkin #define RTIT_CTL_PASSTHROUGH RTIT_CTL_TRACEEN 293*d35869baSAlexander Shishkin 294*d35869baSAlexander Shishkin #define PT_CONFIG_MASK (RTIT_CTL_TRACEEN | \ 295*d35869baSAlexander Shishkin RTIT_CTL_TSC_EN | \ 296fd1c601cSBorislav Petkov RTIT_CTL_DISRETC | \ 297*d35869baSAlexander Shishkin RTIT_CTL_BRANCH_EN | \ 298fd1c601cSBorislav Petkov RTIT_CTL_CYC_PSB | \ 2998ee83b2aSAlexander Shishkin RTIT_CTL_MTC | \ 3008ee83b2aSAlexander Shishkin RTIT_CTL_PWR_EVT_EN | \ 3018ee83b2aSAlexander Shishkin RTIT_CTL_FUP_ON_PTW | \ 3028ee83b2aSAlexander Shishkin RTIT_CTL_PTW_EN) 303fd1c601cSBorislav Petkov 304fd1c601cSBorislav Petkov static bool pt_event_valid(struct perf_event *event) 305fd1c601cSBorislav Petkov { 306fd1c601cSBorislav Petkov u64 config = event->attr.config; 307fd1c601cSBorislav Petkov u64 allowed, requested; 308fd1c601cSBorislav Petkov 309fd1c601cSBorislav Petkov if ((config & PT_CONFIG_MASK) != config) 310fd1c601cSBorislav Petkov return false; 311fd1c601cSBorislav Petkov 312fd1c601cSBorislav Petkov if (config & RTIT_CTL_CYC_PSB) { 313fd1c601cSBorislav Petkov if (!pt_cap_get(PT_CAP_psb_cyc)) 314fd1c601cSBorislav Petkov return false; 315fd1c601cSBorislav Petkov 316fd1c601cSBorislav Petkov allowed = pt_cap_get(PT_CAP_psb_periods); 317fd1c601cSBorislav Petkov requested = (config & RTIT_CTL_PSB_FREQ) >> 318fd1c601cSBorislav Petkov RTIT_CTL_PSB_FREQ_OFFSET; 319fd1c601cSBorislav Petkov if (requested && (!(allowed & BIT(requested)))) 320fd1c601cSBorislav Petkov return false; 321fd1c601cSBorislav Petkov 322fd1c601cSBorislav Petkov allowed = pt_cap_get(PT_CAP_cycle_thresholds); 323fd1c601cSBorislav Petkov requested = (config & RTIT_CTL_CYC_THRESH) >> 324fd1c601cSBorislav Petkov RTIT_CTL_CYC_THRESH_OFFSET; 325fd1c601cSBorislav Petkov if (requested && (!(allowed & BIT(requested)))) 326fd1c601cSBorislav Petkov return false; 327fd1c601cSBorislav Petkov } 328fd1c601cSBorislav Petkov 329fd1c601cSBorislav Petkov if (config & RTIT_CTL_MTC) { 330fd1c601cSBorislav Petkov /* 331fd1c601cSBorislav Petkov * In the unlikely case that CPUID lists valid mtc periods, 332fd1c601cSBorislav Petkov * but not the mtc capability, drop out here. 333fd1c601cSBorislav Petkov * 334fd1c601cSBorislav Petkov * Spec says that setting mtc period bits while mtc bit in 335fd1c601cSBorislav Petkov * CPUID is 0 will #GP, so better safe than sorry. 336fd1c601cSBorislav Petkov */ 337fd1c601cSBorislav Petkov if (!pt_cap_get(PT_CAP_mtc)) 338fd1c601cSBorislav Petkov return false; 339fd1c601cSBorislav Petkov 340fd1c601cSBorislav Petkov allowed = pt_cap_get(PT_CAP_mtc_periods); 341fd1c601cSBorislav Petkov if (!allowed) 342fd1c601cSBorislav Petkov return false; 343fd1c601cSBorislav Petkov 344fd1c601cSBorislav Petkov requested = (config & RTIT_CTL_MTC_RANGE) >> 345fd1c601cSBorislav Petkov RTIT_CTL_MTC_RANGE_OFFSET; 346fd1c601cSBorislav Petkov 347fd1c601cSBorislav Petkov if (!(allowed & BIT(requested))) 348fd1c601cSBorislav Petkov return false; 349fd1c601cSBorislav Petkov } 350fd1c601cSBorislav Petkov 3518ee83b2aSAlexander Shishkin if (config & RTIT_CTL_PWR_EVT_EN && 3528ee83b2aSAlexander Shishkin !pt_cap_get(PT_CAP_power_event_trace)) 3538ee83b2aSAlexander Shishkin return false; 3548ee83b2aSAlexander Shishkin 3558ee83b2aSAlexander Shishkin if (config & RTIT_CTL_PTW) { 3568ee83b2aSAlexander Shishkin if (!pt_cap_get(PT_CAP_ptwrite)) 3578ee83b2aSAlexander Shishkin return false; 3588ee83b2aSAlexander Shishkin 3598ee83b2aSAlexander Shishkin /* FUPonPTW without PTW doesn't make sense */ 3608ee83b2aSAlexander Shishkin if ((config & RTIT_CTL_FUP_ON_PTW) && 3618ee83b2aSAlexander Shishkin !(config & RTIT_CTL_PTW_EN)) 3628ee83b2aSAlexander Shishkin return false; 3638ee83b2aSAlexander Shishkin } 3648ee83b2aSAlexander Shishkin 365*d35869baSAlexander Shishkin /* 366*d35869baSAlexander Shishkin * Setting bit 0 (TraceEn in RTIT_CTL MSR) in the attr.config 367*d35869baSAlexander Shishkin * clears the assomption that BranchEn must always be enabled, 368*d35869baSAlexander Shishkin * as was the case with the first implementation of PT. 369*d35869baSAlexander Shishkin * If this bit is not set, the legacy behavior is preserved 370*d35869baSAlexander Shishkin * for compatibility with the older userspace. 371*d35869baSAlexander Shishkin * 372*d35869baSAlexander Shishkin * Re-using bit 0 for this purpose is fine because it is never 373*d35869baSAlexander Shishkin * directly set by the user; previous attempts at setting it in 374*d35869baSAlexander Shishkin * the attr.config resulted in -EINVAL. 375*d35869baSAlexander Shishkin */ 376*d35869baSAlexander Shishkin if (config & RTIT_CTL_PASSTHROUGH) { 377*d35869baSAlexander Shishkin /* 378*d35869baSAlexander Shishkin * Disallow not setting BRANCH_EN where BRANCH_EN is 379*d35869baSAlexander Shishkin * always required. 380*d35869baSAlexander Shishkin */ 381*d35869baSAlexander Shishkin if (pt_pmu.branch_en_always_on && 382*d35869baSAlexander Shishkin !(config & RTIT_CTL_BRANCH_EN)) 383*d35869baSAlexander Shishkin return false; 384*d35869baSAlexander Shishkin } else { 385*d35869baSAlexander Shishkin /* 386*d35869baSAlexander Shishkin * Disallow BRANCH_EN without the PASSTHROUGH. 387*d35869baSAlexander Shishkin */ 388*d35869baSAlexander Shishkin if (config & RTIT_CTL_BRANCH_EN) 389*d35869baSAlexander Shishkin return false; 390*d35869baSAlexander Shishkin } 391*d35869baSAlexander Shishkin 392fd1c601cSBorislav Petkov return true; 393fd1c601cSBorislav Petkov } 394fd1c601cSBorislav Petkov 395fd1c601cSBorislav Petkov /* 396fd1c601cSBorislav Petkov * PT configuration helpers 397fd1c601cSBorislav Petkov * These all are cpu affine and operate on a local PT 398fd1c601cSBorislav Petkov */ 399fd1c601cSBorislav Petkov 400eadf48caSAlexander Shishkin /* Address ranges and their corresponding msr configuration registers */ 401eadf48caSAlexander Shishkin static const struct pt_address_range { 402eadf48caSAlexander Shishkin unsigned long msr_a; 403eadf48caSAlexander Shishkin unsigned long msr_b; 404eadf48caSAlexander Shishkin unsigned int reg_off; 405eadf48caSAlexander Shishkin } pt_address_ranges[] = { 406eadf48caSAlexander Shishkin { 407eadf48caSAlexander Shishkin .msr_a = MSR_IA32_RTIT_ADDR0_A, 408eadf48caSAlexander Shishkin .msr_b = MSR_IA32_RTIT_ADDR0_B, 409eadf48caSAlexander Shishkin .reg_off = RTIT_CTL_ADDR0_OFFSET, 410eadf48caSAlexander Shishkin }, 411eadf48caSAlexander Shishkin { 412eadf48caSAlexander Shishkin .msr_a = MSR_IA32_RTIT_ADDR1_A, 413eadf48caSAlexander Shishkin .msr_b = MSR_IA32_RTIT_ADDR1_B, 414eadf48caSAlexander Shishkin .reg_off = RTIT_CTL_ADDR1_OFFSET, 415eadf48caSAlexander Shishkin }, 416eadf48caSAlexander Shishkin { 417eadf48caSAlexander Shishkin .msr_a = MSR_IA32_RTIT_ADDR2_A, 418eadf48caSAlexander Shishkin .msr_b = MSR_IA32_RTIT_ADDR2_B, 419eadf48caSAlexander Shishkin .reg_off = RTIT_CTL_ADDR2_OFFSET, 420eadf48caSAlexander Shishkin }, 421eadf48caSAlexander Shishkin { 422eadf48caSAlexander Shishkin .msr_a = MSR_IA32_RTIT_ADDR3_A, 423eadf48caSAlexander Shishkin .msr_b = MSR_IA32_RTIT_ADDR3_B, 424eadf48caSAlexander Shishkin .reg_off = RTIT_CTL_ADDR3_OFFSET, 425eadf48caSAlexander Shishkin } 426eadf48caSAlexander Shishkin }; 427eadf48caSAlexander Shishkin 428eadf48caSAlexander Shishkin static u64 pt_config_filters(struct perf_event *event) 429eadf48caSAlexander Shishkin { 430eadf48caSAlexander Shishkin struct pt_filters *filters = event->hw.addr_filters; 431eadf48caSAlexander Shishkin struct pt *pt = this_cpu_ptr(&pt_ctx); 432eadf48caSAlexander Shishkin unsigned int range = 0; 433eadf48caSAlexander Shishkin u64 rtit_ctl = 0; 434eadf48caSAlexander Shishkin 435eadf48caSAlexander Shishkin if (!filters) 436eadf48caSAlexander Shishkin return 0; 437eadf48caSAlexander Shishkin 438eadf48caSAlexander Shishkin perf_event_addr_filters_sync(event); 439eadf48caSAlexander Shishkin 440eadf48caSAlexander Shishkin for (range = 0; range < filters->nr_filters; range++) { 441eadf48caSAlexander Shishkin struct pt_filter *filter = &filters->filter[range]; 442eadf48caSAlexander Shishkin 443eadf48caSAlexander Shishkin /* 444eadf48caSAlexander Shishkin * Note, if the range has zero start/end addresses due 445eadf48caSAlexander Shishkin * to its dynamic object not being loaded yet, we just 446eadf48caSAlexander Shishkin * go ahead and program zeroed range, which will simply 447eadf48caSAlexander Shishkin * produce no data. Note^2: if executable code at 0x0 448eadf48caSAlexander Shishkin * is a concern, we can set up an "invalid" configuration 449eadf48caSAlexander Shishkin * such as msr_b < msr_a. 450eadf48caSAlexander Shishkin */ 451eadf48caSAlexander Shishkin 452eadf48caSAlexander Shishkin /* avoid redundant msr writes */ 453eadf48caSAlexander Shishkin if (pt->filters.filter[range].msr_a != filter->msr_a) { 454eadf48caSAlexander Shishkin wrmsrl(pt_address_ranges[range].msr_a, filter->msr_a); 455eadf48caSAlexander Shishkin pt->filters.filter[range].msr_a = filter->msr_a; 456eadf48caSAlexander Shishkin } 457eadf48caSAlexander Shishkin 458eadf48caSAlexander Shishkin if (pt->filters.filter[range].msr_b != filter->msr_b) { 459eadf48caSAlexander Shishkin wrmsrl(pt_address_ranges[range].msr_b, filter->msr_b); 460eadf48caSAlexander Shishkin pt->filters.filter[range].msr_b = filter->msr_b; 461eadf48caSAlexander Shishkin } 462eadf48caSAlexander Shishkin 463eadf48caSAlexander Shishkin rtit_ctl |= filter->config << pt_address_ranges[range].reg_off; 464eadf48caSAlexander Shishkin } 465eadf48caSAlexander Shishkin 466eadf48caSAlexander Shishkin return rtit_ctl; 467eadf48caSAlexander Shishkin } 468eadf48caSAlexander Shishkin 469fd1c601cSBorislav Petkov static void pt_config(struct perf_event *event) 470fd1c601cSBorislav Petkov { 471ee368428SAlexander Shishkin struct pt *pt = this_cpu_ptr(&pt_ctx); 472fd1c601cSBorislav Petkov u64 reg; 473fd1c601cSBorislav Petkov 474fd1c601cSBorislav Petkov if (!event->hw.itrace_started) { 475fd1c601cSBorislav Petkov event->hw.itrace_started = 1; 476fd1c601cSBorislav Petkov wrmsrl(MSR_IA32_RTIT_STATUS, 0); 477fd1c601cSBorislav Petkov } 478fd1c601cSBorislav Petkov 479eadf48caSAlexander Shishkin reg = pt_config_filters(event); 480*d35869baSAlexander Shishkin reg |= RTIT_CTL_TOPA | RTIT_CTL_TRACEEN; 481*d35869baSAlexander Shishkin 482*d35869baSAlexander Shishkin /* 483*d35869baSAlexander Shishkin * Previously, we had BRANCH_EN on by default, but now that PT has 484*d35869baSAlexander Shishkin * grown features outside of branch tracing, it is useful to allow 485*d35869baSAlexander Shishkin * the user to disable it. Setting bit 0 in the event's attr.config 486*d35869baSAlexander Shishkin * allows BRANCH_EN to pass through instead of being always on. See 487*d35869baSAlexander Shishkin * also the comment in pt_event_valid(). 488*d35869baSAlexander Shishkin */ 489*d35869baSAlexander Shishkin if (event->attr.config & BIT(0)) { 490*d35869baSAlexander Shishkin reg |= event->attr.config & RTIT_CTL_BRANCH_EN; 491*d35869baSAlexander Shishkin } else { 492*d35869baSAlexander Shishkin reg |= RTIT_CTL_BRANCH_EN; 493*d35869baSAlexander Shishkin } 494fd1c601cSBorislav Petkov 495fd1c601cSBorislav Petkov if (!event->attr.exclude_kernel) 496fd1c601cSBorislav Petkov reg |= RTIT_CTL_OS; 497fd1c601cSBorislav Petkov if (!event->attr.exclude_user) 498fd1c601cSBorislav Petkov reg |= RTIT_CTL_USR; 499fd1c601cSBorislav Petkov 500fd1c601cSBorislav Petkov reg |= (event->attr.config & PT_CONFIG_MASK); 501fd1c601cSBorislav Petkov 5021c5ac21aSAlexander Shishkin event->hw.config = reg; 503ee368428SAlexander Shishkin if (READ_ONCE(pt->vmx_on)) 504ee368428SAlexander Shishkin perf_aux_output_flag(&pt->handle, PERF_AUX_FLAG_PARTIAL); 505ee368428SAlexander Shishkin else 506fd1c601cSBorislav Petkov wrmsrl(MSR_IA32_RTIT_CTL, reg); 507fd1c601cSBorislav Petkov } 508fd1c601cSBorislav Petkov 5091c5ac21aSAlexander Shishkin static void pt_config_stop(struct perf_event *event) 510fd1c601cSBorislav Petkov { 511ee368428SAlexander Shishkin struct pt *pt = this_cpu_ptr(&pt_ctx); 5121c5ac21aSAlexander Shishkin u64 ctl = READ_ONCE(event->hw.config); 513fd1c601cSBorislav Petkov 5141c5ac21aSAlexander Shishkin /* may be already stopped by a PMI */ 5151c5ac21aSAlexander Shishkin if (!(ctl & RTIT_CTL_TRACEEN)) 5161c5ac21aSAlexander Shishkin return; 5171c5ac21aSAlexander Shishkin 518fd1c601cSBorislav Petkov ctl &= ~RTIT_CTL_TRACEEN; 519ee368428SAlexander Shishkin if (!READ_ONCE(pt->vmx_on)) 520fd1c601cSBorislav Petkov wrmsrl(MSR_IA32_RTIT_CTL, ctl); 521fd1c601cSBorislav Petkov 5221c5ac21aSAlexander Shishkin WRITE_ONCE(event->hw.config, ctl); 5231c5ac21aSAlexander Shishkin 524fd1c601cSBorislav Petkov /* 525fd1c601cSBorislav Petkov * A wrmsr that disables trace generation serializes other PT 526fd1c601cSBorislav Petkov * registers and causes all data packets to be written to memory, 527fd1c601cSBorislav Petkov * but a fence is required for the data to become globally visible. 528fd1c601cSBorislav Petkov * 529fd1c601cSBorislav Petkov * The below WMB, separating data store and aux_head store matches 530fd1c601cSBorislav Petkov * the consumer's RMB that separates aux_head load and data load. 531fd1c601cSBorislav Petkov */ 532fd1c601cSBorislav Petkov wmb(); 533fd1c601cSBorislav Petkov } 534fd1c601cSBorislav Petkov 535fd1c601cSBorislav Petkov static void pt_config_buffer(void *buf, unsigned int topa_idx, 536fd1c601cSBorislav Petkov unsigned int output_off) 537fd1c601cSBorislav Petkov { 538fd1c601cSBorislav Petkov u64 reg; 539fd1c601cSBorislav Petkov 540fd1c601cSBorislav Petkov wrmsrl(MSR_IA32_RTIT_OUTPUT_BASE, virt_to_phys(buf)); 541fd1c601cSBorislav Petkov 542fd1c601cSBorislav Petkov reg = 0x7f | ((u64)topa_idx << 7) | ((u64)output_off << 32); 543fd1c601cSBorislav Petkov 544fd1c601cSBorislav Petkov wrmsrl(MSR_IA32_RTIT_OUTPUT_MASK, reg); 545fd1c601cSBorislav Petkov } 546fd1c601cSBorislav Petkov 547fd1c601cSBorislav Petkov /* 548fd1c601cSBorislav Petkov * Keep ToPA table-related metadata on the same page as the actual table, 549fd1c601cSBorislav Petkov * taking up a few words from the top 550fd1c601cSBorislav Petkov */ 551fd1c601cSBorislav Petkov 552fd1c601cSBorislav Petkov #define TENTS_PER_PAGE (((PAGE_SIZE - 40) / sizeof(struct topa_entry)) - 1) 553fd1c601cSBorislav Petkov 554fd1c601cSBorislav Petkov /** 555fd1c601cSBorislav Petkov * struct topa - page-sized ToPA table with metadata at the top 556fd1c601cSBorislav Petkov * @table: actual ToPA table entries, as understood by PT hardware 557fd1c601cSBorislav Petkov * @list: linkage to struct pt_buffer's list of tables 558fd1c601cSBorislav Petkov * @phys: physical address of this page 559fd1c601cSBorislav Petkov * @offset: offset of the first entry in this table in the buffer 560fd1c601cSBorislav Petkov * @size: total size of all entries in this table 561fd1c601cSBorislav Petkov * @last: index of the last initialized entry in this table 562fd1c601cSBorislav Petkov */ 563fd1c601cSBorislav Petkov struct topa { 564fd1c601cSBorislav Petkov struct topa_entry table[TENTS_PER_PAGE]; 565fd1c601cSBorislav Petkov struct list_head list; 566fd1c601cSBorislav Petkov u64 phys; 567fd1c601cSBorislav Petkov u64 offset; 568fd1c601cSBorislav Petkov size_t size; 569fd1c601cSBorislav Petkov int last; 570fd1c601cSBorislav Petkov }; 571fd1c601cSBorislav Petkov 572fd1c601cSBorislav Petkov /* make -1 stand for the last table entry */ 573fd1c601cSBorislav Petkov #define TOPA_ENTRY(t, i) ((i) == -1 ? &(t)->table[(t)->last] : &(t)->table[(i)]) 574fd1c601cSBorislav Petkov 575fd1c601cSBorislav Petkov /** 576fd1c601cSBorislav Petkov * topa_alloc() - allocate page-sized ToPA table 577fd1c601cSBorislav Petkov * @cpu: CPU on which to allocate. 578fd1c601cSBorislav Petkov * @gfp: Allocation flags. 579fd1c601cSBorislav Petkov * 580fd1c601cSBorislav Petkov * Return: On success, return the pointer to ToPA table page. 581fd1c601cSBorislav Petkov */ 582fd1c601cSBorislav Petkov static struct topa *topa_alloc(int cpu, gfp_t gfp) 583fd1c601cSBorislav Petkov { 584fd1c601cSBorislav Petkov int node = cpu_to_node(cpu); 585fd1c601cSBorislav Petkov struct topa *topa; 586fd1c601cSBorislav Petkov struct page *p; 587fd1c601cSBorislav Petkov 588fd1c601cSBorislav Petkov p = alloc_pages_node(node, gfp | __GFP_ZERO, 0); 589fd1c601cSBorislav Petkov if (!p) 590fd1c601cSBorislav Petkov return NULL; 591fd1c601cSBorislav Petkov 592fd1c601cSBorislav Petkov topa = page_address(p); 593fd1c601cSBorislav Petkov topa->last = 0; 594fd1c601cSBorislav Petkov topa->phys = page_to_phys(p); 595fd1c601cSBorislav Petkov 596fd1c601cSBorislav Petkov /* 597fd1c601cSBorislav Petkov * In case of singe-entry ToPA, always put the self-referencing END 598fd1c601cSBorislav Petkov * link as the 2nd entry in the table 599fd1c601cSBorislav Petkov */ 600fd1c601cSBorislav Petkov if (!pt_cap_get(PT_CAP_topa_multiple_entries)) { 601fd1c601cSBorislav Petkov TOPA_ENTRY(topa, 1)->base = topa->phys >> TOPA_SHIFT; 602fd1c601cSBorislav Petkov TOPA_ENTRY(topa, 1)->end = 1; 603fd1c601cSBorislav Petkov } 604fd1c601cSBorislav Petkov 605fd1c601cSBorislav Petkov return topa; 606fd1c601cSBorislav Petkov } 607fd1c601cSBorislav Petkov 608fd1c601cSBorislav Petkov /** 609fd1c601cSBorislav Petkov * topa_free() - free a page-sized ToPA table 610fd1c601cSBorislav Petkov * @topa: Table to deallocate. 611fd1c601cSBorislav Petkov */ 612fd1c601cSBorislav Petkov static void topa_free(struct topa *topa) 613fd1c601cSBorislav Petkov { 614fd1c601cSBorislav Petkov free_page((unsigned long)topa); 615fd1c601cSBorislav Petkov } 616fd1c601cSBorislav Petkov 617fd1c601cSBorislav Petkov /** 618fd1c601cSBorislav Petkov * topa_insert_table() - insert a ToPA table into a buffer 619fd1c601cSBorislav Petkov * @buf: PT buffer that's being extended. 620fd1c601cSBorislav Petkov * @topa: New topa table to be inserted. 621fd1c601cSBorislav Petkov * 622fd1c601cSBorislav Petkov * If it's the first table in this buffer, set up buffer's pointers 623fd1c601cSBorislav Petkov * accordingly; otherwise, add a END=1 link entry to @topa to the current 624fd1c601cSBorislav Petkov * "last" table and adjust the last table pointer to @topa. 625fd1c601cSBorislav Petkov */ 626fd1c601cSBorislav Petkov static void topa_insert_table(struct pt_buffer *buf, struct topa *topa) 627fd1c601cSBorislav Petkov { 628fd1c601cSBorislav Petkov struct topa *last = buf->last; 629fd1c601cSBorislav Petkov 630fd1c601cSBorislav Petkov list_add_tail(&topa->list, &buf->tables); 631fd1c601cSBorislav Petkov 632fd1c601cSBorislav Petkov if (!buf->first) { 633fd1c601cSBorislav Petkov buf->first = buf->last = buf->cur = topa; 634fd1c601cSBorislav Petkov return; 635fd1c601cSBorislav Petkov } 636fd1c601cSBorislav Petkov 637fd1c601cSBorislav Petkov topa->offset = last->offset + last->size; 638fd1c601cSBorislav Petkov buf->last = topa; 639fd1c601cSBorislav Petkov 640fd1c601cSBorislav Petkov if (!pt_cap_get(PT_CAP_topa_multiple_entries)) 641fd1c601cSBorislav Petkov return; 642fd1c601cSBorislav Petkov 643fd1c601cSBorislav Petkov BUG_ON(last->last != TENTS_PER_PAGE - 1); 644fd1c601cSBorislav Petkov 645fd1c601cSBorislav Petkov TOPA_ENTRY(last, -1)->base = topa->phys >> TOPA_SHIFT; 646fd1c601cSBorislav Petkov TOPA_ENTRY(last, -1)->end = 1; 647fd1c601cSBorislav Petkov } 648fd1c601cSBorislav Petkov 649fd1c601cSBorislav Petkov /** 650fd1c601cSBorislav Petkov * topa_table_full() - check if a ToPA table is filled up 651fd1c601cSBorislav Petkov * @topa: ToPA table. 652fd1c601cSBorislav Petkov */ 653fd1c601cSBorislav Petkov static bool topa_table_full(struct topa *topa) 654fd1c601cSBorislav Petkov { 655fd1c601cSBorislav Petkov /* single-entry ToPA is a special case */ 656fd1c601cSBorislav Petkov if (!pt_cap_get(PT_CAP_topa_multiple_entries)) 657fd1c601cSBorislav Petkov return !!topa->last; 658fd1c601cSBorislav Petkov 659fd1c601cSBorislav Petkov return topa->last == TENTS_PER_PAGE - 1; 660fd1c601cSBorislav Petkov } 661fd1c601cSBorislav Petkov 662fd1c601cSBorislav Petkov /** 663fd1c601cSBorislav Petkov * topa_insert_pages() - create a list of ToPA tables 664fd1c601cSBorislav Petkov * @buf: PT buffer being initialized. 665fd1c601cSBorislav Petkov * @gfp: Allocation flags. 666fd1c601cSBorislav Petkov * 667fd1c601cSBorislav Petkov * This initializes a list of ToPA tables with entries from 668fd1c601cSBorislav Petkov * the data_pages provided by rb_alloc_aux(). 669fd1c601cSBorislav Petkov * 670fd1c601cSBorislav Petkov * Return: 0 on success or error code. 671fd1c601cSBorislav Petkov */ 672fd1c601cSBorislav Petkov static int topa_insert_pages(struct pt_buffer *buf, gfp_t gfp) 673fd1c601cSBorislav Petkov { 674fd1c601cSBorislav Petkov struct topa *topa = buf->last; 675fd1c601cSBorislav Petkov int order = 0; 676fd1c601cSBorislav Petkov struct page *p; 677fd1c601cSBorislav Petkov 678fd1c601cSBorislav Petkov p = virt_to_page(buf->data_pages[buf->nr_pages]); 679fd1c601cSBorislav Petkov if (PagePrivate(p)) 680fd1c601cSBorislav Petkov order = page_private(p); 681fd1c601cSBorislav Petkov 682fd1c601cSBorislav Petkov if (topa_table_full(topa)) { 683fd1c601cSBorislav Petkov topa = topa_alloc(buf->cpu, gfp); 684fd1c601cSBorislav Petkov if (!topa) 685fd1c601cSBorislav Petkov return -ENOMEM; 686fd1c601cSBorislav Petkov 687fd1c601cSBorislav Petkov topa_insert_table(buf, topa); 688fd1c601cSBorislav Petkov } 689fd1c601cSBorislav Petkov 690fd1c601cSBorislav Petkov TOPA_ENTRY(topa, -1)->base = page_to_phys(p) >> TOPA_SHIFT; 691fd1c601cSBorislav Petkov TOPA_ENTRY(topa, -1)->size = order; 692fd1c601cSBorislav Petkov if (!buf->snapshot && !pt_cap_get(PT_CAP_topa_multiple_entries)) { 693fd1c601cSBorislav Petkov TOPA_ENTRY(topa, -1)->intr = 1; 694fd1c601cSBorislav Petkov TOPA_ENTRY(topa, -1)->stop = 1; 695fd1c601cSBorislav Petkov } 696fd1c601cSBorislav Petkov 697fd1c601cSBorislav Petkov topa->last++; 698fd1c601cSBorislav Petkov topa->size += sizes(order); 699fd1c601cSBorislav Petkov 700fd1c601cSBorislav Petkov buf->nr_pages += 1ul << order; 701fd1c601cSBorislav Petkov 702fd1c601cSBorislav Petkov return 0; 703fd1c601cSBorislav Petkov } 704fd1c601cSBorislav Petkov 705fd1c601cSBorislav Petkov /** 706fd1c601cSBorislav Petkov * pt_topa_dump() - print ToPA tables and their entries 707fd1c601cSBorislav Petkov * @buf: PT buffer. 708fd1c601cSBorislav Petkov */ 709fd1c601cSBorislav Petkov static void pt_topa_dump(struct pt_buffer *buf) 710fd1c601cSBorislav Petkov { 711fd1c601cSBorislav Petkov struct topa *topa; 712fd1c601cSBorislav Petkov 713fd1c601cSBorislav Petkov list_for_each_entry(topa, &buf->tables, list) { 714fd1c601cSBorislav Petkov int i; 715fd1c601cSBorislav Petkov 716fd1c601cSBorislav Petkov pr_debug("# table @%p (%016Lx), off %llx size %zx\n", topa->table, 717fd1c601cSBorislav Petkov topa->phys, topa->offset, topa->size); 718fd1c601cSBorislav Petkov for (i = 0; i < TENTS_PER_PAGE; i++) { 719fd1c601cSBorislav Petkov pr_debug("# entry @%p (%lx sz %u %c%c%c) raw=%16llx\n", 720fd1c601cSBorislav Petkov &topa->table[i], 721fd1c601cSBorislav Petkov (unsigned long)topa->table[i].base << TOPA_SHIFT, 722fd1c601cSBorislav Petkov sizes(topa->table[i].size), 723fd1c601cSBorislav Petkov topa->table[i].end ? 'E' : ' ', 724fd1c601cSBorislav Petkov topa->table[i].intr ? 'I' : ' ', 725fd1c601cSBorislav Petkov topa->table[i].stop ? 'S' : ' ', 726fd1c601cSBorislav Petkov *(u64 *)&topa->table[i]); 727fd1c601cSBorislav Petkov if ((pt_cap_get(PT_CAP_topa_multiple_entries) && 728fd1c601cSBorislav Petkov topa->table[i].stop) || 729fd1c601cSBorislav Petkov topa->table[i].end) 730fd1c601cSBorislav Petkov break; 731fd1c601cSBorislav Petkov } 732fd1c601cSBorislav Petkov } 733fd1c601cSBorislav Petkov } 734fd1c601cSBorislav Petkov 735fd1c601cSBorislav Petkov /** 736fd1c601cSBorislav Petkov * pt_buffer_advance() - advance to the next output region 737fd1c601cSBorislav Petkov * @buf: PT buffer. 738fd1c601cSBorislav Petkov * 739fd1c601cSBorislav Petkov * Advance the current pointers in the buffer to the next ToPA entry. 740fd1c601cSBorislav Petkov */ 741fd1c601cSBorislav Petkov static void pt_buffer_advance(struct pt_buffer *buf) 742fd1c601cSBorislav Petkov { 743fd1c601cSBorislav Petkov buf->output_off = 0; 744fd1c601cSBorislav Petkov buf->cur_idx++; 745fd1c601cSBorislav Petkov 746fd1c601cSBorislav Petkov if (buf->cur_idx == buf->cur->last) { 747fd1c601cSBorislav Petkov if (buf->cur == buf->last) 748fd1c601cSBorislav Petkov buf->cur = buf->first; 749fd1c601cSBorislav Petkov else 750fd1c601cSBorislav Petkov buf->cur = list_entry(buf->cur->list.next, struct topa, 751fd1c601cSBorislav Petkov list); 752fd1c601cSBorislav Petkov buf->cur_idx = 0; 753fd1c601cSBorislav Petkov } 754fd1c601cSBorislav Petkov } 755fd1c601cSBorislav Petkov 756fd1c601cSBorislav Petkov /** 757fd1c601cSBorislav Petkov * pt_update_head() - calculate current offsets and sizes 758fd1c601cSBorislav Petkov * @pt: Per-cpu pt context. 759fd1c601cSBorislav Petkov * 760fd1c601cSBorislav Petkov * Update buffer's current write pointer position and data size. 761fd1c601cSBorislav Petkov */ 762fd1c601cSBorislav Petkov static void pt_update_head(struct pt *pt) 763fd1c601cSBorislav Petkov { 764fd1c601cSBorislav Petkov struct pt_buffer *buf = perf_get_aux(&pt->handle); 765fd1c601cSBorislav Petkov u64 topa_idx, base, old; 766fd1c601cSBorislav Petkov 767fd1c601cSBorislav Petkov /* offset of the first region in this table from the beginning of buf */ 768fd1c601cSBorislav Petkov base = buf->cur->offset + buf->output_off; 769fd1c601cSBorislav Petkov 770fd1c601cSBorislav Petkov /* offset of the current output region within this table */ 771fd1c601cSBorislav Petkov for (topa_idx = 0; topa_idx < buf->cur_idx; topa_idx++) 772fd1c601cSBorislav Petkov base += sizes(buf->cur->table[topa_idx].size); 773fd1c601cSBorislav Petkov 774fd1c601cSBorislav Petkov if (buf->snapshot) { 775fd1c601cSBorislav Petkov local_set(&buf->data_size, base); 776fd1c601cSBorislav Petkov } else { 777fd1c601cSBorislav Petkov old = (local64_xchg(&buf->head, base) & 778fd1c601cSBorislav Petkov ((buf->nr_pages << PAGE_SHIFT) - 1)); 779fd1c601cSBorislav Petkov if (base < old) 780fd1c601cSBorislav Petkov base += buf->nr_pages << PAGE_SHIFT; 781fd1c601cSBorislav Petkov 782fd1c601cSBorislav Petkov local_add(base - old, &buf->data_size); 783fd1c601cSBorislav Petkov } 784fd1c601cSBorislav Petkov } 785fd1c601cSBorislav Petkov 786fd1c601cSBorislav Petkov /** 787fd1c601cSBorislav Petkov * pt_buffer_region() - obtain current output region's address 788fd1c601cSBorislav Petkov * @buf: PT buffer. 789fd1c601cSBorislav Petkov */ 790fd1c601cSBorislav Petkov static void *pt_buffer_region(struct pt_buffer *buf) 791fd1c601cSBorislav Petkov { 792fd1c601cSBorislav Petkov return phys_to_virt(buf->cur->table[buf->cur_idx].base << TOPA_SHIFT); 793fd1c601cSBorislav Petkov } 794fd1c601cSBorislav Petkov 795fd1c601cSBorislav Petkov /** 796fd1c601cSBorislav Petkov * pt_buffer_region_size() - obtain current output region's size 797fd1c601cSBorislav Petkov * @buf: PT buffer. 798fd1c601cSBorislav Petkov */ 799fd1c601cSBorislav Petkov static size_t pt_buffer_region_size(struct pt_buffer *buf) 800fd1c601cSBorislav Petkov { 801fd1c601cSBorislav Petkov return sizes(buf->cur->table[buf->cur_idx].size); 802fd1c601cSBorislav Petkov } 803fd1c601cSBorislav Petkov 804fd1c601cSBorislav Petkov /** 805fd1c601cSBorislav Petkov * pt_handle_status() - take care of possible status conditions 806fd1c601cSBorislav Petkov * @pt: Per-cpu pt context. 807fd1c601cSBorislav Petkov */ 808fd1c601cSBorislav Petkov static void pt_handle_status(struct pt *pt) 809fd1c601cSBorislav Petkov { 810fd1c601cSBorislav Petkov struct pt_buffer *buf = perf_get_aux(&pt->handle); 811fd1c601cSBorislav Petkov int advance = 0; 812fd1c601cSBorislav Petkov u64 status; 813fd1c601cSBorislav Petkov 814fd1c601cSBorislav Petkov rdmsrl(MSR_IA32_RTIT_STATUS, status); 815fd1c601cSBorislav Petkov 816fd1c601cSBorislav Petkov if (status & RTIT_STATUS_ERROR) { 817fd1c601cSBorislav Petkov pr_err_ratelimited("ToPA ERROR encountered, trying to recover\n"); 818fd1c601cSBorislav Petkov pt_topa_dump(buf); 819fd1c601cSBorislav Petkov status &= ~RTIT_STATUS_ERROR; 820fd1c601cSBorislav Petkov } 821fd1c601cSBorislav Petkov 822fd1c601cSBorislav Petkov if (status & RTIT_STATUS_STOPPED) { 823fd1c601cSBorislav Petkov status &= ~RTIT_STATUS_STOPPED; 824fd1c601cSBorislav Petkov 825fd1c601cSBorislav Petkov /* 826fd1c601cSBorislav Petkov * On systems that only do single-entry ToPA, hitting STOP 827fd1c601cSBorislav Petkov * means we are already losing data; need to let the decoder 828fd1c601cSBorislav Petkov * know. 829fd1c601cSBorislav Petkov */ 830fd1c601cSBorislav Petkov if (!pt_cap_get(PT_CAP_topa_multiple_entries) || 831fd1c601cSBorislav Petkov buf->output_off == sizes(TOPA_ENTRY(buf->cur, buf->cur_idx)->size)) { 832f4c0b0aaSWill Deacon perf_aux_output_flag(&pt->handle, 833f4c0b0aaSWill Deacon PERF_AUX_FLAG_TRUNCATED); 834fd1c601cSBorislav Petkov advance++; 835fd1c601cSBorislav Petkov } 836fd1c601cSBorislav Petkov } 837fd1c601cSBorislav Petkov 838fd1c601cSBorislav Petkov /* 839fd1c601cSBorislav Petkov * Also on single-entry ToPA implementations, interrupt will come 840fd1c601cSBorislav Petkov * before the output reaches its output region's boundary. 841fd1c601cSBorislav Petkov */ 842fd1c601cSBorislav Petkov if (!pt_cap_get(PT_CAP_topa_multiple_entries) && !buf->snapshot && 843fd1c601cSBorislav Petkov pt_buffer_region_size(buf) - buf->output_off <= TOPA_PMI_MARGIN) { 844fd1c601cSBorislav Petkov void *head = pt_buffer_region(buf); 845fd1c601cSBorislav Petkov 846fd1c601cSBorislav Petkov /* everything within this margin needs to be zeroed out */ 847fd1c601cSBorislav Petkov memset(head + buf->output_off, 0, 848fd1c601cSBorislav Petkov pt_buffer_region_size(buf) - 849fd1c601cSBorislav Petkov buf->output_off); 850fd1c601cSBorislav Petkov advance++; 851fd1c601cSBorislav Petkov } 852fd1c601cSBorislav Petkov 853fd1c601cSBorislav Petkov if (advance) 854fd1c601cSBorislav Petkov pt_buffer_advance(buf); 855fd1c601cSBorislav Petkov 856fd1c601cSBorislav Petkov wrmsrl(MSR_IA32_RTIT_STATUS, status); 857fd1c601cSBorislav Petkov } 858fd1c601cSBorislav Petkov 859fd1c601cSBorislav Petkov /** 860fd1c601cSBorislav Petkov * pt_read_offset() - translate registers into buffer pointers 861fd1c601cSBorislav Petkov * @buf: PT buffer. 862fd1c601cSBorislav Petkov * 863fd1c601cSBorislav Petkov * Set buffer's output pointers from MSR values. 864fd1c601cSBorislav Petkov */ 865fd1c601cSBorislav Petkov static void pt_read_offset(struct pt_buffer *buf) 866fd1c601cSBorislav Petkov { 867fd1c601cSBorislav Petkov u64 offset, base_topa; 868fd1c601cSBorislav Petkov 869fd1c601cSBorislav Petkov rdmsrl(MSR_IA32_RTIT_OUTPUT_BASE, base_topa); 870fd1c601cSBorislav Petkov buf->cur = phys_to_virt(base_topa); 871fd1c601cSBorislav Petkov 872fd1c601cSBorislav Petkov rdmsrl(MSR_IA32_RTIT_OUTPUT_MASK, offset); 873fd1c601cSBorislav Petkov /* offset within current output region */ 874fd1c601cSBorislav Petkov buf->output_off = offset >> 32; 875fd1c601cSBorislav Petkov /* index of current output region within this table */ 876fd1c601cSBorislav Petkov buf->cur_idx = (offset & 0xffffff80) >> 7; 877fd1c601cSBorislav Petkov } 878fd1c601cSBorislav Petkov 879fd1c601cSBorislav Petkov /** 880fd1c601cSBorislav Petkov * pt_topa_next_entry() - obtain index of the first page in the next ToPA entry 881fd1c601cSBorislav Petkov * @buf: PT buffer. 882fd1c601cSBorislav Petkov * @pg: Page offset in the buffer. 883fd1c601cSBorislav Petkov * 884fd1c601cSBorislav Petkov * When advancing to the next output region (ToPA entry), given a page offset 885fd1c601cSBorislav Petkov * into the buffer, we need to find the offset of the first page in the next 886fd1c601cSBorislav Petkov * region. 887fd1c601cSBorislav Petkov */ 888fd1c601cSBorislav Petkov static unsigned int pt_topa_next_entry(struct pt_buffer *buf, unsigned int pg) 889fd1c601cSBorislav Petkov { 890fd1c601cSBorislav Petkov struct topa_entry *te = buf->topa_index[pg]; 891fd1c601cSBorislav Petkov 892fd1c601cSBorislav Petkov /* one region */ 893fd1c601cSBorislav Petkov if (buf->first == buf->last && buf->first->last == 1) 894fd1c601cSBorislav Petkov return pg; 895fd1c601cSBorislav Petkov 896fd1c601cSBorislav Petkov do { 897fd1c601cSBorislav Petkov pg++; 898fd1c601cSBorislav Petkov pg &= buf->nr_pages - 1; 899fd1c601cSBorislav Petkov } while (buf->topa_index[pg] == te); 900fd1c601cSBorislav Petkov 901fd1c601cSBorislav Petkov return pg; 902fd1c601cSBorislav Petkov } 903fd1c601cSBorislav Petkov 904fd1c601cSBorislav Petkov /** 905fd1c601cSBorislav Petkov * pt_buffer_reset_markers() - place interrupt and stop bits in the buffer 906fd1c601cSBorislav Petkov * @buf: PT buffer. 907fd1c601cSBorislav Petkov * @handle: Current output handle. 908fd1c601cSBorislav Petkov * 909fd1c601cSBorislav Petkov * Place INT and STOP marks to prevent overwriting old data that the consumer 910fd1c601cSBorislav Petkov * hasn't yet collected and waking up the consumer after a certain fraction of 911fd1c601cSBorislav Petkov * the buffer has filled up. Only needed and sensible for non-snapshot counters. 912fd1c601cSBorislav Petkov * 913fd1c601cSBorislav Petkov * This obviously relies on buf::head to figure out buffer markers, so it has 914fd1c601cSBorislav Petkov * to be called after pt_buffer_reset_offsets() and before the hardware tracing 915fd1c601cSBorislav Petkov * is enabled. 916fd1c601cSBorislav Petkov */ 917fd1c601cSBorislav Petkov static int pt_buffer_reset_markers(struct pt_buffer *buf, 918fd1c601cSBorislav Petkov struct perf_output_handle *handle) 919fd1c601cSBorislav Petkov 920fd1c601cSBorislav Petkov { 921fd1c601cSBorislav Petkov unsigned long head = local64_read(&buf->head); 922fd1c601cSBorislav Petkov unsigned long idx, npages, wakeup; 923fd1c601cSBorislav Petkov 924fd1c601cSBorislav Petkov /* can't stop in the middle of an output region */ 925fd1c601cSBorislav Petkov if (buf->output_off + handle->size + 1 < 926f4c0b0aaSWill Deacon sizes(TOPA_ENTRY(buf->cur, buf->cur_idx)->size)) { 927f4c0b0aaSWill Deacon perf_aux_output_flag(handle, PERF_AUX_FLAG_TRUNCATED); 928fd1c601cSBorislav Petkov return -EINVAL; 929f4c0b0aaSWill Deacon } 930fd1c601cSBorislav Petkov 931fd1c601cSBorislav Petkov 932fd1c601cSBorislav Petkov /* single entry ToPA is handled by marking all regions STOP=1 INT=1 */ 933fd1c601cSBorislav Petkov if (!pt_cap_get(PT_CAP_topa_multiple_entries)) 934fd1c601cSBorislav Petkov return 0; 935fd1c601cSBorislav Petkov 936fd1c601cSBorislav Petkov /* clear STOP and INT from current entry */ 937fd1c601cSBorislav Petkov buf->topa_index[buf->stop_pos]->stop = 0; 9385fbe4788SAlexander Shishkin buf->topa_index[buf->stop_pos]->intr = 0; 939fd1c601cSBorislav Petkov buf->topa_index[buf->intr_pos]->intr = 0; 940fd1c601cSBorislav Petkov 941fd1c601cSBorislav Petkov /* how many pages till the STOP marker */ 942fd1c601cSBorislav Petkov npages = handle->size >> PAGE_SHIFT; 943fd1c601cSBorislav Petkov 944fd1c601cSBorislav Petkov /* if it's on a page boundary, fill up one more page */ 945fd1c601cSBorislav Petkov if (!offset_in_page(head + handle->size + 1)) 946fd1c601cSBorislav Petkov npages++; 947fd1c601cSBorislav Petkov 948fd1c601cSBorislav Petkov idx = (head >> PAGE_SHIFT) + npages; 949fd1c601cSBorislav Petkov idx &= buf->nr_pages - 1; 950fd1c601cSBorislav Petkov buf->stop_pos = idx; 951fd1c601cSBorislav Petkov 952fd1c601cSBorislav Petkov wakeup = handle->wakeup >> PAGE_SHIFT; 953fd1c601cSBorislav Petkov 954fd1c601cSBorislav Petkov /* in the worst case, wake up the consumer one page before hard stop */ 955fd1c601cSBorislav Petkov idx = (head >> PAGE_SHIFT) + npages - 1; 956fd1c601cSBorislav Petkov if (idx > wakeup) 957fd1c601cSBorislav Petkov idx = wakeup; 958fd1c601cSBorislav Petkov 959fd1c601cSBorislav Petkov idx &= buf->nr_pages - 1; 960fd1c601cSBorislav Petkov buf->intr_pos = idx; 961fd1c601cSBorislav Petkov 962fd1c601cSBorislav Petkov buf->topa_index[buf->stop_pos]->stop = 1; 9635fbe4788SAlexander Shishkin buf->topa_index[buf->stop_pos]->intr = 1; 964fd1c601cSBorislav Petkov buf->topa_index[buf->intr_pos]->intr = 1; 965fd1c601cSBorislav Petkov 966fd1c601cSBorislav Petkov return 0; 967fd1c601cSBorislav Petkov } 968fd1c601cSBorislav Petkov 969fd1c601cSBorislav Petkov /** 970fd1c601cSBorislav Petkov * pt_buffer_setup_topa_index() - build topa_index[] table of regions 971fd1c601cSBorislav Petkov * @buf: PT buffer. 972fd1c601cSBorislav Petkov * 973fd1c601cSBorislav Petkov * topa_index[] references output regions indexed by offset into the 974fd1c601cSBorislav Petkov * buffer for purposes of quick reverse lookup. 975fd1c601cSBorislav Petkov */ 976fd1c601cSBorislav Petkov static void pt_buffer_setup_topa_index(struct pt_buffer *buf) 977fd1c601cSBorislav Petkov { 978fd1c601cSBorislav Petkov struct topa *cur = buf->first, *prev = buf->last; 979fd1c601cSBorislav Petkov struct topa_entry *te_cur = TOPA_ENTRY(cur, 0), 980fd1c601cSBorislav Petkov *te_prev = TOPA_ENTRY(prev, prev->last - 1); 981fd1c601cSBorislav Petkov int pg = 0, idx = 0; 982fd1c601cSBorislav Petkov 983fd1c601cSBorislav Petkov while (pg < buf->nr_pages) { 984fd1c601cSBorislav Petkov int tidx; 985fd1c601cSBorislav Petkov 986fd1c601cSBorislav Petkov /* pages within one topa entry */ 987fd1c601cSBorislav Petkov for (tidx = 0; tidx < 1 << te_cur->size; tidx++, pg++) 988fd1c601cSBorislav Petkov buf->topa_index[pg] = te_prev; 989fd1c601cSBorislav Petkov 990fd1c601cSBorislav Petkov te_prev = te_cur; 991fd1c601cSBorislav Petkov 992fd1c601cSBorislav Petkov if (idx == cur->last - 1) { 993fd1c601cSBorislav Petkov /* advance to next topa table */ 994fd1c601cSBorislav Petkov idx = 0; 995fd1c601cSBorislav Petkov cur = list_entry(cur->list.next, struct topa, list); 996fd1c601cSBorislav Petkov } else { 997fd1c601cSBorislav Petkov idx++; 998fd1c601cSBorislav Petkov } 999fd1c601cSBorislav Petkov te_cur = TOPA_ENTRY(cur, idx); 1000fd1c601cSBorislav Petkov } 1001fd1c601cSBorislav Petkov 1002fd1c601cSBorislav Petkov } 1003fd1c601cSBorislav Petkov 1004fd1c601cSBorislav Petkov /** 1005fd1c601cSBorislav Petkov * pt_buffer_reset_offsets() - adjust buffer's write pointers from aux_head 1006fd1c601cSBorislav Petkov * @buf: PT buffer. 1007fd1c601cSBorislav Petkov * @head: Write pointer (aux_head) from AUX buffer. 1008fd1c601cSBorislav Petkov * 1009fd1c601cSBorislav Petkov * Find the ToPA table and entry corresponding to given @head and set buffer's 1010fd1c601cSBorislav Petkov * "current" pointers accordingly. This is done after we have obtained the 1011fd1c601cSBorislav Petkov * current aux_head position from a successful call to perf_aux_output_begin() 1012fd1c601cSBorislav Petkov * to make sure the hardware is writing to the right place. 1013fd1c601cSBorislav Petkov * 1014fd1c601cSBorislav Petkov * This function modifies buf::{cur,cur_idx,output_off} that will be programmed 1015fd1c601cSBorislav Petkov * into PT msrs when the tracing is enabled and buf::head and buf::data_size, 1016fd1c601cSBorislav Petkov * which are used to determine INT and STOP markers' locations by a subsequent 1017fd1c601cSBorislav Petkov * call to pt_buffer_reset_markers(). 1018fd1c601cSBorislav Petkov */ 1019fd1c601cSBorislav Petkov static void pt_buffer_reset_offsets(struct pt_buffer *buf, unsigned long head) 1020fd1c601cSBorislav Petkov { 1021fd1c601cSBorislav Petkov int pg; 1022fd1c601cSBorislav Petkov 1023fd1c601cSBorislav Petkov if (buf->snapshot) 1024fd1c601cSBorislav Petkov head &= (buf->nr_pages << PAGE_SHIFT) - 1; 1025fd1c601cSBorislav Petkov 1026fd1c601cSBorislav Petkov pg = (head >> PAGE_SHIFT) & (buf->nr_pages - 1); 1027fd1c601cSBorislav Petkov pg = pt_topa_next_entry(buf, pg); 1028fd1c601cSBorislav Petkov 1029fd1c601cSBorislav Petkov buf->cur = (struct topa *)((unsigned long)buf->topa_index[pg] & PAGE_MASK); 1030fd1c601cSBorislav Petkov buf->cur_idx = ((unsigned long)buf->topa_index[pg] - 1031fd1c601cSBorislav Petkov (unsigned long)buf->cur) / sizeof(struct topa_entry); 1032fd1c601cSBorislav Petkov buf->output_off = head & (sizes(buf->cur->table[buf->cur_idx].size) - 1); 1033fd1c601cSBorislav Petkov 1034fd1c601cSBorislav Petkov local64_set(&buf->head, head); 1035fd1c601cSBorislav Petkov local_set(&buf->data_size, 0); 1036fd1c601cSBorislav Petkov } 1037fd1c601cSBorislav Petkov 1038fd1c601cSBorislav Petkov /** 1039fd1c601cSBorislav Petkov * pt_buffer_fini_topa() - deallocate ToPA structure of a buffer 1040fd1c601cSBorislav Petkov * @buf: PT buffer. 1041fd1c601cSBorislav Petkov */ 1042fd1c601cSBorislav Petkov static void pt_buffer_fini_topa(struct pt_buffer *buf) 1043fd1c601cSBorislav Petkov { 1044fd1c601cSBorislav Petkov struct topa *topa, *iter; 1045fd1c601cSBorislav Petkov 1046fd1c601cSBorislav Petkov list_for_each_entry_safe(topa, iter, &buf->tables, list) { 1047fd1c601cSBorislav Petkov /* 1048fd1c601cSBorislav Petkov * right now, this is in free_aux() path only, so 1049fd1c601cSBorislav Petkov * no need to unlink this table from the list 1050fd1c601cSBorislav Petkov */ 1051fd1c601cSBorislav Petkov topa_free(topa); 1052fd1c601cSBorislav Petkov } 1053fd1c601cSBorislav Petkov } 1054fd1c601cSBorislav Petkov 1055fd1c601cSBorislav Petkov /** 1056fd1c601cSBorislav Petkov * pt_buffer_init_topa() - initialize ToPA table for pt buffer 1057fd1c601cSBorislav Petkov * @buf: PT buffer. 1058fd1c601cSBorislav Petkov * @size: Total size of all regions within this ToPA. 1059fd1c601cSBorislav Petkov * @gfp: Allocation flags. 1060fd1c601cSBorislav Petkov */ 1061fd1c601cSBorislav Petkov static int pt_buffer_init_topa(struct pt_buffer *buf, unsigned long nr_pages, 1062fd1c601cSBorislav Petkov gfp_t gfp) 1063fd1c601cSBorislav Petkov { 1064fd1c601cSBorislav Petkov struct topa *topa; 1065fd1c601cSBorislav Petkov int err; 1066fd1c601cSBorislav Petkov 1067fd1c601cSBorislav Petkov topa = topa_alloc(buf->cpu, gfp); 1068fd1c601cSBorislav Petkov if (!topa) 1069fd1c601cSBorislav Petkov return -ENOMEM; 1070fd1c601cSBorislav Petkov 1071fd1c601cSBorislav Petkov topa_insert_table(buf, topa); 1072fd1c601cSBorislav Petkov 1073fd1c601cSBorislav Petkov while (buf->nr_pages < nr_pages) { 1074fd1c601cSBorislav Petkov err = topa_insert_pages(buf, gfp); 1075fd1c601cSBorislav Petkov if (err) { 1076fd1c601cSBorislav Petkov pt_buffer_fini_topa(buf); 1077fd1c601cSBorislav Petkov return -ENOMEM; 1078fd1c601cSBorislav Petkov } 1079fd1c601cSBorislav Petkov } 1080fd1c601cSBorislav Petkov 1081fd1c601cSBorislav Petkov pt_buffer_setup_topa_index(buf); 1082fd1c601cSBorislav Petkov 1083fd1c601cSBorislav Petkov /* link last table to the first one, unless we're double buffering */ 1084fd1c601cSBorislav Petkov if (pt_cap_get(PT_CAP_topa_multiple_entries)) { 1085fd1c601cSBorislav Petkov TOPA_ENTRY(buf->last, -1)->base = buf->first->phys >> TOPA_SHIFT; 1086fd1c601cSBorislav Petkov TOPA_ENTRY(buf->last, -1)->end = 1; 1087fd1c601cSBorislav Petkov } 1088fd1c601cSBorislav Petkov 1089fd1c601cSBorislav Petkov pt_topa_dump(buf); 1090fd1c601cSBorislav Petkov return 0; 1091fd1c601cSBorislav Petkov } 1092fd1c601cSBorislav Petkov 1093fd1c601cSBorislav Petkov /** 1094fd1c601cSBorislav Petkov * pt_buffer_setup_aux() - set up topa tables for a PT buffer 1095fd1c601cSBorislav Petkov * @cpu: Cpu on which to allocate, -1 means current. 1096fd1c601cSBorislav Petkov * @pages: Array of pointers to buffer pages passed from perf core. 1097fd1c601cSBorislav Petkov * @nr_pages: Number of pages in the buffer. 1098fd1c601cSBorislav Petkov * @snapshot: If this is a snapshot/overwrite counter. 1099fd1c601cSBorislav Petkov * 1100fd1c601cSBorislav Petkov * This is a pmu::setup_aux callback that sets up ToPA tables and all the 1101fd1c601cSBorislav Petkov * bookkeeping for an AUX buffer. 1102fd1c601cSBorislav Petkov * 1103fd1c601cSBorislav Petkov * Return: Our private PT buffer structure. 1104fd1c601cSBorislav Petkov */ 1105fd1c601cSBorislav Petkov static void * 1106fd1c601cSBorislav Petkov pt_buffer_setup_aux(int cpu, void **pages, int nr_pages, bool snapshot) 1107fd1c601cSBorislav Petkov { 1108fd1c601cSBorislav Petkov struct pt_buffer *buf; 1109fd1c601cSBorislav Petkov int node, ret; 1110fd1c601cSBorislav Petkov 1111fd1c601cSBorislav Petkov if (!nr_pages) 1112fd1c601cSBorislav Petkov return NULL; 1113fd1c601cSBorislav Petkov 1114fd1c601cSBorislav Petkov if (cpu == -1) 1115fd1c601cSBorislav Petkov cpu = raw_smp_processor_id(); 1116fd1c601cSBorislav Petkov node = cpu_to_node(cpu); 1117fd1c601cSBorislav Petkov 1118fd1c601cSBorislav Petkov buf = kzalloc_node(offsetof(struct pt_buffer, topa_index[nr_pages]), 1119fd1c601cSBorislav Petkov GFP_KERNEL, node); 1120fd1c601cSBorislav Petkov if (!buf) 1121fd1c601cSBorislav Petkov return NULL; 1122fd1c601cSBorislav Petkov 1123fd1c601cSBorislav Petkov buf->cpu = cpu; 1124fd1c601cSBorislav Petkov buf->snapshot = snapshot; 1125fd1c601cSBorislav Petkov buf->data_pages = pages; 1126fd1c601cSBorislav Petkov 1127fd1c601cSBorislav Petkov INIT_LIST_HEAD(&buf->tables); 1128fd1c601cSBorislav Petkov 1129fd1c601cSBorislav Petkov ret = pt_buffer_init_topa(buf, nr_pages, GFP_KERNEL); 1130fd1c601cSBorislav Petkov if (ret) { 1131fd1c601cSBorislav Petkov kfree(buf); 1132fd1c601cSBorislav Petkov return NULL; 1133fd1c601cSBorislav Petkov } 1134fd1c601cSBorislav Petkov 1135fd1c601cSBorislav Petkov return buf; 1136fd1c601cSBorislav Petkov } 1137fd1c601cSBorislav Petkov 1138fd1c601cSBorislav Petkov /** 1139fd1c601cSBorislav Petkov * pt_buffer_free_aux() - perf AUX deallocation path callback 1140fd1c601cSBorislav Petkov * @data: PT buffer. 1141fd1c601cSBorislav Petkov */ 1142fd1c601cSBorislav Petkov static void pt_buffer_free_aux(void *data) 1143fd1c601cSBorislav Petkov { 1144fd1c601cSBorislav Petkov struct pt_buffer *buf = data; 1145fd1c601cSBorislav Petkov 1146fd1c601cSBorislav Petkov pt_buffer_fini_topa(buf); 1147fd1c601cSBorislav Petkov kfree(buf); 1148fd1c601cSBorislav Petkov } 1149fd1c601cSBorislav Petkov 1150eadf48caSAlexander Shishkin static int pt_addr_filters_init(struct perf_event *event) 1151eadf48caSAlexander Shishkin { 1152eadf48caSAlexander Shishkin struct pt_filters *filters; 1153eadf48caSAlexander Shishkin int node = event->cpu == -1 ? -1 : cpu_to_node(event->cpu); 1154eadf48caSAlexander Shishkin 1155eadf48caSAlexander Shishkin if (!pt_cap_get(PT_CAP_num_address_ranges)) 1156eadf48caSAlexander Shishkin return 0; 1157eadf48caSAlexander Shishkin 1158eadf48caSAlexander Shishkin filters = kzalloc_node(sizeof(struct pt_filters), GFP_KERNEL, node); 1159eadf48caSAlexander Shishkin if (!filters) 1160eadf48caSAlexander Shishkin return -ENOMEM; 1161eadf48caSAlexander Shishkin 1162eadf48caSAlexander Shishkin if (event->parent) 1163eadf48caSAlexander Shishkin memcpy(filters, event->parent->hw.addr_filters, 1164eadf48caSAlexander Shishkin sizeof(*filters)); 1165eadf48caSAlexander Shishkin 1166eadf48caSAlexander Shishkin event->hw.addr_filters = filters; 1167eadf48caSAlexander Shishkin 1168eadf48caSAlexander Shishkin return 0; 1169eadf48caSAlexander Shishkin } 1170eadf48caSAlexander Shishkin 1171eadf48caSAlexander Shishkin static void pt_addr_filters_fini(struct perf_event *event) 1172eadf48caSAlexander Shishkin { 1173eadf48caSAlexander Shishkin kfree(event->hw.addr_filters); 1174eadf48caSAlexander Shishkin event->hw.addr_filters = NULL; 1175eadf48caSAlexander Shishkin } 1176eadf48caSAlexander Shishkin 1177ddfdad99SAlexander Shishkin static inline bool valid_kernel_ip(unsigned long ip) 1178ddfdad99SAlexander Shishkin { 1179ddfdad99SAlexander Shishkin return virt_addr_valid(ip) && kernel_ip(ip); 1180ddfdad99SAlexander Shishkin } 1181ddfdad99SAlexander Shishkin 1182eadf48caSAlexander Shishkin static int pt_event_addr_filters_validate(struct list_head *filters) 1183eadf48caSAlexander Shishkin { 1184eadf48caSAlexander Shishkin struct perf_addr_filter *filter; 1185eadf48caSAlexander Shishkin int range = 0; 1186eadf48caSAlexander Shishkin 1187eadf48caSAlexander Shishkin list_for_each_entry(filter, filters, entry) { 1188eadf48caSAlexander Shishkin /* PT doesn't support single address triggers */ 118995f60084SAlexander Shishkin if (!filter->range || !filter->size) 1190eadf48caSAlexander Shishkin return -EOPNOTSUPP; 1191eadf48caSAlexander Shishkin 11921155bafcSAlexander Shishkin if (!filter->inode) { 11931155bafcSAlexander Shishkin if (!valid_kernel_ip(filter->offset)) 1194eadf48caSAlexander Shishkin return -EINVAL; 1195eadf48caSAlexander Shishkin 11961155bafcSAlexander Shishkin if (!valid_kernel_ip(filter->offset + filter->size)) 11971155bafcSAlexander Shishkin return -EINVAL; 11981155bafcSAlexander Shishkin } 11991155bafcSAlexander Shishkin 1200eadf48caSAlexander Shishkin if (++range > pt_cap_get(PT_CAP_num_address_ranges)) 1201eadf48caSAlexander Shishkin return -EOPNOTSUPP; 1202eadf48caSAlexander Shishkin } 1203eadf48caSAlexander Shishkin 1204eadf48caSAlexander Shishkin return 0; 1205eadf48caSAlexander Shishkin } 1206eadf48caSAlexander Shishkin 1207eadf48caSAlexander Shishkin static void pt_event_addr_filters_sync(struct perf_event *event) 1208eadf48caSAlexander Shishkin { 1209eadf48caSAlexander Shishkin struct perf_addr_filters_head *head = perf_event_addr_filters(event); 1210eadf48caSAlexander Shishkin unsigned long msr_a, msr_b, *offs = event->addr_filters_offs; 1211eadf48caSAlexander Shishkin struct pt_filters *filters = event->hw.addr_filters; 1212eadf48caSAlexander Shishkin struct perf_addr_filter *filter; 1213eadf48caSAlexander Shishkin int range = 0; 1214eadf48caSAlexander Shishkin 1215eadf48caSAlexander Shishkin if (!filters) 1216eadf48caSAlexander Shishkin return; 1217eadf48caSAlexander Shishkin 1218eadf48caSAlexander Shishkin list_for_each_entry(filter, &head->list, entry) { 1219eadf48caSAlexander Shishkin if (filter->inode && !offs[range]) { 1220eadf48caSAlexander Shishkin msr_a = msr_b = 0; 1221eadf48caSAlexander Shishkin } else { 1222eadf48caSAlexander Shishkin /* apply the offset */ 1223eadf48caSAlexander Shishkin msr_a = filter->offset + offs[range]; 122495f60084SAlexander Shishkin msr_b = filter->size + msr_a - 1; 1225eadf48caSAlexander Shishkin } 1226eadf48caSAlexander Shishkin 1227eadf48caSAlexander Shishkin filters->filter[range].msr_a = msr_a; 1228eadf48caSAlexander Shishkin filters->filter[range].msr_b = msr_b; 1229eadf48caSAlexander Shishkin filters->filter[range].config = filter->filter ? 1 : 2; 1230eadf48caSAlexander Shishkin range++; 1231eadf48caSAlexander Shishkin } 1232eadf48caSAlexander Shishkin 1233eadf48caSAlexander Shishkin filters->nr_filters = range; 1234eadf48caSAlexander Shishkin } 1235eadf48caSAlexander Shishkin 1236fd1c601cSBorislav Petkov /** 1237fd1c601cSBorislav Petkov * intel_pt_interrupt() - PT PMI handler 1238fd1c601cSBorislav Petkov */ 1239fd1c601cSBorislav Petkov void intel_pt_interrupt(void) 1240fd1c601cSBorislav Petkov { 1241fd1c601cSBorislav Petkov struct pt *pt = this_cpu_ptr(&pt_ctx); 1242fd1c601cSBorislav Petkov struct pt_buffer *buf; 1243fd1c601cSBorislav Petkov struct perf_event *event = pt->handle.event; 1244fd1c601cSBorislav Petkov 1245fd1c601cSBorislav Petkov /* 1246fd1c601cSBorislav Petkov * There may be a dangling PT bit in the interrupt status register 1247fd1c601cSBorislav Petkov * after PT has been disabled by pt_event_stop(). Make sure we don't 1248fd1c601cSBorislav Petkov * do anything (particularly, re-enable) for this event here. 1249fd1c601cSBorislav Petkov */ 12501b6de591SAlexander Shishkin if (!READ_ONCE(pt->handle_nmi)) 1251fd1c601cSBorislav Petkov return; 1252fd1c601cSBorislav Petkov 1253fd1c601cSBorislav Petkov if (!event) 1254fd1c601cSBorislav Petkov return; 1255fd1c601cSBorislav Petkov 12561c5ac21aSAlexander Shishkin pt_config_stop(event); 12571c5ac21aSAlexander Shishkin 1258fd1c601cSBorislav Petkov buf = perf_get_aux(&pt->handle); 1259fd1c601cSBorislav Petkov if (!buf) 1260fd1c601cSBorislav Petkov return; 1261fd1c601cSBorislav Petkov 1262fd1c601cSBorislav Petkov pt_read_offset(buf); 1263fd1c601cSBorislav Petkov 1264fd1c601cSBorislav Petkov pt_handle_status(pt); 1265fd1c601cSBorislav Petkov 1266fd1c601cSBorislav Petkov pt_update_head(pt); 1267fd1c601cSBorislav Petkov 1268f4c0b0aaSWill Deacon perf_aux_output_end(&pt->handle, local_xchg(&buf->data_size, 0)); 1269fd1c601cSBorislav Petkov 1270fd1c601cSBorislav Petkov if (!event->hw.state) { 1271fd1c601cSBorislav Petkov int ret; 1272fd1c601cSBorislav Petkov 1273fd1c601cSBorislav Petkov buf = perf_aux_output_begin(&pt->handle, event); 1274fd1c601cSBorislav Petkov if (!buf) { 1275fd1c601cSBorislav Petkov event->hw.state = PERF_HES_STOPPED; 1276fd1c601cSBorislav Petkov return; 1277fd1c601cSBorislav Petkov } 1278fd1c601cSBorislav Petkov 1279fd1c601cSBorislav Petkov pt_buffer_reset_offsets(buf, pt->handle.head); 1280fd1c601cSBorislav Petkov /* snapshot counters don't use PMI, so it's safe */ 1281fd1c601cSBorislav Petkov ret = pt_buffer_reset_markers(buf, &pt->handle); 1282fd1c601cSBorislav Petkov if (ret) { 1283f4c0b0aaSWill Deacon perf_aux_output_end(&pt->handle, 0); 1284fd1c601cSBorislav Petkov return; 1285fd1c601cSBorislav Petkov } 1286fd1c601cSBorislav Petkov 1287fd1c601cSBorislav Petkov pt_config_buffer(buf->cur->table, buf->cur_idx, 1288fd1c601cSBorislav Petkov buf->output_off); 1289fd1c601cSBorislav Petkov pt_config(event); 1290fd1c601cSBorislav Petkov } 1291fd1c601cSBorislav Petkov } 1292fd1c601cSBorislav Petkov 12931c5ac21aSAlexander Shishkin void intel_pt_handle_vmx(int on) 12941c5ac21aSAlexander Shishkin { 12951c5ac21aSAlexander Shishkin struct pt *pt = this_cpu_ptr(&pt_ctx); 12961c5ac21aSAlexander Shishkin struct perf_event *event; 12971c5ac21aSAlexander Shishkin unsigned long flags; 12981c5ac21aSAlexander Shishkin 12991c5ac21aSAlexander Shishkin /* PT plays nice with VMX, do nothing */ 13001c5ac21aSAlexander Shishkin if (pt_pmu.vmx) 13011c5ac21aSAlexander Shishkin return; 13021c5ac21aSAlexander Shishkin 13031c5ac21aSAlexander Shishkin /* 13041c5ac21aSAlexander Shishkin * VMXON will clear RTIT_CTL.TraceEn; we need to make 13051c5ac21aSAlexander Shishkin * sure to not try to set it while VMX is on. Disable 13061c5ac21aSAlexander Shishkin * interrupts to avoid racing with pmu callbacks; 13071c5ac21aSAlexander Shishkin * concurrent PMI should be handled fine. 13081c5ac21aSAlexander Shishkin */ 13091c5ac21aSAlexander Shishkin local_irq_save(flags); 13101c5ac21aSAlexander Shishkin WRITE_ONCE(pt->vmx_on, on); 13111c5ac21aSAlexander Shishkin 1312ee368428SAlexander Shishkin /* 1313ee368428SAlexander Shishkin * If an AUX transaction is in progress, it will contain 1314ee368428SAlexander Shishkin * gap(s), so flag it PARTIAL to inform the user. 1315ee368428SAlexander Shishkin */ 13161c5ac21aSAlexander Shishkin event = pt->handle.event; 13171c5ac21aSAlexander Shishkin if (event) 1318ee368428SAlexander Shishkin perf_aux_output_flag(&pt->handle, 1319ee368428SAlexander Shishkin PERF_AUX_FLAG_PARTIAL); 1320ee368428SAlexander Shishkin 1321ee368428SAlexander Shishkin /* Turn PTs back on */ 1322ee368428SAlexander Shishkin if (!on && event) 1323ee368428SAlexander Shishkin wrmsrl(MSR_IA32_RTIT_CTL, event->hw.config); 1324ee368428SAlexander Shishkin 13251c5ac21aSAlexander Shishkin local_irq_restore(flags); 13261c5ac21aSAlexander Shishkin } 13271c5ac21aSAlexander Shishkin EXPORT_SYMBOL_GPL(intel_pt_handle_vmx); 13281c5ac21aSAlexander Shishkin 1329fd1c601cSBorislav Petkov /* 1330fd1c601cSBorislav Petkov * PMU callbacks 1331fd1c601cSBorislav Petkov */ 1332fd1c601cSBorislav Petkov 1333fd1c601cSBorislav Petkov static void pt_event_start(struct perf_event *event, int mode) 1334fd1c601cSBorislav Petkov { 133566d21901SAlexander Shishkin struct hw_perf_event *hwc = &event->hw; 1336fd1c601cSBorislav Petkov struct pt *pt = this_cpu_ptr(&pt_ctx); 133766d21901SAlexander Shishkin struct pt_buffer *buf; 1338fd1c601cSBorislav Petkov 133966d21901SAlexander Shishkin buf = perf_aux_output_begin(&pt->handle, event); 134066d21901SAlexander Shishkin if (!buf) 134166d21901SAlexander Shishkin goto fail_stop; 134266d21901SAlexander Shishkin 134366d21901SAlexander Shishkin pt_buffer_reset_offsets(buf, pt->handle.head); 134466d21901SAlexander Shishkin if (!buf->snapshot) { 134566d21901SAlexander Shishkin if (pt_buffer_reset_markers(buf, &pt->handle)) 134666d21901SAlexander Shishkin goto fail_end_stop; 1347fd1c601cSBorislav Petkov } 1348fd1c601cSBorislav Petkov 13491b6de591SAlexander Shishkin WRITE_ONCE(pt->handle_nmi, 1); 135066d21901SAlexander Shishkin hwc->state = 0; 1351fd1c601cSBorislav Petkov 1352fd1c601cSBorislav Petkov pt_config_buffer(buf->cur->table, buf->cur_idx, 1353fd1c601cSBorislav Petkov buf->output_off); 1354fd1c601cSBorislav Petkov pt_config(event); 135566d21901SAlexander Shishkin 135666d21901SAlexander Shishkin return; 135766d21901SAlexander Shishkin 135866d21901SAlexander Shishkin fail_end_stop: 1359f4c0b0aaSWill Deacon perf_aux_output_end(&pt->handle, 0); 136066d21901SAlexander Shishkin fail_stop: 136166d21901SAlexander Shishkin hwc->state = PERF_HES_STOPPED; 1362fd1c601cSBorislav Petkov } 1363fd1c601cSBorislav Petkov 1364fd1c601cSBorislav Petkov static void pt_event_stop(struct perf_event *event, int mode) 1365fd1c601cSBorislav Petkov { 1366fd1c601cSBorislav Petkov struct pt *pt = this_cpu_ptr(&pt_ctx); 1367fd1c601cSBorislav Petkov 1368fd1c601cSBorislav Petkov /* 1369fd1c601cSBorislav Petkov * Protect against the PMI racing with disabling wrmsr, 1370fd1c601cSBorislav Petkov * see comment in intel_pt_interrupt(). 1371fd1c601cSBorislav Petkov */ 13721b6de591SAlexander Shishkin WRITE_ONCE(pt->handle_nmi, 0); 13731c5ac21aSAlexander Shishkin 13741c5ac21aSAlexander Shishkin pt_config_stop(event); 1375fd1c601cSBorislav Petkov 1376fd1c601cSBorislav Petkov if (event->hw.state == PERF_HES_STOPPED) 1377fd1c601cSBorislav Petkov return; 1378fd1c601cSBorislav Petkov 1379fd1c601cSBorislav Petkov event->hw.state = PERF_HES_STOPPED; 1380fd1c601cSBorislav Petkov 1381fd1c601cSBorislav Petkov if (mode & PERF_EF_UPDATE) { 1382fd1c601cSBorislav Petkov struct pt_buffer *buf = perf_get_aux(&pt->handle); 1383fd1c601cSBorislav Petkov 1384fd1c601cSBorislav Petkov if (!buf) 1385fd1c601cSBorislav Petkov return; 1386fd1c601cSBorislav Petkov 1387fd1c601cSBorislav Petkov if (WARN_ON_ONCE(pt->handle.event != event)) 1388fd1c601cSBorislav Petkov return; 1389fd1c601cSBorislav Petkov 1390fd1c601cSBorislav Petkov pt_read_offset(buf); 1391fd1c601cSBorislav Petkov 1392fd1c601cSBorislav Petkov pt_handle_status(pt); 1393fd1c601cSBorislav Petkov 1394fd1c601cSBorislav Petkov pt_update_head(pt); 1395fd1c601cSBorislav Petkov 1396fd1c601cSBorislav Petkov if (buf->snapshot) 1397fd1c601cSBorislav Petkov pt->handle.head = 1398fd1c601cSBorislav Petkov local_xchg(&buf->data_size, 1399fd1c601cSBorislav Petkov buf->nr_pages << PAGE_SHIFT); 1400f4c0b0aaSWill Deacon perf_aux_output_end(&pt->handle, local_xchg(&buf->data_size, 0)); 1401fd1c601cSBorislav Petkov } 1402fd1c601cSBorislav Petkov } 1403fd1c601cSBorislav Petkov 140466d21901SAlexander Shishkin static void pt_event_del(struct perf_event *event, int mode) 140566d21901SAlexander Shishkin { 140666d21901SAlexander Shishkin pt_event_stop(event, PERF_EF_UPDATE); 140766d21901SAlexander Shishkin } 140866d21901SAlexander Shishkin 1409fd1c601cSBorislav Petkov static int pt_event_add(struct perf_event *event, int mode) 1410fd1c601cSBorislav Petkov { 1411fd1c601cSBorislav Petkov struct pt *pt = this_cpu_ptr(&pt_ctx); 1412fd1c601cSBorislav Petkov struct hw_perf_event *hwc = &event->hw; 1413fd1c601cSBorislav Petkov int ret = -EBUSY; 1414fd1c601cSBorislav Petkov 1415fd1c601cSBorislav Petkov if (pt->handle.event) 1416fd1c601cSBorislav Petkov goto fail; 1417fd1c601cSBorislav Petkov 1418fd1c601cSBorislav Petkov if (mode & PERF_EF_START) { 1419fd1c601cSBorislav Petkov pt_event_start(event, 0); 142066d21901SAlexander Shishkin ret = -EINVAL; 1421fd1c601cSBorislav Petkov if (hwc->state == PERF_HES_STOPPED) 142266d21901SAlexander Shishkin goto fail; 1423fd1c601cSBorislav Petkov } else { 1424fd1c601cSBorislav Petkov hwc->state = PERF_HES_STOPPED; 1425fd1c601cSBorislav Petkov } 1426fd1c601cSBorislav Petkov 142766d21901SAlexander Shishkin ret = 0; 1428fd1c601cSBorislav Petkov fail: 142966d21901SAlexander Shishkin 1430fd1c601cSBorislav Petkov return ret; 1431fd1c601cSBorislav Petkov } 1432fd1c601cSBorislav Petkov 1433fd1c601cSBorislav Petkov static void pt_event_read(struct perf_event *event) 1434fd1c601cSBorislav Petkov { 1435fd1c601cSBorislav Petkov } 1436fd1c601cSBorislav Petkov 1437fd1c601cSBorislav Petkov static void pt_event_destroy(struct perf_event *event) 1438fd1c601cSBorislav Petkov { 1439eadf48caSAlexander Shishkin pt_addr_filters_fini(event); 1440fd1c601cSBorislav Petkov x86_del_exclusive(x86_lbr_exclusive_pt); 1441fd1c601cSBorislav Petkov } 1442fd1c601cSBorislav Petkov 1443fd1c601cSBorislav Petkov static int pt_event_init(struct perf_event *event) 1444fd1c601cSBorislav Petkov { 1445fd1c601cSBorislav Petkov if (event->attr.type != pt_pmu.pmu.type) 1446fd1c601cSBorislav Petkov return -ENOENT; 1447fd1c601cSBorislav Petkov 1448fd1c601cSBorislav Petkov if (!pt_event_valid(event)) 1449fd1c601cSBorislav Petkov return -EINVAL; 1450fd1c601cSBorislav Petkov 1451fd1c601cSBorislav Petkov if (x86_add_exclusive(x86_lbr_exclusive_pt)) 1452fd1c601cSBorislav Petkov return -EBUSY; 1453fd1c601cSBorislav Petkov 1454eadf48caSAlexander Shishkin if (pt_addr_filters_init(event)) { 1455eadf48caSAlexander Shishkin x86_del_exclusive(x86_lbr_exclusive_pt); 1456eadf48caSAlexander Shishkin return -ENOMEM; 1457eadf48caSAlexander Shishkin } 1458eadf48caSAlexander Shishkin 1459fd1c601cSBorislav Petkov event->destroy = pt_event_destroy; 1460fd1c601cSBorislav Petkov 1461fd1c601cSBorislav Petkov return 0; 1462fd1c601cSBorislav Petkov } 1463fd1c601cSBorislav Petkov 1464fd1c601cSBorislav Petkov void cpu_emergency_stop_pt(void) 1465fd1c601cSBorislav Petkov { 1466fd1c601cSBorislav Petkov struct pt *pt = this_cpu_ptr(&pt_ctx); 1467fd1c601cSBorislav Petkov 1468fd1c601cSBorislav Petkov if (pt->handle.event) 1469fd1c601cSBorislav Petkov pt_event_stop(pt->handle.event, PERF_EF_UPDATE); 1470fd1c601cSBorislav Petkov } 1471fd1c601cSBorislav Petkov 1472fd1c601cSBorislav Petkov static __init int pt_init(void) 1473fd1c601cSBorislav Petkov { 1474fd1c601cSBorislav Petkov int ret, cpu, prior_warn = 0; 1475fd1c601cSBorislav Petkov 1476fd1c601cSBorislav Petkov BUILD_BUG_ON(sizeof(struct topa) > PAGE_SIZE); 1477fd1c601cSBorislav Petkov 1478e465de1cSAlexander Shishkin if (!boot_cpu_has(X86_FEATURE_INTEL_PT)) 1479fd1c601cSBorislav Petkov return -ENODEV; 1480fd1c601cSBorislav Petkov 1481fd1c601cSBorislav Petkov get_online_cpus(); 1482fd1c601cSBorislav Petkov for_each_online_cpu(cpu) { 1483fd1c601cSBorislav Petkov u64 ctl; 1484fd1c601cSBorislav Petkov 1485fd1c601cSBorislav Petkov ret = rdmsrl_safe_on_cpu(cpu, MSR_IA32_RTIT_CTL, &ctl); 1486fd1c601cSBorislav Petkov if (!ret && (ctl & RTIT_CTL_TRACEEN)) 1487fd1c601cSBorislav Petkov prior_warn++; 1488fd1c601cSBorislav Petkov } 1489fd1c601cSBorislav Petkov put_online_cpus(); 1490fd1c601cSBorislav Petkov 1491fd1c601cSBorislav Petkov if (prior_warn) { 1492fd1c601cSBorislav Petkov x86_add_exclusive(x86_lbr_exclusive_pt); 1493fd1c601cSBorislav Petkov pr_warn("PT is enabled at boot time, doing nothing\n"); 1494fd1c601cSBorislav Petkov 1495fd1c601cSBorislav Petkov return -EBUSY; 1496fd1c601cSBorislav Petkov } 1497fd1c601cSBorislav Petkov 1498fd1c601cSBorislav Petkov ret = pt_pmu_hw_init(); 1499fd1c601cSBorislav Petkov if (ret) 1500fd1c601cSBorislav Petkov return ret; 1501fd1c601cSBorislav Petkov 1502fd1c601cSBorislav Petkov if (!pt_cap_get(PT_CAP_topa_output)) { 1503fd1c601cSBorislav Petkov pr_warn("ToPA output is not supported on this CPU\n"); 1504fd1c601cSBorislav Petkov return -ENODEV; 1505fd1c601cSBorislav Petkov } 1506fd1c601cSBorislav Petkov 1507fd1c601cSBorislav Petkov if (!pt_cap_get(PT_CAP_topa_multiple_entries)) 1508fd1c601cSBorislav Petkov pt_pmu.pmu.capabilities = 1509fd1c601cSBorislav Petkov PERF_PMU_CAP_AUX_NO_SG | PERF_PMU_CAP_AUX_SW_DOUBLEBUF; 1510fd1c601cSBorislav Petkov 1511fd1c601cSBorislav Petkov pt_pmu.pmu.capabilities |= PERF_PMU_CAP_EXCLUSIVE | PERF_PMU_CAP_ITRACE; 1512fd1c601cSBorislav Petkov pt_pmu.pmu.attr_groups = pt_attr_groups; 1513fd1c601cSBorislav Petkov pt_pmu.pmu.task_ctx_nr = perf_sw_context; 1514fd1c601cSBorislav Petkov pt_pmu.pmu.event_init = pt_event_init; 1515fd1c601cSBorislav Petkov pt_pmu.pmu.add = pt_event_add; 1516fd1c601cSBorislav Petkov pt_pmu.pmu.del = pt_event_del; 1517fd1c601cSBorislav Petkov pt_pmu.pmu.start = pt_event_start; 1518fd1c601cSBorislav Petkov pt_pmu.pmu.stop = pt_event_stop; 1519fd1c601cSBorislav Petkov pt_pmu.pmu.read = pt_event_read; 1520fd1c601cSBorislav Petkov pt_pmu.pmu.setup_aux = pt_buffer_setup_aux; 1521fd1c601cSBorislav Petkov pt_pmu.pmu.free_aux = pt_buffer_free_aux; 1522eadf48caSAlexander Shishkin pt_pmu.pmu.addr_filters_sync = pt_event_addr_filters_sync; 1523eadf48caSAlexander Shishkin pt_pmu.pmu.addr_filters_validate = pt_event_addr_filters_validate; 1524eadf48caSAlexander Shishkin pt_pmu.pmu.nr_addr_filters = 1525eadf48caSAlexander Shishkin pt_cap_get(PT_CAP_num_address_ranges); 1526eadf48caSAlexander Shishkin 1527fd1c601cSBorislav Petkov ret = perf_pmu_register(&pt_pmu.pmu, "intel_pt", -1); 1528fd1c601cSBorislav Petkov 1529fd1c601cSBorislav Petkov return ret; 1530fd1c601cSBorislav Petkov } 1531fd1c601cSBorislav Petkov arch_initcall(pt_init); 1532