diff options
Diffstat (limited to 'arch/x86/kernel/cpu/perf_event_intel.c')
-rw-r--r-- | arch/x86/kernel/cpu/perf_event_intel.c | 78 |
1 files changed, 73 insertions, 5 deletions
diff --git a/arch/x86/kernel/cpu/perf_event_intel.c b/arch/x86/kernel/cpu/perf_event_intel.c index f31a1655d1ff..0fa4f242f050 100644 --- a/arch/x86/kernel/cpu/perf_event_intel.c +++ b/arch/x86/kernel/cpu/perf_event_intel.c | |||
@@ -190,9 +190,9 @@ static struct extra_reg intel_snbep_extra_regs[] __read_mostly = { | |||
190 | EVENT_EXTRA_END | 190 | EVENT_EXTRA_END |
191 | }; | 191 | }; |
192 | 192 | ||
193 | EVENT_ATTR_STR(mem-loads, mem_ld_nhm, "event=0x0b,umask=0x10,ldlat=3"); | 193 | EVENT_ATTR_STR(mem-loads, mem_ld_nhm, "event=0x0b,umask=0x10,ldlat=3"); |
194 | EVENT_ATTR_STR(mem-loads, mem_ld_snb, "event=0xcd,umask=0x1,ldlat=3"); | 194 | EVENT_ATTR_STR(mem-loads, mem_ld_snb, "event=0xcd,umask=0x1,ldlat=3"); |
195 | EVENT_ATTR_STR(mem-stores, mem_st_snb, "event=0xcd,umask=0x2"); | 195 | EVENT_ATTR_STR(mem-stores, mem_st_snb, "event=0xcd,umask=0x2"); |
196 | 196 | ||
197 | struct attribute *nhm_events_attrs[] = { | 197 | struct attribute *nhm_events_attrs[] = { |
198 | EVENT_PTR(mem_ld_nhm), | 198 | EVENT_PTR(mem_ld_nhm), |
@@ -1184,6 +1184,11 @@ static void intel_pmu_disable_fixed(struct hw_perf_event *hwc) | |||
1184 | wrmsrl(hwc->config_base, ctrl_val); | 1184 | wrmsrl(hwc->config_base, ctrl_val); |
1185 | } | 1185 | } |
1186 | 1186 | ||
1187 | static inline bool event_is_checkpointed(struct perf_event *event) | ||
1188 | { | ||
1189 | return (event->hw.config & HSW_IN_TX_CHECKPOINTED) != 0; | ||
1190 | } | ||
1191 | |||
1187 | static void intel_pmu_disable_event(struct perf_event *event) | 1192 | static void intel_pmu_disable_event(struct perf_event *event) |
1188 | { | 1193 | { |
1189 | struct hw_perf_event *hwc = &event->hw; | 1194 | struct hw_perf_event *hwc = &event->hw; |
@@ -1197,6 +1202,7 @@ static void intel_pmu_disable_event(struct perf_event *event) | |||
1197 | 1202 | ||
1198 | cpuc->intel_ctrl_guest_mask &= ~(1ull << hwc->idx); | 1203 | cpuc->intel_ctrl_guest_mask &= ~(1ull << hwc->idx); |
1199 | cpuc->intel_ctrl_host_mask &= ~(1ull << hwc->idx); | 1204 | cpuc->intel_ctrl_host_mask &= ~(1ull << hwc->idx); |
1205 | cpuc->intel_cp_status &= ~(1ull << hwc->idx); | ||
1200 | 1206 | ||
1201 | /* | 1207 | /* |
1202 | * must disable before any actual event | 1208 | * must disable before any actual event |
@@ -1271,6 +1277,9 @@ static void intel_pmu_enable_event(struct perf_event *event) | |||
1271 | if (event->attr.exclude_guest) | 1277 | if (event->attr.exclude_guest) |
1272 | cpuc->intel_ctrl_host_mask |= (1ull << hwc->idx); | 1278 | cpuc->intel_ctrl_host_mask |= (1ull << hwc->idx); |
1273 | 1279 | ||
1280 | if (unlikely(event_is_checkpointed(event))) | ||
1281 | cpuc->intel_cp_status |= (1ull << hwc->idx); | ||
1282 | |||
1274 | if (unlikely(hwc->config_base == MSR_ARCH_PERFMON_FIXED_CTR_CTRL)) { | 1283 | if (unlikely(hwc->config_base == MSR_ARCH_PERFMON_FIXED_CTR_CTRL)) { |
1275 | intel_pmu_enable_fixed(hwc); | 1284 | intel_pmu_enable_fixed(hwc); |
1276 | return; | 1285 | return; |
@@ -1289,6 +1298,17 @@ static void intel_pmu_enable_event(struct perf_event *event) | |||
1289 | int intel_pmu_save_and_restart(struct perf_event *event) | 1298 | int intel_pmu_save_and_restart(struct perf_event *event) |
1290 | { | 1299 | { |
1291 | x86_perf_event_update(event); | 1300 | x86_perf_event_update(event); |
1301 | /* | ||
1302 | * For a checkpointed counter always reset back to 0. This | ||
1303 | * avoids a situation where the counter overflows, aborts the | ||
1304 | * transaction and is then set back to shortly before the | ||
1305 | * overflow, and overflows and aborts again. | ||
1306 | */ | ||
1307 | if (unlikely(event_is_checkpointed(event))) { | ||
1308 | /* No race with NMIs because the counter should not be armed */ | ||
1309 | wrmsrl(event->hw.event_base, 0); | ||
1310 | local64_set(&event->hw.prev_count, 0); | ||
1311 | } | ||
1292 | return x86_perf_event_set_period(event); | 1312 | return x86_perf_event_set_period(event); |
1293 | } | 1313 | } |
1294 | 1314 | ||
@@ -1372,6 +1392,13 @@ again: | |||
1372 | x86_pmu.drain_pebs(regs); | 1392 | x86_pmu.drain_pebs(regs); |
1373 | } | 1393 | } |
1374 | 1394 | ||
1395 | /* | ||
1396 | * Checkpointed counters can lead to 'spurious' PMIs because the | ||
1397 | * rollback caused by the PMI will have cleared the overflow status | ||
1398 | * bit. Therefore always force probe these counters. | ||
1399 | */ | ||
1400 | status |= cpuc->intel_cp_status; | ||
1401 | |||
1375 | for_each_set_bit(bit, (unsigned long *)&status, X86_PMC_IDX_MAX) { | 1402 | for_each_set_bit(bit, (unsigned long *)&status, X86_PMC_IDX_MAX) { |
1376 | struct perf_event *event = cpuc->events[bit]; | 1403 | struct perf_event *event = cpuc->events[bit]; |
1377 | 1404 | ||
@@ -1837,6 +1864,20 @@ static int hsw_hw_config(struct perf_event *event) | |||
1837 | event->attr.precise_ip > 0)) | 1864 | event->attr.precise_ip > 0)) |
1838 | return -EOPNOTSUPP; | 1865 | return -EOPNOTSUPP; |
1839 | 1866 | ||
1867 | if (event_is_checkpointed(event)) { | ||
1868 | /* | ||
1869 | * Sampling of checkpointed events can cause situations where | ||
1870 | * the CPU constantly aborts because of a overflow, which is | ||
1871 | * then checkpointed back and ignored. Forbid checkpointing | ||
1872 | * for sampling. | ||
1873 | * | ||
1874 | * But still allow a long sampling period, so that perf stat | ||
1875 | * from KVM works. | ||
1876 | */ | ||
1877 | if (event->attr.sample_period > 0 && | ||
1878 | event->attr.sample_period < 0x7fffffff) | ||
1879 | return -EOPNOTSUPP; | ||
1880 | } | ||
1840 | return 0; | 1881 | return 0; |
1841 | } | 1882 | } |
1842 | 1883 | ||
@@ -2182,10 +2223,36 @@ static __init void intel_nehalem_quirk(void) | |||
2182 | } | 2223 | } |
2183 | } | 2224 | } |
2184 | 2225 | ||
2185 | EVENT_ATTR_STR(mem-loads, mem_ld_hsw, "event=0xcd,umask=0x1,ldlat=3"); | 2226 | EVENT_ATTR_STR(mem-loads, mem_ld_hsw, "event=0xcd,umask=0x1,ldlat=3"); |
2186 | EVENT_ATTR_STR(mem-stores, mem_st_hsw, "event=0xd0,umask=0x82") | 2227 | EVENT_ATTR_STR(mem-stores, mem_st_hsw, "event=0xd0,umask=0x82") |
2228 | |||
2229 | /* Haswell special events */ | ||
2230 | EVENT_ATTR_STR(tx-start, tx_start, "event=0xc9,umask=0x1"); | ||
2231 | EVENT_ATTR_STR(tx-commit, tx_commit, "event=0xc9,umask=0x2"); | ||
2232 | EVENT_ATTR_STR(tx-abort, tx_abort, "event=0xc9,umask=0x4"); | ||
2233 | EVENT_ATTR_STR(tx-capacity, tx_capacity, "event=0x54,umask=0x2"); | ||
2234 | EVENT_ATTR_STR(tx-conflict, tx_conflict, "event=0x54,umask=0x1"); | ||
2235 | EVENT_ATTR_STR(el-start, el_start, "event=0xc8,umask=0x1"); | ||
2236 | EVENT_ATTR_STR(el-commit, el_commit, "event=0xc8,umask=0x2"); | ||
2237 | EVENT_ATTR_STR(el-abort, el_abort, "event=0xc8,umask=0x4"); | ||
2238 | EVENT_ATTR_STR(el-capacity, el_capacity, "event=0x54,umask=0x2"); | ||
2239 | EVENT_ATTR_STR(el-conflict, el_conflict, "event=0x54,umask=0x1"); | ||
2240 | EVENT_ATTR_STR(cycles-t, cycles_t, "event=0x3c,in_tx=1"); | ||
2241 | EVENT_ATTR_STR(cycles-ct, cycles_ct, "event=0x3c,in_tx=1,in_tx_cp=1"); | ||
2187 | 2242 | ||
2188 | static struct attribute *hsw_events_attrs[] = { | 2243 | static struct attribute *hsw_events_attrs[] = { |
2244 | EVENT_PTR(tx_start), | ||
2245 | EVENT_PTR(tx_commit), | ||
2246 | EVENT_PTR(tx_abort), | ||
2247 | EVENT_PTR(tx_capacity), | ||
2248 | EVENT_PTR(tx_conflict), | ||
2249 | EVENT_PTR(el_start), | ||
2250 | EVENT_PTR(el_commit), | ||
2251 | EVENT_PTR(el_abort), | ||
2252 | EVENT_PTR(el_capacity), | ||
2253 | EVENT_PTR(el_conflict), | ||
2254 | EVENT_PTR(cycles_t), | ||
2255 | EVENT_PTR(cycles_ct), | ||
2189 | EVENT_PTR(mem_ld_hsw), | 2256 | EVENT_PTR(mem_ld_hsw), |
2190 | EVENT_PTR(mem_st_hsw), | 2257 | EVENT_PTR(mem_st_hsw), |
2191 | NULL | 2258 | NULL |
@@ -2452,6 +2519,7 @@ __init int intel_pmu_init(void) | |||
2452 | x86_pmu.hw_config = hsw_hw_config; | 2519 | x86_pmu.hw_config = hsw_hw_config; |
2453 | x86_pmu.get_event_constraints = hsw_get_event_constraints; | 2520 | x86_pmu.get_event_constraints = hsw_get_event_constraints; |
2454 | x86_pmu.cpu_events = hsw_events_attrs; | 2521 | x86_pmu.cpu_events = hsw_events_attrs; |
2522 | x86_pmu.lbr_double_abort = true; | ||
2455 | pr_cont("Haswell events, "); | 2523 | pr_cont("Haswell events, "); |
2456 | break; | 2524 | break; |
2457 | 2525 | ||