18cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd/**
28cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * @file op_model_p4.c
38cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * P4 model-specific MSR operations
48cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd *
58cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * @remark Copyright 2002 OProfile authors
68cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * @remark Read the file COPYING
78cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd *
88cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * @author Graydon Hoare
98cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd */
108cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
118cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include "op_x86_model.h"
128cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include "op_msr.h"
138cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include "op_apic.h"
148cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include "op_arch.h"
158cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
168cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#define NUM_EVENTS 39
178cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
188cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#define NUM_COUNTERS_NON_HT 8
198cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#define NUM_ESCRS_NON_HT 45
208cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#define NUM_CCCRS_NON_HT 18
218cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#define NUM_CONTROLS_NON_HT (NUM_ESCRS_NON_HT + NUM_CCCRS_NON_HT)
228cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
238cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#define NUM_COUNTERS_HT2 4
248cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#define NUM_ESCRS_HT2 23
258cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#define NUM_CCCRS_HT2 9
268cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#define NUM_CONTROLS_HT2 (NUM_ESCRS_HT2 + NUM_CCCRS_HT2)
278cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
288cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddstatic unsigned int num_counters = NUM_COUNTERS_NON_HT;
298cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
308cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
318cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd/* this has to be checked dynamically since the
328cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd   hyper-threadedness of a chip is discovered at
338cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd   kernel boot-time. */
348cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddstatic inline void setup_num_counters(void)
358cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{
368cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#ifdef HT_SUPPORT
378cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	if (smp_num_siblings == 2)
388cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		num_counters = NUM_COUNTERS_HT2;
398cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#endif
408cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd}
418cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
428cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddstatic int inline addr_increment(void)
438cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{
448cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#ifdef HT_SUPPORT
458cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	return smp_num_siblings == 2 ? 2 : 1;
468cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#else
478cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	return 1;
488cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#endif
498cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd}
508cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
518cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
528cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd/* tables to simulate simplified hardware view of p4 registers */
538cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddstruct p4_counter_binding {
548cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	int virt_counter;
558cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	int counter_address;
568cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	int cccr_address;
578cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd};
588cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
598cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddstruct p4_event_binding {
608cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	/* value to put in CCCR */
618cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	int escr_select;
628cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	/* value to put in ESCR */
638cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	int event_select;
648cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	struct {
658cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		/* for this counter... */
668cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		int virt_counter;
678cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		/* use this ESCR       */
688cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		int escr_address;
698cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	} bindings[2];
708cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd};
718cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
728cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd/* nb: these CTR_* defines are a duplicate of defines in
738cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd   event/i386.p4*events. */
748cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
758cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
768cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#define CTR_BPU_0      (1 << 0)
778cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#define CTR_MS_0       (1 << 1)
788cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#define CTR_FLAME_0    (1 << 2)
798cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#define CTR_IQ_4       (1 << 3)
808cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#define CTR_BPU_2      (1 << 4)
818cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#define CTR_MS_2       (1 << 5)
828cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#define CTR_FLAME_2    (1 << 6)
838cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#define CTR_IQ_5       (1 << 7)
848cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
858cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddstatic struct p4_counter_binding p4_counters[NUM_COUNTERS_NON_HT] = {
868cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	{ CTR_BPU_0,   MSR_P4_BPU_PERFCTR0,   MSR_P4_BPU_CCCR0 },
878cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	{ CTR_MS_0,    MSR_P4_MS_PERFCTR0,    MSR_P4_MS_CCCR0 },
888cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	{ CTR_FLAME_0, MSR_P4_FLAME_PERFCTR0, MSR_P4_FLAME_CCCR0 },
898cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	{ CTR_IQ_4,    MSR_P4_IQ_PERFCTR4,    MSR_P4_IQ_CCCR4 },
908cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	{ CTR_BPU_2,   MSR_P4_BPU_PERFCTR2,   MSR_P4_BPU_CCCR2 },
918cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	{ CTR_MS_2,    MSR_P4_MS_PERFCTR2,    MSR_P4_MS_CCCR2 },
928cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	{ CTR_FLAME_2, MSR_P4_FLAME_PERFCTR2, MSR_P4_FLAME_CCCR2 },
938cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	{ CTR_IQ_5,    MSR_P4_IQ_PERFCTR5,    MSR_P4_IQ_CCCR5 }
948cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd};
958cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
968cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#define NUM_UNUSED_CCCRS	NUM_CCCRS_NON_HT - NUM_COUNTERS_NON_HT
978cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
988cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd/* All cccr we don't use. */
998cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddstatic int p4_unused_cccr[NUM_UNUSED_CCCRS] = {
1008cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	MSR_P4_BPU_CCCR1, 	MSR_P4_BPU_CCCR3,
1018cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	MSR_P4_MS_CCCR1, 	MSR_P4_MS_CCCR3,
1028cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	MSR_P4_FLAME_CCCR1, 	MSR_P4_FLAME_CCCR3,
1038cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	MSR_P4_IQ_CCCR0, 	MSR_P4_IQ_CCCR1,
1048cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	MSR_P4_IQ_CCCR2, 	MSR_P4_IQ_CCCR3
1058cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd};
1068cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1078cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd/* p4 event codes in libop/op_event.h are indices into this table. */
1088cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1098cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddstatic struct p4_event_binding p4_events[NUM_EVENTS] = {
1108cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1118cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	{ /* BRANCH_RETIRED */
1128cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		0x05, 0x06,
1138cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		{ {CTR_IQ_4, MSR_P4_CRU_ESCR2},
1148cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		  {CTR_IQ_5, MSR_P4_CRU_ESCR3} }
1158cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	},
1168cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1178cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	{ /* MISPRED_BRANCH_RETIRED */
1188cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		0x04, 0x03,
1198cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		{ { CTR_IQ_4, MSR_P4_CRU_ESCR0},
1208cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		  { CTR_IQ_5, MSR_P4_CRU_ESCR1} }
1218cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	},
1228cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1238cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	{ /* TC_DELIVER_MODE */
1248cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		0x01, 0x01,
1258cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		{ { CTR_MS_0, MSR_P4_TC_ESCR0},
1268cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		  { CTR_MS_2, MSR_P4_TC_ESCR1} }
1278cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	},
1288cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1298cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	{ /* BPU_FETCH_REQUEST */
1308cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		0x00, 0x03,
1318cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		{ { CTR_BPU_0, MSR_P4_BPU_ESCR0},
1328cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		  { CTR_BPU_2, MSR_P4_BPU_ESCR1} }
1338cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	},
1348cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1358cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	{ /* ITLB_REFERENCE */
1368cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		0x03, 0x18,
1378cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		{ { CTR_BPU_0, MSR_P4_ITLB_ESCR0},
1388cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		  { CTR_BPU_2, MSR_P4_ITLB_ESCR1} }
1398cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	},
1408cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1418cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	{ /* MEMORY_CANCEL */
1428cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		0x05, 0x02,
1438cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		{ { CTR_FLAME_0, MSR_P4_DAC_ESCR0},
1448cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		  { CTR_FLAME_2, MSR_P4_DAC_ESCR1} }
1458cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	},
1468cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1478cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	{ /* MEMORY_COMPLETE */
1488cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		0x02, 0x08,
1498cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		{ { CTR_FLAME_0, MSR_P4_SAAT_ESCR0},
1508cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		  { CTR_FLAME_2, MSR_P4_SAAT_ESCR1} }
1518cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	},
1528cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1538cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	{ /* LOAD_PORT_REPLAY */
1548cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		0x02, 0x04,
1558cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		{ { CTR_FLAME_0, MSR_P4_SAAT_ESCR0},
1568cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		  { CTR_FLAME_2, MSR_P4_SAAT_ESCR1} }
1578cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	},
1588cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1598cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	{ /* STORE_PORT_REPLAY */
1608cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		0x02, 0x05,
1618cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		{ { CTR_FLAME_0, MSR_P4_SAAT_ESCR0},
1628cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		  { CTR_FLAME_2, MSR_P4_SAAT_ESCR1} }
1638cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	},
1648cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1658cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	{ /* MOB_LOAD_REPLAY */
1668cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		0x02, 0x03,
1678cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		{ { CTR_BPU_0, MSR_P4_MOB_ESCR0},
1688cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		  { CTR_BPU_2, MSR_P4_MOB_ESCR1} }
1698cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	},
1708cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1718cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	{ /* PAGE_WALK_TYPE */
1728cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		0x04, 0x01,
1738cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		{ { CTR_BPU_0, MSR_P4_PMH_ESCR0},
1748cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		  { CTR_BPU_2, MSR_P4_PMH_ESCR1} }
1758cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	},
1768cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1778cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	{ /* BSQ_CACHE_REFERENCE */
1788cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		0x07, 0x0c,
1798cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		{ { CTR_BPU_0, MSR_P4_BSU_ESCR0},
1808cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		  { CTR_BPU_2, MSR_P4_BSU_ESCR1} }
1818cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	},
1828cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1838cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	/* intel doc vol 3 table A-1: P4 and xeon with cpuid signature < 0xf27
1848cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 * doen't allow MSR_FSB_ESCR1 so only counter 0 is available */
1858cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	{ /* IOQ_ALLOCATION */
1868cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		0x06, 0x03,
1878cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		{ { CTR_BPU_0, MSR_P4_FSB_ESCR0},
1888cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		  { 0, 0 } }
1898cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	},
1908cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1918cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	{ /* IOQ_ACTIVE_ENTRIES */
1928cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		0x06, 0x1a,
1938cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		{ { CTR_BPU_2, MSR_P4_FSB_ESCR1},
1948cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		  { 0, 0 } }
1958cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	},
1968cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1978cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	{ /* FSB_DATA_ACTIVITY */
1988cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		0x06, 0x17,
1998cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		{ { CTR_BPU_0, MSR_P4_FSB_ESCR0},
2008cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		  { CTR_BPU_2, MSR_P4_FSB_ESCR1} }
2018cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	},
2028cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
2038cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	{ /* BSQ_ALLOCATION */
2048cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		0x07, 0x05,
2058cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		{ { CTR_BPU_0, MSR_P4_BSU_ESCR0},
2068cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		  { 0, 0 } }
2078cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	},
2088cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
2098cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	{ /* BSQ_ACTIVE_ENTRIES */
2108cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		0x07, 0x06,
2118cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		/* FIXME intel doc don't say which ESCR1 to use, using
2128cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		   BSU_ESCR1 is a sensible guess but will need validation */
2138cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		{ { CTR_BPU_2, MSR_P4_BSU_ESCR1 },
2148cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		  { 0, 0 } }
2158cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	},
2168cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
2178cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	{ /* X87_ASSIST */
2188cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		0x05, 0x03,
2198cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		{ { CTR_IQ_4, MSR_P4_CRU_ESCR2},
2208cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		  { CTR_IQ_5, MSR_P4_CRU_ESCR3} }
2218cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	},
2228cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
2238cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	{ /* SSE_INPUT_ASSIST */
2248cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		0x01, 0x34,
2258cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		{ { CTR_FLAME_0, MSR_P4_FIRM_ESCR0},
2268cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		  { CTR_FLAME_2, MSR_P4_FIRM_ESCR1} }
2278cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	},
2288cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
2298cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	{ /* PACKED_SP_UOP */
2308cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		0x01, 0x08,
2318cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		{ { CTR_FLAME_0, MSR_P4_FIRM_ESCR0},
2328cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		  { CTR_FLAME_2, MSR_P4_FIRM_ESCR1} }
2338cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	},
2348cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
2358cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	{ /* PACKED_DP_UOP */
2368cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		0x01, 0x0c,
2378cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		{ { CTR_FLAME_0, MSR_P4_FIRM_ESCR0},
2388cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		  { CTR_FLAME_2, MSR_P4_FIRM_ESCR1} }
2398cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	},
2408cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
2418cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	{ /* SCALAR_SP_UOP */
2428cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		0x01, 0x0a,
2438cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		{ { CTR_FLAME_0, MSR_P4_FIRM_ESCR0},
2448cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		  { CTR_FLAME_2, MSR_P4_FIRM_ESCR1} }
2458cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	},
2468cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
2478cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	{ /* SCALAR_DP_UOP */
2488cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		0x01, 0x0e,
2498cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		{ { CTR_FLAME_0, MSR_P4_FIRM_ESCR0},
2508cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		  { CTR_FLAME_2, MSR_P4_FIRM_ESCR1} }
2518cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	},
2528cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
2538cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	{ /* 64BIT_MMX_UOP */
2548cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		0x01, 0x02,
2558cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		{ { CTR_FLAME_0, MSR_P4_FIRM_ESCR0},
2568cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		  { CTR_FLAME_2, MSR_P4_FIRM_ESCR1} }
2578cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	},
2588cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
2598cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	{ /* 128BIT_MMX_UOP */
2608cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		0x01, 0x1a,
2618cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		{ { CTR_FLAME_0, MSR_P4_FIRM_ESCR0},
2628cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		  { CTR_FLAME_2, MSR_P4_FIRM_ESCR1} }
2638cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	},
2648cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
2658cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	{ /* X87_FP_UOP */
2668cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		0x01, 0x04,
2678cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		{ { CTR_FLAME_0, MSR_P4_FIRM_ESCR0},
2688cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		  { CTR_FLAME_2, MSR_P4_FIRM_ESCR1} }
2698cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	},
2708cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
2718cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	{ /* X87_SIMD_MOVES_UOP */
2728cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		0x01, 0x2e,
2738cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		{ { CTR_FLAME_0, MSR_P4_FIRM_ESCR0},
2748cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		  { CTR_FLAME_2, MSR_P4_FIRM_ESCR1} }
2758cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	},
2768cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
2778cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	{ /* MACHINE_CLEAR */
2788cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		0x05, 0x02,
2798cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		{ { CTR_IQ_4, MSR_P4_CRU_ESCR2},
2808cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		  { CTR_IQ_5, MSR_P4_CRU_ESCR3} }
2818cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	},
2828cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
2838cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	{ /* GLOBAL_POWER_EVENTS */
2848cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		0x06, 0x13 /* older manual says 0x05, newer 0x13 */,
2858cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		{ { CTR_BPU_0, MSR_P4_FSB_ESCR0},
2868cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		  { CTR_BPU_2, MSR_P4_FSB_ESCR1} }
2878cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	},
2888cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
2898cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	{ /* TC_MS_XFER */
2908cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		0x00, 0x05,
2918cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		{ { CTR_MS_0, MSR_P4_MS_ESCR0},
2928cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		  { CTR_MS_2, MSR_P4_MS_ESCR1} }
2938cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	},
2948cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
2958cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	{ /* UOP_QUEUE_WRITES */
2968cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		0x00, 0x09,
2978cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		{ { CTR_MS_0, MSR_P4_MS_ESCR0},
2988cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		  { CTR_MS_2, MSR_P4_MS_ESCR1} }
2998cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	},
3008cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
3018cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	{ /* FRONT_END_EVENT */
3028cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		0x05, 0x08,
3038cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		{ { CTR_IQ_4, MSR_P4_CRU_ESCR2},
3048cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		  { CTR_IQ_5, MSR_P4_CRU_ESCR3} }
3058cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	},
3068cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
3078cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	{ /* EXECUTION_EVENT */
3088cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		0x05, 0x0c,
3098cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		{ { CTR_IQ_4, MSR_P4_CRU_ESCR2},
3108cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		  { CTR_IQ_5, MSR_P4_CRU_ESCR3} }
3118cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	},
3128cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
3138cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	{ /* REPLAY_EVENT */
3148cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		0x05, 0x09,
3158cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		{ { CTR_IQ_4, MSR_P4_CRU_ESCR2},
3168cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		  { CTR_IQ_5, MSR_P4_CRU_ESCR3} }
3178cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	},
3188cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
3198cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	{ /* INSTR_RETIRED */
3208cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		0x04, 0x02,
3218cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		{ { CTR_IQ_4, MSR_P4_CRU_ESCR0},
3228cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		  { CTR_IQ_5, MSR_P4_CRU_ESCR1} }
3238cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	},
3248cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
3258cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	{ /* UOPS_RETIRED */
3268cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		0x04, 0x01,
3278cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		{ { CTR_IQ_4, MSR_P4_CRU_ESCR0},
3288cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		  { CTR_IQ_5, MSR_P4_CRU_ESCR1} }
3298cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	},
3308cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
3318cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	{ /* UOP_TYPE */
3328cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		0x02, 0x02,
3338cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		{ { CTR_IQ_4, MSR_P4_RAT_ESCR0},
3348cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		  { CTR_IQ_5, MSR_P4_RAT_ESCR1} }
3358cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	},
3368cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
3378cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	{ /* RETIRED_MISPRED_BRANCH_TYPE */
3388cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		0x02, 0x05,
3398cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		{ { CTR_MS_0, MSR_P4_TBPU_ESCR0},
3408cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		  { CTR_MS_2, MSR_P4_TBPU_ESCR1} }
3418cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	},
3428cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
3438cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	{ /* RETIRED_BRANCH_TYPE */
3448cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		0x02, 0x04,
3458cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		{ { CTR_MS_0, MSR_P4_TBPU_ESCR0},
3468cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		  { CTR_MS_2, MSR_P4_TBPU_ESCR1} }
3478cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	}
3488cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd};
3498cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
3508cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
3518cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#define MISC_PMC_ENABLED_P(x) ((x) & 1 << 7)
3528cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
3538cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#define ESCR_RESERVED_BITS 0x80000003
3548cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#define ESCR_CLEAR(escr) ((escr) &= ESCR_RESERVED_BITS)
3558cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#define ESCR_SET_USR_0(escr, usr) ((escr) |= (((usr) & 1) << 2))
3568cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#define ESCR_SET_OS_0(escr, os) ((escr) |= (((os) & 1) << 3))
3578cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#define ESCR_SET_USR_1(escr, usr) ((escr) |= (((usr) & 1)))
3588cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#define ESCR_SET_OS_1(escr, os) ((escr) |= (((os) & 1) << 1))
3598cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#define ESCR_SET_EVENT_SELECT(escr, sel) ((escr) |= (((sel) & 0x3f) << 25))
3608cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#define ESCR_SET_EVENT_MASK(escr, mask) ((escr) |= (((mask) & 0xffff) << 9))
3618cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#define ESCR_READ(escr, high, ev, i) do {rdmsr(ev->bindings[(i)].escr_address, (escr), (high));} while (0)
3628cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#define ESCR_WRITE(escr, high, ev, i) do {wrmsr(ev->bindings[(i)].escr_address, (escr), (high));} while (0)
3638cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
3648cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#define CCCR_RESERVED_BITS 0x38030FFF
3658cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#define CCCR_CLEAR(cccr) ((cccr) &= CCCR_RESERVED_BITS)
3668cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#define CCCR_SET_REQUIRED_BITS(cccr) ((cccr) |= 0x00030000)
3678cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#define CCCR_SET_ESCR_SELECT(cccr, sel) ((cccr) |= (((sel) & 0x07) << 13))
3688cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#define CCCR_SET_PMI_OVF_0(cccr) ((cccr) |= (1 << 26))
3698cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#define CCCR_SET_PMI_OVF_1(cccr) ((cccr) |= (1 << 27))
3708cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#define CCCR_SET_ENABLE(cccr) ((cccr) |= (1 << 12))
3718cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#define CCCR_SET_DISABLE(cccr) ((cccr) &= ~(1 << 12))
3728cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#define CCCR_READ(low, high, i) do {rdmsr(p4_counters[(i)].cccr_address, (low), (high));} while (0)
3738cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#define CCCR_WRITE(low, high, i) do {wrmsr(p4_counters[(i)].cccr_address, (low), (high));} while (0)
3748cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#define CCCR_OVF_P(cccr) ((cccr) & (1U << 31))
3758cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#define CCCR_CLEAR_OVF(cccr) ((cccr) &= (~(1U << 31)))
3768cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
3778cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#define CTR_READ(l, h, i) do {rdmsr(p4_counters[(i)].counter_address, (l), (h));} while (0)
3788cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#define CTR_WRITE(l, i) do {wrmsr(p4_counters[(i)].counter_address, -(u32)(l), -1);} while (0)
3798cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#define CTR_OVERFLOW_P(ctr) (!((ctr) & 0x80000000))
3808cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
3818cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
3828cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd/* this assigns a "stagger" to the current CPU, which is used throughout
3838cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd   the code in this module as an extra array offset, to select the "even"
3848cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd   or "odd" part of all the divided resources. */
3858cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddstatic unsigned int get_stagger(void)
3868cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{
3878cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#ifdef HT_SUPPORT
3888cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	int cpu;
3898cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	if (smp_num_siblings > 1) {
3908cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		cpu = smp_processor_id();
3918cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		return (cpu_sibling_map[cpu] > cpu) ? 0 : 1;
3928cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	}
3938cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#endif
3948cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	return 0;
3958cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd}
3968cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
3978cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
3988cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd/* finally, mediate access to a real hardware counter
3998cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd   by passing a "virtual" counter numer to this macro,
4008cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd   along with your stagger setting. */
4018cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#define VIRT_CTR(stagger, i) ((i) + ((num_counters) * (stagger)))
4028cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
4038cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
4048cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddstatic void p4_fill_in_addresses(struct op_msrs * const msrs)
4058cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{
4068cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	unsigned int i;
4078cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	unsigned int addr, stag;
4088cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
4098cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	setup_num_counters();
4108cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	stag = get_stagger();
4118cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
4128cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	/* the counter registers we pay attention to */
4138cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	for (i = 0; i < num_counters; ++i) {
4148cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		msrs->counters.addrs[i] =
4158cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			p4_counters[VIRT_CTR(stag, i)].counter_address;
4168cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	}
4178cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
4188cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	/* FIXME: bad feeling, we don't save the 10 counters we don't use. */
4198cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
4208cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	/* 18 CCCR registers */
4218cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	for (i = 0, addr = MSR_P4_BPU_CCCR0 + stag;
4228cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	     addr <= MSR_P4_IQ_CCCR5; ++i, addr += addr_increment()) {
4238cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		msrs->controls.addrs[i] = addr;
4248cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	}
4258cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
4268cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	/* 43 ESCR registers in three or four discontiguous group */
4278cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	for (addr = MSR_P4_BSU_ESCR0 + stag;
4288cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	     addr < MSR_P4_IQ_ESCR0; ++i, addr += addr_increment()) {
4298cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		msrs->controls.addrs[i] = addr;
4308cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	}
4318cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
4328cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	/* no IQ_ESCR0/1 on some models, we save a seconde time BSU_ESCR0/1
4338cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 * to avoid special case in nmi_{save|restore}_registers() */
4348cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	if (boot_cpu_data.x86_model >= 0x3) {
4358cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		for (addr = MSR_P4_BSU_ESCR0 + stag;
4368cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		     addr <= MSR_P4_BSU_ESCR1; ++i, addr += addr_increment()) {
4378cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			msrs->controls.addrs[i] = addr;
4388cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		}
4398cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	} else {
4408cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		for (addr = MSR_P4_IQ_ESCR0 + stag;
4418cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		     addr <= MSR_P4_IQ_ESCR1; ++i, addr += addr_increment()) {
4428cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			msrs->controls.addrs[i] = addr;
4438cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		}
4448cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	}
4458cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
4468cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	for (addr = MSR_P4_RAT_ESCR0 + stag;
4478cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	     addr <= MSR_P4_SSU_ESCR0; ++i, addr += addr_increment()) {
4488cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		msrs->controls.addrs[i] = addr;
4498cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	}
4508cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
4518cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	for (addr = MSR_P4_MS_ESCR0 + stag;
4528cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	     addr <= MSR_P4_TC_ESCR1; ++i, addr += addr_increment()) {
4538cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		msrs->controls.addrs[i] = addr;
4548cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	}
4558cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
4568cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	for (addr = MSR_P4_IX_ESCR0 + stag;
4578cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	     addr <= MSR_P4_CRU_ESCR3; ++i, addr += addr_increment()) {
4588cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		msrs->controls.addrs[i] = addr;
4598cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	}
4608cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
4618cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	/* there are 2 remaining non-contiguously located ESCRs */
4628cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
4638cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	if (num_counters == NUM_COUNTERS_NON_HT) {
4648cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		/* standard non-HT CPUs handle both remaining ESCRs*/
4658cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		msrs->controls.addrs[i++] = MSR_P4_CRU_ESCR5;
4668cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		msrs->controls.addrs[i++] = MSR_P4_CRU_ESCR4;
4678cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
4688cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	} else if (stag == 0) {
4698cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		/* HT CPUs give the first remainder to the even thread, as
4708cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		   the 32nd control register */
4718cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		msrs->controls.addrs[i++] = MSR_P4_CRU_ESCR4;
4728cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
4738cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	} else {
4748cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		/* and two copies of the second to the odd thread,
4758cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		   for the 22st and 23nd control registers */
4768cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		msrs->controls.addrs[i++] = MSR_P4_CRU_ESCR5;
4778cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		msrs->controls.addrs[i++] = MSR_P4_CRU_ESCR5;
4788cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	}
4798cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd}
4808cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
4818cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
4828cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddstatic void pmc_setup_one_p4_counter(unsigned int ctr)
4838cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{
4848cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	int i;
4858cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	int const maxbind = 2;
4868cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	unsigned int cccr = 0;
4878cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	unsigned int escr = 0;
4888cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	unsigned int high = 0;
4898cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	unsigned int counter_bit;
4908cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	struct p4_event_binding * ev = NULL;
4918cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	unsigned int stag;
4928cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
4938cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	stag = get_stagger();
4948cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
4958cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	/* convert from counter *number* to counter *bit* */
4968cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	counter_bit = 1 << VIRT_CTR(stag, ctr);
4978cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
4988cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	/* find our event binding structure. */
4998cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	if (sysctl.ctr[ctr].event <= 0 || sysctl.ctr[ctr].event > NUM_EVENTS) {
5008cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		printk(KERN_ERR
5018cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		       "oprofile: P4 event code 0x%x out of range\n",
5028cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		       sysctl.ctr[ctr].event);
5038cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		return;
5048cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	}
5058cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
5068cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	ev = &(p4_events[sysctl.ctr[ctr].event - 1]);
5078cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
5088cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	for (i = 0; i < maxbind; i++) {
5098cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		if (ev->bindings[i].virt_counter & counter_bit) {
5108cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
5118cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			/* modify ESCR */
5128cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			ESCR_READ(escr, high, ev, i);
5138cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			ESCR_CLEAR(escr);
5148cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			if (stag == 0) {
5158cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd				ESCR_SET_USR_0(escr, sysctl.ctr[ctr].user);
5168cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd				ESCR_SET_OS_0(escr, sysctl.ctr[ctr].kernel);
5178cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			} else {
5188cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd				ESCR_SET_USR_1(escr, sysctl.ctr[ctr].user);
5198cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd				ESCR_SET_OS_1(escr, sysctl.ctr[ctr].kernel);
5208cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			}
5218cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			ESCR_SET_EVENT_SELECT(escr, ev->event_select);
5228cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			ESCR_SET_EVENT_MASK(escr, sysctl.ctr[ctr].unit_mask);
5238cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			ESCR_WRITE(escr, high, ev, i);
5248cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
5258cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			/* modify CCCR */
5268cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			CCCR_READ(cccr, high, VIRT_CTR(stag, ctr));
5278cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			CCCR_CLEAR(cccr);
5288cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			CCCR_SET_REQUIRED_BITS(cccr);
5298cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			CCCR_SET_ESCR_SELECT(cccr, ev->escr_select);
5308cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			if (stag == 0) {
5318cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd				CCCR_SET_PMI_OVF_0(cccr);
5328cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			} else {
5338cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd				CCCR_SET_PMI_OVF_1(cccr);
5348cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			}
5358cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			CCCR_WRITE(cccr, high, VIRT_CTR(stag, ctr));
5368cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			return;
5378cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		}
5388cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	}
5398cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
5408cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	printk(KERN_ERR
5418cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	       "oprofile: P4 event code 0x%x no binding, ctr %d\n",
5428cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	       sysctl.ctr[ctr].event, ctr);
5438cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd}
5448cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
5458cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
5468cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddstatic void p4_setup_ctrs(struct op_msrs const * const msrs)
5478cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{
5488cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	unsigned int i;
5498cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	unsigned int low, high;
5508cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	unsigned int addr;
5518cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	unsigned int stag;
5528cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
5538cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	stag = get_stagger();
5548cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
5558cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	rdmsr(MSR_IA32_MISC_ENABLE, low, high);
5568cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	if (!MISC_PMC_ENABLED_P(low)) {
5578cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		printk(KERN_ERR "oprofile: P4 PMC not available\n");
5588cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		return;
5598cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	}
5608cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
5618cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	/* clear the cccrs we will use */
5628cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	for (i = 0 ; i < num_counters ; i++) {
5638cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		rdmsr(p4_counters[VIRT_CTR(stag, i)].cccr_address, low, high);
5648cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		CCCR_CLEAR(low);
5658cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		CCCR_SET_REQUIRED_BITS(low);
5668cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		wrmsr(p4_counters[VIRT_CTR(stag, i)].cccr_address, low, high);
5678cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	}
5688cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
5698cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	/* clear cccrs outside our concern */
5708cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	for (i = stag ; i < NUM_UNUSED_CCCRS ; i += addr_increment()) {
5718cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		rdmsr(p4_unused_cccr[i], low, high);
5728cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		CCCR_CLEAR(low);
5738cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		CCCR_SET_REQUIRED_BITS(low);
5748cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		wrmsr(p4_unused_cccr[i], low, high);
5758cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	}
5768cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
5778cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	/* clear all escrs (including those outside our concern) */
5788cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	for (addr = MSR_P4_BSU_ESCR0 + stag;
5798cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	     addr <  MSR_P4_IQ_ESCR0; addr += addr_increment()) {
5808cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		wrmsr(addr, 0, 0);
5818cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	}
5828cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
5838cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	/* On older models clear also MSR_P4_IQ_ESCR0/1 */
5848cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	if (boot_cpu_data.x86_model < 0x3) {
5858cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		wrmsr(MSR_P4_IQ_ESCR0, 0, 0);
5868cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		wrmsr(MSR_P4_IQ_ESCR1, 0, 0);
5878cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	}
5888cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
5898cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	for (addr = MSR_P4_RAT_ESCR0 + stag;
5908cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	     addr <= MSR_P4_SSU_ESCR0; ++i, addr += addr_increment()) {
5918cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		wrmsr(addr, 0, 0);
5928cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	}
5938cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
5948cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	for (addr = MSR_P4_MS_ESCR0 + stag;
5958cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	     addr <= MSR_P4_TC_ESCR1; addr += addr_increment()) {
5968cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		wrmsr(addr, 0, 0);
5978cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	}
5988cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
5998cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	for (addr = MSR_P4_IX_ESCR0 + stag;
6008cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	     addr <= MSR_P4_CRU_ESCR3; addr += addr_increment()) {
6018cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		wrmsr(addr, 0, 0);
6028cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	}
6038cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
6048cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	if (num_counters == NUM_COUNTERS_NON_HT) {
6058cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		wrmsr(MSR_P4_CRU_ESCR4, 0, 0);
6068cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		wrmsr(MSR_P4_CRU_ESCR5, 0, 0);
6078cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	} else if (stag == 0) {
6088cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		wrmsr(MSR_P4_CRU_ESCR4, 0, 0);
6098cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	} else {
6108cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		wrmsr(MSR_P4_CRU_ESCR5, 0, 0);
6118cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	}
6128cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
6138cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	/* setup all counters */
6148cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	for (i = 0 ; i < num_counters ; ++i) {
6158cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		if (sysctl.ctr[i].event) {
6168cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			pmc_setup_one_p4_counter(i);
6178cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			CTR_WRITE(sysctl.ctr[i].count, VIRT_CTR(stag, i));
6188cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		}
6198cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	}
6208cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd}
6218cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
6228cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
6238cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddstatic void p4_check_ctrs(unsigned int const cpu,
6248cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			  struct op_msrs const * const msrs,
6258cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			  struct pt_regs * const regs)
6268cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{
6278cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	unsigned long ctr, low, high, stag, real;
6288cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	int i;
6298cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
6308cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	stag = get_stagger();
6318cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
6328cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	for (i = 0; i < num_counters; ++i) {
6338cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
6348cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		if (!sysctl.ctr[i].enabled)
6358cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			continue;
6368cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
6378cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		/*
6388cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		 * there is some eccentricity in the hardware which
6398cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		 * requires that we perform 2 extra corrections:
6408cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		 *
6418cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		 * - check both the CCCR:OVF flag for overflow and the
6428cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		 *   counter high bit for un-flagged overflows.
6438cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		 *
6448cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		 * - write the counter back twice to ensure it gets
6458cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		 *   updated properly.
6468cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		 *
6478cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		 * the former seems to be related to extra NMIs happening
6488cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		 * during the current NMI; the latter is reported as errata
6498cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		 * N15 in intel doc 249199-029, pentium 4 specification
6508cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		 * update, though their suggested work-around does not
6518cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		 * appear to solve the problem.
6528cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		 */
6538cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
6548cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		real = VIRT_CTR(stag, i);
6558cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
6568cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		CCCR_READ(low, high, real);
6578cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 		CTR_READ(ctr, high, real);
6588cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		if (CCCR_OVF_P(low) || CTR_OVERFLOW_P(ctr)) {
6598cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			op_do_profile(cpu, instruction_pointer(regs), IRQ_ENABLED(regs), i);
6608cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 			CTR_WRITE(oprof_data[cpu].ctr_count[i], real);
6618cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			CCCR_CLEAR_OVF(low);
6628cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			CCCR_WRITE(low, high, real);
6638cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 			CTR_WRITE(oprof_data[cpu].ctr_count[i], real);
6648cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		}
6658cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	}
6668cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
6678cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	/* P4 quirk: you have to re-unmask the apic vector */
6688cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	apic_write(APIC_LVTPC, apic_read(APIC_LVTPC) & ~APIC_LVT_MASKED);
6698cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd}
6708cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
6718cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
6728cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddstatic void p4_start(struct op_msrs const * const msrs)
6738cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{
6748cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	unsigned int low, high, stag;
6758cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	int i;
6768cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
6778cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	stag = get_stagger();
6788cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
6798cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	for (i = 0; i < num_counters; ++i) {
6808cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		if (!sysctl.ctr[i].enabled)
6818cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			continue;
6828cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		CCCR_READ(low, high, VIRT_CTR(stag, i));
6838cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		CCCR_SET_ENABLE(low);
6848cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		CCCR_WRITE(low, high, VIRT_CTR(stag, i));
6858cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	}
6868cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd}
6878cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
6888cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
6898cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddstatic void p4_stop(struct op_msrs const * const msrs)
6908cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{
6918cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	unsigned int low, high, stag;
6928cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	int i;
6938cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
6948cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	stag = get_stagger();
6958cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
6968cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	for (i = 0; i < num_counters; ++i) {
6978cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		/* FIXME: 2.6 driver doesn't do that ? */
6988cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		if (!sysctl.ctr[i].enabled)
6998cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			continue;
7008cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		CCCR_READ(low, high, VIRT_CTR(stag, i));
7018cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		CCCR_SET_DISABLE(low);
7028cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		CCCR_WRITE(low, high, VIRT_CTR(stag, i));
7038cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	}
7048cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd}
7058cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
7068cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#ifdef HT_SUPPORT
7078cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
7088cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddstruct op_x86_model_spec const op_p4_ht2_spec = {
7098cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	.num_counters = NUM_COUNTERS_HT2,
7108cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	.num_controls = NUM_CONTROLS_HT2,
7118cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	.fill_in_addresses = &p4_fill_in_addresses,
7128cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	.setup_ctrs = &p4_setup_ctrs,
7138cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	.check_ctrs = &p4_check_ctrs,
7148cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	.start = &p4_start,
7158cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	.stop = &p4_stop
7168cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd};
7178cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#endif
7188cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
7198cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddstruct op_x86_model_spec const op_p4_spec = {
7208cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	.num_counters = NUM_COUNTERS_NON_HT,
7218cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	.num_controls = NUM_CONTROLS_NON_HT,
7228cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	.fill_in_addresses = &p4_fill_in_addresses,
7238cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	.setup_ctrs = &p4_setup_ctrs,
7248cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	.check_ctrs = &p4_check_ctrs,
7258cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	.start = &p4_start,
7268cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	.stop = &p4_stop
7278cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd};
728