diff options
author | Yan, Zheng <zheng.z.yan@intel.com> | 2012-08-06 01:11:22 -0400 |
---|---|---|
committer | Thomas Gleixner <tglx@linutronix.de> | 2012-08-13 13:01:04 -0400 |
commit | cb37af77124e8532e6ae3f9ca332593ba423b5f8 (patch) | |
tree | da6d33dfaf0ce299193a2e32f3ce218156fe33ba /arch | |
parent | ebb6cc03596cc89c89670473282ea46573feb34f (diff) |
perf/x86: Add Intel Westmere-EX uncore support
The Westmere-EX uncore is similar to the Nehalem-EX uncore. The
differences are:
- Westmere-EX uncore has 10 instances of Cbox. The MSRs for Cbox8
and Cbox9 in the Westmere-EX aren't contiguous with Cbox 0~7.
- The fvid field in the ZDP_CTL_FVC register in the Mbox is
different. It's 5 bits in the Nehalem-EX, 6 bits in the
Westmere-EX.
Signed-off-by: Yan, Zheng <zheng.z.yan@intel.com>
Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Link: http://lkml.kernel.org/r/1344229882-3907-3-git-send-email-zheng.z.yan@intel.com
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/x86/kernel/cpu/perf_event_intel_uncore.c | 56 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/perf_event_intel_uncore.h | 45 |
2 files changed, 68 insertions, 33 deletions
diff --git a/arch/x86/kernel/cpu/perf_event_intel_uncore.c b/arch/x86/kernel/cpu/perf_event_intel_uncore.c index 84434e2a676f..0a5571080e74 100644 --- a/arch/x86/kernel/cpu/perf_event_intel_uncore.c +++ b/arch/x86/kernel/cpu/perf_event_intel_uncore.c | |||
@@ -901,16 +901,21 @@ static struct attribute_group nhmex_uncore_cbox_format_group = { | |||
901 | .attrs = nhmex_uncore_cbox_formats_attr, | 901 | .attrs = nhmex_uncore_cbox_formats_attr, |
902 | }; | 902 | }; |
903 | 903 | ||
904 | /* msr offset for each instance of cbox */ | ||
905 | static unsigned nhmex_cbox_msr_offsets[] = { | ||
906 | 0x0, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, 0x240, 0x2c0, | ||
907 | }; | ||
908 | |||
904 | static struct intel_uncore_type nhmex_uncore_cbox = { | 909 | static struct intel_uncore_type nhmex_uncore_cbox = { |
905 | .name = "cbox", | 910 | .name = "cbox", |
906 | .num_counters = 6, | 911 | .num_counters = 6, |
907 | .num_boxes = 8, | 912 | .num_boxes = 10, |
908 | .perf_ctr_bits = 48, | 913 | .perf_ctr_bits = 48, |
909 | .event_ctl = NHMEX_C0_MSR_PMON_EV_SEL0, | 914 | .event_ctl = NHMEX_C0_MSR_PMON_EV_SEL0, |
910 | .perf_ctr = NHMEX_C0_MSR_PMON_CTR0, | 915 | .perf_ctr = NHMEX_C0_MSR_PMON_CTR0, |
911 | .event_mask = NHMEX_PMON_RAW_EVENT_MASK, | 916 | .event_mask = NHMEX_PMON_RAW_EVENT_MASK, |
912 | .box_ctl = NHMEX_C0_MSR_PMON_GLOBAL_CTL, | 917 | .box_ctl = NHMEX_C0_MSR_PMON_GLOBAL_CTL, |
913 | .msr_offset = NHMEX_C_MSR_OFFSET, | 918 | .msr_offsets = nhmex_cbox_msr_offsets, |
914 | .pair_ctr_ctl = 1, | 919 | .pair_ctr_ctl = 1, |
915 | .ops = &nhmex_uncore_ops, | 920 | .ops = &nhmex_uncore_ops, |
916 | .format_group = &nhmex_uncore_cbox_format_group | 921 | .format_group = &nhmex_uncore_cbox_format_group |
@@ -1138,6 +1143,9 @@ static struct extra_reg nhmex_uncore_mbox_extra_regs[] = { | |||
1138 | EVENT_EXTRA_END | 1143 | EVENT_EXTRA_END |
1139 | }; | 1144 | }; |
1140 | 1145 | ||
1146 | /* Nehalem-EX or Westmere-EX ? */ | ||
1147 | bool uncore_nhmex; | ||
1148 | |||
1141 | static bool nhmex_mbox_get_shared_reg(struct intel_uncore_box *box, int idx, u64 config) | 1149 | static bool nhmex_mbox_get_shared_reg(struct intel_uncore_box *box, int idx, u64 config) |
1142 | { | 1150 | { |
1143 | struct intel_uncore_extra_reg *er; | 1151 | struct intel_uncore_extra_reg *er; |
@@ -1167,18 +1175,29 @@ static bool nhmex_mbox_get_shared_reg(struct intel_uncore_box *box, int idx, u64 | |||
1167 | return false; | 1175 | return false; |
1168 | 1176 | ||
1169 | /* mask of the shared fields */ | 1177 | /* mask of the shared fields */ |
1170 | mask = NHMEX_M_PMON_ZDP_CTL_FVC_MASK; | 1178 | if (uncore_nhmex) |
1179 | mask = NHMEX_M_PMON_ZDP_CTL_FVC_MASK; | ||
1180 | else | ||
1181 | mask = WSMEX_M_PMON_ZDP_CTL_FVC_MASK; | ||
1171 | er = &box->shared_regs[EXTRA_REG_NHMEX_M_ZDP_CTL_FVC]; | 1182 | er = &box->shared_regs[EXTRA_REG_NHMEX_M_ZDP_CTL_FVC]; |
1172 | 1183 | ||
1173 | raw_spin_lock_irqsave(&er->lock, flags); | 1184 | raw_spin_lock_irqsave(&er->lock, flags); |
1174 | /* add mask of the non-shared field if it's in use */ | 1185 | /* add mask of the non-shared field if it's in use */ |
1175 | if (__BITS_VALUE(atomic_read(&er->ref), idx, 8)) | 1186 | if (__BITS_VALUE(atomic_read(&er->ref), idx, 8)) { |
1176 | mask |= NHMEX_M_PMON_ZDP_CTL_FVC_EVENT_MASK(idx); | 1187 | if (uncore_nhmex) |
1188 | mask |= NHMEX_M_PMON_ZDP_CTL_FVC_EVENT_MASK(idx); | ||
1189 | else | ||
1190 | mask |= WSMEX_M_PMON_ZDP_CTL_FVC_EVENT_MASK(idx); | ||
1191 | } | ||
1177 | 1192 | ||
1178 | if (!atomic_read(&er->ref) || !((er->config ^ config) & mask)) { | 1193 | if (!atomic_read(&er->ref) || !((er->config ^ config) & mask)) { |
1179 | atomic_add(1 << (idx * 8), &er->ref); | 1194 | atomic_add(1 << (idx * 8), &er->ref); |
1180 | mask = NHMEX_M_PMON_ZDP_CTL_FVC_MASK | | 1195 | if (uncore_nhmex) |
1181 | NHMEX_M_PMON_ZDP_CTL_FVC_EVENT_MASK(idx); | 1196 | mask = NHMEX_M_PMON_ZDP_CTL_FVC_MASK | |
1197 | NHMEX_M_PMON_ZDP_CTL_FVC_EVENT_MASK(idx); | ||
1198 | else | ||
1199 | mask = WSMEX_M_PMON_ZDP_CTL_FVC_MASK | | ||
1200 | WSMEX_M_PMON_ZDP_CTL_FVC_EVENT_MASK(idx); | ||
1182 | er->config &= ~mask; | 1201 | er->config &= ~mask; |
1183 | er->config |= (config & mask); | 1202 | er->config |= (config & mask); |
1184 | ret = true; | 1203 | ret = true; |
@@ -1212,7 +1231,10 @@ u64 nhmex_mbox_alter_er(struct perf_event *event, int new_idx, bool modify) | |||
1212 | 1231 | ||
1213 | /* get the non-shared control bits and shift them */ | 1232 | /* get the non-shared control bits and shift them */ |
1214 | idx = orig_idx - EXTRA_REG_NHMEX_M_ZDP_CTL_FVC; | 1233 | idx = orig_idx - EXTRA_REG_NHMEX_M_ZDP_CTL_FVC; |
1215 | config &= NHMEX_M_PMON_ZDP_CTL_FVC_EVENT_MASK(idx); | 1234 | if (uncore_nhmex) |
1235 | config &= NHMEX_M_PMON_ZDP_CTL_FVC_EVENT_MASK(idx); | ||
1236 | else | ||
1237 | config &= WSMEX_M_PMON_ZDP_CTL_FVC_EVENT_MASK(idx); | ||
1216 | if (new_idx > orig_idx) { | 1238 | if (new_idx > orig_idx) { |
1217 | idx = new_idx - orig_idx; | 1239 | idx = new_idx - orig_idx; |
1218 | config <<= 3 * idx; | 1240 | config <<= 3 * idx; |
@@ -1222,6 +1244,10 @@ u64 nhmex_mbox_alter_er(struct perf_event *event, int new_idx, bool modify) | |||
1222 | } | 1244 | } |
1223 | 1245 | ||
1224 | /* add the shared control bits back */ | 1246 | /* add the shared control bits back */ |
1247 | if (uncore_nhmex) | ||
1248 | config |= NHMEX_M_PMON_ZDP_CTL_FVC_MASK & reg1->config; | ||
1249 | else | ||
1250 | config |= WSMEX_M_PMON_ZDP_CTL_FVC_MASK & reg1->config; | ||
1225 | config |= NHMEX_M_PMON_ZDP_CTL_FVC_MASK & reg1->config; | 1251 | config |= NHMEX_M_PMON_ZDP_CTL_FVC_MASK & reg1->config; |
1226 | if (modify) { | 1252 | if (modify) { |
1227 | /* adjust the main event selector */ | 1253 | /* adjust the main event selector */ |
@@ -1480,6 +1506,12 @@ static struct uncore_event_desc nhmex_uncore_mbox_events[] = { | |||
1480 | { /* end: all zeroes */ }, | 1506 | { /* end: all zeroes */ }, |
1481 | }; | 1507 | }; |
1482 | 1508 | ||
1509 | static struct uncore_event_desc wsmex_uncore_mbox_events[] = { | ||
1510 | INTEL_UNCORE_EVENT_DESC(bbox_cmds_read, "inc_sel=0xd,fvc=0x5000"), | ||
1511 | INTEL_UNCORE_EVENT_DESC(bbox_cmds_write, "inc_sel=0xd,fvc=0x5040"), | ||
1512 | { /* end: all zeroes */ }, | ||
1513 | }; | ||
1514 | |||
1483 | static struct intel_uncore_ops nhmex_uncore_mbox_ops = { | 1515 | static struct intel_uncore_ops nhmex_uncore_mbox_ops = { |
1484 | NHMEX_UNCORE_OPS_COMMON_INIT(), | 1516 | NHMEX_UNCORE_OPS_COMMON_INIT(), |
1485 | .enable_event = nhmex_mbox_msr_enable_event, | 1517 | .enable_event = nhmex_mbox_msr_enable_event, |
@@ -2791,7 +2823,13 @@ static int __init uncore_cpu_init(void) | |||
2791 | snbep_uncore_cbox.num_boxes = max_cores; | 2823 | snbep_uncore_cbox.num_boxes = max_cores; |
2792 | msr_uncores = snbep_msr_uncores; | 2824 | msr_uncores = snbep_msr_uncores; |
2793 | break; | 2825 | break; |
2794 | case 46: | 2826 | case 46: /* Nehalem-EX */ |
2827 | uncore_nhmex = true; | ||
2828 | case 47: /* Westmere-EX aka. Xeon E7 */ | ||
2829 | if (!uncore_nhmex) | ||
2830 | nhmex_uncore_mbox.event_descs = wsmex_uncore_mbox_events; | ||
2831 | if (nhmex_uncore_cbox.num_boxes > max_cores) | ||
2832 | nhmex_uncore_cbox.num_boxes = max_cores; | ||
2795 | msr_uncores = nhmex_msr_uncores; | 2833 | msr_uncores = nhmex_msr_uncores; |
2796 | break; | 2834 | break; |
2797 | default: | 2835 | default: |
diff --git a/arch/x86/kernel/cpu/perf_event_intel_uncore.h b/arch/x86/kernel/cpu/perf_event_intel_uncore.h index 8384e9b543b7..5b81c1856aac 100644 --- a/arch/x86/kernel/cpu/perf_event_intel_uncore.h +++ b/arch/x86/kernel/cpu/perf_event_intel_uncore.h | |||
@@ -276,18 +276,12 @@ | |||
276 | NHMEX_M_PMON_CTL_INC_SEL_MASK | \ | 276 | NHMEX_M_PMON_CTL_INC_SEL_MASK | \ |
277 | NHMEX_M_PMON_CTL_SET_FLAG_SEL_MASK) | 277 | NHMEX_M_PMON_CTL_SET_FLAG_SEL_MASK) |
278 | 278 | ||
279 | 279 | #define NHMEX_M_PMON_ZDP_CTL_FVC_MASK (((1 << 11) - 1) | (1 << 23)) | |
280 | #define NHMEX_M_PMON_ZDP_CTL_FVC_FVID_MASK 0x1f | ||
281 | #define NHMEX_M_PMON_ZDP_CTL_FVC_BCMD_MASK (0x7 << 5) | ||
282 | #define NHMEX_M_PMON_ZDP_CTL_FVC_RSP_MASK (0x7 << 8) | ||
283 | #define NHMEX_M_PMON_ZDP_CTL_FVC_PBOX_INIT_ERR (1 << 23) | ||
284 | #define NHMEX_M_PMON_ZDP_CTL_FVC_MASK \ | ||
285 | (NHMEX_M_PMON_ZDP_CTL_FVC_FVID_MASK | \ | ||
286 | NHMEX_M_PMON_ZDP_CTL_FVC_BCMD_MASK | \ | ||
287 | NHMEX_M_PMON_ZDP_CTL_FVC_RSP_MASK | \ | ||
288 | NHMEX_M_PMON_ZDP_CTL_FVC_PBOX_INIT_ERR) | ||
289 | #define NHMEX_M_PMON_ZDP_CTL_FVC_EVENT_MASK(n) (0x7 << (11 + 3 * (n))) | 280 | #define NHMEX_M_PMON_ZDP_CTL_FVC_EVENT_MASK(n) (0x7 << (11 + 3 * (n))) |
290 | 281 | ||
282 | #define WSMEX_M_PMON_ZDP_CTL_FVC_MASK (((1 << 12) - 1) | (1 << 24)) | ||
283 | #define WSMEX_M_PMON_ZDP_CTL_FVC_EVENT_MASK(n) (0x7 << (12 + 3 * (n))) | ||
284 | |||
291 | /* | 285 | /* |
292 | * use the 9~13 bits to select event If the 7th bit is not set, | 286 | * use the 9~13 bits to select event If the 7th bit is not set, |
293 | * otherwise use the 19~21 bits to select event. | 287 | * otherwise use the 19~21 bits to select event. |
@@ -369,6 +363,7 @@ struct intel_uncore_type { | |||
369 | unsigned num_shared_regs:8; | 363 | unsigned num_shared_regs:8; |
370 | unsigned single_fixed:1; | 364 | unsigned single_fixed:1; |
371 | unsigned pair_ctr_ctl:1; | 365 | unsigned pair_ctr_ctl:1; |
366 | unsigned *msr_offsets; | ||
372 | struct event_constraint unconstrainted; | 367 | struct event_constraint unconstrainted; |
373 | struct event_constraint *constraints; | 368 | struct event_constraint *constraints; |
374 | struct intel_uncore_pmu *pmus; | 369 | struct intel_uncore_pmu *pmus; |
@@ -486,29 +481,31 @@ unsigned uncore_pci_perf_ctr(struct intel_uncore_box *box, int idx) | |||
486 | return idx * 8 + box->pmu->type->perf_ctr; | 481 | return idx * 8 + box->pmu->type->perf_ctr; |
487 | } | 482 | } |
488 | 483 | ||
489 | static inline | 484 | static inline unsigned uncore_msr_box_offset(struct intel_uncore_box *box) |
490 | unsigned uncore_msr_box_ctl(struct intel_uncore_box *box) | 485 | { |
486 | struct intel_uncore_pmu *pmu = box->pmu; | ||
487 | return pmu->type->msr_offsets ? | ||
488 | pmu->type->msr_offsets[pmu->pmu_idx] : | ||
489 | pmu->type->msr_offset * pmu->pmu_idx; | ||
490 | } | ||
491 | |||
492 | static inline unsigned uncore_msr_box_ctl(struct intel_uncore_box *box) | ||
491 | { | 493 | { |
492 | if (!box->pmu->type->box_ctl) | 494 | if (!box->pmu->type->box_ctl) |
493 | return 0; | 495 | return 0; |
494 | return box->pmu->type->box_ctl + | 496 | return box->pmu->type->box_ctl + uncore_msr_box_offset(box); |
495 | box->pmu->type->msr_offset * box->pmu->pmu_idx; | ||
496 | } | 497 | } |
497 | 498 | ||
498 | static inline | 499 | static inline unsigned uncore_msr_fixed_ctl(struct intel_uncore_box *box) |
499 | unsigned uncore_msr_fixed_ctl(struct intel_uncore_box *box) | ||
500 | { | 500 | { |
501 | if (!box->pmu->type->fixed_ctl) | 501 | if (!box->pmu->type->fixed_ctl) |
502 | return 0; | 502 | return 0; |
503 | return box->pmu->type->fixed_ctl + | 503 | return box->pmu->type->fixed_ctl + uncore_msr_box_offset(box); |
504 | box->pmu->type->msr_offset * box->pmu->pmu_idx; | ||
505 | } | 504 | } |
506 | 505 | ||
507 | static inline | 506 | static inline unsigned uncore_msr_fixed_ctr(struct intel_uncore_box *box) |
508 | unsigned uncore_msr_fixed_ctr(struct intel_uncore_box *box) | ||
509 | { | 507 | { |
510 | return box->pmu->type->fixed_ctr + | 508 | return box->pmu->type->fixed_ctr + uncore_msr_box_offset(box); |
511 | box->pmu->type->msr_offset * box->pmu->pmu_idx; | ||
512 | } | 509 | } |
513 | 510 | ||
514 | static inline | 511 | static inline |
@@ -516,7 +513,7 @@ unsigned uncore_msr_event_ctl(struct intel_uncore_box *box, int idx) | |||
516 | { | 513 | { |
517 | return box->pmu->type->event_ctl + | 514 | return box->pmu->type->event_ctl + |
518 | (box->pmu->type->pair_ctr_ctl ? 2 * idx : idx) + | 515 | (box->pmu->type->pair_ctr_ctl ? 2 * idx : idx) + |
519 | box->pmu->type->msr_offset * box->pmu->pmu_idx; | 516 | uncore_msr_box_offset(box); |
520 | } | 517 | } |
521 | 518 | ||
522 | static inline | 519 | static inline |
@@ -524,7 +521,7 @@ unsigned uncore_msr_perf_ctr(struct intel_uncore_box *box, int idx) | |||
524 | { | 521 | { |
525 | return box->pmu->type->perf_ctr + | 522 | return box->pmu->type->perf_ctr + |
526 | (box->pmu->type->pair_ctr_ctl ? 2 * idx : idx) + | 523 | (box->pmu->type->pair_ctr_ctl ? 2 * idx : idx) + |
527 | box->pmu->type->msr_offset * box->pmu->pmu_idx; | 524 | uncore_msr_box_offset(box); |
528 | } | 525 | } |
529 | 526 | ||
530 | static inline | 527 | static inline |