patch-2_6_7-vs1_9_1_12
[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 = smp_processor_id();
386         return (cpu != first_cpu(cpu_sibling_map[cpu]));
387 #endif  
388         return 0;
389 }
390
391
392 /* finally, mediate access to a real hardware counter
393    by passing a "virtual" counter numer to this macro,
394    along with your stagger setting. */
395 #define VIRT_CTR(stagger, i) ((i) + ((num_counters) * (stagger)))
396
397 static unsigned long reset_value[NUM_COUNTERS_NON_HT];
398
399
400 static void p4_fill_in_addresses(struct op_msrs * const msrs)
401 {
402         unsigned int i; 
403         unsigned int addr, stag;
404
405         setup_num_counters();
406         stag = get_stagger();
407
408         /* the counter registers we pay attention to */
409         for (i = 0; i < num_counters; ++i) {
410                 msrs->counters[i].addr = 
411                         p4_counters[VIRT_CTR(stag, i)].counter_address;
412         }
413
414         /* FIXME: bad feeling, we don't save the 10 counters we don't use. */
415
416         /* 18 CCCR registers */
417         for (i = 0, addr = MSR_P4_BPU_CCCR0 + stag;
418              addr <= MSR_P4_IQ_CCCR5; ++i, addr += addr_increment()) {
419                 msrs->controls[i].addr = addr;
420         }
421         
422         /* 43 ESCR registers in three discontiguous group */
423         for (addr = MSR_P4_BSU_ESCR0 + stag;
424              addr <= MSR_P4_SSU_ESCR0; ++i, addr += addr_increment()) { 
425                 msrs->controls[i].addr = addr;
426         }
427         
428         for (addr = MSR_P4_MS_ESCR0 + stag;
429              addr <= MSR_P4_TC_ESCR1; ++i, addr += addr_increment()) { 
430                 msrs->controls[i].addr = addr;
431         }
432         
433         for (addr = MSR_P4_IX_ESCR0 + stag;
434              addr <= MSR_P4_CRU_ESCR3; ++i, addr += addr_increment()) { 
435                 msrs->controls[i].addr = addr;
436         }
437
438         /* there are 2 remaining non-contiguously located ESCRs */
439
440         if (num_counters == NUM_COUNTERS_NON_HT) {              
441                 /* standard non-HT CPUs handle both remaining ESCRs*/
442                 msrs->controls[i++].addr = MSR_P4_CRU_ESCR5;
443                 msrs->controls[i++].addr = MSR_P4_CRU_ESCR4;
444
445         } else if (stag == 0) {
446                 /* HT CPUs give the first remainder to the even thread, as
447                    the 32nd control register */
448                 msrs->controls[i++].addr = MSR_P4_CRU_ESCR4;
449
450         } else {
451                 /* and two copies of the second to the odd thread,
452                    for the 22st and 23nd control registers */
453                 msrs->controls[i++].addr = MSR_P4_CRU_ESCR5;
454                 msrs->controls[i++].addr = MSR_P4_CRU_ESCR5;
455         }
456 }
457
458
459 static void pmc_setup_one_p4_counter(unsigned int ctr)
460 {
461         int i;
462         int const maxbind = 2;
463         unsigned int cccr = 0;
464         unsigned int escr = 0;
465         unsigned int high = 0;
466         unsigned int counter_bit;
467         struct p4_event_binding * ev = 0;
468         unsigned int stag;
469
470         stag = get_stagger();
471         
472         /* convert from counter *number* to counter *bit* */
473         counter_bit = 1 << VIRT_CTR(stag, ctr);
474         
475         /* find our event binding structure. */
476         if (counter_config[ctr].event <= 0 || counter_config[ctr].event > NUM_EVENTS) {
477                 printk(KERN_ERR 
478                        "oprofile: P4 event code 0x%lx out of range\n", 
479                        counter_config[ctr].event);
480                 return;
481         }
482         
483         ev = &(p4_events[counter_config[ctr].event - 1]);
484         
485         for (i = 0; i < maxbind; i++) {
486                 if (ev->bindings[i].virt_counter & counter_bit) {
487
488                         /* modify ESCR */
489                         ESCR_READ(escr, high, ev, i);
490                         ESCR_CLEAR(escr);
491                         if (stag == 0) {
492                                 ESCR_SET_USR_0(escr, counter_config[ctr].user);
493                                 ESCR_SET_OS_0(escr, counter_config[ctr].kernel);
494                         } else {
495                                 ESCR_SET_USR_1(escr, counter_config[ctr].user);
496                                 ESCR_SET_OS_1(escr, counter_config[ctr].kernel);
497                         }
498                         ESCR_SET_EVENT_SELECT(escr, ev->event_select);
499                         ESCR_SET_EVENT_MASK(escr, counter_config[ctr].unit_mask);                       
500                         ESCR_WRITE(escr, high, ev, i);
501                        
502                         /* modify CCCR */
503                         CCCR_READ(cccr, high, VIRT_CTR(stag, ctr));
504                         CCCR_CLEAR(cccr);
505                         CCCR_SET_REQUIRED_BITS(cccr);
506                         CCCR_SET_ESCR_SELECT(cccr, ev->escr_select);
507                         if (stag == 0) {
508                                 CCCR_SET_PMI_OVF_0(cccr);
509                         } else {
510                                 CCCR_SET_PMI_OVF_1(cccr);
511                         }
512                         CCCR_WRITE(cccr, high, VIRT_CTR(stag, ctr));
513                         return;
514                 }
515         }
516
517         printk(KERN_ERR 
518                "oprofile: P4 event code 0x%lx no binding, stag %d ctr %d\n",
519                counter_config[ctr].event, stag, ctr);
520 }
521
522
523 static void p4_setup_ctrs(struct op_msrs const * const msrs)
524 {
525         unsigned int i;
526         unsigned int low, high;
527         unsigned int addr;
528         unsigned int stag;
529
530         stag = get_stagger();
531
532         rdmsr(MSR_IA32_MISC_ENABLE, low, high);
533         if (! MISC_PMC_ENABLED_P(low)) {
534                 printk(KERN_ERR "oprofile: P4 PMC not available\n");
535                 return;
536         }
537
538         /* clear the cccrs we will use */
539         for (i = 0 ; i < num_counters ; i++) {
540                 rdmsr(p4_counters[VIRT_CTR(stag, i)].cccr_address, low, high);
541                 CCCR_CLEAR(low);
542                 CCCR_SET_REQUIRED_BITS(low);
543                 wrmsr(p4_counters[VIRT_CTR(stag, i)].cccr_address, low, high);
544         }
545
546         /* clear cccrs outside our concern */
547         for (i = stag ; i < NUM_UNUSED_CCCRS ; i += addr_increment()) {
548                 rdmsr(p4_unused_cccr[i], low, high);
549                 CCCR_CLEAR(low);
550                 CCCR_SET_REQUIRED_BITS(low);
551                 wrmsr(p4_unused_cccr[i], low, high);
552         }
553
554         /* clear all escrs (including those outside our concern) */
555         for (addr = MSR_P4_BSU_ESCR0 + stag;
556              addr <= MSR_P4_SSU_ESCR0; addr += addr_increment()) { 
557                 wrmsr(addr, 0, 0);
558         }
559         
560         for (addr = MSR_P4_MS_ESCR0 + stag;
561              addr <= MSR_P4_TC_ESCR1; addr += addr_increment()){ 
562                 wrmsr(addr, 0, 0);
563         }
564         
565         for (addr = MSR_P4_IX_ESCR0 + stag;
566              addr <= MSR_P4_CRU_ESCR3; addr += addr_increment()){ 
567                 wrmsr(addr, 0, 0);
568         }
569
570         if (num_counters == NUM_COUNTERS_NON_HT) {              
571                 wrmsr(MSR_P4_CRU_ESCR4, 0, 0);
572                 wrmsr(MSR_P4_CRU_ESCR5, 0, 0);
573         } else if (stag == 0) {
574                 wrmsr(MSR_P4_CRU_ESCR4, 0, 0);
575         } else {
576                 wrmsr(MSR_P4_CRU_ESCR5, 0, 0);
577         }               
578         
579         /* setup all counters */
580         for (i = 0 ; i < num_counters ; ++i) {
581                 if (counter_config[i].event) {
582                         reset_value[i] = counter_config[i].count;
583                         pmc_setup_one_p4_counter(i);
584                         CTR_WRITE(counter_config[i].count, VIRT_CTR(stag, i));
585                 } else {
586                         reset_value[i] = 0;
587                 }
588         }
589 }
590
591
592 static int p4_check_ctrs(unsigned int const cpu, 
593                           struct op_msrs const * const msrs,
594                           struct pt_regs * const regs)
595 {
596         unsigned long ctr, low, high, stag, real;
597         int i;
598         unsigned long eip = instruction_pointer(regs);
599         int is_kernel = !user_mode(regs);
600
601         stag = get_stagger();
602
603         for (i = 0; i < num_counters; ++i) {
604                 
605                 if (!reset_value[i]) 
606                         continue;
607
608                 /* 
609                  * there is some eccentricity in the hardware which
610                  * requires that we perform 2 extra corrections:
611                  *
612                  * - check both the CCCR:OVF flag for overflow and the
613                  *   counter high bit for un-flagged overflows.
614                  *
615                  * - write the counter back twice to ensure it gets
616                  *   updated properly.
617                  * 
618                  * the former seems to be related to extra NMIs happening
619                  * during the current NMI; the latter is reported as errata
620                  * N15 in intel doc 249199-029, pentium 4 specification
621                  * update, though their suggested work-around does not
622                  * appear to solve the problem.
623                  */
624                 
625                 real = VIRT_CTR(stag, i);
626
627                 CCCR_READ(low, high, real);
628                 CTR_READ(ctr, high, real);
629                 if (CCCR_OVF_P(low) || CTR_OVERFLOW_P(ctr)) {
630                         oprofile_add_sample(eip, is_kernel, i, cpu);
631                         CTR_WRITE(reset_value[i], real);
632                         CCCR_CLEAR_OVF(low);
633                         CCCR_WRITE(low, high, real);
634                         CTR_WRITE(reset_value[i], real);
635                 }
636         }
637
638         /* P4 quirk: you have to re-unmask the apic vector */
639         apic_write(APIC_LVTPC, apic_read(APIC_LVTPC) & ~APIC_LVT_MASKED);
640
641         /* See op_model_ppro.c */
642         return 1;
643 }
644
645
646 static void p4_start(struct op_msrs const * const msrs)
647 {
648         unsigned int low, high, stag;
649         int i;
650
651         stag = get_stagger();
652
653         for (i = 0; i < num_counters; ++i) {
654                 if (!reset_value[i])
655                         continue;
656                 CCCR_READ(low, high, VIRT_CTR(stag, i));
657                 CCCR_SET_ENABLE(low);
658                 CCCR_WRITE(low, high, VIRT_CTR(stag, i));
659         }
660 }
661
662
663 static void p4_stop(struct op_msrs const * const msrs)
664 {
665         unsigned int low, high, stag;
666         int i;
667
668         stag = get_stagger();
669
670         for (i = 0; i < num_counters; ++i) {
671                 CCCR_READ(low, high, VIRT_CTR(stag, i));
672                 CCCR_SET_DISABLE(low);
673                 CCCR_WRITE(low, high, VIRT_CTR(stag, i));
674         }
675 }
676
677
678 #ifdef CONFIG_SMP
679 struct op_x86_model_spec const op_p4_ht2_spec = {
680         .num_counters = NUM_COUNTERS_HT2,
681         .num_controls = NUM_CONTROLS_HT2,
682         .fill_in_addresses = &p4_fill_in_addresses,
683         .setup_ctrs = &p4_setup_ctrs,
684         .check_ctrs = &p4_check_ctrs,
685         .start = &p4_start,
686         .stop = &p4_stop
687 };
688 #endif
689
690 struct op_x86_model_spec const op_p4_spec = {
691         .num_counters = NUM_COUNTERS_NON_HT,
692         .num_controls = NUM_CONTROLS_NON_HT,
693         .fill_in_addresses = &p4_fill_in_addresses,
694         .setup_ctrs = &p4_setup_ctrs,
695         .check_ctrs = &p4_check_ctrs,
696         .start = &p4_start,
697         .stop = &p4_stop
698 };