diff options
author | Yan, Zheng <zheng.z.yan@intel.com> | 2012-08-06 01:11:21 -0400 |
---|---|---|
committer | Thomas Gleixner <tglx@linutronix.de> | 2012-08-13 13:01:03 -0400 |
commit | ebb6cc03596cc89c89670473282ea46573feb34f (patch) | |
tree | 2e045ae53633e0777a1ba73d934cfc357d7e5e88 | |
parent | cffa59baa5f1cf3e3e9e172697db48912471531c (diff) |
perf/x86: Fixes for Nehalem-EX uncore driver
This patch includes following fixes and update:
- Only some events in the Sbox and Mbox can use the match/mask
registers, add code to check this.
- The format definitions for xbr_mm_cfg and xbr_match registers
in the Rbox are wrong, xbr_mm_cfg should use 32 bits, xbr_match
should use 64 bits.
- Cleanup the Rbox code. Compute the addresses extra registers in
the enable_event function instead of the hw_config function.
This simplifies the code in nhmex_rbox_alter_er().
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-2-git-send-email-zheng.z.yan@intel.com
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
-rw-r--r-- | arch/x86/kernel/cpu/perf_event_intel_uncore.c | 195 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/perf_event_intel_uncore.h | 1 |
2 files changed, 87 insertions, 109 deletions
diff --git a/arch/x86/kernel/cpu/perf_event_intel_uncore.c b/arch/x86/kernel/cpu/perf_event_intel_uncore.c index a7ccd68aa13a..84434e2a676f 100644 --- a/arch/x86/kernel/cpu/perf_event_intel_uncore.c +++ b/arch/x86/kernel/cpu/perf_event_intel_uncore.c | |||
@@ -796,7 +796,6 @@ static struct intel_uncore_type *nhm_msr_uncores[] = { | |||
796 | 796 | ||
797 | DEFINE_UNCORE_FORMAT_ATTR(event5, event, "config:1-5"); | 797 | DEFINE_UNCORE_FORMAT_ATTR(event5, event, "config:1-5"); |
798 | DEFINE_UNCORE_FORMAT_ATTR(counter, counter, "config:6-7"); | 798 | DEFINE_UNCORE_FORMAT_ATTR(counter, counter, "config:6-7"); |
799 | DEFINE_UNCORE_FORMAT_ATTR(mm_cfg, mm_cfg, "config:63"); | ||
800 | DEFINE_UNCORE_FORMAT_ATTR(match, match, "config1:0-63"); | 799 | DEFINE_UNCORE_FORMAT_ATTR(match, match, "config1:0-63"); |
801 | DEFINE_UNCORE_FORMAT_ATTR(mask, mask, "config2:0-63"); | 800 | DEFINE_UNCORE_FORMAT_ATTR(mask, mask, "config2:0-63"); |
802 | 801 | ||
@@ -1032,24 +1031,22 @@ static struct intel_uncore_type nhmex_uncore_bbox = { | |||
1032 | 1031 | ||
1033 | static int nhmex_sbox_hw_config(struct intel_uncore_box *box, struct perf_event *event) | 1032 | static int nhmex_sbox_hw_config(struct intel_uncore_box *box, struct perf_event *event) |
1034 | { | 1033 | { |
1035 | struct hw_perf_event_extra *reg1 = &event->hw.extra_reg; | 1034 | struct hw_perf_event *hwc = &event->hw; |
1036 | struct hw_perf_event_extra *reg2 = &event->hw.branch_reg; | 1035 | struct hw_perf_event_extra *reg1 = &hwc->extra_reg; |
1036 | struct hw_perf_event_extra *reg2 = &hwc->branch_reg; | ||
1037 | 1037 | ||
1038 | if (event->attr.config & NHMEX_S_PMON_MM_CFG_EN) { | 1038 | /* only TO_R_PROG_EV event uses the match/mask register */ |
1039 | reg1->config = event->attr.config1; | 1039 | if ((hwc->config & NHMEX_PMON_CTL_EV_SEL_MASK) != |
1040 | reg2->config = event->attr.config2; | 1040 | NHMEX_S_EVENT_TO_R_PROG_EV) |
1041 | } else { | 1041 | return 0; |
1042 | reg1->config = ~0ULL; | ||
1043 | reg2->config = ~0ULL; | ||
1044 | } | ||
1045 | 1042 | ||
1046 | if (box->pmu->pmu_idx == 0) | 1043 | if (box->pmu->pmu_idx == 0) |
1047 | reg1->reg = NHMEX_S0_MSR_MM_CFG; | 1044 | reg1->reg = NHMEX_S0_MSR_MM_CFG; |
1048 | else | 1045 | else |
1049 | reg1->reg = NHMEX_S1_MSR_MM_CFG; | 1046 | reg1->reg = NHMEX_S1_MSR_MM_CFG; |
1050 | |||
1051 | reg1->idx = 0; | 1047 | reg1->idx = 0; |
1052 | 1048 | reg1->config = event->attr.config1; | |
1049 | reg2->config = event->attr.config2; | ||
1053 | return 0; | 1050 | return 0; |
1054 | } | 1051 | } |
1055 | 1052 | ||
@@ -1059,8 +1056,8 @@ static void nhmex_sbox_msr_enable_event(struct intel_uncore_box *box, struct per | |||
1059 | struct hw_perf_event_extra *reg1 = &hwc->extra_reg; | 1056 | struct hw_perf_event_extra *reg1 = &hwc->extra_reg; |
1060 | struct hw_perf_event_extra *reg2 = &hwc->branch_reg; | 1057 | struct hw_perf_event_extra *reg2 = &hwc->branch_reg; |
1061 | 1058 | ||
1062 | wrmsrl(reg1->reg, 0); | 1059 | if (reg1->idx != EXTRA_REG_NONE) { |
1063 | if (reg1->config != ~0ULL || reg2->config != ~0ULL) { | 1060 | wrmsrl(reg1->reg, 0); |
1064 | wrmsrl(reg1->reg + 1, reg1->config); | 1061 | wrmsrl(reg1->reg + 1, reg1->config); |
1065 | wrmsrl(reg1->reg + 2, reg2->config); | 1062 | wrmsrl(reg1->reg + 2, reg2->config); |
1066 | wrmsrl(reg1->reg, NHMEX_S_PMON_MM_CFG_EN); | 1063 | wrmsrl(reg1->reg, NHMEX_S_PMON_MM_CFG_EN); |
@@ -1074,7 +1071,6 @@ static struct attribute *nhmex_uncore_sbox_formats_attr[] = { | |||
1074 | &format_attr_edge.attr, | 1071 | &format_attr_edge.attr, |
1075 | &format_attr_inv.attr, | 1072 | &format_attr_inv.attr, |
1076 | &format_attr_thresh8.attr, | 1073 | &format_attr_thresh8.attr, |
1077 | &format_attr_mm_cfg.attr, | ||
1078 | &format_attr_match.attr, | 1074 | &format_attr_match.attr, |
1079 | &format_attr_mask.attr, | 1075 | &format_attr_mask.attr, |
1080 | NULL, | 1076 | NULL, |
@@ -1264,7 +1260,8 @@ again: | |||
1264 | } | 1260 | } |
1265 | 1261 | ||
1266 | /* for the match/mask registers */ | 1262 | /* for the match/mask registers */ |
1267 | if ((uncore_box_is_fake(box) || !reg2->alloc) && | 1263 | if (reg2->idx != EXTRA_REG_NONE && |
1264 | (uncore_box_is_fake(box) || !reg2->alloc) && | ||
1268 | !nhmex_mbox_get_shared_reg(box, reg2->idx, reg2->config)) | 1265 | !nhmex_mbox_get_shared_reg(box, reg2->idx, reg2->config)) |
1269 | goto fail; | 1266 | goto fail; |
1270 | 1267 | ||
@@ -1278,7 +1275,8 @@ again: | |||
1278 | if (idx[0] != 0xff && idx[0] != __BITS_VALUE(reg1->idx, 0, 8)) | 1275 | if (idx[0] != 0xff && idx[0] != __BITS_VALUE(reg1->idx, 0, 8)) |
1279 | nhmex_mbox_alter_er(event, idx[0], true); | 1276 | nhmex_mbox_alter_er(event, idx[0], true); |
1280 | reg1->alloc |= alloc; | 1277 | reg1->alloc |= alloc; |
1281 | reg2->alloc = 1; | 1278 | if (reg2->idx != EXTRA_REG_NONE) |
1279 | reg2->alloc = 1; | ||
1282 | } | 1280 | } |
1283 | return NULL; | 1281 | return NULL; |
1284 | fail: | 1282 | fail: |
@@ -1342,9 +1340,6 @@ static int nhmex_mbox_hw_config(struct intel_uncore_box *box, struct perf_event | |||
1342 | struct extra_reg *er; | 1340 | struct extra_reg *er; |
1343 | unsigned msr; | 1341 | unsigned msr; |
1344 | int reg_idx = 0; | 1342 | int reg_idx = 0; |
1345 | |||
1346 | if (WARN_ON_ONCE(reg1->idx != -1)) | ||
1347 | return -EINVAL; | ||
1348 | /* | 1343 | /* |
1349 | * The mbox events may require 2 extra MSRs at the most. But only | 1344 | * The mbox events may require 2 extra MSRs at the most. But only |
1350 | * the lower 32 bits in these MSRs are significant, so we can use | 1345 | * the lower 32 bits in these MSRs are significant, so we can use |
@@ -1355,11 +1350,6 @@ static int nhmex_mbox_hw_config(struct intel_uncore_box *box, struct perf_event | |||
1355 | continue; | 1350 | continue; |
1356 | if (event->attr.config1 & ~er->valid_mask) | 1351 | if (event->attr.config1 & ~er->valid_mask) |
1357 | return -EINVAL; | 1352 | return -EINVAL; |
1358 | if (er->idx == __BITS_VALUE(reg1->idx, 0, 8) || | ||
1359 | er->idx == __BITS_VALUE(reg1->idx, 1, 8)) | ||
1360 | continue; | ||
1361 | if (WARN_ON_ONCE(reg_idx >= 2)) | ||
1362 | return -EINVAL; | ||
1363 | 1353 | ||
1364 | msr = er->msr + type->msr_offset * box->pmu->pmu_idx; | 1354 | msr = er->msr + type->msr_offset * box->pmu->pmu_idx; |
1365 | if (WARN_ON_ONCE(msr >= 0xffff || er->idx >= 0xff)) | 1355 | if (WARN_ON_ONCE(msr >= 0xffff || er->idx >= 0xff)) |
@@ -1368,6 +1358,8 @@ static int nhmex_mbox_hw_config(struct intel_uncore_box *box, struct perf_event | |||
1368 | /* always use the 32~63 bits to pass the PLD config */ | 1358 | /* always use the 32~63 bits to pass the PLD config */ |
1369 | if (er->idx == EXTRA_REG_NHMEX_M_PLD) | 1359 | if (er->idx == EXTRA_REG_NHMEX_M_PLD) |
1370 | reg_idx = 1; | 1360 | reg_idx = 1; |
1361 | else if (WARN_ON_ONCE(reg_idx > 0)) | ||
1362 | return -EINVAL; | ||
1371 | 1363 | ||
1372 | reg1->idx &= ~(0xff << (reg_idx * 8)); | 1364 | reg1->idx &= ~(0xff << (reg_idx * 8)); |
1373 | reg1->reg &= ~(0xffff << (reg_idx * 16)); | 1365 | reg1->reg &= ~(0xffff << (reg_idx * 16)); |
@@ -1376,17 +1368,21 @@ static int nhmex_mbox_hw_config(struct intel_uncore_box *box, struct perf_event | |||
1376 | reg1->config = event->attr.config1; | 1368 | reg1->config = event->attr.config1; |
1377 | reg_idx++; | 1369 | reg_idx++; |
1378 | } | 1370 | } |
1379 | /* use config2 to pass the filter config */ | 1371 | /* |
1380 | reg2->idx = EXTRA_REG_NHMEX_M_FILTER; | 1372 | * The mbox only provides ability to perform address matching |
1381 | if (event->attr.config2 & NHMEX_M_PMON_MM_CFG_EN) | 1373 | * for the PLD events. |
1382 | reg2->config = event->attr.config2; | 1374 | */ |
1383 | else | 1375 | if (reg_idx == 2) { |
1384 | reg2->config = ~0ULL; | 1376 | reg2->idx = EXTRA_REG_NHMEX_M_FILTER; |
1385 | if (box->pmu->pmu_idx == 0) | 1377 | if (event->attr.config2 & NHMEX_M_PMON_MM_CFG_EN) |
1386 | reg2->reg = NHMEX_M0_MSR_PMU_MM_CFG; | 1378 | reg2->config = event->attr.config2; |
1387 | else | 1379 | else |
1388 | reg2->reg = NHMEX_M1_MSR_PMU_MM_CFG; | 1380 | reg2->config = ~0ULL; |
1389 | 1381 | if (box->pmu->pmu_idx == 0) | |
1382 | reg2->reg = NHMEX_M0_MSR_PMU_MM_CFG; | ||
1383 | else | ||
1384 | reg2->reg = NHMEX_M1_MSR_PMU_MM_CFG; | ||
1385 | } | ||
1390 | return 0; | 1386 | return 0; |
1391 | } | 1387 | } |
1392 | 1388 | ||
@@ -1422,34 +1418,36 @@ static void nhmex_mbox_msr_enable_event(struct intel_uncore_box *box, struct per | |||
1422 | wrmsrl(__BITS_VALUE(reg1->reg, 1, 16), | 1418 | wrmsrl(__BITS_VALUE(reg1->reg, 1, 16), |
1423 | nhmex_mbox_shared_reg_config(box, idx)); | 1419 | nhmex_mbox_shared_reg_config(box, idx)); |
1424 | 1420 | ||
1425 | wrmsrl(reg2->reg, 0); | 1421 | if (reg2->idx != EXTRA_REG_NONE) { |
1426 | if (reg2->config != ~0ULL) { | 1422 | wrmsrl(reg2->reg, 0); |
1427 | wrmsrl(reg2->reg + 1, | 1423 | if (reg2->config != ~0ULL) { |
1428 | reg2->config & NHMEX_M_PMON_ADDR_MATCH_MASK); | 1424 | wrmsrl(reg2->reg + 1, |
1429 | wrmsrl(reg2->reg + 2, NHMEX_M_PMON_ADDR_MASK_MASK & | 1425 | reg2->config & NHMEX_M_PMON_ADDR_MATCH_MASK); |
1430 | (reg2->config >> NHMEX_M_PMON_ADDR_MASK_SHIFT)); | 1426 | wrmsrl(reg2->reg + 2, NHMEX_M_PMON_ADDR_MASK_MASK & |
1431 | wrmsrl(reg2->reg, NHMEX_M_PMON_MM_CFG_EN); | 1427 | (reg2->config >> NHMEX_M_PMON_ADDR_MASK_SHIFT)); |
1428 | wrmsrl(reg2->reg, NHMEX_M_PMON_MM_CFG_EN); | ||
1429 | } | ||
1432 | } | 1430 | } |
1433 | 1431 | ||
1434 | wrmsrl(hwc->config_base, hwc->config | NHMEX_PMON_CTL_EN_BIT0); | 1432 | wrmsrl(hwc->config_base, hwc->config | NHMEX_PMON_CTL_EN_BIT0); |
1435 | } | 1433 | } |
1436 | 1434 | ||
1437 | DEFINE_UNCORE_FORMAT_ATTR(count_mode, count_mode, "config:2-3"); | 1435 | DEFINE_UNCORE_FORMAT_ATTR(count_mode, count_mode, "config:2-3"); |
1438 | DEFINE_UNCORE_FORMAT_ATTR(storage_mode, storage_mode, "config:4-5"); | 1436 | DEFINE_UNCORE_FORMAT_ATTR(storage_mode, storage_mode, "config:4-5"); |
1439 | DEFINE_UNCORE_FORMAT_ATTR(wrap_mode, wrap_mode, "config:6"); | 1437 | DEFINE_UNCORE_FORMAT_ATTR(wrap_mode, wrap_mode, "config:6"); |
1440 | DEFINE_UNCORE_FORMAT_ATTR(flag_mode, flag_mode, "config:7"); | 1438 | DEFINE_UNCORE_FORMAT_ATTR(flag_mode, flag_mode, "config:7"); |
1441 | DEFINE_UNCORE_FORMAT_ATTR(inc_sel, inc_sel, "config:9-13"); | 1439 | DEFINE_UNCORE_FORMAT_ATTR(inc_sel, inc_sel, "config:9-13"); |
1442 | DEFINE_UNCORE_FORMAT_ATTR(set_flag_sel, set_flag_sel, "config:19-21"); | 1440 | DEFINE_UNCORE_FORMAT_ATTR(set_flag_sel, set_flag_sel, "config:19-21"); |
1443 | DEFINE_UNCORE_FORMAT_ATTR(filter_cfg, filter_cfg, "config2:63"); | 1441 | DEFINE_UNCORE_FORMAT_ATTR(filter_cfg_en, filter_cfg_en, "config2:63"); |
1444 | DEFINE_UNCORE_FORMAT_ATTR(filter_match, filter_match, "config2:0-33"); | 1442 | DEFINE_UNCORE_FORMAT_ATTR(filter_match, filter_match, "config2:0-33"); |
1445 | DEFINE_UNCORE_FORMAT_ATTR(filter_mask, filter_mask, "config2:34-61"); | 1443 | DEFINE_UNCORE_FORMAT_ATTR(filter_mask, filter_mask, "config2:34-61"); |
1446 | DEFINE_UNCORE_FORMAT_ATTR(dsp, dsp, "config1:0-31"); | 1444 | DEFINE_UNCORE_FORMAT_ATTR(dsp, dsp, "config1:0-31"); |
1447 | DEFINE_UNCORE_FORMAT_ATTR(thr, thr, "config1:0-31"); | 1445 | DEFINE_UNCORE_FORMAT_ATTR(thr, thr, "config1:0-31"); |
1448 | DEFINE_UNCORE_FORMAT_ATTR(fvc, fvc, "config1:0-31"); | 1446 | DEFINE_UNCORE_FORMAT_ATTR(fvc, fvc, "config1:0-31"); |
1449 | DEFINE_UNCORE_FORMAT_ATTR(pgt, pgt, "config1:0-31"); | 1447 | DEFINE_UNCORE_FORMAT_ATTR(pgt, pgt, "config1:0-31"); |
1450 | DEFINE_UNCORE_FORMAT_ATTR(map, map, "config1:0-31"); | 1448 | DEFINE_UNCORE_FORMAT_ATTR(map, map, "config1:0-31"); |
1451 | DEFINE_UNCORE_FORMAT_ATTR(iss, iss, "config1:0-31"); | 1449 | DEFINE_UNCORE_FORMAT_ATTR(iss, iss, "config1:0-31"); |
1452 | DEFINE_UNCORE_FORMAT_ATTR(pld, pld, "config1:32-63"); | 1450 | DEFINE_UNCORE_FORMAT_ATTR(pld, pld, "config1:32-63"); |
1453 | 1451 | ||
1454 | static struct attribute *nhmex_uncore_mbox_formats_attr[] = { | 1452 | static struct attribute *nhmex_uncore_mbox_formats_attr[] = { |
1455 | &format_attr_count_mode.attr, | 1453 | &format_attr_count_mode.attr, |
@@ -1458,7 +1456,7 @@ static struct attribute *nhmex_uncore_mbox_formats_attr[] = { | |||
1458 | &format_attr_flag_mode.attr, | 1456 | &format_attr_flag_mode.attr, |
1459 | &format_attr_inc_sel.attr, | 1457 | &format_attr_inc_sel.attr, |
1460 | &format_attr_set_flag_sel.attr, | 1458 | &format_attr_set_flag_sel.attr, |
1461 | &format_attr_filter_cfg.attr, | 1459 | &format_attr_filter_cfg_en.attr, |
1462 | &format_attr_filter_match.attr, | 1460 | &format_attr_filter_match.attr, |
1463 | &format_attr_filter_mask.attr, | 1461 | &format_attr_filter_mask.attr, |
1464 | &format_attr_dsp.attr, | 1462 | &format_attr_dsp.attr, |
@@ -1513,7 +1511,7 @@ void nhmex_rbox_alter_er(struct intel_uncore_box *box, struct perf_event *event) | |||
1513 | struct hw_perf_event_extra *reg1 = &hwc->extra_reg; | 1511 | struct hw_perf_event_extra *reg1 = &hwc->extra_reg; |
1514 | int port; | 1512 | int port; |
1515 | 1513 | ||
1516 | /* adjust the main event selector */ | 1514 | /* adjust the main event selector and extra register index */ |
1517 | if (reg1->idx % 2) { | 1515 | if (reg1->idx % 2) { |
1518 | reg1->idx--; | 1516 | reg1->idx--; |
1519 | hwc->config -= 1 << NHMEX_R_PMON_CTL_EV_SEL_SHIFT; | 1517 | hwc->config -= 1 << NHMEX_R_PMON_CTL_EV_SEL_SHIFT; |
@@ -1522,29 +1520,17 @@ void nhmex_rbox_alter_er(struct intel_uncore_box *box, struct perf_event *event) | |||
1522 | hwc->config += 1 << NHMEX_R_PMON_CTL_EV_SEL_SHIFT; | 1520 | hwc->config += 1 << NHMEX_R_PMON_CTL_EV_SEL_SHIFT; |
1523 | } | 1521 | } |
1524 | 1522 | ||
1525 | /* adjust address or config of extra register */ | 1523 | /* adjust extra register config */ |
1526 | port = reg1->idx / 6 + box->pmu->pmu_idx * 4; | 1524 | port = reg1->idx / 6 + box->pmu->pmu_idx * 4; |
1527 | switch (reg1->idx % 6) { | 1525 | switch (reg1->idx % 6) { |
1528 | case 0: | ||
1529 | reg1->reg = NHMEX_R_MSR_PORTN_IPERF_CFG0(port); | ||
1530 | break; | ||
1531 | case 1: | ||
1532 | reg1->reg = NHMEX_R_MSR_PORTN_IPERF_CFG1(port); | ||
1533 | break; | ||
1534 | case 2: | 1526 | case 2: |
1535 | /* the 8~15 bits to the 0~7 bits */ | 1527 | /* shift the 8~15 bits to the 0~7 bits */ |
1536 | reg1->config >>= 8; | 1528 | reg1->config >>= 8; |
1537 | break; | 1529 | break; |
1538 | case 3: | 1530 | case 3: |
1539 | /* the 0~7 bits to the 8~15 bits */ | 1531 | /* shift the 0~7 bits to the 8~15 bits */ |
1540 | reg1->config <<= 8; | 1532 | reg1->config <<= 8; |
1541 | break; | 1533 | break; |
1542 | case 4: | ||
1543 | reg1->reg = NHMEX_R_MSR_PORTN_XBR_SET1_MM_CFG(port); | ||
1544 | break; | ||
1545 | case 5: | ||
1546 | reg1->reg = NHMEX_R_MSR_PORTN_XBR_SET2_MM_CFG(port); | ||
1547 | break; | ||
1548 | }; | 1534 | }; |
1549 | } | 1535 | } |
1550 | 1536 | ||
@@ -1671,7 +1657,7 @@ static int nhmex_rbox_hw_config(struct intel_uncore_box *box, struct perf_event | |||
1671 | struct hw_perf_event *hwc = &event->hw; | 1657 | struct hw_perf_event *hwc = &event->hw; |
1672 | struct hw_perf_event_extra *reg1 = &event->hw.extra_reg; | 1658 | struct hw_perf_event_extra *reg1 = &event->hw.extra_reg; |
1673 | struct hw_perf_event_extra *reg2 = &event->hw.branch_reg; | 1659 | struct hw_perf_event_extra *reg2 = &event->hw.branch_reg; |
1674 | int port, idx; | 1660 | int idx; |
1675 | 1661 | ||
1676 | idx = (event->hw.config & NHMEX_R_PMON_CTL_EV_SEL_MASK) >> | 1662 | idx = (event->hw.config & NHMEX_R_PMON_CTL_EV_SEL_MASK) >> |
1677 | NHMEX_R_PMON_CTL_EV_SEL_SHIFT; | 1663 | NHMEX_R_PMON_CTL_EV_SEL_SHIFT; |
@@ -1681,27 +1667,11 @@ static int nhmex_rbox_hw_config(struct intel_uncore_box *box, struct perf_event | |||
1681 | reg1->idx = idx; | 1667 | reg1->idx = idx; |
1682 | reg1->config = event->attr.config1; | 1668 | reg1->config = event->attr.config1; |
1683 | 1669 | ||
1684 | port = idx / 6 + box->pmu->pmu_idx * 4; | 1670 | switch (idx % 6) { |
1685 | idx %= 6; | ||
1686 | switch (idx) { | ||
1687 | case 0: | ||
1688 | reg1->reg = NHMEX_R_MSR_PORTN_IPERF_CFG0(port); | ||
1689 | break; | ||
1690 | case 1: | ||
1691 | reg1->reg = NHMEX_R_MSR_PORTN_IPERF_CFG1(port); | ||
1692 | break; | ||
1693 | case 2: | ||
1694 | case 3: | ||
1695 | reg1->reg = NHMEX_R_MSR_PORTN_QLX_CFG(port); | ||
1696 | break; | ||
1697 | case 4: | 1671 | case 4: |
1698 | case 5: | 1672 | case 5: |
1699 | if (idx == 4) | ||
1700 | reg1->reg = NHMEX_R_MSR_PORTN_XBR_SET1_MM_CFG(port); | ||
1701 | else | ||
1702 | reg1->reg = NHMEX_R_MSR_PORTN_XBR_SET2_MM_CFG(port); | ||
1703 | reg2->config = event->attr.config2; | ||
1704 | hwc->config |= event->attr.config & (~0ULL << 32); | 1673 | hwc->config |= event->attr.config & (~0ULL << 32); |
1674 | reg2->config = event->attr.config2; | ||
1705 | break; | 1675 | break; |
1706 | }; | 1676 | }; |
1707 | return 0; | 1677 | return 0; |
@@ -1727,28 +1697,34 @@ static void nhmex_rbox_msr_enable_event(struct intel_uncore_box *box, struct per | |||
1727 | struct hw_perf_event *hwc = &event->hw; | 1697 | struct hw_perf_event *hwc = &event->hw; |
1728 | struct hw_perf_event_extra *reg1 = &hwc->extra_reg; | 1698 | struct hw_perf_event_extra *reg1 = &hwc->extra_reg; |
1729 | struct hw_perf_event_extra *reg2 = &hwc->branch_reg; | 1699 | struct hw_perf_event_extra *reg2 = &hwc->branch_reg; |
1730 | int idx, er_idx; | 1700 | int idx, port; |
1731 | 1701 | ||
1732 | idx = reg1->idx % 6; | 1702 | idx = reg1->idx; |
1733 | er_idx = idx; | 1703 | port = idx / 6 + box->pmu->pmu_idx * 4; |
1734 | if (er_idx > 2) | ||
1735 | er_idx--; | ||
1736 | er_idx += (reg1->idx / 6) * 5; | ||
1737 | 1704 | ||
1738 | switch (idx) { | 1705 | switch (idx % 6) { |
1739 | case 0: | 1706 | case 0: |
1707 | wrmsrl(NHMEX_R_MSR_PORTN_IPERF_CFG0(port), reg1->config); | ||
1708 | break; | ||
1740 | case 1: | 1709 | case 1: |
1741 | wrmsrl(reg1->reg, reg1->config); | 1710 | wrmsrl(NHMEX_R_MSR_PORTN_IPERF_CFG1(port), reg1->config); |
1742 | break; | 1711 | break; |
1743 | case 2: | 1712 | case 2: |
1744 | case 3: | 1713 | case 3: |
1745 | wrmsrl(reg1->reg, nhmex_rbox_shared_reg_config(box, er_idx)); | 1714 | wrmsrl(NHMEX_R_MSR_PORTN_QLX_CFG(port), |
1715 | nhmex_rbox_shared_reg_config(box, 2 + (idx / 6) * 5)); | ||
1746 | break; | 1716 | break; |
1747 | case 4: | 1717 | case 4: |
1718 | wrmsrl(NHMEX_R_MSR_PORTN_XBR_SET1_MM_CFG(port), | ||
1719 | hwc->config >> 32); | ||
1720 | wrmsrl(NHMEX_R_MSR_PORTN_XBR_SET1_MATCH(port), reg1->config); | ||
1721 | wrmsrl(NHMEX_R_MSR_PORTN_XBR_SET1_MASK(port), reg2->config); | ||
1722 | break; | ||
1748 | case 5: | 1723 | case 5: |
1749 | wrmsrl(reg1->reg, reg1->config); | 1724 | wrmsrl(NHMEX_R_MSR_PORTN_XBR_SET2_MM_CFG(port), |
1750 | wrmsrl(reg1->reg + 1, hwc->config >> 32); | 1725 | hwc->config >> 32); |
1751 | wrmsrl(reg1->reg + 2, reg2->config); | 1726 | wrmsrl(NHMEX_R_MSR_PORTN_XBR_SET2_MATCH(port), reg1->config); |
1727 | wrmsrl(NHMEX_R_MSR_PORTN_XBR_SET2_MASK(port), reg2->config); | ||
1752 | break; | 1728 | break; |
1753 | }; | 1729 | }; |
1754 | 1730 | ||
@@ -1756,8 +1732,8 @@ static void nhmex_rbox_msr_enable_event(struct intel_uncore_box *box, struct per | |||
1756 | (hwc->config & NHMEX_R_PMON_CTL_EV_SEL_MASK)); | 1732 | (hwc->config & NHMEX_R_PMON_CTL_EV_SEL_MASK)); |
1757 | } | 1733 | } |
1758 | 1734 | ||
1759 | DEFINE_UNCORE_FORMAT_ATTR(xbr_match, xbr_match, "config:32-63"); | 1735 | DEFINE_UNCORE_FORMAT_ATTR(xbr_mm_cfg, xbr_mm_cfg, "config:32-63"); |
1760 | DEFINE_UNCORE_FORMAT_ATTR(xbr_mm_cfg, xbr_mm_cfg, "config1:0-63"); | 1736 | DEFINE_UNCORE_FORMAT_ATTR(xbr_match, xbr_match, "config1:0-63"); |
1761 | DEFINE_UNCORE_FORMAT_ATTR(xbr_mask, xbr_mask, "config2:0-63"); | 1737 | DEFINE_UNCORE_FORMAT_ATTR(xbr_mask, xbr_mask, "config2:0-63"); |
1762 | DEFINE_UNCORE_FORMAT_ATTR(qlx_cfg, qlx_cfg, "config1:0-15"); | 1738 | DEFINE_UNCORE_FORMAT_ATTR(qlx_cfg, qlx_cfg, "config1:0-15"); |
1763 | DEFINE_UNCORE_FORMAT_ATTR(iperf_cfg, iperf_cfg, "config1:0-31"); | 1739 | DEFINE_UNCORE_FORMAT_ATTR(iperf_cfg, iperf_cfg, "config1:0-31"); |
@@ -2303,6 +2279,7 @@ int uncore_pmu_event_init(struct perf_event *event) | |||
2303 | event->hw.idx = -1; | 2279 | event->hw.idx = -1; |
2304 | event->hw.last_tag = ~0ULL; | 2280 | event->hw.last_tag = ~0ULL; |
2305 | event->hw.extra_reg.idx = EXTRA_REG_NONE; | 2281 | event->hw.extra_reg.idx = EXTRA_REG_NONE; |
2282 | event->hw.branch_reg.idx = EXTRA_REG_NONE; | ||
2306 | 2283 | ||
2307 | if (event->attr.config == UNCORE_FIXED_EVENT) { | 2284 | if (event->attr.config == UNCORE_FIXED_EVENT) { |
2308 | /* no fixed counter */ | 2285 | /* no fixed counter */ |
diff --git a/arch/x86/kernel/cpu/perf_event_intel_uncore.h b/arch/x86/kernel/cpu/perf_event_intel_uncore.h index c9e5dc56630a..8384e9b543b7 100644 --- a/arch/x86/kernel/cpu/perf_event_intel_uncore.h +++ b/arch/x86/kernel/cpu/perf_event_intel_uncore.h | |||
@@ -230,6 +230,7 @@ | |||
230 | #define NHMEX_S1_MSR_MASK 0xe5a | 230 | #define NHMEX_S1_MSR_MASK 0xe5a |
231 | 231 | ||
232 | #define NHMEX_S_PMON_MM_CFG_EN (0x1ULL << 63) | 232 | #define NHMEX_S_PMON_MM_CFG_EN (0x1ULL << 63) |
233 | #define NHMEX_S_EVENT_TO_R_PROG_EV 0 | ||
233 | 234 | ||
234 | /* NHM-EX Mbox */ | 235 | /* NHM-EX Mbox */ |
235 | #define NHMEX_M0_MSR_GLOBAL_CTL 0xca0 | 236 | #define NHMEX_M0_MSR_GLOBAL_CTL 0xca0 |