ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-2.6.6.tar.bz2
[linux-2.6.git] / arch / i386 / oprofile / op_model_p4.c
1 /**
2  * @file op_model_p4.c
3  * P4 model-specific MSR operations
4  *
5  * @remark Copyright 2002 OProfile authors
6  * @remark Read the file COPYING
7  *
8  * @author Graydon Hoare
9  */
10
11 #include <linux/oprofile.h>
12 #include <linux/smp.h>
13 #include <asm/msr.h>
14 #include <asm/ptrace.h>
15 #include <asm/fixmap.h>
16 #include <asm/apic.h>
17
18 #include "op_x86_model.h"
19 #include "op_counter.h"
20
21 #define NUM_EVENTS 39
22
23 #define NUM_COUNTERS_NON_HT 8
24 #define NUM_ESCRS_NON_HT 45
25 #define NUM_CCCRS_NON_HT 18
26 #define NUM_CONTROLS_NON_HT (NUM_ESCRS_NON_HT + NUM_CCCRS_NON_HT)
27
28 #define NUM_COUNTERS_HT2 4
29 #define NUM_ESCRS_HT2 23
30 #define NUM_CCCRS_HT2 9
31 #define NUM_CONTROLS_HT2 (NUM_ESCRS_HT2 + NUM_CCCRS_HT2)
32
33 static unsigned int num_counters = NUM_COUNTERS_NON_HT;
34
35
36 /* this has to be checked dynamically since the
37    hyper-threadedness of a chip is discovered at
38    kernel boot-time. */
39 static inline void setup_num_counters(void)
40 {
41 #ifdef CONFIG_SMP
42         if (smp_num_siblings == 2)
43                 num_counters = NUM_COUNTERS_HT2;
44 #endif
45 }
46
47 static int inline addr_increment(void)
48 {
49 #ifdef CONFIG_SMP
50         return smp_num_siblings == 2 ? 2 : 1;
51 #else
52         return 1;
53 #endif
54 }
55
56
57 /* tables to simulate simplified hardware view of p4 registers */
58 struct p4_counter_binding {
59         int virt_counter;
60         int counter_address;
61         int cccr_address;
62 };
63
64 struct p4_event_binding {
65         int escr_select;  /* value to put in CCCR */
66         int event_select; /* value to put in ESCR */
67         struct {
68                 int virt_counter; /* for this counter... */
69                 int escr_address; /* use this ESCR       */
70         } bindings[2];
71 };
72
73 /* nb: these CTR_* defines are a duplicate of defines in
74    event/i386.p4*events. */
75
76
77 #define CTR_BPU_0      (1 << 0)
78 #define CTR_MS_0       (1 << 1)
79 #define CTR_FLAME_0    (1 << 2)
80 #define CTR_IQ_4       (1 << 3)
81 #define CTR_BPU_2      (1 << 4)
82 #define CTR_MS_2       (1 << 5)
83 #define CTR_FLAME_2    (1 << 6)
84 #define CTR_IQ_5       (1 << 7)
85
86 static struct p4_counter_binding p4_counters [NUM_COUNTERS_NON_HT] = {
87         { CTR_BPU_0,   MSR_P4_BPU_PERFCTR0,   MSR_P4_BPU_CCCR0 },
88         { CTR_MS_0,    MSR_P4_MS_PERFCTR0,    MSR_P4_MS_CCCR0 },
89         { CTR_FLAME_0, MSR_P4_FLAME_PERFCTR0, MSR_P4_FLAME_CCCR0 },
90         { CTR_IQ_4,    MSR_P4_IQ_PERFCTR4,    MSR_P4_IQ_CCCR4 },
91         { CTR_BPU_2,   MSR_P4_BPU_PERFCTR2,   MSR_P4_BPU_CCCR2 },
92         { CTR_MS_2,    MSR_P4_MS_PERFCTR2,    MSR_P4_MS_CCCR2 },
93         { CTR_FLAME_2, MSR_P4_FLAME_PERFCTR2, MSR_P4_FLAME_CCCR2 },
94         { CTR_IQ_5,    MSR_P4_IQ_PERFCTR5,    MSR_P4_IQ_CCCR5 }
95 };
96
97 #define NUM_UNUSED_CCCRS        NUM_CCCRS_NON_HT - NUM_COUNTERS_NON_HT
98
99 /* All cccr we don't use. */
100 static int p4_unused_cccr[NUM_UNUSED_CCCRS] = {
101         MSR_P4_BPU_CCCR1,       MSR_P4_BPU_CCCR3,
102         MSR_P4_MS_CCCR1,        MSR_P4_MS_CCCR3,
103         MSR_P4_FLAME_CCCR1,     MSR_P4_FLAME_CCCR3,
104         MSR_P4_IQ_CCCR0,        MSR_P4_IQ_CCCR1,
105         MSR_P4_IQ_CCCR2,        MSR_P4_IQ_CCCR3
106 };
107
108 /* p4 event codes in libop/op_event.h are indices into this table. */
109
110 static struct p4_event_binding p4_events[NUM_EVENTS] = {
111         
112         { /* BRANCH_RETIRED */
113                 0x05, 0x06, 
114                 { {CTR_IQ_4, MSR_P4_CRU_ESCR2},
115                   {CTR_IQ_5, MSR_P4_CRU_ESCR3} }
116         },
117         
118         { /* MISPRED_BRANCH_RETIRED */
119                 0x04, 0x03, 
120                 { { CTR_IQ_4, MSR_P4_CRU_ESCR0},
121                   { CTR_IQ_5, MSR_P4_CRU_ESCR1} }
122         },
123         
124         { /* TC_DELIVER_MODE */
125                 0x01, 0x01,
126                 { { CTR_MS_0, MSR_P4_TC_ESCR0},  
127                   { CTR_MS_2, MSR_P4_TC_ESCR1} }
128         },
129         
130         { /* BPU_FETCH_REQUEST */
131                 0x00, 0x03, 
132                 { { CTR_BPU_0, MSR_P4_BPU_ESCR0},
133                   { CTR_BPU_2, MSR_P4_BPU_ESCR1} }
134         },
135
136         { /* ITLB_REFERENCE */
137                 0x03, 0x18,
138                 { { CTR_BPU_0, MSR_P4_ITLB_ESCR0},
139                   { CTR_BPU_2, MSR_P4_ITLB_ESCR1} }
140         },
141
142         { /* MEMORY_CANCEL */
143                 0x05, 0x02,
144                 { { CTR_FLAME_0, MSR_P4_DAC_ESCR0},
145                   { CTR_FLAME_2, MSR_P4_DAC_ESCR1} }
146         },
147
148         { /* MEMORY_COMPLETE */
149                 0x02, 0x08,
150                 { { CTR_FLAME_0, MSR_P4_SAAT_ESCR0},
151                   { CTR_FLAME_2, MSR_P4_SAAT_ESCR1} }
152         },
153
154         { /* LOAD_PORT_REPLAY */
155                 0x02, 0x04, 
156                 { { CTR_FLAME_0, MSR_P4_SAAT_ESCR0},
157                   { CTR_FLAME_2, MSR_P4_SAAT_ESCR1} }
158         },
159
160         { /* STORE_PORT_REPLAY */
161                 0x02, 0x05,
162                 { { CTR_FLAME_0, MSR_P4_SAAT_ESCR0},
163                   { CTR_FLAME_2, MSR_P4_SAAT_ESCR1} }
164         },
165
166         { /* MOB_LOAD_REPLAY */
167                 0x02, 0x03,
168                 { { CTR_BPU_0, MSR_P4_MOB_ESCR0},
169                   { CTR_BPU_2, MSR_P4_MOB_ESCR1} }
170         },
171
172         { /* PAGE_WALK_TYPE */
173                 0x04, 0x01,
174                 { { CTR_BPU_0, MSR_P4_PMH_ESCR0},
175                   { CTR_BPU_2, MSR_P4_PMH_ESCR1} }
176         },
177
178         { /* BSQ_CACHE_REFERENCE */
179                 0x07, 0x0c, 
180                 { { CTR_BPU_0, MSR_P4_BSU_ESCR0},
181                   { CTR_BPU_2, MSR_P4_BSU_ESCR1} }
182         },
183
184         { /* IOQ_ALLOCATION */
185                 0x06, 0x03, 
186                 { { CTR_BPU_0, MSR_P4_FSB_ESCR0},
187                   { 0, 0 } }
188         },
189
190         { /* IOQ_ACTIVE_ENTRIES */
191                 0x06, 0x1a, 
192                 { { CTR_BPU_2, MSR_P4_FSB_ESCR1},
193                   { 0, 0 } }
194         },
195
196         { /* FSB_DATA_ACTIVITY */
197                 0x06, 0x17, 
198                 { { CTR_BPU_0, MSR_P4_FSB_ESCR0},
199                   { CTR_BPU_2, MSR_P4_FSB_ESCR1} }
200         },
201
202         { /* BSQ_ALLOCATION */
203                 0x07, 0x05, 
204                 { { CTR_BPU_0, MSR_P4_BSU_ESCR0},
205                   { 0, 0 } }
206         },
207
208         { /* BSQ_ACTIVE_ENTRIES */
209                 0x07, 0x06,
210                 { { CTR_BPU_2, MSR_P4_BSU_ESCR1 /* guess */},  
211                   { 0, 0 } }
212         },
213
214         { /* X87_ASSIST */
215                 0x05, 0x03, 
216                 { { CTR_IQ_4, MSR_P4_CRU_ESCR2},
217                   { CTR_IQ_5, MSR_P4_CRU_ESCR3} }
218         },
219
220         { /* SSE_INPUT_ASSIST */
221                 0x01, 0x34,
222                 { { CTR_FLAME_0, MSR_P4_FIRM_ESCR0},
223                   { CTR_FLAME_2, MSR_P4_FIRM_ESCR1} }
224         },
225   
226         { /* PACKED_SP_UOP */
227                 0x01, 0x08, 
228                 { { CTR_FLAME_0, MSR_P4_FIRM_ESCR0},
229                   { CTR_FLAME_2, MSR_P4_FIRM_ESCR1} }
230         },
231   
232         { /* PACKED_DP_UOP */
233                 0x01, 0x0c, 
234                 { { CTR_FLAME_0, MSR_P4_FIRM_ESCR0},
235                   { CTR_FLAME_2, MSR_P4_FIRM_ESCR1} }
236         },
237
238         { /* SCALAR_SP_UOP */
239                 0x01, 0x0a, 
240                 { { CTR_FLAME_0, MSR_P4_FIRM_ESCR0},
241                   { CTR_FLAME_2, MSR_P4_FIRM_ESCR1} }
242         },
243
244         { /* SCALAR_DP_UOP */
245                 0x01, 0x0e,
246                 { { CTR_FLAME_0, MSR_P4_FIRM_ESCR0},
247                   { CTR_FLAME_2, MSR_P4_FIRM_ESCR1} }
248         },
249
250         { /* 64BIT_MMX_UOP */
251                 0x01, 0x02, 
252                 { { CTR_FLAME_0, MSR_P4_FIRM_ESCR0},
253                   { CTR_FLAME_2, MSR_P4_FIRM_ESCR1} }
254         },
255   
256         { /* 128BIT_MMX_UOP */
257                 0x01, 0x1a, 
258                 { { CTR_FLAME_0, MSR_P4_FIRM_ESCR0},
259                   { CTR_FLAME_2, MSR_P4_FIRM_ESCR1} }
260         },
261
262         { /* X87_FP_UOP */
263                 0x01, 0x04, 
264                 { { CTR_FLAME_0, MSR_P4_FIRM_ESCR0},
265                   { CTR_FLAME_2, MSR_P4_FIRM_ESCR1} }
266         },
267   
268         { /* X87_SIMD_MOVES_UOP */
269                 0x01, 0x2e, 
270                 { { CTR_FLAME_0, MSR_P4_FIRM_ESCR0},
271                   { CTR_FLAME_2, MSR_P4_FIRM_ESCR1} }
272         },
273   
274         { /* MACHINE_CLEAR */
275                 0x05, 0x02, 
276                 { { CTR_IQ_4, MSR_P4_CRU_ESCR2},
277                   { CTR_IQ_5, MSR_P4_CRU_ESCR3} }
278         },
279
280         { /* GLOBAL_POWER_EVENTS */
281                 0x06, 0x13 /* older manual says 0x05, newer 0x13 */,
282                 { { CTR_BPU_0, MSR_P4_FSB_ESCR0},
283                   { CTR_BPU_2, MSR_P4_FSB_ESCR1} }
284         },
285   
286         { /* TC_MS_XFER */
287                 0x00, 0x05, 
288                 { { CTR_MS_0, MSR_P4_MS_ESCR0},
289                   { CTR_MS_2, MSR_P4_MS_ESCR1} }
290         },
291
292         { /* UOP_QUEUE_WRITES */
293                 0x00, 0x09,
294                 { { CTR_MS_0, MSR_P4_MS_ESCR0},
295                   { CTR_MS_2, MSR_P4_MS_ESCR1} }
296         },
297
298         { /* FRONT_END_EVENT */
299                 0x05, 0x08,
300                 { { CTR_IQ_4, MSR_P4_CRU_ESCR2},
301                   { CTR_IQ_5, MSR_P4_CRU_ESCR3} }
302         },
303
304         { /* EXECUTION_EVENT */
305                 0x05, 0x0c,
306                 { { CTR_IQ_4, MSR_P4_CRU_ESCR2},
307                   { CTR_IQ_5, MSR_P4_CRU_ESCR3} }
308         },
309
310         { /* REPLAY_EVENT */
311                 0x05, 0x09,
312                 { { CTR_IQ_4, MSR_P4_CRU_ESCR2},
313                   { CTR_IQ_5, MSR_P4_CRU_ESCR3} }
314         },
315
316         { /* INSTR_RETIRED */
317                 0x04, 0x02, 
318                 { { CTR_IQ_4, MSR_P4_CRU_ESCR0},
319                   { CTR_IQ_5, MSR_P4_CRU_ESCR1} }
320         },
321
322         { /* UOPS_RETIRED */
323                 0x04, 0x01,
324                 { { CTR_IQ_4, MSR_P4_CRU_ESCR0},
325                   { CTR_IQ_5, MSR_P4_CRU_ESCR1} }
326         },
327
328         { /* UOP_TYPE */    
329                 0x02, 0x02, 
330                 { { CTR_IQ_4, MSR_P4_RAT_ESCR0},
331                   { CTR_IQ_5, MSR_P4_RAT_ESCR1} }
332         },
333
334         { /* RETIRED_MISPRED_BRANCH_TYPE */
335                 0x02, 0x05, 
336                 { { CTR_MS_0, MSR_P4_TBPU_ESCR0},
337                   { CTR_MS_2, MSR_P4_TBPU_ESCR1} }
338         },
339
340         { /* RETIRED_BRANCH_TYPE */
341                 0x02, 0x04,
342                 { { CTR_MS_0, MSR_P4_TBPU_ESCR0},
343                   { CTR_MS_2, MSR_P4_TBPU_ESCR1} }
344         }
345 };
346
347
348 #define MISC_PMC_ENABLED_P(x) ((x) & 1 << 7)
349
350 #define ESCR_RESERVED_BITS 0x80000003
351 #define ESCR_CLEAR(escr) ((escr) &= ESCR_RESERVED_BITS)
352 #define ESCR_SET_USR_0(escr, usr) ((escr) |= (((usr) & 1) << 2))
353 #define ESCR_SET_OS_0(escr, os) ((escr) |= (((os) & 1) << 3))
354 #define ESCR_SET_USR_1(escr, usr) ((escr) |= (((usr) & 1)))
355 #define ESCR_SET_OS_1(escr, os) ((escr) |= (((os) & 1) << 1))
356 #define ESCR_SET_EVENT_SELECT(escr, sel) ((escr) |= (((sel) & 0x3f) << 25))
357 #define ESCR_SET_EVENT_MASK(escr, mask) ((escr) |= (((mask) & 0xffff) << 9))
358 #define ESCR_READ(escr,high,ev,i) do {rdmsr(ev->bindings[(i)].escr_address, (escr), (high));} while (0)
359 #define ESCR_WRITE(escr,high,ev,i) do {wrmsr(ev->bindings[(i)].escr_address, (escr), (high));} while (0)
360
361 #define CCCR_RESERVED_BITS 0x38030FFF
362 #define CCCR_CLEAR(cccr) ((cccr) &= CCCR_RESERVED_BITS)
363 #define CCCR_SET_REQUIRED_BITS(cccr) ((cccr) |= 0x00030000)
364 #define CCCR_SET_ESCR_SELECT(cccr, sel) ((cccr) |= (((sel) & 0x07) << 13))
365 #define CCCR_SET_PMI_OVF_0(cccr) ((cccr) |= (1<<26))
366 #define CCCR_SET_PMI_OVF_1(cccr) ((cccr) |= (1<<27))
367 #define CCCR_SET_ENABLE(cccr) ((cccr) |= (1<<12))
368 #define CCCR_SET_DISABLE(cccr) ((cccr) &= ~(1<<12))
369 #define CCCR_READ(low, high, i) do {rdmsr(p4_counters[(i)].cccr_address, (low), (high));} while (0)
370 #define CCCR_WRITE(low, high, i) do {wrmsr(p4_counters[(i)].cccr_address, (low), (high));} while (0)
371 #define CCCR_OVF_P(cccr) ((cccr) & (1U<<31))
372 #define CCCR_CLEAR_OVF(cccr) ((cccr) &= (~(1U<<31)))
373
374 #define CTR_READ(l,h,i) do {rdmsr(p4_counters[(i)].counter_address, (l), (h));} while (0)
375 #define CTR_WRITE(l,i) do {wrmsr(p4_counters[(i)].counter_address, -(u32)(l), -1);} while (0)
376 #define CTR_OVERFLOW_P(ctr) (!((ctr) & 0x80000000))
377
378
379 /* this assigns a "stagger" to the current CPU, which is used throughout
380    the code in this module as an extra array offset, to select the "even"
381    or "odd" part of all the divided resources. */
382 static unsigned int get_stagger(void)
383 {
384 #ifdef CONFIG_SMP
385         int cpu;
386         if (smp_num_siblings > 1) {
387                 cpu = smp_processor_id();
388                 return (cpu_sibling_map[cpu] > cpu) ? 0 : 1;
389         }
390 #endif  
391         return 0;
392 }
393
394
395 /* finally, mediate access to a real hardware counter
396    by passing a "virtual" counter numer to this macro,
397    along with your stagger setting. */
398 #define VIRT_CTR(stagger, i) ((i) + ((num_counters) * (stagger)))
399
400 static unsigned long reset_value[NUM_COUNTERS_NON_HT];
401
402
403 static void p4_fill_in_addresses(struct op_msrs * const msrs)
404 {
405         unsigned int i; 
406         unsigned int addr, stag;
407
408         setup_num_counters();
409         stag = get_stagger();
410
411         /* the counter registers we pay attention to */
412         for (i = 0; i < num_counters; ++i) {
413                 msrs->counters[i].addr = 
414                         p4_counters[VIRT_CTR(stag, i)].counter_address;
415         }
416
417         /* FIXME: bad feeling, we don't save the 10 counters we don't use. */
418
419         /* 18 CCCR registers */
420         for (i = 0, addr = MSR_P4_BPU_CCCR0 + stag;
421              addr <= MSR_P4_IQ_CCCR5; ++i, addr += addr_increment()) {
422                 msrs->controls[i].addr = addr;
423         }
424         
425         /* 43 ESCR registers in three discontiguous group */
426         for (addr = MSR_P4_BSU_ESCR0 + stag;
427              addr <= MSR_P4_SSU_ESCR0; ++i, addr += addr_increment()) { 
428                 msrs->controls[i].addr = addr;
429         }
430         
431         for (addr = MSR_P4_MS_ESCR0 + stag;
432              addr <= MSR_P4_TC_ESCR1; ++i, addr += addr_increment()) { 
433                 msrs->controls[i].addr = addr;
434         }
435         
436         for (addr = MSR_P4_IX_ESCR0 + stag;
437              addr <= MSR_P4_CRU_ESCR3; ++i, addr += addr_increment()) { 
438                 msrs->controls[i].addr = addr;
439         }
440
441         /* there are 2 remaining non-contiguously located ESCRs */
442
443         if (num_counters == NUM_COUNTERS_NON_HT) {              
444                 /* standard non-HT CPUs handle both remaining ESCRs*/
445                 msrs->controls[i++].addr = MSR_P4_CRU_ESCR5;
446                 msrs->controls[i++].addr = MSR_P4_CRU_ESCR4;
447
448         } else if (stag == 0) {
449                 /* HT CPUs give the first remainder to the even thread, as
450                    the 32nd control register */
451                 msrs->controls[i++].addr = MSR_P4_CRU_ESCR4;
452
453         } else {
454                 /* and two copies of the second to the odd thread,
455                    for the 22st and 23nd control registers */
456                 msrs->controls[i++].addr = MSR_P4_CRU_ESCR5;
457                 msrs->controls[i++].addr = MSR_P4_CRU_ESCR5;
458         }
459 }
460
461
462 static void pmc_setup_one_p4_counter(unsigned int ctr)
463 {
464         int i;
465         int const maxbind = 2;
466         unsigned int cccr = 0;
467         unsigned int escr = 0;
468         unsigned int high = 0;
469         unsigned int counter_bit;
470         struct p4_event_binding * ev = 0;
471         unsigned int stag;
472
473         stag = get_stagger();
474         
475         /* convert from counter *number* to counter *bit* */
476         counter_bit = 1 << VIRT_CTR(stag, ctr);
477         
478         /* find our event binding structure. */
479         if (counter_config[ctr].event <= 0 || counter_config[ctr].event > NUM_EVENTS) {
480                 printk(KERN_ERR 
481                        "oprofile: P4 event code 0x%lx out of range\n", 
482                        counter_config[ctr].event);
483                 return;
484         }
485         
486         ev = &(p4_events[counter_config[ctr].event - 1]);
487         
488         for (i = 0; i < maxbind; i++) {
489                 if (ev->bindings[i].virt_counter & counter_bit) {
490
491                         /* modify ESCR */
492                         ESCR_READ(escr, high, ev, i);
493                         ESCR_CLEAR(escr);
494                         if (stag == 0) {
495                                 ESCR_SET_USR_0(escr, counter_config[ctr].user);
496                                 ESCR_SET_OS_0(escr, counter_config[ctr].kernel);
497                         } else {
498                                 ESCR_SET_USR_1(escr, counter_config[ctr].user);
499                                 ESCR_SET_OS_1(escr, counter_config[ctr].kernel);
500                         }
501                         ESCR_SET_EVENT_SELECT(escr, ev->event_select);
502                         ESCR_SET_EVENT_MASK(escr, counter_config[ctr].unit_mask);                       
503                         ESCR_WRITE(escr, high, ev, i);
504                        
505                         /* modify CCCR */
506                         CCCR_READ(cccr, high, VIRT_CTR(stag, ctr));
507                         CCCR_CLEAR(cccr);
508                         CCCR_SET_REQUIRED_BITS(cccr);
509                         CCCR_SET_ESCR_SELECT(cccr, ev->escr_select);
510                         if (stag == 0) {
511                                 CCCR_SET_PMI_OVF_0(cccr);
512                         } else {
513                                 CCCR_SET_PMI_OVF_1(cccr);
514                         }
515                         CCCR_WRITE(cccr, high, VIRT_CTR(stag, ctr));
516                         return;
517                 }
518         }
519
520         printk(KERN_ERR 
521                "oprofile: P4 event code 0x%lx no binding, stag %d ctr %d\n",
522                counter_config[ctr].event, stag, ctr);
523 }
524
525
526 static void p4_setup_ctrs(struct op_msrs const * const msrs)
527 {
528         unsigned int i;
529         unsigned int low, high;
530         unsigned int addr;
531         unsigned int stag;
532
533         stag = get_stagger();
534
535         rdmsr(MSR_IA32_MISC_ENABLE, low, high);
536         if (! MISC_PMC_ENABLED_P(low)) {
537                 printk(KERN_ERR "oprofile: P4 PMC not available\n");
538                 return;
539         }
540
541         /* clear the cccrs we will use */
542         for (i = 0 ; i < num_counters ; i++) {
543                 rdmsr(p4_counters[VIRT_CTR(stag, i)].cccr_address, low, high);
544                 CCCR_CLEAR(low);
545                 CCCR_SET_REQUIRED_BITS(low);
546                 wrmsr(p4_counters[VIRT_CTR(stag, i)].cccr_address, low, high);
547         }
548
549         /* clear cccrs outside our concern */
550         for (i = stag ; i < NUM_UNUSED_CCCRS ; i += addr_increment()) {
551                 rdmsr(p4_unused_cccr[i], low, high);
552                 CCCR_CLEAR(low);
553                 CCCR_SET_REQUIRED_BITS(low);
554                 wrmsr(p4_unused_cccr[i], low, high);
555         }
556
557         /* clear all escrs (including those outside our concern) */
558         for (addr = MSR_P4_BSU_ESCR0 + stag;
559              addr <= MSR_P4_SSU_ESCR0; addr += addr_increment()) { 
560                 wrmsr(addr, 0, 0);
561         }
562         
563         for (addr = MSR_P4_MS_ESCR0 + stag;
564              addr <= MSR_P4_TC_ESCR1; addr += addr_increment()){ 
565                 wrmsr(addr, 0, 0);
566         }
567         
568         for (addr = MSR_P4_IX_ESCR0 + stag;
569              addr <= MSR_P4_CRU_ESCR3; addr += addr_increment()){ 
570                 wrmsr(addr, 0, 0);
571         }
572
573         if (num_counters == NUM_COUNTERS_NON_HT) {              
574                 wrmsr(MSR_P4_CRU_ESCR4, 0, 0);
575                 wrmsr(MSR_P4_CRU_ESCR5, 0, 0);
576         } else if (stag == 0) {
577                 wrmsr(MSR_P4_CRU_ESCR4, 0, 0);
578         } else {
579                 wrmsr(MSR_P4_CRU_ESCR5, 0, 0);
580         }               
581         
582         /* setup all counters */
583         for (i = 0 ; i < num_counters ; ++i) {
584                 if (counter_config[i].event) {
585                         reset_value[i] = counter_config[i].count;
586                         pmc_setup_one_p4_counter(i);
587                         CTR_WRITE(counter_config[i].count, VIRT_CTR(stag, i));
588                 } else {
589                         reset_value[i] = 0;
590                 }
591         }
592 }
593
594
595 static int p4_check_ctrs(unsigned int const cpu, 
596                           struct op_msrs const * const msrs,
597                           struct pt_regs * const regs)
598 {
599         unsigned long ctr, low, high, stag, real;
600         int i;
601         unsigned long eip = instruction_pointer(regs);
602         int is_kernel = !user_mode(regs);
603
604         stag = get_stagger();
605
606         for (i = 0; i < num_counters; ++i) {
607                 
608                 if (!reset_value[i]) 
609                         continue;
610
611                 /* 
612                  * there is some eccentricity in the hardware which
613                  * requires that we perform 2 extra corrections:
614                  *
615                  * - check both the CCCR:OVF flag for overflow and the
616                  *   counter high bit for un-flagged overflows.
617                  *
618                  * - write the counter back twice to ensure it gets
619                  *   updated properly.
620                  * 
621                  * the former seems to be related to extra NMIs happening
622                  * during the current NMI; the latter is reported as errata
623                  * N15 in intel doc 249199-029, pentium 4 specification
624                  * update, though their suggested work-around does not
625                  * appear to solve the problem.
626                  */
627                 
628                 real = VIRT_CTR(stag, i);
629
630                 CCCR_READ(low, high, real);
631                 CTR_READ(ctr, high, real);
632                 if (CCCR_OVF_P(low) || CTR_OVERFLOW_P(ctr)) {
633                         oprofile_add_sample(eip, is_kernel, i, cpu);
634                         CTR_WRITE(reset_value[i], real);
635                         CCCR_CLEAR_OVF(low);
636                         CCCR_WRITE(low, high, real);
637                         CTR_WRITE(reset_value[i], real);
638                 }
639         }
640
641         /* P4 quirk: you have to re-unmask the apic vector */
642         apic_write(APIC_LVTPC, apic_read(APIC_LVTPC) & ~APIC_LVT_MASKED);
643
644         /* See op_model_ppro.c */
645         return 1;
646 }
647
648
649 static void p4_start(struct op_msrs const * const msrs)
650 {
651         unsigned int low, high, stag;
652         int i;
653
654         stag = get_stagger();
655
656         for (i = 0; i < num_counters; ++i) {
657                 if (!reset_value[i])
658                         continue;
659                 CCCR_READ(low, high, VIRT_CTR(stag, i));
660                 CCCR_SET_ENABLE(low);
661                 CCCR_WRITE(low, high, VIRT_CTR(stag, i));
662         }
663 }
664
665
666 static void p4_stop(struct op_msrs const * const msrs)
667 {
668         unsigned int low, high, stag;
669         int i;
670
671         stag = get_stagger();
672
673         for (i = 0; i < num_counters; ++i) {
674                 CCCR_READ(low, high, VIRT_CTR(stag, i));
675                 CCCR_SET_DISABLE(low);
676                 CCCR_WRITE(low, high, VIRT_CTR(stag, i));
677         }
678 }
679
680
681 #ifdef CONFIG_SMP
682 struct op_x86_model_spec const op_p4_ht2_spec = {
683         .num_counters = NUM_COUNTERS_HT2,
684         .num_controls = NUM_CONTROLS_HT2,
685         .fill_in_addresses = &p4_fill_in_addresses,
686         .setup_ctrs = &p4_setup_ctrs,
687         .check_ctrs = &p4_check_ctrs,
688         .start = &p4_start,
689         .stop = &p4_stop
690 };
691 #endif
692
693 struct op_x86_model_spec const op_p4_spec = {
694         .num_counters = NUM_COUNTERS_NON_HT,
695         .num_controls = NUM_CONTROLS_NON_HT,
696         .fill_in_addresses = &p4_fill_in_addresses,
697         .setup_ctrs = &p4_setup_ctrs,
698         .check_ctrs = &p4_check_ctrs,
699         .start = &p4_start,
700         .stop = &p4_stop
701 };