• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * @file op_model_athlon.h
3  * athlon / K7 model-specific MSR operations
4  *
5  * @remark Copyright 2002 OProfile authors
6  * @remark Read the file COPYING
7  *
8  * @author John Levon
9  * @author Philippe Elie
10  * @author Graydon Hoare
11  */
12 
13 #include "op_x86_model.h"
14 #include "op_arch.h"
15 #include "op_msr.h"
16 
17 #define NUM_COUNTERS 4
18 #define NUM_CONTROLS 4
19 
20 #define CTR_READ(l, h, msrs, c) do {rdmsr(msrs->counters.addrs[(c)], (l), (h));} while (0)
21 #define CTR_WRITE(l, msrs, c) do {wrmsr(msrs->counters.addrs[(c)], -(u32)(l), 0xffff);} while (0)
22 #define CTR_OVERFLOWED(n) (!((n) & (1U << 31)))
23 
24 #define CTRL_READ(l, h, msrs, c) do {rdmsr(msrs->controls.addrs[(c)], (l), (h));} while (0)
25 #define CTRL_WRITE(l, h, msrs, c) do {wrmsr(msrs->controls.addrs[(c)], (l), (h));} while (0)
26 #define CTRL_SET_ACTIVE(n) (n |= (1 << 22))
27 #define CTRL_SET_INACTIVE(n) (n &= ~(1 << 22))
28 #define CTRL_CLEAR(x) (x &= (1 << 21))
29 #define CTRL_SET_ENABLE(val) (val |= 1 << 20)
30 #define CTRL_SET_USR(val, u) (val |= ((u & 1) << 16))
31 #define CTRL_SET_KERN(val, k) (val |= ((k & 1) << 17))
32 #define CTRL_SET_UM(val, m) (val |= (m << 8))
33 #define CTRL_SET_EVENT(val, e) (val |= e)
34 
35 
athlon_fill_in_addresses(struct op_msrs * const msrs)36 static void athlon_fill_in_addresses(struct op_msrs * const msrs)
37 {
38 	msrs->counters.addrs[0] = MSR_K7_PERFCTR0;
39 	msrs->counters.addrs[1] = MSR_K7_PERFCTR1;
40 	msrs->counters.addrs[2] = MSR_K7_PERFCTR2;
41 	msrs->counters.addrs[3] = MSR_K7_PERFCTR3;
42 
43 	msrs->controls.addrs[0] = MSR_K7_EVNTSEL0;
44 	msrs->controls.addrs[1] = MSR_K7_EVNTSEL1;
45 	msrs->controls.addrs[2] = MSR_K7_EVNTSEL2;
46 	msrs->controls.addrs[3] = MSR_K7_EVNTSEL3;
47 }
48 
49 
athlon_setup_ctrs(struct op_msrs const * const msrs)50 static void athlon_setup_ctrs(struct op_msrs const * const msrs)
51 {
52 	uint low, high;
53 	int i;
54 
55 	/* clear all counters */
56 	for (i = 0 ; i < NUM_CONTROLS; ++i) {
57 		CTRL_READ(low, high, msrs, i);
58 		CTRL_CLEAR(low);
59 		CTRL_WRITE(low, high, msrs, i);
60 	}
61 
62 	/* avoid a false detection of ctr overflows in NMI handler */
63 	for (i = 0; i < NUM_COUNTERS; ++i)
64 		CTR_WRITE(1, msrs, i);
65 
66 	/* enable active counters */
67 	for (i = 0; i < NUM_COUNTERS; ++i) {
68 		if (sysctl.ctr[i].enabled) {
69 
70 			CTR_WRITE(sysctl.ctr[i].count, msrs, i);
71 
72 			CTRL_READ(low, high, msrs, i);
73 			CTRL_CLEAR(low);
74 			CTRL_SET_ENABLE(low);
75 			CTRL_SET_USR(low, sysctl.ctr[i].user);
76 			CTRL_SET_KERN(low, sysctl.ctr[i].kernel);
77 			CTRL_SET_UM(low, sysctl.ctr[i].unit_mask);
78 			CTRL_SET_EVENT(low, sysctl.ctr[i].event);
79 			CTRL_WRITE(low, high, msrs, i);
80 		}
81 	}
82 }
83 
84 
athlon_check_ctrs(uint const cpu,struct op_msrs const * const msrs,struct pt_regs * const regs)85 static void athlon_check_ctrs(uint const cpu,
86 			      struct op_msrs const * const msrs,
87 			      struct pt_regs * const regs)
88 {
89 	uint low, high;
90 	int i;
91 	for (i = 0 ; i < NUM_COUNTERS; ++i) {
92 		if (sysctl.ctr[i].enabled) {
93 			CTR_READ(low, high, msrs, i);
94 			if (CTR_OVERFLOWED(low)) {
95 				op_do_profile(cpu, instruction_pointer(regs), IRQ_ENABLED(regs), i);
96 				CTR_WRITE(oprof_data[cpu].ctr_count[i], msrs, i);
97 			}
98 		}
99 	}
100 }
101 
102 
athlon_start(struct op_msrs const * const msrs)103 static void athlon_start(struct op_msrs const * const msrs)
104 {
105 	uint low, high;
106 	int i;
107 	for (i = 0 ; i < NUM_COUNTERS ; ++i) {
108 		if (sysctl.ctr[i].enabled) {
109 			CTRL_READ(low, high, msrs, i);
110 			CTRL_SET_ACTIVE(low);
111 			CTRL_WRITE(low, high, msrs, i);
112 		}
113 	}
114 }
115 
116 
athlon_stop(struct op_msrs const * const msrs)117 static void athlon_stop(struct op_msrs const * const msrs)
118 {
119 	uint low, high;
120 	int i;
121 	for (i = 0 ; i < NUM_COUNTERS ; ++i) {
122 		if (sysctl.ctr[i].enabled) {
123 			CTRL_READ(low, high, msrs, i);
124 			CTRL_SET_INACTIVE(low);
125 			CTRL_WRITE(low, high, msrs, i);
126 		}
127 	}
128 }
129 
130 
131 struct op_x86_model_spec const op_athlon_spec = {
132 	.num_counters = NUM_COUNTERS,
133 	.num_controls = NUM_CONTROLS,
134 	.fill_in_addresses = &athlon_fill_in_addresses,
135 	.setup_ctrs = &athlon_setup_ctrs,
136 	.check_ctrs = &athlon_check_ctrs,
137 	.start = &athlon_start,
138 	.stop = &athlon_stop
139 };
140