diff options
| -rw-r--r-- | arch/x86/include/asm/perf_event_p4.h | 99 | ||||
| -rw-r--r-- | arch/x86/kernel/cpu/perf_event_p4.c | 147 |
2 files changed, 163 insertions, 83 deletions
diff --git a/arch/x86/include/asm/perf_event_p4.h b/arch/x86/include/asm/perf_event_p4.h index 64a8ebff06fc..def500776b16 100644 --- a/arch/x86/include/asm/perf_event_p4.h +++ b/arch/x86/include/asm/perf_event_p4.h | |||
| @@ -19,7 +19,6 @@ | |||
| 19 | #define ARCH_P4_RESERVED_ESCR (2) /* IQ_ESCR(0,1) not always present */ | 19 | #define ARCH_P4_RESERVED_ESCR (2) /* IQ_ESCR(0,1) not always present */ |
| 20 | #define ARCH_P4_MAX_ESCR (ARCH_P4_TOTAL_ESCR - ARCH_P4_RESERVED_ESCR) | 20 | #define ARCH_P4_MAX_ESCR (ARCH_P4_TOTAL_ESCR - ARCH_P4_RESERVED_ESCR) |
| 21 | #define ARCH_P4_MAX_CCCR (18) | 21 | #define ARCH_P4_MAX_CCCR (18) |
| 22 | #define ARCH_P4_MAX_COUNTER (ARCH_P4_MAX_CCCR / 2) | ||
| 23 | 22 | ||
| 24 | #define P4_ESCR_EVENT_MASK 0x7e000000U | 23 | #define P4_ESCR_EVENT_MASK 0x7e000000U |
| 25 | #define P4_ESCR_EVENT_SHIFT 25 | 24 | #define P4_ESCR_EVENT_SHIFT 25 |
| @@ -71,10 +70,6 @@ | |||
| 71 | #define P4_CCCR_THRESHOLD(v) ((v) << P4_CCCR_THRESHOLD_SHIFT) | 70 | #define P4_CCCR_THRESHOLD(v) ((v) << P4_CCCR_THRESHOLD_SHIFT) |
| 72 | #define P4_CCCR_ESEL(v) ((v) << P4_CCCR_ESCR_SELECT_SHIFT) | 71 | #define P4_CCCR_ESEL(v) ((v) << P4_CCCR_ESCR_SELECT_SHIFT) |
| 73 | 72 | ||
| 74 | /* Custom bits in reerved CCCR area */ | ||
| 75 | #define P4_CCCR_CACHE_OPS_MASK 0x0000003fU | ||
| 76 | |||
| 77 | |||
| 78 | /* Non HT mask */ | 73 | /* Non HT mask */ |
| 79 | #define P4_CCCR_MASK \ | 74 | #define P4_CCCR_MASK \ |
| 80 | (P4_CCCR_OVF | \ | 75 | (P4_CCCR_OVF | \ |
| @@ -106,8 +101,7 @@ | |||
| 106 | * ESCR and CCCR but rather an only packed value should | 101 | * ESCR and CCCR but rather an only packed value should |
| 107 | * be unpacked and written to a proper addresses | 102 | * be unpacked and written to a proper addresses |
| 108 | * | 103 | * |
| 109 | * the base idea is to pack as much info as | 104 | * the base idea is to pack as much info as possible |
| 110 | * possible | ||
| 111 | */ | 105 | */ |
| 112 | #define p4_config_pack_escr(v) (((u64)(v)) << 32) | 106 | #define p4_config_pack_escr(v) (((u64)(v)) << 32) |
| 113 | #define p4_config_pack_cccr(v) (((u64)(v)) & 0xffffffffULL) | 107 | #define p4_config_pack_cccr(v) (((u64)(v)) & 0xffffffffULL) |
| @@ -130,8 +124,6 @@ | |||
| 130 | t; \ | 124 | t; \ |
| 131 | }) | 125 | }) |
| 132 | 126 | ||
| 133 | #define p4_config_unpack_cache_event(v) (((u64)(v)) & P4_CCCR_CACHE_OPS_MASK) | ||
| 134 | |||
| 135 | #define P4_CONFIG_HT_SHIFT 63 | 127 | #define P4_CONFIG_HT_SHIFT 63 |
| 136 | #define P4_CONFIG_HT (1ULL << P4_CONFIG_HT_SHIFT) | 128 | #define P4_CONFIG_HT (1ULL << P4_CONFIG_HT_SHIFT) |
| 137 | 129 | ||
| @@ -214,6 +206,12 @@ static inline u32 p4_default_escr_conf(int cpu, int exclude_os, int exclude_usr) | |||
| 214 | return escr; | 206 | return escr; |
| 215 | } | 207 | } |
| 216 | 208 | ||
| 209 | /* | ||
| 210 | * This are the events which should be used in "Event Select" | ||
| 211 | * field of ESCR register, they are like unique keys which allow | ||
| 212 | * the kernel to determinate which CCCR and COUNTER should be | ||
| 213 | * used to track an event | ||
| 214 | */ | ||
| 217 | enum P4_EVENTS { | 215 | enum P4_EVENTS { |
| 218 | P4_EVENT_TC_DELIVER_MODE, | 216 | P4_EVENT_TC_DELIVER_MODE, |
| 219 | P4_EVENT_BPU_FETCH_REQUEST, | 217 | P4_EVENT_BPU_FETCH_REQUEST, |
| @@ -561,7 +559,7 @@ enum P4_EVENT_OPCODES { | |||
| 561 | * a caller should use P4_ESCR_EMASK_NAME helper to | 559 | * a caller should use P4_ESCR_EMASK_NAME helper to |
| 562 | * pick the EventMask needed, for example | 560 | * pick the EventMask needed, for example |
| 563 | * | 561 | * |
| 564 | * P4_ESCR_EMASK_NAME(P4_EVENT_TC_DELIVER_MODE, DD) | 562 | * P4_ESCR_EMASK_BIT(P4_EVENT_TC_DELIVER_MODE, DD) |
| 565 | */ | 563 | */ |
| 566 | enum P4_ESCR_EMASKS { | 564 | enum P4_ESCR_EMASKS { |
| 567 | P4_GEN_ESCR_EMASK(P4_EVENT_TC_DELIVER_MODE, DD, 0), | 565 | P4_GEN_ESCR_EMASK(P4_EVENT_TC_DELIVER_MODE, DD, 0), |
| @@ -753,43 +751,50 @@ enum P4_ESCR_EMASKS { | |||
| 753 | P4_GEN_ESCR_EMASK(P4_EVENT_INSTR_COMPLETED, BOGUS, 1), | 751 | P4_GEN_ESCR_EMASK(P4_EVENT_INSTR_COMPLETED, BOGUS, 1), |
| 754 | }; | 752 | }; |
| 755 | 753 | ||
| 756 | /* P4 PEBS: stale for a while */ | 754 | /* |
| 757 | #define P4_PEBS_METRIC_MASK 0x00001fffU | 755 | * P4 PEBS specifics (Replay Event only) |
| 758 | #define P4_PEBS_UOB_TAG 0x01000000U | 756 | * |
| 759 | #define P4_PEBS_ENABLE 0x02000000U | 757 | * Format (bits): |
| 760 | 758 | * 0-6: metric from P4_PEBS_METRIC enum | |
| 761 | /* Replay metrics for MSR_IA32_PEBS_ENABLE and MSR_P4_PEBS_MATRIX_VERT */ | 759 | * 7 : reserved |
| 762 | #define P4_PEBS__1stl_cache_load_miss_retired 0x3000001 | 760 | * 8 : reserved |
| 763 | #define P4_PEBS__2ndl_cache_load_miss_retired 0x3000002 | 761 | * 9-11 : reserved |
| 764 | #define P4_PEBS__dtlb_load_miss_retired 0x3000004 | 762 | * |
| 765 | #define P4_PEBS__dtlb_store_miss_retired 0x3000004 | 763 | * Note we have UOP and PEBS bits reserved for now |
| 766 | #define P4_PEBS__dtlb_all_miss_retired 0x3000004 | 764 | * just in case if we will need them once |
| 767 | #define P4_PEBS__tagged_mispred_branch 0x3018000 | 765 | */ |
| 768 | #define P4_PEBS__mob_load_replay_retired 0x3000200 | 766 | #define P4_PEBS_CONFIG_ENABLE (1 << 7) |
| 769 | #define P4_PEBS__split_load_retired 0x3000400 | 767 | #define P4_PEBS_CONFIG_UOP_TAG (1 << 8) |
| 770 | #define P4_PEBS__split_store_retired 0x3000400 | 768 | #define P4_PEBS_CONFIG_METRIC_MASK 0x3f |
| 771 | 769 | #define P4_PEBS_CONFIG_MASK 0xff | |
| 772 | #define P4_VERT__1stl_cache_load_miss_retired 0x0000001 | 770 | |
| 773 | #define P4_VERT__2ndl_cache_load_miss_retired 0x0000001 | 771 | /* |
| 774 | #define P4_VERT__dtlb_load_miss_retired 0x0000001 | 772 | * mem: Only counters MSR_IQ_COUNTER4 (16) and |
| 775 | #define P4_VERT__dtlb_store_miss_retired 0x0000002 | 773 | * MSR_IQ_COUNTER5 (17) are allowed for PEBS sampling |
| 776 | #define P4_VERT__dtlb_all_miss_retired 0x0000003 | 774 | */ |
| 777 | #define P4_VERT__tagged_mispred_branch 0x0000010 | 775 | #define P4_PEBS_ENABLE 0x02000000U |
| 778 | #define P4_VERT__mob_load_replay_retired 0x0000001 | 776 | #define P4_PEBS_ENABLE_UOP_TAG 0x01000000U |
| 779 | #define P4_VERT__split_load_retired 0x0000001 | 777 | |
| 780 | #define P4_VERT__split_store_retired 0x0000002 | 778 | #define p4_config_unpack_metric(v) (((u64)(v)) & P4_PEBS_CONFIG_METRIC_MASK) |
| 781 | 779 | #define p4_config_unpack_pebs(v) (((u64)(v)) & P4_PEBS_CONFIG_MASK) | |
| 782 | enum P4_CACHE_EVENTS { | 780 | |
| 783 | P4_CACHE__NONE, | 781 | #define p4_config_pebs_has(v, mask) (p4_config_unpack_pebs(v) & (mask)) |
| 784 | 782 | ||
| 785 | P4_CACHE__1stl_cache_load_miss_retired, | 783 | enum P4_PEBS_METRIC { |
| 786 | P4_CACHE__2ndl_cache_load_miss_retired, | 784 | P4_PEBS_METRIC__none, |
| 787 | P4_CACHE__dtlb_load_miss_retired, | 785 | |
| 788 | P4_CACHE__dtlb_store_miss_retired, | 786 | P4_PEBS_METRIC__1stl_cache_load_miss_retired, |
| 789 | P4_CACHE__itlb_reference_hit, | 787 | P4_PEBS_METRIC__2ndl_cache_load_miss_retired, |
| 790 | P4_CACHE__itlb_reference_miss, | 788 | P4_PEBS_METRIC__dtlb_load_miss_retired, |
| 791 | 789 | P4_PEBS_METRIC__dtlb_store_miss_retired, | |
| 792 | P4_CACHE__MAX | 790 | P4_PEBS_METRIC__dtlb_all_miss_retired, |
| 791 | P4_PEBS_METRIC__tagged_mispred_branch, | ||
| 792 | P4_PEBS_METRIC__mob_load_replay_retired, | ||
| 793 | P4_PEBS_METRIC__split_load_retired, | ||
| 794 | P4_PEBS_METRIC__split_store_retired, | ||
| 795 | |||
| 796 | P4_PEBS_METRIC__max | ||
| 793 | }; | 797 | }; |
| 794 | 798 | ||
| 795 | #endif /* PERF_EVENT_P4_H */ | 799 | #endif /* PERF_EVENT_P4_H */ |
| 800 | |||
diff --git a/arch/x86/kernel/cpu/perf_event_p4.c b/arch/x86/kernel/cpu/perf_event_p4.c index 9286e736a70a..107711bf0ee8 100644 --- a/arch/x86/kernel/cpu/perf_event_p4.c +++ b/arch/x86/kernel/cpu/perf_event_p4.c | |||
| @@ -21,22 +21,36 @@ struct p4_event_bind { | |||
| 21 | char cntr[2][P4_CNTR_LIMIT]; /* counter index (offset), -1 on abscence */ | 21 | char cntr[2][P4_CNTR_LIMIT]; /* counter index (offset), -1 on abscence */ |
| 22 | }; | 22 | }; |
| 23 | 23 | ||
| 24 | struct p4_cache_event_bind { | 24 | struct p4_pebs_bind { |
| 25 | unsigned int metric_pebs; | 25 | unsigned int metric_pebs; |
| 26 | unsigned int metric_vert; | 26 | unsigned int metric_vert; |
| 27 | }; | 27 | }; |
| 28 | 28 | ||
| 29 | #define P4_GEN_CACHE_EVENT_BIND(name) \ | 29 | /* it sets P4_PEBS_ENABLE_UOP_TAG as well */ |
| 30 | [P4_CACHE__##name] = { \ | 30 | #define P4_GEN_PEBS_BIND(name, pebs, vert) \ |
| 31 | .metric_pebs = P4_PEBS__##name, \ | 31 | [P4_PEBS_METRIC__##name] = { \ |
| 32 | .metric_vert = P4_VERT__##name, \ | 32 | .metric_pebs = pebs | P4_PEBS_ENABLE_UOP_TAG, \ |
| 33 | .metric_vert = vert, \ | ||
| 33 | } | 34 | } |
| 34 | 35 | ||
| 35 | static struct p4_cache_event_bind p4_cache_event_bind_map[] = { | 36 | /* |
| 36 | P4_GEN_CACHE_EVENT_BIND(1stl_cache_load_miss_retired), | 37 | * note we have P4_PEBS_ENABLE_UOP_TAG always set here |
| 37 | P4_GEN_CACHE_EVENT_BIND(2ndl_cache_load_miss_retired), | 38 | * |
| 38 | P4_GEN_CACHE_EVENT_BIND(dtlb_load_miss_retired), | 39 | * it's needed for mapping P4_PEBS_CONFIG_METRIC_MASK bits of |
| 39 | P4_GEN_CACHE_EVENT_BIND(dtlb_store_miss_retired), | 40 | * event configuration to find out which values are to be |
| 41 | * written into MSR_IA32_PEBS_ENABLE and MSR_P4_PEBS_MATRIX_VERT | ||
| 42 | * resgisters | ||
| 43 | */ | ||
| 44 | static struct p4_pebs_bind p4_pebs_bind_map[] = { | ||
| 45 | P4_GEN_PEBS_BIND(1stl_cache_load_miss_retired, 0x0000001, 0x0000001), | ||
| 46 | P4_GEN_PEBS_BIND(2ndl_cache_load_miss_retired, 0x0000002, 0x0000001), | ||
| 47 | P4_GEN_PEBS_BIND(dtlb_load_miss_retired, 0x0000004, 0x0000001), | ||
| 48 | P4_GEN_PEBS_BIND(dtlb_store_miss_retired, 0x0000004, 0x0000002), | ||
| 49 | P4_GEN_PEBS_BIND(dtlb_all_miss_retired, 0x0000004, 0x0000003), | ||
| 50 | P4_GEN_PEBS_BIND(tagged_mispred_branch, 0x0018000, 0x0000010), | ||
| 51 | P4_GEN_PEBS_BIND(mob_load_replay_retired, 0x0000200, 0x0000001), | ||
| 52 | P4_GEN_PEBS_BIND(split_load_retired, 0x0000400, 0x0000001), | ||
| 53 | P4_GEN_PEBS_BIND(split_store_retired, 0x0000400, 0x0000002), | ||
| 40 | }; | 54 | }; |
| 41 | 55 | ||
| 42 | /* | 56 | /* |
| @@ -281,10 +295,10 @@ static struct p4_event_bind p4_event_bind_map[] = { | |||
| 281 | }, | 295 | }, |
| 282 | }; | 296 | }; |
| 283 | 297 | ||
| 284 | #define P4_GEN_CACHE_EVENT(event, bit, cache_event) \ | 298 | #define P4_GEN_CACHE_EVENT(event, bit, metric) \ |
| 285 | p4_config_pack_escr(P4_ESCR_EVENT(event) | \ | 299 | p4_config_pack_escr(P4_ESCR_EVENT(event) | \ |
| 286 | P4_ESCR_EMASK_BIT(event, bit)) | \ | 300 | P4_ESCR_EMASK_BIT(event, bit)) | \ |
| 287 | p4_config_pack_cccr(cache_event | \ | 301 | p4_config_pack_cccr(metric | \ |
| 288 | P4_CCCR_ESEL(P4_OPCODE_ESEL(P4_OPCODE(event)))) | 302 | P4_CCCR_ESEL(P4_OPCODE_ESEL(P4_OPCODE(event)))) |
| 289 | 303 | ||
| 290 | static __initconst const u64 p4_hw_cache_event_ids | 304 | static __initconst const u64 p4_hw_cache_event_ids |
| @@ -296,34 +310,34 @@ static __initconst const u64 p4_hw_cache_event_ids | |||
| 296 | [ C(OP_READ) ] = { | 310 | [ C(OP_READ) ] = { |
| 297 | [ C(RESULT_ACCESS) ] = 0x0, | 311 | [ C(RESULT_ACCESS) ] = 0x0, |
| 298 | [ C(RESULT_MISS) ] = P4_GEN_CACHE_EVENT(P4_EVENT_REPLAY_EVENT, NBOGUS, | 312 | [ C(RESULT_MISS) ] = P4_GEN_CACHE_EVENT(P4_EVENT_REPLAY_EVENT, NBOGUS, |
| 299 | P4_CACHE__1stl_cache_load_miss_retired), | 313 | P4_PEBS_METRIC__1stl_cache_load_miss_retired), |
| 300 | }, | 314 | }, |
| 301 | }, | 315 | }, |
| 302 | [ C(LL ) ] = { | 316 | [ C(LL ) ] = { |
| 303 | [ C(OP_READ) ] = { | 317 | [ C(OP_READ) ] = { |
| 304 | [ C(RESULT_ACCESS) ] = 0x0, | 318 | [ C(RESULT_ACCESS) ] = 0x0, |
| 305 | [ C(RESULT_MISS) ] = P4_GEN_CACHE_EVENT(P4_EVENT_REPLAY_EVENT, NBOGUS, | 319 | [ C(RESULT_MISS) ] = P4_GEN_CACHE_EVENT(P4_EVENT_REPLAY_EVENT, NBOGUS, |
| 306 | P4_CACHE__2ndl_cache_load_miss_retired), | 320 | P4_PEBS_METRIC__2ndl_cache_load_miss_retired), |
| 307 | }, | 321 | }, |
| 308 | }, | 322 | }, |
| 309 | [ C(DTLB) ] = { | 323 | [ C(DTLB) ] = { |
| 310 | [ C(OP_READ) ] = { | 324 | [ C(OP_READ) ] = { |
| 311 | [ C(RESULT_ACCESS) ] = 0x0, | 325 | [ C(RESULT_ACCESS) ] = 0x0, |
| 312 | [ C(RESULT_MISS) ] = P4_GEN_CACHE_EVENT(P4_EVENT_REPLAY_EVENT, NBOGUS, | 326 | [ C(RESULT_MISS) ] = P4_GEN_CACHE_EVENT(P4_EVENT_REPLAY_EVENT, NBOGUS, |
| 313 | P4_CACHE__dtlb_load_miss_retired), | 327 | P4_PEBS_METRIC__dtlb_load_miss_retired), |
| 314 | }, | 328 | }, |
| 315 | [ C(OP_WRITE) ] = { | 329 | [ C(OP_WRITE) ] = { |
| 316 | [ C(RESULT_ACCESS) ] = 0x0, | 330 | [ C(RESULT_ACCESS) ] = 0x0, |
| 317 | [ C(RESULT_MISS) ] = P4_GEN_CACHE_EVENT(P4_EVENT_REPLAY_EVENT, NBOGUS, | 331 | [ C(RESULT_MISS) ] = P4_GEN_CACHE_EVENT(P4_EVENT_REPLAY_EVENT, NBOGUS, |
| 318 | P4_CACHE__dtlb_store_miss_retired), | 332 | P4_PEBS_METRIC__dtlb_store_miss_retired), |
| 319 | }, | 333 | }, |
| 320 | }, | 334 | }, |
| 321 | [ C(ITLB) ] = { | 335 | [ C(ITLB) ] = { |
| 322 | [ C(OP_READ) ] = { | 336 | [ C(OP_READ) ] = { |
| 323 | [ C(RESULT_ACCESS) ] = P4_GEN_CACHE_EVENT(P4_EVENT_ITLB_REFERENCE, HIT, | 337 | [ C(RESULT_ACCESS) ] = P4_GEN_CACHE_EVENT(P4_EVENT_ITLB_REFERENCE, HIT, |
| 324 | P4_CACHE__itlb_reference_hit), | 338 | P4_PEBS_METRIC__none), |
| 325 | [ C(RESULT_MISS) ] = P4_GEN_CACHE_EVENT(P4_EVENT_ITLB_REFERENCE, MISS, | 339 | [ C(RESULT_MISS) ] = P4_GEN_CACHE_EVENT(P4_EVENT_ITLB_REFERENCE, MISS, |
| 326 | P4_CACHE__itlb_reference_miss), | 340 | P4_PEBS_METRIC__none), |
| 327 | }, | 341 | }, |
| 328 | [ C(OP_WRITE) ] = { | 342 | [ C(OP_WRITE) ] = { |
| 329 | [ C(RESULT_ACCESS) ] = -1, | 343 | [ C(RESULT_ACCESS) ] = -1, |
| @@ -414,11 +428,37 @@ static u64 p4_pmu_event_map(int hw_event) | |||
| 414 | return config; | 428 | return config; |
| 415 | } | 429 | } |
| 416 | 430 | ||
| 431 | static int p4_validate_raw_event(struct perf_event *event) | ||
| 432 | { | ||
| 433 | unsigned int v; | ||
| 434 | |||
| 435 | /* user data may have out-of-bound event index */ | ||
| 436 | v = p4_config_unpack_event(event->attr.config); | ||
| 437 | if (v >= ARRAY_SIZE(p4_event_bind_map)) { | ||
| 438 | pr_warning("P4 PMU: Unknown event code: %d\n", v); | ||
| 439 | return -EINVAL; | ||
| 440 | } | ||
| 441 | |||
| 442 | /* | ||
| 443 | * it may have some screwed PEBS bits | ||
| 444 | */ | ||
| 445 | if (p4_config_pebs_has(event->attr.config, P4_PEBS_CONFIG_ENABLE)) { | ||
| 446 | pr_warning("P4 PMU: PEBS are not supported yet\n"); | ||
| 447 | return -EINVAL; | ||
| 448 | } | ||
| 449 | v = p4_config_unpack_metric(event->attr.config); | ||
| 450 | if (v >= ARRAY_SIZE(p4_pebs_bind_map)) { | ||
| 451 | pr_warning("P4 PMU: Unknown metric code: %d\n", v); | ||
| 452 | return -EINVAL; | ||
| 453 | } | ||
| 454 | |||
| 455 | return 0; | ||
| 456 | } | ||
| 457 | |||
| 417 | static int p4_hw_config(struct perf_event *event) | 458 | static int p4_hw_config(struct perf_event *event) |
| 418 | { | 459 | { |
| 419 | int cpu = get_cpu(); | 460 | int cpu = get_cpu(); |
| 420 | int rc = 0; | 461 | int rc = 0; |
| 421 | unsigned int evnt; | ||
| 422 | u32 escr, cccr; | 462 | u32 escr, cccr; |
| 423 | 463 | ||
| 424 | /* | 464 | /* |
| @@ -438,12 +478,9 @@ static int p4_hw_config(struct perf_event *event) | |||
| 438 | 478 | ||
| 439 | if (event->attr.type == PERF_TYPE_RAW) { | 479 | if (event->attr.type == PERF_TYPE_RAW) { |
| 440 | 480 | ||
| 441 | /* user data may have out-of-bound event index */ | 481 | rc = p4_validate_raw_event(event); |
| 442 | evnt = p4_config_unpack_event(event->attr.config); | 482 | if (rc) |
| 443 | if (evnt >= ARRAY_SIZE(p4_event_bind_map)) { | ||
| 444 | rc = -EINVAL; | ||
| 445 | goto out; | 483 | goto out; |
| 446 | } | ||
| 447 | 484 | ||
| 448 | /* | 485 | /* |
| 449 | * We don't control raw events so it's up to the caller | 486 | * We don't control raw events so it's up to the caller |
| @@ -451,12 +488,15 @@ static int p4_hw_config(struct perf_event *event) | |||
| 451 | * on HT machine but allow HT-compatible specifics to be | 488 | * on HT machine but allow HT-compatible specifics to be |
| 452 | * passed on) | 489 | * passed on) |
| 453 | * | 490 | * |
| 491 | * Note that for RAW events we allow user to use P4_CCCR_RESERVED | ||
| 492 | * bits since we keep additional info here (for cache events and etc) | ||
| 493 | * | ||
| 454 | * XXX: HT wide things should check perf_paranoid_cpu() && | 494 | * XXX: HT wide things should check perf_paranoid_cpu() && |
| 455 | * CAP_SYS_ADMIN | 495 | * CAP_SYS_ADMIN |
| 456 | */ | 496 | */ |
| 457 | event->hw.config |= event->attr.config & | 497 | event->hw.config |= event->attr.config & |
| 458 | (p4_config_pack_escr(P4_ESCR_MASK_HT) | | 498 | (p4_config_pack_escr(P4_ESCR_MASK_HT) | |
| 459 | p4_config_pack_cccr(P4_CCCR_MASK_HT)); | 499 | p4_config_pack_cccr(P4_CCCR_MASK_HT | P4_CCCR_RESERVED)); |
| 460 | } | 500 | } |
| 461 | 501 | ||
| 462 | rc = x86_setup_perfctr(event); | 502 | rc = x86_setup_perfctr(event); |
| @@ -482,6 +522,29 @@ static inline int p4_pmu_clear_cccr_ovf(struct hw_perf_event *hwc) | |||
| 482 | return overflow; | 522 | return overflow; |
| 483 | } | 523 | } |
| 484 | 524 | ||
| 525 | static void p4_pmu_disable_pebs(void) | ||
| 526 | { | ||
| 527 | /* | ||
| 528 | * FIXME | ||
| 529 | * | ||
| 530 | * It's still allowed that two threads setup same cache | ||
| 531 | * events so we can't simply clear metrics until we knew | ||
| 532 | * noone is depending on us, so we need kind of counter | ||
| 533 | * for "ReplayEvent" users. | ||
| 534 | * | ||
| 535 | * What is more complex -- RAW events, if user (for some | ||
| 536 | * reason) will pass some cache event metric with improper | ||
| 537 | * event opcode -- it's fine from hardware point of view | ||
| 538 | * but completely nonsence from "meaning" of such action. | ||
| 539 | * | ||
| 540 | * So at moment let leave metrics turned on forever -- it's | ||
| 541 | * ok for now but need to be revisited! | ||
| 542 | * | ||
| 543 | * (void)checking_wrmsrl(MSR_IA32_PEBS_ENABLE, (u64)0); | ||
| 544 | * (void)checking_wrmsrl(MSR_P4_PEBS_MATRIX_VERT, (u64)0); | ||
| 545 | */ | ||
| 546 | } | ||
| 547 | |||
| 485 | static inline void p4_pmu_disable_event(struct perf_event *event) | 548 | static inline void p4_pmu_disable_event(struct perf_event *event) |
| 486 | { | 549 | { |
| 487 | struct hw_perf_event *hwc = &event->hw; | 550 | struct hw_perf_event *hwc = &event->hw; |
| @@ -507,6 +570,26 @@ static void p4_pmu_disable_all(void) | |||
| 507 | continue; | 570 | continue; |
| 508 | p4_pmu_disable_event(event); | 571 | p4_pmu_disable_event(event); |
| 509 | } | 572 | } |
| 573 | |||
| 574 | p4_pmu_disable_pebs(); | ||
| 575 | } | ||
| 576 | |||
| 577 | /* configuration must be valid */ | ||
| 578 | static void p4_pmu_enable_pebs(u64 config) | ||
| 579 | { | ||
| 580 | struct p4_pebs_bind *bind; | ||
| 581 | unsigned int idx; | ||
| 582 | |||
| 583 | BUILD_BUG_ON(P4_PEBS_METRIC__max > P4_PEBS_CONFIG_METRIC_MASK); | ||
| 584 | |||
| 585 | idx = p4_config_unpack_metric(config); | ||
| 586 | if (idx == P4_PEBS_METRIC__none) | ||
| 587 | return; | ||
| 588 | |||
| 589 | bind = &p4_pebs_bind_map[idx]; | ||
| 590 | |||
| 591 | (void)checking_wrmsrl(MSR_IA32_PEBS_ENABLE, (u64)bind->metric_pebs); | ||
| 592 | (void)checking_wrmsrl(MSR_P4_PEBS_MATRIX_VERT, (u64)bind->metric_vert); | ||
| 510 | } | 593 | } |
| 511 | 594 | ||
| 512 | static void p4_pmu_enable_event(struct perf_event *event) | 595 | static void p4_pmu_enable_event(struct perf_event *event) |
| @@ -515,9 +598,7 @@ static void p4_pmu_enable_event(struct perf_event *event) | |||
| 515 | int thread = p4_ht_config_thread(hwc->config); | 598 | int thread = p4_ht_config_thread(hwc->config); |
| 516 | u64 escr_conf = p4_config_unpack_escr(p4_clear_ht_bit(hwc->config)); | 599 | u64 escr_conf = p4_config_unpack_escr(p4_clear_ht_bit(hwc->config)); |
| 517 | unsigned int idx = p4_config_unpack_event(hwc->config); | 600 | unsigned int idx = p4_config_unpack_event(hwc->config); |
| 518 | unsigned int idx_cache = p4_config_unpack_cache_event(hwc->config); | ||
| 519 | struct p4_event_bind *bind; | 601 | struct p4_event_bind *bind; |
| 520 | struct p4_cache_event_bind *bind_cache; | ||
| 521 | u64 escr_addr, cccr; | 602 | u64 escr_addr, cccr; |
| 522 | 603 | ||
| 523 | bind = &p4_event_bind_map[idx]; | 604 | bind = &p4_event_bind_map[idx]; |
| @@ -537,16 +618,10 @@ static void p4_pmu_enable_event(struct perf_event *event) | |||
| 537 | cccr = p4_config_unpack_cccr(hwc->config); | 618 | cccr = p4_config_unpack_cccr(hwc->config); |
| 538 | 619 | ||
| 539 | /* | 620 | /* |
| 540 | * it could be Cache event so that we need to | 621 | * it could be Cache event so we need to write metrics |
| 541 | * set metrics into additional MSRs | 622 | * into additional MSRs |
| 542 | */ | 623 | */ |
| 543 | BUILD_BUG_ON(P4_CACHE__MAX > P4_CCCR_CACHE_OPS_MASK); | 624 | p4_pmu_enable_pebs(hwc->config); |
| 544 | if (idx_cache > P4_CACHE__NONE && | ||
| 545 | idx_cache < ARRAY_SIZE(p4_cache_event_bind_map)) { | ||
| 546 | bind_cache = &p4_cache_event_bind_map[idx_cache]; | ||
| 547 | (void)checking_wrmsrl(MSR_IA32_PEBS_ENABLE, (u64)bind_cache->metric_pebs); | ||
| 548 | (void)checking_wrmsrl(MSR_P4_PEBS_MATRIX_VERT, (u64)bind_cache->metric_vert); | ||
| 549 | } | ||
| 550 | 625 | ||
| 551 | (void)checking_wrmsrl(escr_addr, escr_conf); | 626 | (void)checking_wrmsrl(escr_addr, escr_conf); |
| 552 | (void)checking_wrmsrl(hwc->config_base + hwc->idx, | 627 | (void)checking_wrmsrl(hwc->config_base + hwc->idx, |
