Merge master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
[linux-2.6] / 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 or four discontiguous group */
423         for (addr = MSR_P4_BSU_ESCR0 + stag;
424              addr < MSR_P4_IQ_ESCR0; ++i, addr += addr_increment()) {
425                 msrs->controls[i].addr = addr;
426         }
427
428         /* no IQ_ESCR0/1 on some models, we save a seconde time BSU_ESCR0/1
429          * to avoid special case in nmi_{save|restore}_registers() */
430         if (boot_cpu_data.x86_model >= 0x3) {
431                 for (addr = MSR_P4_BSU_ESCR0 + stag;
432                      addr <= MSR_P4_BSU_ESCR1; ++i, addr += addr_increment()) {
433                         msrs->controls[i].addr = addr;
434                 }
435         } else {
436                 for (addr = MSR_P4_IQ_ESCR0 + stag;
437                      addr <= MSR_P4_IQ_ESCR1; ++i, addr += addr_increment()) {
438                         msrs->controls[i].addr = addr;
439                 }
440         }
441
442         for (addr = MSR_P4_RAT_ESCR0 + stag;
443              addr <= MSR_P4_SSU_ESCR0; ++i, addr += addr_increment()) {
444                 msrs->controls[i].addr = addr;
445         }
446         
447         for (addr = MSR_P4_MS_ESCR0 + stag;
448              addr <= MSR_P4_TC_ESCR1; ++i, addr += addr_increment()) { 
449                 msrs->controls[i].addr = addr;
450         }
451         
452         for (addr = MSR_P4_IX_ESCR0 + stag;
453              addr <= MSR_P4_CRU_ESCR3; ++i, addr += addr_increment()) { 
454                 msrs->controls[i].addr = addr;
455         }
456
457         /* there are 2 remaining non-contiguously located ESCRs */
458
459         if (num_counters == NUM_COUNTERS_NON_HT) {              
460                 /* standard non-HT CPUs handle both remaining ESCRs*/
461                 msrs->controls[i++].addr = MSR_P4_CRU_ESCR5;
462                 msrs->controls[i++].addr = MSR_P4_CRU_ESCR4;
463
464         } else if (stag == 0) {
465                 /* HT CPUs give the first remainder to the even thread, as
466                    the 32nd control register */
467                 msrs->controls[i++].addr = MSR_P4_CRU_ESCR4;
468
469         } else {
470                 /* and two copies of the second to the odd thread,
471                    for the 22st and 23nd control registers */
472                 msrs->controls[i++].addr = MSR_P4_CRU_ESCR5;
473                 msrs->controls[i++].addr = MSR_P4_CRU_ESCR5;
474         }
475 }
476
477
478 static void pmc_setup_one_p4_counter(unsigned int ctr)
479 {
480         int i;
481         int const maxbind = 2;
482         unsigned int cccr = 0;
483         unsigned int escr = 0;
484         unsigned int high = 0;
485         unsigned int counter_bit;
486         struct p4_event_binding *ev = NULL;
487         unsigned int stag;
488
489         stag = get_stagger();
490         
491         /* convert from counter *number* to counter *bit* */
492         counter_bit = 1 << VIRT_CTR(stag, ctr);
493         
494         /* find our event binding structure. */
495         if (counter_config[ctr].event <= 0 || counter_config[ctr].event > NUM_EVENTS) {
496                 printk(KERN_ERR 
497                        "oprofile: P4 event code 0x%lx out of range\n", 
498                        counter_config[ctr].event);
499                 return;
500         }
501         
502         ev = &(p4_events[counter_config[ctr].event - 1]);
503         
504         for (i = 0; i < maxbind; i++) {
505                 if (ev->bindings[i].virt_counter & counter_bit) {
506
507                         /* modify ESCR */
508                         ESCR_READ(escr, high, ev, i);
509                         ESCR_CLEAR(escr);
510                         if (stag == 0) {
511                                 ESCR_SET_USR_0(escr, counter_config[ctr].user);
512                                 ESCR_SET_OS_0(escr, counter_config[ctr].kernel);
513                         } else {
514                                 ESCR_SET_USR_1(escr, counter_config[ctr].user);
515                                 ESCR_SET_OS_1(escr, counter_config[ctr].kernel);
516                         }
517                         ESCR_SET_EVENT_SELECT(escr, ev->event_select);
518                         ESCR_SET_EVENT_MASK(escr, counter_config[ctr].unit_mask);                       
519                         ESCR_WRITE(escr, high, ev, i);
520                        
521                         /* modify CCCR */
522                         CCCR_READ(cccr, high, VIRT_CTR(stag, ctr));
523                         CCCR_CLEAR(cccr);
524                         CCCR_SET_REQUIRED_BITS(cccr);
525                         CCCR_SET_ESCR_SELECT(cccr, ev->escr_select);
526                         if (stag == 0) {
527                                 CCCR_SET_PMI_OVF_0(cccr);
528                         } else {
529                                 CCCR_SET_PMI_OVF_1(cccr);
530                         }
531                         CCCR_WRITE(cccr, high, VIRT_CTR(stag, ctr));
532                         return;
533                 }
534         }
535
536         printk(KERN_ERR 
537                "oprofile: P4 event code 0x%lx no binding, stag %d ctr %d\n",
538                counter_config[ctr].event, stag, ctr);
539 }
540
541
542 static void p4_setup_ctrs(struct op_msrs const * const msrs)
543 {
544         unsigned int i;
545         unsigned int low, high;
546         unsigned int addr;
547         unsigned int stag;
548
549         stag = get_stagger();
550
551         rdmsr(MSR_IA32_MISC_ENABLE, low, high);
552         if (! MISC_PMC_ENABLED_P(low)) {
553                 printk(KERN_ERR "oprofile: P4 PMC not available\n");
554                 return;
555         }
556
557         /* clear the cccrs we will use */
558         for (i = 0 ; i < num_counters ; i++) {
559                 rdmsr(p4_counters[VIRT_CTR(stag, i)].cccr_address, low, high);
560                 CCCR_CLEAR(low);
561                 CCCR_SET_REQUIRED_BITS(low);
562                 wrmsr(p4_counters[VIRT_CTR(stag, i)].cccr_address, low, high);
563         }
564
565         /* clear cccrs outside our concern */
566         for (i = stag ; i < NUM_UNUSED_CCCRS ; i += addr_increment()) {
567                 rdmsr(p4_unused_cccr[i], low, high);
568                 CCCR_CLEAR(low);
569                 CCCR_SET_REQUIRED_BITS(low);
570                 wrmsr(p4_unused_cccr[i], low, high);
571         }
572
573         /* clear all escrs (including those outside our concern) */
574         for (addr = MSR_P4_BSU_ESCR0 + stag;
575              addr <  MSR_P4_IQ_ESCR0; addr += addr_increment()) {
576                 wrmsr(addr, 0, 0);
577         }
578
579         /* On older models clear also MSR_P4_IQ_ESCR0/1 */
580         if (boot_cpu_data.x86_model < 0x3) {
581                 wrmsr(MSR_P4_IQ_ESCR0, 0, 0);
582                 wrmsr(MSR_P4_IQ_ESCR1, 0, 0);
583         }
584
585         for (addr = MSR_P4_RAT_ESCR0 + stag;
586              addr <= MSR_P4_SSU_ESCR0; ++i, addr += addr_increment()) {
587                 wrmsr(addr, 0, 0);
588         }
589         
590         for (addr = MSR_P4_MS_ESCR0 + stag;
591              addr <= MSR_P4_TC_ESCR1; addr += addr_increment()){ 
592                 wrmsr(addr, 0, 0);
593         }
594         
595         for (addr = MSR_P4_IX_ESCR0 + stag;
596              addr <= MSR_P4_CRU_ESCR3; addr += addr_increment()){ 
597                 wrmsr(addr, 0, 0);
598         }
599
600         if (num_counters == NUM_COUNTERS_NON_HT) {              
601                 wrmsr(MSR_P4_CRU_ESCR4, 0, 0);
602                 wrmsr(MSR_P4_CRU_ESCR5, 0, 0);
603         } else if (stag == 0) {
604                 wrmsr(MSR_P4_CRU_ESCR4, 0, 0);
605         } else {
606                 wrmsr(MSR_P4_CRU_ESCR5, 0, 0);
607         }               
608         
609         /* setup all counters */
610         for (i = 0 ; i < num_counters ; ++i) {
611                 if (counter_config[i].enabled) {
612                         reset_value[i] = counter_config[i].count;
613                         pmc_setup_one_p4_counter(i);
614                         CTR_WRITE(counter_config[i].count, VIRT_CTR(stag, i));
615                 } else {
616                         reset_value[i] = 0;
617                 }
618         }
619 }
620
621
622 static int p4_check_ctrs(struct pt_regs * const regs,
623                          struct op_msrs const * const msrs)
624 {
625         unsigned long ctr, low, high, stag, real;
626         int i;
627
628         stag = get_stagger();
629
630         for (i = 0; i < num_counters; ++i) {
631                 
632                 if (!reset_value[i]) 
633                         continue;
634
635                 /* 
636                  * there is some eccentricity in the hardware which
637                  * requires that we perform 2 extra corrections:
638                  *
639                  * - check both the CCCR:OVF flag for overflow and the
640                  *   counter high bit for un-flagged overflows.
641                  *
642                  * - write the counter back twice to ensure it gets
643                  *   updated properly.
644                  * 
645                  * the former seems to be related to extra NMIs happening
646                  * during the current NMI; the latter is reported as errata
647                  * N15 in intel doc 249199-029, pentium 4 specification
648                  * update, though their suggested work-around does not
649                  * appear to solve the problem.
650                  */
651                 
652                 real = VIRT_CTR(stag, i);
653
654                 CCCR_READ(low, high, real);
655                 CTR_READ(ctr, high, real);
656                 if (CCCR_OVF_P(low) || CTR_OVERFLOW_P(ctr)) {
657                         oprofile_add_sample(regs, i);
658                         CTR_WRITE(reset_value[i], real);
659                         CCCR_CLEAR_OVF(low);
660                         CCCR_WRITE(low, high, real);
661                         CTR_WRITE(reset_value[i], real);
662                 }
663         }
664
665         /* P4 quirk: you have to re-unmask the apic vector */
666         apic_write(APIC_LVTPC, apic_read(APIC_LVTPC) & ~APIC_LVT_MASKED);
667
668         /* See op_model_ppro.c */
669         return 1;
670 }
671
672
673 static void p4_start(struct op_msrs const * const msrs)
674 {
675         unsigned int low, high, stag;
676         int i;
677
678         stag = get_stagger();
679
680         for (i = 0; i < num_counters; ++i) {
681                 if (!reset_value[i])
682                         continue;
683                 CCCR_READ(low, high, VIRT_CTR(stag, i));
684                 CCCR_SET_ENABLE(low);
685                 CCCR_WRITE(low, high, VIRT_CTR(stag, i));
686         }
687 }
688
689
690 static void p4_stop(struct op_msrs const * const msrs)
691 {
692         unsigned int low, high, stag;
693         int i;
694
695         stag = get_stagger();
696
697         for (i = 0; i < num_counters; ++i) {
698                 CCCR_READ(low, high, VIRT_CTR(stag, i));
699                 CCCR_SET_DISABLE(low);
700                 CCCR_WRITE(low, high, VIRT_CTR(stag, i));
701         }
702 }
703
704
705 #ifdef CONFIG_SMP
706 struct op_x86_model_spec const op_p4_ht2_spec = {
707         .num_counters = NUM_COUNTERS_HT2,
708         .num_controls = NUM_CONTROLS_HT2,
709         .fill_in_addresses = &p4_fill_in_addresses,
710         .setup_ctrs = &p4_setup_ctrs,
711         .check_ctrs = &p4_check_ctrs,
712         .start = &p4_start,
713         .stop = &p4_stop
714 };
715 #endif
716
717 struct op_x86_model_spec const op_p4_spec = {
718         .num_counters = NUM_COUNTERS_NON_HT,
719         .num_controls = NUM_CONTROLS_NON_HT,
720         .fill_in_addresses = &p4_fill_in_addresses,
721         .setup_ctrs = &p4_setup_ctrs,
722         .check_ctrs = &p4_check_ctrs,
723         .start = &p4_start,
724         .stop = &p4_stop
725 };