10 #include <linux/perf_event.h>
13 #include <asm/hardirq.h>
18 #define P4_CNTR_LIMIT 3
36 #define P4_GEN_PEBS_BIND(name, pebs, vert) \
37 [P4_PEBS_METRIC__##name] = { \
38 .metric_pebs = pebs | P4_PEBS_ENABLE_UOP_TAG, \
39 .metric_vert = vert, \
84 .cntr = { {4, 5, -1}, {6, 7, -1} },
91 .cntr = { {0, -1, -1}, {2, -1, -1} },
100 .cntr = { {0, -1, -1}, {2, -1, -1} },
108 .cntr = { {8, 9, -1}, {10, 11, -1} },
116 .cntr = { {8, 9, -1}, {10, 11, -1} },
123 .cntr = { {8, 9, -1}, {10, 11, -1} },
130 .cntr = { {8, 9, -1}, {10, 11, -1} },
140 .cntr = { {0, -1, -1}, {2, -1, -1} },
149 .cntr = { {0, -1, -1}, {2, -1, -1} },
164 .cntr = { {0, -1, -1}, {2, -1, -1} },
181 .cntr = { {0, -1, -1}, {2, -1, -1} },
198 .cntr = { {2, -1, -1}, {3, -1, -1} },
211 .cntr = { {0, -1, -1}, {2, -1, -1} },
230 .cntr = { {0, -1, -1}, {1, -1, -1} },
249 .cntr = { {2, -1, -1}, {3, -1, -1} },
257 .cntr = { {8, 9, -1}, {10, 11, -1} },
265 .cntr = { {8, 9, -1}, {10, 11, -1} },
273 .cntr = { {8, 9, -1}, {10, 11, -1} },
281 .cntr = { {8, 9, -1}, {10, 11, -1} },
289 .cntr = { {8, 9, -1}, {10, 11, -1} },
297 .cntr = { {8, 9, -1}, {10, 11, -1} },
305 .cntr = { {8, 9, -1}, {10, 11, -1} },
313 .cntr = { {8, 9, -1}, {10, 11, -1} },
320 .cntr = { {4, 5, -1}, {6, 7, -1} },
327 .cntr = { {0, -1, -1}, {2, -1, -1} },
334 .cntr = { {4, 5, -1}, {6, 7, -1} },
343 .cntr = { {4, 5, -1}, {6, 7, -1} },
353 .cntr = { {4, 5, -1}, {6, 7, -1} },
363 .cntr = { {4, 5, -1}, {6, 7, -1} },
370 .cntr = { {12, 13, 16}, {14, 15, 17} },
379 .cntr = { {8, 9, -1}, {10, 11, -1} },
385 .cntr = { {0, -1, -1}, {2, -1, -1} },
391 .cntr = { {0, -1, -1}, {2, -1, -1} },
397 .cntr = { {0, -1, -1}, {2, -1, -1} },
403 .cntr = { {0, -1, -1}, {2, -1, -1} },
411 .cntr = { {12, 13, 16}, {14, 15, 17} },
425 .cntr = { {12, 13, 16}, {14, 15, 17} },
433 .cntr = { {12, 13, 16}, {14, 15, 17} },
443 .cntr = { {12, 13, 16}, {14, 15, 17} },
451 .cntr = { {12, 13, 16}, {14, 15, 17} },
459 .cntr = { {12, 13, 16}, {14, 15, 17} },
469 .cntr = { {12, 13, 16}, {14, 15, 17} },
476 .cntr = { {12, 13, 16}, {14, 15, 17} },
487 .cntr = { {12, 13, 16}, {14, 15, 17} },
496 .cntr = { {12, 13, 16}, {14, 15, 17} },
504 .cntr = { {12, 13, 16}, {14, 15, 17} },
508 #define P4_GEN_CACHE_EVENT(event, bit, metric) \
509 p4_config_pack_escr(P4_ESCR_EVENT(event) | \
510 P4_ESCR_EMASK_BIT(event, bit)) | \
511 p4_config_pack_cccr(metric | \
512 P4_CCCR_ESEL(P4_OPCODE_ESEL(P4_OPCODE(event))))
521 [
C(RESULT_ACCESS) ] = 0x0,
528 [
C(RESULT_ACCESS) ] = 0x0,
535 [
C(RESULT_ACCESS) ] = 0x0,
540 [
C(RESULT_ACCESS) ] = 0x0,
553 [
C(RESULT_ACCESS) ] = -1,
554 [
C(RESULT_MISS) ] = -1,
556 [
C(OP_PREFETCH) ] = {
557 [
C(RESULT_ACCESS) ] = -1,
558 [
C(RESULT_MISS) ] = -1,
563 [
C(RESULT_ACCESS) ] = -1,
564 [
C(RESULT_MISS) ] = -1,
567 [
C(RESULT_ACCESS) ] = -1,
568 [
C(RESULT_MISS) ] = -1,
570 [
C(OP_PREFETCH) ] = {
571 [
C(RESULT_ACCESS) ] = -1,
572 [
C(RESULT_MISS) ] = -1,
711 bind = &p4_event_bind_map[evnt];
716 static u64 p4_pmu_event_map(
int hw_event)
722 config = p4_general_events[hw_event];
723 bind = p4_config_get_bind(config);
731 static bool p4_event_match_cpu_model(
unsigned int event_idx)
751 unsigned int v, emask;
759 if (!p4_event_match_cpu_model(v))
778 if (p4_ht_active() && p4_event_bind_map[v].
shared) {
801 static int p4_hw_config(
struct perf_event *event)
813 cccr = p4_default_cccr_conf(cpu);
814 escr = p4_default_escr_conf(cpu, event->
attr.exclude_kernel,
815 event->
attr.exclude_user);
819 if (p4_ht_active() && p4_ht_thread(cpu))
820 event->hw.config = p4_set_ht_bit(event->hw.config);
831 rc = p4_validate_raw_event(event);
839 event->hw.config |=
event->attr.config;
840 bind = p4_config_get_bind(event->
attr.config);
855 static inline int p4_pmu_clear_cccr_ovf(
struct hw_perf_event *hwc)
860 rdmsrl(hwc->config_base, v);
862 wrmsrl(hwc->config_base, v & ~P4_CCCR_OVF);
873 rdmsrl(hwc->event_base, v);
880 static void p4_pmu_disable_pebs(
void)
903 static inline void p4_pmu_disable_event(
struct perf_event *event)
912 (
void)wrmsrl_safe(hwc->config_base,
917 static void p4_pmu_disable_all(
void)
926 p4_pmu_disable_event(event);
929 p4_pmu_disable_pebs();
933 static void p4_pmu_enable_pebs(
u64 config)
944 bind = &p4_pebs_bind_map[
idx];
950 static void p4_pmu_enable_event(
struct perf_event *event)
953 int thread = p4_ht_config_thread(hwc->config);
959 bind = &p4_event_bind_map[
idx];
979 p4_pmu_enable_pebs(hwc->config);
981 (
void)wrmsrl_safe(escr_addr, escr_conf);
982 (
void)wrmsrl_safe(hwc->config_base,
986 static void p4_pmu_enable_all(
int added)
995 p4_pmu_enable_event(event);
1001 struct perf_sample_data
data;
1005 int idx, handled = 0;
1026 overflow = p4_pmu_clear_cccr_ovf(hwc);
1035 perf_sample_data_init(&
data, 0, hwc->last_period);
1067 static void p4_pmu_swap_config_ts(
struct hw_perf_event *hwc,
int cpu)
1074 if (!p4_should_swap_ts(hwc->config, cpu))
1085 if (p4_ht_thread(cpu)) {
1089 escr &= ~P4_ESCR_T0_OS;
1093 escr &= ~P4_ESCR_T0_USR;
1103 escr &= ~P4_ESCR_T1_OS;
1107 escr &= ~P4_ESCR_T1_USR;
1124 #define P4_ESCR_MSR_BASE 0x000003a0
1125 #define P4_ESCR_MSR_MAX 0x000003e1
1126 #define P4_ESCR_MSR_TABLE_SIZE (P4_ESCR_MSR_MAX - P4_ESCR_MSR_BASE + 1)
1127 #define P4_ESCR_MSR_IDX(msr) (msr - P4_ESCR_MSR_BASE)
1128 #define P4_ESCR_MSR_TABLE_ENTRY(msr) [P4_ESCR_MSR_IDX(msr)] = msr
1179 static int p4_get_escr_idx(
unsigned int addr)
1184 !p4_escr_table[idx] ||
1185 p4_escr_table[idx] != addr)) {
1186 WARN_ONCE(1,
"P4 PMU: Wrong address passed: %x\n", addr);
1193 static int p4_next_cntr(
int thread,
unsigned long *used_mask,
1200 if (j != -1 && !
test_bit(j, used_mask))
1207 static int p4_pmu_schedule_events(
struct cpu_hw_events *cpuc,
int n,
int *assign)
1215 int cntr_idx, escr_idx;
1222 for (i = 0, num = n; i <
n; i++, num--) {
1225 thread = p4_ht_thread(cpu);
1237 bind = p4_config_get_bind(hwc->config);
1238 escr_idx = p4_get_escr_idx(bind->
escr_msr[thread]);
1242 if (hwc->idx != -1 && !p4_should_swap_ts(hwc->config, cpu)) {
1243 cntr_idx = hwc->idx;
1245 assign[
i] = hwc->idx;
1249 cntr_idx = p4_next_cntr(thread, used_mask, bind);
1250 if (cntr_idx == -1 ||
test_bit(escr_idx, escr_mask)) {
1254 config_alias = p4_get_alias_event(hwc->config);
1257 hwc->config = config_alias;
1262 p4_pmu_swap_config_ts(hwc, cpu);
1264 assign[
i] = cntr_idx;
1271 return num ? -
EINVAL : 0;
1278 static struct attribute *intel_p4_formats_attr[] = {
1279 &format_attr_cccr.attr,
1280 &format_attr_escr.attr,
1281 &format_attr_ht.attr,
1286 .name =
"Netburst P4/Xeon",
1287 .handle_irq = p4_pmu_handle_irq,
1288 .disable_all = p4_pmu_disable_all,
1289 .enable_all = p4_pmu_enable_all,
1290 .enable = p4_pmu_enable_event,
1291 .disable = p4_pmu_disable_event,
1294 .event_map = p4_pmu_event_map,
1308 .hw_config = p4_hw_config,
1309 .schedule_events = p4_pmu_schedule_events,
1318 .perfctr_second_write = 1,
1320 .format_attrs = intel_p4_formats_attr,
1331 if (!(low & (1 << 7))) {
1332 pr_cont(
"unsupported Netburst CPU model %d ",