1
2
3
4
5
6
7
8
9
10
11#include <linux/oprofile.h>
12#include <linux/smp.h>
13#include <linux/ptrace.h>
14#include <asm/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
37static unsigned int num_counters = NUM_COUNTERS_NON_HT;
38static unsigned int num_controls = NUM_CONTROLS_NON_HT;
39
40
41
42
43static 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
53static inline int 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
64struct p4_counter_binding {
65 int virt_counter;
66 int counter_address;
67 int cccr_address;
68};
69
70struct p4_event_binding {
71 int escr_select;
72 int event_select;
73 struct {
74 int virt_counter;
75 int escr_address;
76 } bindings[2];
77};
78
79
80
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
92static 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
106
107static struct p4_event_binding p4_events[NUM_EVENTS] = {
108
109 {
110 0x05, 0x06,
111 { {CTR_IQ_4, MSR_P4_CRU_ESCR2},
112 {CTR_IQ_5, MSR_P4_CRU_ESCR3} }
113 },
114
115 {
116 0x04, 0x03,
117 { { CTR_IQ_4, MSR_P4_CRU_ESCR0},
118 { CTR_IQ_5, MSR_P4_CRU_ESCR1} }
119 },
120
121 {
122 0x01, 0x01,
123 { { CTR_MS_0, MSR_P4_TC_ESCR0},
124 { CTR_MS_2, MSR_P4_TC_ESCR1} }
125 },
126
127 {
128 0x00, 0x03,
129 { { CTR_BPU_0, MSR_P4_BPU_ESCR0},
130 { CTR_BPU_2, MSR_P4_BPU_ESCR1} }
131 },
132
133 {
134 0x03, 0x18,
135 { { CTR_BPU_0, MSR_P4_ITLB_ESCR0},
136 { CTR_BPU_2, MSR_P4_ITLB_ESCR1} }
137 },
138
139 {
140 0x05, 0x02,
141 { { CTR_FLAME_0, MSR_P4_DAC_ESCR0},
142 { CTR_FLAME_2, MSR_P4_DAC_ESCR1} }
143 },
144
145 {
146 0x02, 0x08,
147 { { CTR_FLAME_0, MSR_P4_SAAT_ESCR0},
148 { CTR_FLAME_2, MSR_P4_SAAT_ESCR1} }
149 },
150
151 {
152 0x02, 0x04,
153 { { CTR_FLAME_0, MSR_P4_SAAT_ESCR0},
154 { CTR_FLAME_2, MSR_P4_SAAT_ESCR1} }
155 },
156
157 {
158 0x02, 0x05,
159 { { CTR_FLAME_0, MSR_P4_SAAT_ESCR0},
160 { CTR_FLAME_2, MSR_P4_SAAT_ESCR1} }
161 },
162
163 {
164 0x02, 0x03,
165 { { CTR_BPU_0, MSR_P4_MOB_ESCR0},
166 { CTR_BPU_2, MSR_P4_MOB_ESCR1} }
167 },
168
169 {
170 0x04, 0x01,
171 { { CTR_BPU_0, MSR_P4_PMH_ESCR0},
172 { CTR_BPU_2, MSR_P4_PMH_ESCR1} }
173 },
174
175 {
176 0x07, 0x0c,
177 { { CTR_BPU_0, MSR_P4_BSU_ESCR0},
178 { CTR_BPU_2, MSR_P4_BSU_ESCR1} }
179 },
180
181 {
182 0x06, 0x03,
183 { { CTR_BPU_0, MSR_P4_FSB_ESCR0},
184 { 0, 0 } }
185 },
186
187 {
188 0x06, 0x1a,
189 { { CTR_BPU_2, MSR_P4_FSB_ESCR1},
190 { 0, 0 } }
191 },
192
193 {
194 0x06, 0x17,
195 { { CTR_BPU_0, MSR_P4_FSB_ESCR0},
196 { CTR_BPU_2, MSR_P4_FSB_ESCR1} }
197 },
198
199 {
200 0x07, 0x05,
201 { { CTR_BPU_0, MSR_P4_BSU_ESCR0},
202 { 0, 0 } }
203 },
204
205 {
206 0x07, 0x06,
207 { { CTR_BPU_2, MSR_P4_BSU_ESCR1 },
208 { 0, 0 } }
209 },
210
211 {
212 0x05, 0x03,
213 { { CTR_IQ_4, MSR_P4_CRU_ESCR2},
214 { CTR_IQ_5, MSR_P4_CRU_ESCR3} }
215 },
216
217 {
218 0x01, 0x34,
219 { { CTR_FLAME_0, MSR_P4_FIRM_ESCR0},
220 { CTR_FLAME_2, MSR_P4_FIRM_ESCR1} }
221 },
222
223 {
224 0x01, 0x08,
225 { { CTR_FLAME_0, MSR_P4_FIRM_ESCR0},
226 { CTR_FLAME_2, MSR_P4_FIRM_ESCR1} }
227 },
228
229 {
230 0x01, 0x0c,
231 { { CTR_FLAME_0, MSR_P4_FIRM_ESCR0},
232 { CTR_FLAME_2, MSR_P4_FIRM_ESCR1} }
233 },
234
235 {
236 0x01, 0x0a,
237 { { CTR_FLAME_0, MSR_P4_FIRM_ESCR0},
238 { CTR_FLAME_2, MSR_P4_FIRM_ESCR1} }
239 },
240
241 {
242 0x01, 0x0e,
243 { { CTR_FLAME_0, MSR_P4_FIRM_ESCR0},
244 { CTR_FLAME_2, MSR_P4_FIRM_ESCR1} }
245 },
246
247 {
248 0x01, 0x02,
249 { { CTR_FLAME_0, MSR_P4_FIRM_ESCR0},
250 { CTR_FLAME_2, MSR_P4_FIRM_ESCR1} }
251 },
252
253 {
254 0x01, 0x1a,
255 { { CTR_FLAME_0, MSR_P4_FIRM_ESCR0},
256 { CTR_FLAME_2, MSR_P4_FIRM_ESCR1} }
257 },
258
259 {
260 0x01, 0x04,
261 { { CTR_FLAME_0, MSR_P4_FIRM_ESCR0},
262 { CTR_FLAME_2, MSR_P4_FIRM_ESCR1} }
263 },
264
265 {
266 0x01, 0x2e,
267 { { CTR_FLAME_0, MSR_P4_FIRM_ESCR0},
268 { CTR_FLAME_2, MSR_P4_FIRM_ESCR1} }
269 },
270
271 {
272 0x05, 0x02,
273 { { CTR_IQ_4, MSR_P4_CRU_ESCR2},
274 { CTR_IQ_5, MSR_P4_CRU_ESCR3} }
275 },
276
277 {
278 0x06, 0x13 ,
279 { { CTR_BPU_0, MSR_P4_FSB_ESCR0},
280 { CTR_BPU_2, MSR_P4_FSB_ESCR1} }
281 },
282
283 {
284 0x00, 0x05,
285 { { CTR_MS_0, MSR_P4_MS_ESCR0},
286 { CTR_MS_2, MSR_P4_MS_ESCR1} }
287 },
288
289 {
290 0x00, 0x09,
291 { { CTR_MS_0, MSR_P4_MS_ESCR0},
292 { CTR_MS_2, MSR_P4_MS_ESCR1} }
293 },
294
295 {
296 0x05, 0x08,
297 { { CTR_IQ_4, MSR_P4_CRU_ESCR2},
298 { CTR_IQ_5, MSR_P4_CRU_ESCR3} }
299 },
300
301 {
302 0x05, 0x0c,
303 { { CTR_IQ_4, MSR_P4_CRU_ESCR2},
304 { CTR_IQ_5, MSR_P4_CRU_ESCR3} }
305 },
306
307 {
308 0x05, 0x09,
309 { { CTR_IQ_4, MSR_P4_CRU_ESCR2},
310 { CTR_IQ_5, MSR_P4_CRU_ESCR3} }
311 },
312
313 {
314 0x04, 0x02,
315 { { CTR_IQ_4, MSR_P4_CRU_ESCR0},
316 { CTR_IQ_5, MSR_P4_CRU_ESCR1} }
317 },
318
319 {
320 0x04, 0x01,
321 { { CTR_IQ_4, MSR_P4_CRU_ESCR0},
322 { CTR_IQ_5, MSR_P4_CRU_ESCR1} }
323 },
324
325 {
326 0x02, 0x02,
327 { { CTR_IQ_4, MSR_P4_RAT_ESCR0},
328 { CTR_IQ_5, MSR_P4_RAT_ESCR1} }
329 },
330
331 {
332 0x02, 0x05,
333 { { CTR_MS_0, MSR_P4_TBPU_ESCR0},
334 { CTR_MS_2, MSR_P4_TBPU_ESCR1} }
335 },
336
337 {
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
369
370
371static unsigned int get_stagger(void)
372{
373#ifdef CONFIG_SMP
374 int cpu = smp_processor_id();
375 return cpu != cpumask_first(this_cpu_cpumask_var_ptr(cpu_sibling_map));
376#endif
377 return 0;
378}
379
380
381
382
383
384#define VIRT_CTR(stagger, i) ((i) + ((num_counters) * (stagger)))
385
386static unsigned long reset_value[NUM_COUNTERS_NON_HT];
387
388static 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
398
399
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
407static int 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
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
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
433
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
467
468 if (num_counters == NUM_COUNTERS_NON_HT) {
469
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
477
478 if (reserve_evntsel_nmi(MSR_P4_CRU_ESCR4))
479 msrs->controls[i++].addr = MSR_P4_CRU_ESCR4;
480
481 } else {
482
483
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 for (i = 0; i < num_counters; ++i) {
491 if (!counter_config[i].enabled)
492 continue;
493 if (msrs->controls[i].addr)
494 continue;
495 op_x86_warn_reserved(i);
496 p4_shutdown(msrs);
497 return -EBUSY;
498 }
499
500 return 0;
501}
502
503
504static void pmc_setup_one_p4_counter(unsigned int ctr)
505{
506 int i;
507 int const maxbind = 2;
508 unsigned int cccr = 0;
509 unsigned int escr = 0;
510 unsigned int high = 0;
511 unsigned int counter_bit;
512 struct p4_event_binding *ev = NULL;
513 unsigned int stag;
514
515 stag = get_stagger();
516
517
518 counter_bit = 1 << VIRT_CTR(stag, ctr);
519
520
521 if (counter_config[ctr].event <= 0 || counter_config[ctr].event > NUM_EVENTS) {
522 printk(KERN_ERR
523 "oprofile: P4 event code 0x%lx out of range\n",
524 counter_config[ctr].event);
525 return;
526 }
527
528 ev = &(p4_events[counter_config[ctr].event - 1]);
529
530 for (i = 0; i < maxbind; i++) {
531 if (ev->bindings[i].virt_counter & counter_bit) {
532
533
534 rdmsr(ev->bindings[i].escr_address, escr, high);
535 ESCR_CLEAR(escr);
536 if (stag == 0) {
537 ESCR_SET_USR_0(escr, counter_config[ctr].user);
538 ESCR_SET_OS_0(escr, counter_config[ctr].kernel);
539 } else {
540 ESCR_SET_USR_1(escr, counter_config[ctr].user);
541 ESCR_SET_OS_1(escr, counter_config[ctr].kernel);
542 }
543 ESCR_SET_EVENT_SELECT(escr, ev->event_select);
544 ESCR_SET_EVENT_MASK(escr, counter_config[ctr].unit_mask);
545 wrmsr(ev->bindings[i].escr_address, escr, high);
546
547
548 rdmsr(p4_counters[VIRT_CTR(stag, ctr)].cccr_address,
549 cccr, high);
550 CCCR_CLEAR(cccr);
551 CCCR_SET_REQUIRED_BITS(cccr);
552 CCCR_SET_ESCR_SELECT(cccr, ev->escr_select);
553 if (stag == 0)
554 CCCR_SET_PMI_OVF_0(cccr);
555 else
556 CCCR_SET_PMI_OVF_1(cccr);
557 wrmsr(p4_counters[VIRT_CTR(stag, ctr)].cccr_address,
558 cccr, high);
559 return;
560 }
561 }
562
563 printk(KERN_ERR
564 "oprofile: P4 event code 0x%lx no binding, stag %d ctr %d\n",
565 counter_config[ctr].event, stag, ctr);
566}
567
568
569static void p4_setup_ctrs(struct op_x86_model_spec const *model,
570 struct op_msrs const * const msrs)
571{
572 unsigned int i;
573 unsigned int low, high;
574 unsigned int stag;
575
576 stag = get_stagger();
577
578 rdmsr(MSR_IA32_MISC_ENABLE, low, high);
579 if (!MISC_PMC_ENABLED_P(low)) {
580 printk(KERN_ERR "oprofile: P4 PMC not available\n");
581 return;
582 }
583
584
585 for (i = 0; i < num_counters; i++) {
586 if (unlikely(!msrs->controls[i].addr))
587 continue;
588 rdmsr(p4_counters[VIRT_CTR(stag, i)].cccr_address, low, high);
589 CCCR_CLEAR(low);
590 CCCR_SET_REQUIRED_BITS(low);
591 wrmsr(p4_counters[VIRT_CTR(stag, i)].cccr_address, low, high);
592 }
593
594
595 for (i = num_counters; i < num_controls; i++) {
596 if (unlikely(!msrs->controls[i].addr))
597 continue;
598 wrmsr(msrs->controls[i].addr, 0, 0);
599 }
600
601
602 for (i = 0; i < num_counters; ++i) {
603 if (counter_config[i].enabled && msrs->controls[i].addr) {
604 reset_value[i] = counter_config[i].count;
605 pmc_setup_one_p4_counter(i);
606 wrmsrl(p4_counters[VIRT_CTR(stag, i)].counter_address,
607 -(u64)counter_config[i].count);
608 } else {
609 reset_value[i] = 0;
610 }
611 }
612}
613
614
615static int p4_check_ctrs(struct pt_regs * const regs,
616 struct op_msrs const * const msrs)
617{
618 unsigned long ctr, low, high, stag, real;
619 int i;
620
621 stag = get_stagger();
622
623 for (i = 0; i < num_counters; ++i) {
624
625 if (!reset_value[i])
626 continue;
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645 real = VIRT_CTR(stag, i);
646
647 rdmsr(p4_counters[real].cccr_address, low, high);
648 rdmsr(p4_counters[real].counter_address, ctr, high);
649 if (CCCR_OVF_P(low) || !(ctr & OP_CTR_OVERFLOW)) {
650 oprofile_add_sample(regs, i);
651 wrmsrl(p4_counters[real].counter_address,
652 -(u64)reset_value[i]);
653 CCCR_CLEAR_OVF(low);
654 wrmsr(p4_counters[real].cccr_address, low, high);
655 wrmsrl(p4_counters[real].counter_address,
656 -(u64)reset_value[i]);
657 }
658 }
659
660
661 apic_write(APIC_LVTPC, apic_read(APIC_LVTPC) & ~APIC_LVT_MASKED);
662
663
664 return 1;
665}
666
667
668static void p4_start(struct op_msrs const * const msrs)
669{
670 unsigned int low, high, stag;
671 int i;
672
673 stag = get_stagger();
674
675 for (i = 0; i < num_counters; ++i) {
676 if (!reset_value[i])
677 continue;
678 rdmsr(p4_counters[VIRT_CTR(stag, i)].cccr_address, low, high);
679 CCCR_SET_ENABLE(low);
680 wrmsr(p4_counters[VIRT_CTR(stag, i)].cccr_address, low, high);
681 }
682}
683
684
685static void p4_stop(struct op_msrs const * const msrs)
686{
687 unsigned int low, high, stag;
688 int i;
689
690 stag = get_stagger();
691
692 for (i = 0; i < num_counters; ++i) {
693 if (!reset_value[i])
694 continue;
695 rdmsr(p4_counters[VIRT_CTR(stag, i)].cccr_address, low, high);
696 CCCR_SET_DISABLE(low);
697 wrmsr(p4_counters[VIRT_CTR(stag, i)].cccr_address, low, high);
698 }
699}
700
701#ifdef CONFIG_SMP
702struct op_x86_model_spec op_p4_ht2_spec = {
703 .num_counters = NUM_COUNTERS_HT2,
704 .num_controls = NUM_CONTROLS_HT2,
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};
712#endif
713
714struct op_x86_model_spec op_p4_spec = {
715 .num_counters = NUM_COUNTERS_NON_HT,
716 .num_controls = NUM_CONTROLS_NON_HT,
717 .fill_in_addresses = &p4_fill_in_addresses,
718 .setup_ctrs = &p4_setup_ctrs,
719 .check_ctrs = &p4_check_ctrs,
720 .start = &p4_start,
721 .stop = &p4_stop,
722 .shutdown = &p4_shutdown
723};
724