ia64/xen-unstable

view tools/misc/cpuperf/module/perfcntr.c @ 6422:e24fd7012ffb

merge?
author cl349@firebug.cl.cam.ac.uk
date Thu Aug 25 10:09:39 2005 +0000 (2005-08-25)
parents cfee4c4a8ed6
children
line source
1 /*
2 * Linux loadable kernel module to use P4 performance counters.
3 *
4 * James Bulpin, Feb 2003.
5 *
6 * $Id$
7 *
8 * $Log$
9 */
11 #define DRV_NAME "perfcntr"
12 #define DRV_VERSION "0.2"
13 #define DRV_RELDATE "02 Jun 2004"
16 #include <linux/module.h>
17 #include <linux/kernel.h>
18 #include <linux/init.h>
19 #include <linux/types.h>
20 #include <linux/proc_fs.h>
21 #include <linux/seq_file.h>
23 #include <asm/uaccess.h>
24 #include <asm/pgtable.h>
25 #include <asm/io.h>
26 #include <asm/processor.h>
28 #define NOHT
30 #include "../p4perf.h"
32 #ifdef NOHT
33 # define CPUMASK 0x00000003
34 #else
35 # define CPUMASK 0x00000005
36 #endif
38 /*****************************************************************************
39 * Module admin *
40 *****************************************************************************/
42 MODULE_AUTHOR("James Bulpin <James.Bulpin@cl.cam.ac.uk>");
43 MODULE_DESCRIPTION("P4 Performance Counters access "
44 DRV_VERSION " " DRV_RELDATE);
45 MODULE_LICENSE("GPL");
47 static char version[] __devinitdata =
48 DRV_NAME ": James Bulpin.\n";
50 static unsigned char foobar[4];
52 /* rpcc: get full 64-bit Pentium TSC value
53 */
54 static __inline__ unsigned long long int rpcc(void)
55 {
56 unsigned int __h, __l;
57 __asm__ __volatile__ ("rdtsc" :"=a" (__l), "=d" (__h));
58 return (((unsigned long long)__h) << 32) + __l;
59 }
61 /*****************************************************************************
62 * Display the counters *
63 *****************************************************************************/
65 //#define processor cpu // post 2.4.16
67 typedef union {
68 struct {
69 unsigned long lo;
70 unsigned long hi;
71 };
72 unsigned long long cnt;
73 } cpu_perfcntr_t;
75 typedef struct counters_t_struct {
76 int processor;
77 unsigned long long tsc;
78 cpu_perfcntr_t counters[18];
79 } counters_t;
81 typedef struct perfcntr_t_struct {
82 unsigned long cpu_mask;
83 counters_t cpus[4]; // Actually for each cpu in system
84 } perfcntr_t;
86 #ifdef HUMAN_READABLE
87 # define SHOW_COUNTER(c) rdmsr (c, l, h);\
88 seq_printf(m, "0x%03x: 0x%08x%08x\n", c, h, l)
89 #else
90 # define SHOW_COUNTER(c) rdmsr (c, l, h);\
91 seq_printf(m, " %llu", \
92 (unsigned long long)h << 32 | (unsigned long long)l)
93 #endif
95 #if 0
96 static unsigned long last_l = 0, last_h = 0, last_msr = 0;
97 static int last_cpu = 0;
98 #endif
100 #define READ_COUNTER(_i, _msr) rdmsr((_msr), l, h); c->counters[_i].lo = l; \
101 c->counters[_i].hi = h;
103 static perfcntr_t perfcntrs;
105 static void show_perfcntr_for(void *v)
106 {
107 unsigned int l, h;
109 perfcntr_t *p = &perfcntrs;
110 counters_t *c;
112 if (!((1 << smp_processor_id()) & p->cpu_mask))
113 return;
115 c = &p->cpus[smp_processor_id()];
117 c->processor = smp_processor_id();
118 c->tsc = rpcc();
120 READ_COUNTER(0, MSR_P4_BPU_COUNTER0);
121 READ_COUNTER(1, MSR_P4_BPU_COUNTER1);
122 READ_COUNTER(2, MSR_P4_BPU_COUNTER2);
123 READ_COUNTER(3, MSR_P4_BPU_COUNTER3);
125 READ_COUNTER(4, MSR_P4_MS_COUNTER0);
126 READ_COUNTER(5, MSR_P4_MS_COUNTER1);
127 READ_COUNTER(6, MSR_P4_MS_COUNTER2);
128 READ_COUNTER(7, MSR_P4_MS_COUNTER3);
130 READ_COUNTER(8, MSR_P4_FLAME_COUNTER0);
131 READ_COUNTER(9, MSR_P4_FLAME_COUNTER1);
132 READ_COUNTER(10, MSR_P4_FLAME_COUNTER2);
133 READ_COUNTER(11, MSR_P4_FLAME_COUNTER3);
135 READ_COUNTER(12, MSR_P4_IQ_COUNTER0);
136 READ_COUNTER(13, MSR_P4_IQ_COUNTER1);
137 READ_COUNTER(14, MSR_P4_IQ_COUNTER2);
138 READ_COUNTER(15, MSR_P4_IQ_COUNTER3);
139 READ_COUNTER(16, MSR_P4_IQ_COUNTER4);
140 READ_COUNTER(17, MSR_P4_IQ_COUNTER5);
142 return;
143 }
145 static int show_perfcntr(struct seq_file *m, void *v)
146 {
147 int i, j;
149 // Get each physical cpu to read counters
150 perfcntrs.cpu_mask = CPUMASK;
152 smp_call_function(show_perfcntr_for, NULL, 1, 1);
153 show_perfcntr_for(NULL);
155 for (i = 0; i < 32; i++) {
156 if (((1 << i) & (perfcntrs.cpu_mask = CPUMASK))) {
157 counters_t *c = &perfcntrs.cpus[i];
158 seq_printf(m, "%u %llu", c->processor, c->tsc);
159 for (j = 0; j < 18; j++) {
160 seq_printf(m, " %llu", c->counters[j].cnt);
161 }
162 seq_printf(m, "\n");
163 }
164 }
166 #if 0
167 unsigned long long t;
168 unsigned int l, h;
170 t = rpcc();
174 #ifdef HUMAN_READABLE
175 seq_printf(m,
176 "show_perfcntr\nprocessor: %u\ntime: %llu\n"
177 "last write: 0x%08lx%08lx -> 0x%lx (CPU%u)\n",
178 smp_processor_id(),
179 t,
180 last_h,
181 last_l,
182 last_msr,
183 last_cpu);
184 #else
185 seq_printf(m, "%u %llu", smp_processor_id(), t);
186 #endif
188 SHOW_COUNTER(MSR_P4_BPU_COUNTER0);
189 SHOW_COUNTER(MSR_P4_BPU_COUNTER1);
190 SHOW_COUNTER(MSR_P4_BPU_COUNTER2);
191 SHOW_COUNTER(MSR_P4_BPU_COUNTER3);
193 SHOW_COUNTER(MSR_P4_MS_COUNTER0);
194 SHOW_COUNTER(MSR_P4_MS_COUNTER1);
195 SHOW_COUNTER(MSR_P4_MS_COUNTER2);
196 SHOW_COUNTER(MSR_P4_MS_COUNTER3);
198 SHOW_COUNTER(MSR_P4_FLAME_COUNTER0);
199 SHOW_COUNTER(MSR_P4_FLAME_COUNTER1);
200 SHOW_COUNTER(MSR_P4_FLAME_COUNTER2);
201 SHOW_COUNTER(MSR_P4_FLAME_COUNTER3);
203 SHOW_COUNTER(MSR_P4_IQ_COUNTER0);
204 SHOW_COUNTER(MSR_P4_IQ_COUNTER1);
205 SHOW_COUNTER(MSR_P4_IQ_COUNTER2);
206 SHOW_COUNTER(MSR_P4_IQ_COUNTER3);
207 SHOW_COUNTER(MSR_P4_IQ_COUNTER4);
208 SHOW_COUNTER(MSR_P4_IQ_COUNTER5);
210 #ifndef HUMAN_READBLE
211 seq_printf(m, "\n");
212 #endif
214 #endif
216 return 0;
217 }
219 /*****************************************************************************
220 * Show counter configuration *
221 *****************************************************************************/
223 typedef union {
224 struct {
225 unsigned long lo;
226 unsigned long hi;
227 };
228 unsigned long long cnt;
229 } cpu_perfcfg_t;
231 typedef struct configs_t_struct {
232 int processor;
233 unsigned long long tsc;
234 cpu_perfcfg_t cccr[18];
235 cpu_perfcfg_t escr[0x42];
236 } configs_t;
238 typedef struct perfcfg_t_struct {
239 unsigned long cpu_mask;
240 configs_t cpus[4]; // Actually for each cpu in system
241 } perfcfg_t;
243 static perfcfg_t perfcfgs;
245 #define READ_CCCR(_i, _msr) rdmsr((_msr), l, h); c->cccr[_i].lo = l; \
246 c->cccr[_i].hi = h;
247 #define READ_ESCR(_i, _msr) rdmsr((_msr), l, h); c->escr[_i].lo = l; \
248 c->escr[_i].hi = h;
250 static void show_perfcfg_for(void *v)
251 {
252 unsigned int l, h;
254 perfcfg_t *p = &perfcfgs;
255 configs_t *c;
257 if (!((1 << smp_processor_id()) & p->cpu_mask))
258 return;
260 c = &p->cpus[smp_processor_id()];
262 c->processor = smp_processor_id();
263 c->tsc = rpcc();
265 READ_CCCR(0, MSR_P4_BPU_CCCR0);
266 READ_CCCR(1, MSR_P4_BPU_CCCR1);
267 READ_CCCR(2, MSR_P4_BPU_CCCR2);
268 READ_CCCR(3, MSR_P4_BPU_CCCR3);
270 READ_CCCR(4, MSR_P4_MS_CCCR0);
271 READ_CCCR(5, MSR_P4_MS_CCCR1);
272 READ_CCCR(6, MSR_P4_MS_CCCR2);
273 READ_CCCR(7, MSR_P4_MS_CCCR3);
275 READ_CCCR(8, MSR_P4_FLAME_CCCR0);
276 READ_CCCR(9, MSR_P4_FLAME_CCCR1);
277 READ_CCCR(10, MSR_P4_FLAME_CCCR2);
278 READ_CCCR(11, MSR_P4_FLAME_CCCR3);
280 READ_CCCR(12, MSR_P4_IQ_CCCR0);
281 READ_CCCR(13, MSR_P4_IQ_CCCR1);
282 READ_CCCR(14, MSR_P4_IQ_CCCR2);
283 READ_CCCR(15, MSR_P4_IQ_CCCR3);
284 READ_CCCR(16, MSR_P4_IQ_CCCR4);
285 READ_CCCR(17, MSR_P4_IQ_CCCR5);
287 READ_ESCR(0x00, MSR_P4_BSU_ESCR0);
288 READ_ESCR(0x02, MSR_P4_FSB_ESCR0);
289 READ_ESCR(0x0a, MSR_P4_MOB_ESCR0);
290 READ_ESCR(0x0c, MSR_P4_PMH_ESCR0);
291 READ_ESCR(0x12, MSR_P4_BPU_ESCR0);
292 READ_ESCR(0x14, MSR_P4_IS_ESCR0);
293 READ_ESCR(0x16, MSR_P4_ITLB_ESCR0);
294 READ_ESCR(0x28, MSR_P4_IX_ESCR0);
295 READ_ESCR(0x01, MSR_P4_BSU_ESCR1);
296 READ_ESCR(0x03, MSR_P4_FSB_ESCR1);
297 READ_ESCR(0x0b, MSR_P4_MOB_ESCR1);
298 READ_ESCR(0x0d, MSR_P4_PMH_ESCR1);
299 READ_ESCR(0x13, MSR_P4_BPU_ESCR1);
300 READ_ESCR(0x15, MSR_P4_IS_ESCR1);
301 READ_ESCR(0x17, MSR_P4_ITLB_ESCR1);
302 READ_ESCR(0x29, MSR_P4_IX_ESCR1);
303 READ_ESCR(0x20, MSR_P4_MS_ESCR0);
304 READ_ESCR(0x22, MSR_P4_TBPU_ESCR0);
305 READ_ESCR(0x24, MSR_P4_TC_ESCR0);
306 READ_ESCR(0x21, MSR_P4_MS_ESCR1);
307 READ_ESCR(0x23, MSR_P4_TBPU_ESCR1);
308 READ_ESCR(0x25, MSR_P4_TC_ESCR1);
309 READ_ESCR(0x04, MSR_P4_FIRM_ESCR0);
310 READ_ESCR(0x06, MSR_P4_FLAME_ESCR0);
311 READ_ESCR(0x08, MSR_P4_DAC_ESCR0);
312 READ_ESCR(0x0e, MSR_P4_SAAT_ESCR0);
313 READ_ESCR(0x10, MSR_P4_U2L_ESCR0);
314 READ_ESCR(0x05, MSR_P4_FIRM_ESCR1);
315 READ_ESCR(0x07, MSR_P4_FLAME_ESCR1);
316 READ_ESCR(0x09, MSR_P4_DAC_ESCR1);
317 READ_ESCR(0x0f, MSR_P4_SAAT_ESCR1);
318 READ_ESCR(0x11, MSR_P4_U2L_ESCR1);
319 READ_ESCR(0x18, MSR_P4_CRU_ESCR0);
320 READ_ESCR(0x2c, MSR_P4_CRU_ESCR2);
321 READ_ESCR(0x40, MSR_P4_CRU_ESCR4);
322 READ_ESCR(0x1a, MSR_P4_IQ_ESCR0);
323 READ_ESCR(0x1c, MSR_P4_RAT_ESCR0);
324 READ_ESCR(0x1e, MSR_P4_SSU_ESCR0);
325 READ_ESCR(0x2a, MSR_P4_ALF_ESCR0);
326 READ_ESCR(0x19, MSR_P4_CRU_ESCR1);
327 READ_ESCR(0x2d, MSR_P4_CRU_ESCR3);
328 READ_ESCR(0x41, MSR_P4_CRU_ESCR5);
329 READ_ESCR(0x1b, MSR_P4_IQ_ESCR1);
330 READ_ESCR(0x1d, MSR_P4_RAT_ESCR1);
331 READ_ESCR(0x2b, MSR_P4_ALF_ESCR1);
333 return;
334 }
336 static char *escr_names[] = {
337 "BSU_ESCR0",
338 "BSU_ESCR1",
339 "FSB_ESCR0",
340 "FSB_ESCR1",
341 "FIRM_ESCR0",
342 "FIRM_ESCR1",
343 "FLAME_ESCR0",
344 "FLAME_ESCR1",
345 "DAC_ESCR0",
346 "DAC_ESCR1",
347 "MOB_ESCR0",
348 "MOB_ESCR1",
349 "PMH_ESCR0",
350 "PMH_ESCR1",
351 "SAAT_ESCR0",
352 "SAAT_ESCR1",
353 "U2L_ESCR0",
354 "U2L_ESCR1",
355 "BPU_ESCR0",
356 "BPU_ESCR1",
357 "IS_ESCR0",
358 "IS_ESCR1",
359 "ITLB_ESCR0",
360 "ITLB_ESCR1",
361 "CRU_ESCR0",
362 "CRU_ESCR1",
363 "IQ_ESCR0",
364 "IQ_ESCR1",
365 "RAT_ESCR0",
366 "RAT_ESCR1",
367 "SSU_ESCR0",
368 "SSU_ESCR1",
369 "MS_ESCR0",
370 "MS_ESCR1",
371 "TBPU_ESCR0",
372 "TBPU_ESCR1",
373 "TC_ESCR0",
374 "TC_ESCR1",
375 "0x3c6",
376 "0x3c7",
377 "IX_ESCR0",
378 "IX_ESCR1",
379 "ALF_ESCR0",
380 "ALF_ESCR1",
381 "CRU_ESCR2",
382 "CRU_ESCR3",
383 "0x3ce",
384 "0x3cf",
385 "0x3d0",
386 "0x3d1",
387 "0x3d2",
388 "0x3d3",
389 "0x3d4",
390 "0x3d5",
391 "0x3d6",
392 "0x3d7",
393 "0x3d8",
394 "0x3d9",
395 "0x3da",
396 "0x3db",
397 "0x3dc",
398 "0x3dd",
399 "0x3de",
400 "0x3df",
401 "CRU_ESCR4",
402 "CRU_ESCR5"
403 };
405 static unsigned long escr_map_0[] =
406 {MSR_P4_BPU_ESCR0, MSR_P4_IS_ESCR0,
407 MSR_P4_MOB_ESCR0, MSR_P4_ITLB_ESCR0,
408 MSR_P4_PMH_ESCR0, MSR_P4_IX_ESCR0,
409 MSR_P4_FSB_ESCR0, MSR_P4_BSU_ESCR0}; //BPU even
410 static unsigned long escr_map_1[] =
411 {MSR_P4_BPU_ESCR1, MSR_P4_IS_ESCR1,
412 MSR_P4_MOB_ESCR1, MSR_P4_ITLB_ESCR1,
413 MSR_P4_PMH_ESCR1, MSR_P4_IX_ESCR1,
414 MSR_P4_FSB_ESCR1, MSR_P4_BSU_ESCR1}; //BPU odd
415 static unsigned long escr_map_2[] =
416 {MSR_P4_MS_ESCR0, MSR_P4_TC_ESCR0, MSR_P4_TBPU_ESCR0,
417 0, 0, 0, 0, 0}; //MS even
418 static unsigned long escr_map_3[] =
419 {MSR_P4_MS_ESCR1, MSR_P4_TC_ESCR1, MSR_P4_TBPU_ESCR1,
420 0, 0, 0, 0, 0}; //MS odd
421 static unsigned long escr_map_4[] =
422 {MSR_P4_FLAME_ESCR0, MSR_P4_FIRM_ESCR0, MSR_P4_SAAT_ESCR0,
423 MSR_P4_U2L_ESCR0, 0, MSR_P4_DAC_ESCR0, 0, 0}; //FLAME even
424 static unsigned long escr_map_5[] =
425 {MSR_P4_FLAME_ESCR1, MSR_P4_FIRM_ESCR1, MSR_P4_SAAT_ESCR1,
426 MSR_P4_U2L_ESCR1, 0, MSR_P4_DAC_ESCR1, 0, 0}; //FLAME odd
427 static unsigned long escr_map_6[] =
428 {MSR_P4_IQ_ESCR0, MSR_P4_ALF_ESCR0,
429 MSR_P4_RAT_ESCR0, MSR_P4_SSU_ESCR0,
430 MSR_P4_CRU_ESCR0, MSR_P4_CRU_ESCR2, MSR_P4_CRU_ESCR4, 0}; //IQ even
431 static unsigned long escr_map_7[] =
432 {MSR_P4_IQ_ESCR1, MSR_P4_ALF_ESCR1,
433 MSR_P4_RAT_ESCR1, 0,
434 MSR_P4_CRU_ESCR1, MSR_P4_CRU_ESCR3, MSR_P4_CRU_ESCR5, 0}; //IQ odd
436 static unsigned long *escr_map[] = {
437 escr_map_0,
438 escr_map_1,
439 escr_map_2,
440 escr_map_3,
441 escr_map_4,
442 escr_map_5,
443 escr_map_6,
444 escr_map_7,
445 };
447 unsigned long get_escr_msr(int c, int e)
448 {
449 int index = -1;
451 // Get the ESCR MSR address from the counter number and the ESCR number.
452 switch (c) {
453 case P4_BPU_COUNTER0_NUMBER:
454 case P4_BPU_COUNTER1_NUMBER:
455 index = 0;
456 break;
457 case P4_BPU_COUNTER2_NUMBER:
458 case P4_BPU_COUNTER3_NUMBER:
459 index = 1;
460 break;
461 case P4_MS_COUNTER0_NUMBER:
462 case P4_MS_COUNTER1_NUMBER:
463 index = 2; // probably !
464 break;
465 case P4_MS_COUNTER2_NUMBER:
466 case P4_MS_COUNTER3_NUMBER:
467 index = 3; // probably !
468 break;
469 case P4_FLAME_COUNTER0_NUMBER:
470 case P4_FLAME_COUNTER1_NUMBER:
471 index = 4; // probably !
472 break;
473 case P4_FLAME_COUNTER2_NUMBER:
474 case P4_FLAME_COUNTER3_NUMBER:
475 index = 5; // probably !
476 break;
477 case P4_IQ_COUNTER0_NUMBER:
478 case P4_IQ_COUNTER1_NUMBER:
479 case P4_IQ_COUNTER4_NUMBER:
480 index = 6;
481 break;
482 case P4_IQ_COUNTER2_NUMBER:
483 case P4_IQ_COUNTER3_NUMBER:
484 case P4_IQ_COUNTER5_NUMBER:
485 index = 7;
486 break;
487 }
489 if (index != -1) {
490 return escr_map[index][e];
491 }
493 return 0;
494 }
496 static char null_string[] = "";
497 static char *get_escr(int c, int e)
498 {
499 unsigned long msr = get_escr_msr(c, e);
501 if ((msr >= 0x3a0) && (msr <= 0x3e1))
502 return escr_names[(int)(msr - 0x3a0)];
503 return null_string;
504 }
506 static int show_perfcfg(struct seq_file *m, void *v)
507 {
508 int i, j;
510 // Get each physical cpu to read configs
511 perfcfgs.cpu_mask = CPUMASK;
513 smp_call_function(show_perfcfg_for, NULL, 1, 1);
514 show_perfcfg_for(NULL);
516 for (i = 0; i < 32; i++) {
517 if (((1 << i) & (perfcfgs.cpu_mask = CPUMASK))) {
518 configs_t *c = &perfcfgs.cpus[i];
519 seq_printf(m, "----------------------------------------\n");
520 seq_printf(m, "%u %llu\n", c->processor, c->tsc);
521 for (j = 0; j < 18; j++) {
522 seq_printf(m, "%08lx", c->cccr[j].lo);
524 if (!(c->cccr[j].lo & P4_CCCR_ENABLE))
525 seq_printf(m, " DISABLED");
526 else {
527 unsigned long escr_msr =
528 get_escr_msr(i, (int)((c->cccr[j].lo >> 13)&7));
529 seq_printf(m, " ESCR=%s",
530 get_escr(i, (int)((c->cccr[j].lo >> 13)&7)));
531 if ((escr_msr >= 0x3a0) && (escr_msr <= 0x3e1)) {
532 unsigned long e = c->escr[(int)(escr_msr - 0x3a0)].lo;
533 seq_printf(m, "(%08lx es=%lx mask=%lx", e,
534 (e >> 25) & 0x7f,
535 (e >> 9) & 0xffff);
536 if ((e & P4_ESCR_T0_USR))
537 seq_printf(m, " T(0)USR");
538 if ((e & P4_ESCR_T0_OS))
539 seq_printf(m, " T(0)OS");
540 if ((e & P4_ESCR_T1_USR))
541 seq_printf(m, " T1USR");
542 if ((e & P4_ESCR_T1_OS))
543 seq_printf(m, " T1OS");
544 seq_printf(m, ")");
545 }
546 seq_printf(m, " AT=%u", (int)((c->cccr[j].lo >> 16)&3));
548 if ((c->cccr[j].lo & P4_CCCR_OVF))
549 seq_printf(m, " OVF");
550 if ((c->cccr[j].lo & P4_CCCR_CASCADE))
551 seq_printf(m, " CASC");
552 if ((c->cccr[j].lo & P4_CCCR_FORCE_OVF))
553 seq_printf(m, " F-OVF");
554 if ((c->cccr[j].lo & P4_CCCR_EDGE))
555 seq_printf(m, " EDGE");
556 if ((c->cccr[j].lo & P4_CCCR_COMPLEMENT))
557 seq_printf(m, " COMPL");
558 if ((c->cccr[j].lo & P4_CCCR_COMPARE))
559 seq_printf(m, " CMP");
560 if ((c->cccr[j].lo & P4_CCCR_OVF_PMI_T0))
561 seq_printf(m, " OVF_PMI(_T0)");
562 if ((c->cccr[j].lo & P4_CCCR_OVF_PMI_T1))
563 seq_printf(m, " OVF_PMI_T1");
564 }
565 seq_printf(m, "\n");
566 }
567 }
568 }
570 return 0;
571 }
573 /*****************************************************************************
574 * Handle writes *
575 *****************************************************************************/
577 static int set_msr_cpu_mask;
578 static unsigned long set_msr_addr;
579 static unsigned long set_msr_lo;
580 static unsigned long set_msr_hi;
582 static void perfcntr_write_for(void *unused)
583 {
584 #ifdef NOHT
585 if (((1 << smp_processor_id()) & set_msr_cpu_mask)) {
586 #endif
587 //printk("perfcntr: wrmsr(%08lx, %08lx, %08lx)\n",
588 // set_msr_addr, set_msr_lo, set_msr_hi);
589 wrmsr(set_msr_addr, set_msr_lo, set_msr_hi);
590 #ifdef NOHT
591 }
592 #endif
593 }
595 ssize_t perfcntr_write(struct file *f,
596 const char *data,
597 size_t size,
598 loff_t *pos)
599 {
600 char *endp;
601 ssize_t ret = 0;
602 //unsigned long l, h, msr;
603 unsigned long long v;
605 set_msr_cpu_mask = (int)simple_strtoul(data, &endp, 16);
606 endp++; // skip past space
607 if ((endp - data) >= size) {
608 ret = -EINVAL;
609 goto out;
610 }
612 set_msr_addr = simple_strtoul(endp, &endp, 16);
613 endp++; // skip past space
614 if ((endp - data) >= size) {
615 ret = -EINVAL;
616 goto out;
617 }
619 v = simple_strtoul(endp, &endp, 16);
620 set_msr_lo = (unsigned long)(v & 0xffffffffULL);
621 set_msr_hi = (unsigned long)(v >> 32);
623 smp_call_function(perfcntr_write_for, NULL, 1, 1);
624 perfcntr_write_for(NULL);
626 #if 0
627 wrmsr(msr, l, h);
628 last_l = l;
629 last_h = h;
630 last_msr = msr;
631 last_cpu = smp_processor_id();
632 #endif
633 ret = size;
635 out:
636 return ret;
637 }
639 /*****************************************************************************
640 * /proc stuff *
641 *****************************************************************************/
643 static void *c_start(struct seq_file *m, loff_t *pos)
644 {
645 //return *pos < NR_CPUS ? cpu_data + *pos : NULL;
646 return *pos == 0 ? foobar : NULL;
647 }
649 static void *c_next(struct seq_file *m, void *v, loff_t *pos)
650 {
651 ++*pos;
652 return c_start(m, pos);
653 }
655 static void c_stop(struct seq_file *m, void *v)
656 {
657 }
659 struct seq_operations perfcntr_op = {
660 start: c_start,
661 next: c_next,
662 stop: c_stop,
663 show: show_perfcntr,
664 };
666 struct seq_operations perfcfg_op = {
667 start: c_start,
668 next: c_next,
669 stop: c_stop,
670 show: show_perfcfg,
671 };
673 static int perfcntr_open(struct inode *inode, struct file *file)
674 {
675 return seq_open(file, &perfcntr_op);
676 }
678 static int perfcfg_open(struct inode *inode, struct file *file)
679 {
680 return seq_open(file, &perfcfg_op);
681 }
683 static struct file_operations proc_perfcntr_operations = {
684 open: perfcntr_open,
685 read: seq_read,
686 write: perfcntr_write,
687 llseek: seq_lseek,
688 release: seq_release,
689 };
691 static struct file_operations proc_perfcfg_operations = {
692 open: perfcfg_open,
693 read: seq_read,
694 write: perfcntr_write,
695 llseek: seq_lseek,
696 release: seq_release,
697 };
699 static void create_seq_entry(char *name, mode_t mode, struct file_operations *f)
700 {
701 struct proc_dir_entry *entry;
702 entry = create_proc_entry(name, mode, NULL);
703 if (entry)
704 entry->proc_fops = f;
705 }
707 /*****************************************************************************
708 * Module init and cleanup *
709 *****************************************************************************/
711 static int __init perfcntr_init(void)
712 {
713 printk(version);
715 create_seq_entry("perfcntr", 0777, &proc_perfcntr_operations);
716 create_seq_entry("perfcntr_config", 0777, &proc_perfcfg_operations);
718 return 0;
719 }
721 static void __exit perfcntr_exit(void)
722 {
723 remove_proc_entry("perfcntr", NULL);
724 remove_proc_entry("perfcntr_config", NULL);
725 }
727 module_init(perfcntr_init);
728 module_exit(perfcntr_exit);
730 /* End of $RCSfile$ */