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