8ad2be79a465dbeb09dba47f53a33015ee6a3522
[linux-flexiantxendom0-3.2.10.git] / arch / ppc64 / kernel / proc_pmc.c
1 /*
2  * proc_pmc.c
3  * Copyright (C) 2001 Mike Corrigan & Dave Engebretsen IBM Corporation
4  * 
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  * 
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  * 
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
18  */
19
20
21 /* Change Activity:
22  * 2001       : mikec    : Created
23  * 2001/06/05 : engebret : Software event count support.
24  * End Change Activity 
25  */
26
27 #include <linux/proc_fs.h>
28 #include <linux/spinlock.h>
29
30 #include <asm/proc_fs.h>
31 #include <asm/paca.h>
32 #include <asm/iSeries/ItLpPaca.h>
33 #include <asm/iSeries/ItLpQueue.h>
34 #include <asm/iSeries/HvCallXm.h>
35 #include <asm/iSeries/IoHriMainStore.h>
36 #include <asm/processor.h>
37 #include <asm/time.h>
38 #include <asm/iSeries/LparData.h>
39 #include <asm/pmc.h>
40 #include <asm/uaccess.h>
41 #include <asm/naca.h>
42 #include <asm/rtas.h>
43
44
45 static int proc_pmc_control_mode = 0;
46
47 static struct proc_dir_entry *proc_ppc64_pmc_system_root = NULL;
48 static struct proc_dir_entry *proc_ppc64_pmc_cpu_root[NR_CPUS] = {NULL, };
49
50 static spinlock_t proc_ppc64_lock;
51 int proc_ppc64_pmc_find_file(void *data);
52 int proc_ppc64_pmc_read(char *page, char **start, off_t off,
53                         int count, int *eof, char *buffer);
54 int proc_ppc64_pmc_stab_read(char *page, char **start, off_t off,
55                              int count, int *eof, void *data);
56 int proc_ppc64_pmc_htab_read(char *page, char **start, off_t off,
57                              int count, int *eof, void *data);
58 int proc_ppc64_pmc_hw_read(char *page, char **start, off_t off, 
59                            int count, int *eof, void *data);
60
61 static struct proc_dir_entry *pmc_proc_root = NULL;
62
63 int proc_get_lpevents( char *page, char **start, off_t off, int count, int *eof, void *data);
64 int proc_reset_lpevents( struct file *file, const char *buffer, unsigned long count, void *data);
65
66 int proc_get_titanTod( char *page, char **start, off_t off, int count, int *eof, void *data);
67
68 int proc_pmc_get_control( char *page, char **start, off_t off, int count, int *eof, void *data);
69
70 int proc_pmc_set_control( struct file *file, const char *buffer, unsigned long count, void *data);
71 int proc_pmc_set_mmcr0( struct file *file, const char *buffer, unsigned long count, void *data);
72 int proc_pmc_set_mmcr1( struct file *file, const char *buffer, unsigned long count, void *data);
73 int proc_pmc_set_mmcra( struct file *file, const char *buffer, unsigned long count, void *data);
74 int proc_pmc_set_pmc1(  struct file *file, const char *buffer, unsigned long count, void *data);
75 int proc_pmc_set_pmc2(  struct file *file, const char *buffer, unsigned long count, void *data);
76 int proc_pmc_set_pmc3(  struct file *file, const char *buffer, unsigned long count, void *data);
77 int proc_pmc_set_pmc4(  struct file *file, const char *buffer, unsigned long count, void *data);
78 int proc_pmc_set_pmc5(  struct file *file, const char *buffer, unsigned long count, void *data);
79 int proc_pmc_set_pmc6(  struct file *file, const char *buffer, unsigned long count, void *data);
80 int proc_pmc_set_pmc7(  struct file *file, const char *buffer, unsigned long count, void *data);
81 int proc_pmc_set_pmc8(  struct file *file, const char *buffer, unsigned long count, void *data);
82
83 #if 0
84 int proc_ppc64_init(void)
85 {
86         unsigned long i;
87         struct proc_dir_entry *ent = NULL;
88         char buf[256];
89
90         printk("proc_ppc64: Creating /proc/ppc64/pmc\n");
91
92         /*
93          * Create the root, system, and cpu directories as follows:
94          *   /proc/ppc64/pmc/system 
95          *   /proc/ppc64/pmc/cpu0 
96          */
97         spin_lock(&proc_ppc64_lock);
98         if (proc_ppc64.root == NULL) {
99                 proc_ppc64_init();
100                 if (!proc_ppc64.root) {
101                         spin_unlock(&proc_ppc64_lock);
102                         return;
103                 }
104         }
105         spin_unlock(&proc_ppc64_lock);
106
107         /* Placeholder for rtas interfaces. */
108         if (proc_ppc64.rtas == NULL) {
109                 return;
110         }
111
112         proc_ppc64_pmc_root = proc_mkdir("pmc", proc_ppc64.root);
113
114         proc_ppc64_pmc_system_root = proc_mkdir("system", proc_ppc64_pmc_root);
115         for (i = 0; i < NR_CPUS; i++) {
116                 if (cpu_online(i)) {
117                         sprintf(buf, "cpu%ld", i); 
118                         proc_ppc64_pmc_cpu_root[i] =
119                                 proc_mkdir(buf, proc_ppc64_pmc_root);
120                 }
121         }
122
123         /* Create directories for the software counters. */
124         for (i = 0; i < NR_CPUS; i++) {
125                 if (!cpu_online(i))
126                         continue;
127                 ent = create_proc_entry("stab", S_IRUGO | S_IWUSR, 
128                                         proc_ppc64_pmc_cpu_root[i]);
129                 if (ent) {
130                         ent->nlink = 1;
131                         ent->data = (void *)proc_ppc64_pmc_cpu_root[i];
132                         ent->read_proc = (void *)proc_ppc64_pmc_stab_read;
133                         ent->write_proc = NULL;
134                 }
135
136                 ent = create_proc_entry("htab", S_IRUGO | S_IWUSR, 
137                                         proc_ppc64_pmc_cpu_root[i]);
138                 if (ent) {
139                         ent->nlink = 1;
140                         ent->data = (void *)proc_ppc64_pmc_cpu_root[i];
141                         ent->read_proc = (void *)proc_ppc64_pmc_htab_read;
142                         ent->write_proc = NULL;
143                 }
144         }
145
146         ent = create_proc_entry("stab", S_IRUGO | S_IWUSR, 
147                                 proc_ppc64_pmc_system_root);
148         if (ent) {
149                 ent->nlink = 1;
150                 ent->data = (void *)proc_ppc64_pmc_system_root;
151                 ent->read_proc = (void *)proc_ppc64_pmc_stab_read;
152                 ent->write_proc = NULL;
153         }
154
155         ent = create_proc_entry("htab", S_IRUGO | S_IWUSR, 
156                                 proc_ppc64_pmc_system_root);
157         if (ent) {
158                 ent->nlink = 1;
159                 ent->data = (void *)proc_ppc64_pmc_system_root;
160                 ent->read_proc = (void *)proc_ppc64_pmc_htab_read;
161                 ent->write_proc = NULL;
162         }
163
164         /* Create directories for the hardware counters. */
165         for (i = 0; i < NR_CPUS; i++) {
166                 if (!cpu_online(i))
167                         continue;
168                 ent = create_proc_entry("hardware", S_IRUGO | S_IWUSR, 
169                                         proc_ppc64_pmc_cpu_root[i]);
170                 if (ent) {
171                         ent->nlink = 1;
172                         ent->data = (void *)proc_ppc64_pmc_cpu_root[i];
173                         ent->read_proc = (void *)proc_ppc64_pmc_hw_read;
174                         ent->write_proc = NULL;
175                 }
176         }
177
178         ent = create_proc_entry("hardware", S_IRUGO | S_IWUSR, 
179                                 proc_ppc64_pmc_system_root);
180         if (ent) {
181                 ent->nlink = 1;
182                 ent->data = (void *)proc_ppc64_pmc_system_root;
183                 ent->read_proc = (void *)proc_ppc64_pmc_hw_read;
184                 ent->write_proc = NULL;
185         }
186 }
187 #endif
188
189 /*
190  * Find the requested 'file' given a proc token.
191  *
192  * Inputs: void * data: proc token
193  * Output: int        : (0, ..., +N) = CPU number.
194  *                      -1           = System.
195  */
196 int proc_ppc64_pmc_find_file(void *data)
197 {
198         int i;
199
200         if ((unsigned long)data == 
201            (unsigned long) proc_ppc64_pmc_system_root) {
202                 return(-1); 
203         } else {
204                 for (i = 0; i < NR_CPUS; i++) {
205                         if (!cpu_online(i))
206                                 continue;
207                         if ((unsigned long)data ==
208                            (unsigned long)proc_ppc64_pmc_cpu_root[i]) {
209                                 return(i); 
210                         }
211                 }
212         }
213
214         /* On error, just default to a type of system. */
215         printk("proc_ppc64_pmc_find_file: failed to find file token.\n"); 
216         return(-1); 
217 }
218
219 int 
220 proc_ppc64_pmc_read(char *page, char **start, off_t off, 
221                     int count, int *eof, char *buffer)
222 {
223         int buffer_size, n;
224
225         if (count < 0) return 0;
226
227         if (buffer == NULL) {
228                 *eof = 1;
229                 return 0;
230         }
231
232         /* Check for read beyond EOF */
233         buffer_size = n = strlen(buffer);
234         if (off >= buffer_size) {
235                 *eof = 1;
236                 return 0;
237         }
238         if (n > (buffer_size - off)) n = buffer_size - off;
239
240         /* Never return more than was requested */
241         if (n > count) {
242                 n = count;
243         } else {
244                 *eof = 1;
245         }
246
247         memcpy(page, buffer + off, n);
248
249         *start = page;
250
251         return n;
252 }
253
254 int 
255 proc_ppc64_pmc_stab_read(char *page, char **start, off_t off, 
256                          int count, int *eof, void *data)
257 {
258         int n, file;
259         char *buffer = NULL;
260
261         if (count < 0) return 0;
262         spin_lock(&proc_ppc64_lock);
263
264         /* Figure out which file is being request. */
265         file = proc_ppc64_pmc_find_file(data);
266
267         /* Update the counters and the text buffer representation. */
268         buffer = ppc64_pmc_stab(file);
269
270         /* Put the data into the requestor's buffer. */
271         n = proc_ppc64_pmc_read(page, start, off, count, eof, buffer); 
272
273         spin_unlock(&proc_ppc64_lock);
274         return n;
275 }
276
277 int 
278 proc_ppc64_pmc_htab_read(char *page, char **start, off_t off, 
279                          int count, int *eof, void *data)
280 {
281         int n, file;
282         char *buffer = NULL;
283
284         if (count < 0) return 0;
285         spin_lock(&proc_ppc64_lock);
286
287         /* Figure out which file is being request. */
288         file = proc_ppc64_pmc_find_file(data);
289
290         /* Update the counters and the text buffer representation. */
291         buffer = ppc64_pmc_htab(file);
292
293         /* Put the data into the requestor's buffer. */
294         n = proc_ppc64_pmc_read(page, start, off, count, eof, buffer);
295
296         spin_unlock(&proc_ppc64_lock);
297         return n;
298 }
299
300 int 
301 proc_ppc64_pmc_hw_read(char *page, char **start, off_t off, 
302                              int count, int *eof, void *data)
303 {
304         int n, file;
305         char *buffer = NULL;
306
307         if (count < 0) return 0;
308         spin_lock(&proc_ppc64_lock);
309
310         /* Figure out which file is being request. */
311         file = proc_ppc64_pmc_find_file(data);
312
313         /* Update the counters and the text buffer representation. */
314         buffer = ppc64_pmc_hw(file);
315
316         /* Put the data into the requestor's buffer. */
317         n = proc_ppc64_pmc_read(page, start, off, count, eof, buffer);
318
319         spin_unlock(&proc_ppc64_lock);
320         return n;
321 }
322
323 /* 
324  * DRENG the remainder of these functions still need work ...
325  */
326 void pmc_proc_init(struct proc_dir_entry *iSeries_proc)
327 {
328     struct proc_dir_entry *ent = NULL;
329
330     ent = create_proc_entry("lpevents", S_IFREG|S_IRUGO, iSeries_proc);
331     if (!ent) return;
332     ent->nlink = 1;
333     ent->data = (void *)0;
334     ent->read_proc = proc_get_lpevents;
335     ent->write_proc = proc_reset_lpevents;
336
337     ent = create_proc_entry("titanTod", S_IFREG|S_IRUGO, iSeries_proc);
338     if (!ent) return;
339     ent->nlink = 1;
340     ent->data = (void *)0;
341     ent->size = 0;
342     ent->read_proc = proc_get_titanTod;
343     ent->write_proc = NULL;
344
345     pmc_proc_root = proc_mkdir("pmc", iSeries_proc);
346     if (!pmc_proc_root) return;
347
348     ent = create_proc_entry("control", S_IFREG|S_IRUSR|S_IWUSR, pmc_proc_root);
349     if (!ent) return;
350     ent->nlink = 1;
351     ent->data = (void *)0;
352     ent->read_proc = proc_pmc_get_control;
353     ent->write_proc = proc_pmc_set_control;
354
355 }
356
357 static int pmc_calc_metrics( char *page, char **start, off_t off, int count, int *eof, int len)
358 {
359         if ( len <= off+count)
360                 *eof = 1;
361         *start = page+off;
362         len -= off;
363         if ( len > count )
364                 len = count;
365         if ( len < 0 )
366                 len = 0;
367         return len;
368 }
369
370 static char * lpEventTypes[9] = {
371         "Hypervisor\t\t",
372         "Machine Facilities\t",
373         "Session Manager\t",
374         "SPD I/O\t\t",
375         "Virtual Bus\t\t",
376         "PCI I/O\t\t",
377         "RIO I/O\t\t",
378         "Virtual Lan\t\t",
379         "Virtual I/O\t\t"
380         };
381         
382
383 int proc_get_lpevents
384 (char *page, char **start, off_t off, int count, int *eof, void *data)
385 {
386         unsigned i;
387         int len = 0;
388
389         len += sprintf( page+len, "LpEventQueue 0\n" );
390         len += sprintf( page+len, "  events processed:\t%lu\n",
391                         (unsigned long)xItLpQueue.xLpIntCount );
392         for (i=0; i<9; ++i) {
393                 len += sprintf( page+len, "    %s %10lu\n",
394                         lpEventTypes[i],
395                         (unsigned long)xItLpQueue.xLpIntCountByType[i] );
396         }
397         len += sprintf( page+len, "\n  events processed by processor:\n" );
398         for (i = 0; i < NR_CPUS; ++i) {
399                 if (cpu_online(i))
400                         len += sprintf( page+len, "    CPU%02d  %10u\n",
401                                 i, paca[i].lpEvent_count );
402         }
403
404         return pmc_calc_metrics( page, start, off, count, eof, len );
405
406 }
407
408 int proc_reset_lpevents( struct file *file, const char *buffer, unsigned long count, void *data )
409 {
410         return count;
411 }
412
413 static unsigned long startTitan = 0;
414 static unsigned long startTb = 0;
415
416
417 int proc_get_titanTod
418 (char *page, char **start, off_t off, int count, int *eof, void *data)
419 {
420         int len = 0;
421         unsigned long tb0, titan_tod;
422
423         tb0 = get_tb();
424         titan_tod = HvCallXm_loadTod();
425
426         len += sprintf( page+len, "Titan\n" );
427         len += sprintf( page+len, "  time base =          %016lx\n", tb0 );
428         len += sprintf( page+len, "  titan tod =          %016lx\n", titan_tod );
429         len += sprintf( page+len, "  xProcFreq =          %016x\n", xIoHriProcessorVpd[0].xProcFreq );
430         len += sprintf( page+len, "  xTimeBaseFreq =      %016x\n", xIoHriProcessorVpd[0].xTimeBaseFreq );
431         len += sprintf( page+len, "  tb_ticks_per_jiffy = %lu\n", tb_ticks_per_jiffy );
432         len += sprintf( page+len, "  tb_ticks_per_usec  = %lu\n", tb_ticks_per_usec );
433
434         if ( !startTitan ) {
435                 startTitan = titan_tod;
436                 startTb = tb0;
437         }
438         else {
439                 unsigned long titan_usec = (titan_tod - startTitan) >> 12;
440                 unsigned long tb_ticks = (tb0 - startTb);
441                 unsigned long titan_jiffies = titan_usec / (1000000/HZ);
442                 unsigned long titan_jiff_usec = titan_jiffies * (1000000/HZ);
443                 unsigned long titan_jiff_rem_usec = titan_usec - titan_jiff_usec;
444                 unsigned long tb_jiffies = tb_ticks / tb_ticks_per_jiffy;
445                 unsigned long tb_jiff_ticks = tb_jiffies * tb_ticks_per_jiffy;
446                 unsigned long tb_jiff_rem_ticks = tb_ticks - tb_jiff_ticks;
447                 unsigned long tb_jiff_rem_usec = tb_jiff_rem_ticks / tb_ticks_per_usec;
448                 unsigned long new_tb_ticks_per_jiffy = (tb_ticks * (1000000/HZ))/titan_usec;
449                 
450                 len += sprintf( page+len, "  titan elapsed = %lu uSec\n", titan_usec);
451                 len += sprintf( page+len, "  tb elapsed    = %lu ticks\n", tb_ticks);
452                 len += sprintf( page+len, "  titan jiffies = %lu.%04lu \n", titan_jiffies, titan_jiff_rem_usec );                               
453                 len += sprintf( page+len, "  tb jiffies    = %lu.%04lu\n", tb_jiffies, tb_jiff_rem_usec );
454                 len += sprintf( page+len, "  new tb_ticks_per_jiffy = %lu\n", new_tb_ticks_per_jiffy ); 
455
456         }
457         
458         return pmc_calc_metrics( page, start, off, count, eof, len );
459 }
460         
461 int proc_pmc_get_control
462 (char *page, char **start, off_t off, int count, int *eof, void *data)
463 {
464         int len = 0;
465
466         if ( proc_pmc_control_mode == PMC_CONTROL_CPI ) {
467                 unsigned long mach_cycles   = mfspr( PMC5 );
468                 unsigned long inst_complete = mfspr( PMC4 );
469                 unsigned long inst_dispatch = mfspr( PMC3 );
470                 unsigned long thread_active_run = mfspr( PMC1 );
471                 unsigned long thread_active  = mfspr( PMC2 );
472                 unsigned long cpi = 0;
473                 unsigned long cpithou = 0;
474                 unsigned long remain;
475         
476                 if ( inst_complete ) {
477                         cpi = thread_active_run / inst_complete;
478                         remain = thread_active_run % inst_complete;
479                         if ( inst_complete > 1000000 ) 
480                                 cpithou = remain / ( inst_complete / 1000 );
481                         else 
482                                 cpithou = ( remain * 1000 ) / inst_complete;
483                 }
484                 len += sprintf( page+len, "PMC CPI Mode\nRaw Counts\n" );
485                 len += sprintf( page+len, "machine cycles           : %12lu\n", mach_cycles );
486                 len += sprintf( page+len, "thread active cycles     : %12lu\n\n", thread_active );
487
488                 len += sprintf( page+len, "instructions completed   : %12lu\n", inst_complete );
489                 len += sprintf( page+len, "instructions dispatched  : %12lu\n", inst_dispatch );
490                 len += sprintf( page+len, "thread active run cycles : %12lu\n", thread_active_run );
491
492                 len += sprintf( page+len, "thread active run cycles/instructions completed\n" );
493                 len += sprintf( page+len, "CPI = %lu.%03lu\n", cpi, cpithou );
494                 
495         }
496         else if ( proc_pmc_control_mode == PMC_CONTROL_TLB ) {
497                 len += sprintf( page+len, "PMC TLB Mode\n" );
498                 len += sprintf( page+len, "I-miss count             : %12lu\n", mfspr( PMC1 ) );
499                 len += sprintf( page+len, "I-miss latency           : %12lu\n", mfspr( PMC2 ) );
500                 len += sprintf( page+len, "D-miss count             : %12lu\n", mfspr( PMC3 ) );
501                 len += sprintf( page+len, "D-miss latency           : %12lu\n", mfspr( PMC4 ) );
502                 len += sprintf( page+len, "IERAT miss count         : %12lu\n", mfspr( PMC5 ) );
503                 len += sprintf( page+len, "D-reference count        : %12lu\n", mfspr( PMC6 ) );
504                 len += sprintf( page+len, "miss PTEs searched       : %12lu\n", mfspr( PMC7 ) );
505                 len += sprintf( page+len, "miss >8 PTEs searched    : %12lu\n", mfspr( PMC8 ) );
506         }
507         /* IMPLEMENT ME */
508         return pmc_calc_metrics( page, start, off, count, eof, len );
509 }
510
511 unsigned long proc_pmc_conv_int( const char *buf, unsigned count )
512 {
513         const char * p;
514         char b0, b1;
515         unsigned v, multiplier, mult, i;
516         unsigned long val;
517         multiplier = 10;
518         p = buf;
519         if ( count >= 3 ) {
520                 b0 = buf[0];
521                 b1 = buf[1];
522                 if ( ( b0 == '0' ) &&
523                      ( ( b1 == 'x' ) || ( b1 == 'X' ) ) ) {
524                         p = buf + 2;
525                         count -= 2;
526                         multiplier = 16;
527                 }
528                         
529         }
530         val = 0;
531         for ( i=0; i<count; ++i ) {
532                 b0 = *p++;
533                 v = 0;
534                 mult = multiplier;
535                 if ( ( b0 >= '0' ) && ( b0 <= '9' ) ) 
536                         v = b0 - '0';
537                 else if ( multiplier == 16 ) {
538                         if ( ( b0 >= 'a' ) && ( b0 <= 'f' ) )
539                                 v = b0 - 'a' + 10;
540                         else if ( ( b0 >= 'A' ) && ( b0 <= 'F' ) )
541                                 v = b0 - 'A' + 10;
542                         else 
543                                 mult = 1;
544                 }
545                 else
546                         mult = 1;
547                 val *= mult;
548                 val += v;
549         }
550
551         return val;
552
553 }
554
555 static inline void proc_pmc_stop(void)
556 {
557         /* Freeze all counters, leave everything else alone */
558         mtspr( MMCR0, mfspr( MMCR0 ) | 0x80000000 );
559 }
560
561 static inline void proc_pmc_start(void)
562 {
563         /* Unfreeze all counters, leave everything else alone */
564         mtspr( MMCR0, mfspr( MMCR0 ) & ~0x80000000 );
565
566 }
567
568 static inline void proc_pmc_reset(void)
569 {
570         /* Clear all the PMCs to zeros 
571          * Assume a "stop" has already frozen the counters
572          * Clear all the PMCs
573          */
574         mtspr( PMC1, 0 );
575         mtspr( PMC2, 0 );
576         mtspr( PMC3, 0 );
577         mtspr( PMC4, 0 );
578         mtspr( PMC5, 0 );
579         mtspr( PMC6, 0 );
580         mtspr( PMC7, 0 );
581         mtspr( PMC8, 0 );
582
583 }
584
585 static inline void proc_pmc_cpi(void)
586 {
587         /* Configure the PMC registers to count cycles and instructions */
588         /* so we can compute cpi */
589         /*
590          * MMCRA[30]    = 1     Don't count in wait state (CTRL[31]=0)
591          * MMCR0[6]     = 1     Freeze counters when any overflow
592          * MMCR0[19:25] = 0x01  PMC1 counts Thread Active Run Cycles
593          * MMCR0[26:31] = 0x05  PMC2 counts Thread Active Cycles
594          * MMCR1[0:4]   = 0x07  PMC3 counts Instructions Dispatched
595          * MMCR1[5:9]   = 0x03  PMC4 counts Instructions Completed
596          * MMCR1[10:14] = 0x06  PMC5 counts Machine Cycles
597          *
598          */
599
600         proc_pmc_control_mode = PMC_CONTROL_CPI;
601         
602         /* Indicate to hypervisor that we are using the PMCs */
603         get_paca()->xLpPacaPtr->xPMCRegsInUse = 1;
604
605         /* Freeze all counters */
606         mtspr( MMCR0, 0x80000000 );
607         mtspr( MMCR1, 0x00000000 );
608         
609         /* Clear all the PMCs */
610         mtspr( PMC1, 0 );
611         mtspr( PMC2, 0 );
612         mtspr( PMC3, 0 );
613         mtspr( PMC4, 0 );
614         mtspr( PMC5, 0 );
615         mtspr( PMC6, 0 );
616         mtspr( PMC7, 0 );
617         mtspr( PMC8, 0 );
618
619         /* Freeze counters in Wait State (CTRL[31]=0) */
620         mtspr( MMCRA, 0x00000002 );
621
622         /* PMC3<-0x07, PMC4<-0x03, PMC5<-0x06 */
623         mtspr( MMCR1, 0x38cc0000 );
624
625         mb();
626         
627         /* PMC1<-0x01, PMC2<-0x05
628          * Start all counters
629          */
630         mtspr( MMCR0, 0x02000045 );
631         
632 }
633
634 static inline void proc_pmc_tlb(void)
635 {
636         /* Configure the PMC registers to count tlb misses  */
637         /*
638          * MMCR0[6]     = 1     Freeze counters when any overflow
639          * MMCR0[19:25] = 0x55  Group count
640          *   PMC1 counts  I misses
641          *   PMC2 counts  I miss duration (latency)
642          *   PMC3 counts  D misses
643          *   PMC4 counts  D miss duration (latency)
644          *   PMC5 counts  IERAT misses
645          *   PMC6 counts  D references (including PMC7)
646          *   PMC7 counts  miss PTEs searched
647          *   PMC8 counts  miss >8 PTEs searched
648          *   
649          */
650
651         proc_pmc_control_mode = PMC_CONTROL_TLB;
652         
653         /* Indicate to hypervisor that we are using the PMCs */
654         get_paca()->xLpPacaPtr->xPMCRegsInUse = 1;
655
656         /* Freeze all counters */
657         mtspr( MMCR0, 0x80000000 );
658         mtspr( MMCR1, 0x00000000 );
659         
660         /* Clear all the PMCs */
661         mtspr( PMC1, 0 );
662         mtspr( PMC2, 0 );
663         mtspr( PMC3, 0 );
664         mtspr( PMC4, 0 );
665         mtspr( PMC5, 0 );
666         mtspr( PMC6, 0 );
667         mtspr( PMC7, 0 );
668         mtspr( PMC8, 0 );
669
670         mtspr( MMCRA, 0x00000000 );
671
672         mb();
673         
674         /* PMC1<-0x55
675          * Start all counters
676          */
677         mtspr( MMCR0, 0x02001540 );
678         
679 }
680
681 int proc_pmc_set_control( struct file *file, const char *buffer, unsigned long count, void *data )
682 {
683         char stkbuf[10];
684         if (count > 9) count = 9;
685         if (copy_from_user (stkbuf, buffer, count)) {
686                 return -EFAULT;
687         }
688         stkbuf[count] = 0;
689
690         if      ( ! strncmp( stkbuf, "stop", 4 ) )
691                 proc_pmc_stop();
692         else if ( ! strncmp( stkbuf, "start", 5 ) )
693                 proc_pmc_start();
694         else if ( ! strncmp( stkbuf, "reset", 5 ) )
695                 proc_pmc_reset();
696         else if ( ! strncmp( stkbuf, "cpi", 3 ) )
697                 proc_pmc_cpi();
698         else if ( ! strncmp( stkbuf, "tlb", 3 ) )
699                 proc_pmc_tlb();
700         
701         /* IMPLEMENT ME */
702         return count;
703 }
704
705 int proc_pmc_set_mmcr0( struct file *file, const char *buffer, unsigned long count, void *data )
706 {
707         unsigned long v;
708         v = proc_pmc_conv_int( buffer, count );
709         v = v & ~0x04000000;    /* Don't allow interrupts for now */
710         if ( v & ~0x80000000 )  /* Inform hypervisor we are using PMCs */
711                 get_paca()->xLpPacaPtr->xPMCRegsInUse = 1;
712         else
713                 get_paca()->xLpPacaPtr->xPMCRegsInUse = 0;
714         mtspr( MMCR0, v );
715         
716         return count;   
717 }
718
719 int proc_pmc_set_mmcr1( struct file *file, const char *buffer, unsigned long count, void *data )
720 {
721         unsigned long v;
722         v = proc_pmc_conv_int( buffer, count );
723         mtspr( MMCR1, v );
724
725         return count;
726 }
727
728 int proc_pmc_set_mmcra( struct file *file, const char *buffer, unsigned long count, void *data )
729 {
730         unsigned long v;
731         v = proc_pmc_conv_int( buffer, count );
732         v = v & ~0x00008000;    /* Don't allow interrupts for now */
733         mtspr( MMCRA, v );
734
735         return count;
736 }
737
738
739 int proc_pmc_set_pmc1( struct file *file, const char *buffer, unsigned long count, void *data )
740 {
741         unsigned long v;
742         v = proc_pmc_conv_int( buffer, count );
743         mtspr( PMC1, v );
744
745         return count;
746 }
747
748 int proc_pmc_set_pmc2( struct file *file, const char *buffer, unsigned long count, void *data )
749 {
750         unsigned long v;
751         v = proc_pmc_conv_int( buffer, count );
752         mtspr( PMC2, v );
753
754         return count;
755 }
756
757 int proc_pmc_set_pmc3( struct file *file, const char *buffer, unsigned long count, void *data )
758 {
759         unsigned long v;
760         v = proc_pmc_conv_int( buffer, count );
761         mtspr( PMC3, v );
762
763         return count;
764 }
765
766 int proc_pmc_set_pmc4( struct file *file, const char *buffer, unsigned long count, void *data )
767 {
768         unsigned long v;
769         v = proc_pmc_conv_int( buffer, count );
770         mtspr( PMC4, v );
771
772         return count;
773 }
774
775 int proc_pmc_set_pmc5( struct file *file, const char *buffer, unsigned long count, void *data )
776 {
777         unsigned long v;
778         v = proc_pmc_conv_int( buffer, count );
779         mtspr( PMC5, v );
780
781         return count;
782 }
783
784 int proc_pmc_set_pmc6( struct file *file, const char *buffer, unsigned long count, void *data )
785 {
786         unsigned long v;
787         v = proc_pmc_conv_int( buffer, count );
788         mtspr( PMC6, v );
789
790         return count;
791 }
792
793 int proc_pmc_set_pmc7( struct file *file, const char *buffer, unsigned long count, void *data )
794 {
795         unsigned long v;
796         v = proc_pmc_conv_int( buffer, count );
797         mtspr( PMC7, v );
798
799         return count;
800 }
801
802 int proc_pmc_set_pmc8( struct file *file, const char *buffer, unsigned long count, void *data )
803 {
804         unsigned long v;
805         v = proc_pmc_conv_int( buffer, count );
806         mtspr( PMC8, v );
807
808         return count;
809 }
810