3 * Copyright (C) 2001 Mike Corrigan & Dave Engebretsen IBM Corporation
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.
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.
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
22 * 2001 : mikec : Created
23 * 2001/06/05 : engebret : Software event count support.
27 #include <linux/proc_fs.h>
28 #include <linux/spinlock.h>
30 #include <asm/proc_fs.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>
38 #include <asm/iSeries/LparData.h>
40 #include <asm/uaccess.h>
45 static int proc_pmc_control_mode = 0;
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, };
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);
61 static struct proc_dir_entry *pmc_proc_root = NULL;
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);
66 int proc_get_titanTod( char *page, char **start, off_t off, int count, int *eof, void *data);
68 int proc_pmc_get_control( char *page, char **start, off_t off, int count, int *eof, void *data);
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);
84 int proc_ppc64_init(void)
87 struct proc_dir_entry *ent = NULL;
90 printk("proc_ppc64: Creating /proc/ppc64/pmc\n");
93 * Create the root, system, and cpu directories as follows:
94 * /proc/ppc64/pmc/system
95 * /proc/ppc64/pmc/cpu0
97 spin_lock(&proc_ppc64_lock);
98 if (proc_ppc64.root == NULL) {
100 if (!proc_ppc64.root) {
101 spin_unlock(&proc_ppc64_lock);
105 spin_unlock(&proc_ppc64_lock);
107 /* Placeholder for rtas interfaces. */
108 if (proc_ppc64.rtas == NULL) {
112 proc_ppc64_pmc_root = proc_mkdir("pmc", proc_ppc64.root);
114 proc_ppc64_pmc_system_root = proc_mkdir("system", proc_ppc64_pmc_root);
115 for (i = 0; i < NR_CPUS; i++) {
117 sprintf(buf, "cpu%ld", i);
118 proc_ppc64_pmc_cpu_root[i] =
119 proc_mkdir(buf, proc_ppc64_pmc_root);
123 /* Create directories for the software counters. */
124 for (i = 0; i < NR_CPUS; i++) {
127 ent = create_proc_entry("stab", S_IRUGO | S_IWUSR,
128 proc_ppc64_pmc_cpu_root[i]);
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;
136 ent = create_proc_entry("htab", S_IRUGO | S_IWUSR,
137 proc_ppc64_pmc_cpu_root[i]);
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;
146 ent = create_proc_entry("stab", S_IRUGO | S_IWUSR,
147 proc_ppc64_pmc_system_root);
150 ent->data = (void *)proc_ppc64_pmc_system_root;
151 ent->read_proc = (void *)proc_ppc64_pmc_stab_read;
152 ent->write_proc = NULL;
155 ent = create_proc_entry("htab", S_IRUGO | S_IWUSR,
156 proc_ppc64_pmc_system_root);
159 ent->data = (void *)proc_ppc64_pmc_system_root;
160 ent->read_proc = (void *)proc_ppc64_pmc_htab_read;
161 ent->write_proc = NULL;
164 /* Create directories for the hardware counters. */
165 for (i = 0; i < NR_CPUS; i++) {
168 ent = create_proc_entry("hardware", S_IRUGO | S_IWUSR,
169 proc_ppc64_pmc_cpu_root[i]);
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;
178 ent = create_proc_entry("hardware", S_IRUGO | S_IWUSR,
179 proc_ppc64_pmc_system_root);
182 ent->data = (void *)proc_ppc64_pmc_system_root;
183 ent->read_proc = (void *)proc_ppc64_pmc_hw_read;
184 ent->write_proc = NULL;
190 * Find the requested 'file' given a proc token.
192 * Inputs: void * data: proc token
193 * Output: int : (0, ..., +N) = CPU number.
196 int proc_ppc64_pmc_find_file(void *data)
200 if ((unsigned long)data ==
201 (unsigned long) proc_ppc64_pmc_system_root) {
204 for (i = 0; i < NR_CPUS; i++) {
207 if ((unsigned long)data ==
208 (unsigned long)proc_ppc64_pmc_cpu_root[i]) {
214 /* On error, just default to a type of system. */
215 printk("proc_ppc64_pmc_find_file: failed to find file token.\n");
220 proc_ppc64_pmc_read(char *page, char **start, off_t off,
221 int count, int *eof, char *buffer)
225 if (count < 0) return 0;
227 if (buffer == NULL) {
232 /* Check for read beyond EOF */
233 buffer_size = n = strlen(buffer);
234 if (off >= buffer_size) {
238 if (n > (buffer_size - off)) n = buffer_size - off;
240 /* Never return more than was requested */
247 memcpy(page, buffer + off, n);
255 proc_ppc64_pmc_stab_read(char *page, char **start, off_t off,
256 int count, int *eof, void *data)
261 if (count < 0) return 0;
262 spin_lock(&proc_ppc64_lock);
264 /* Figure out which file is being request. */
265 file = proc_ppc64_pmc_find_file(data);
267 /* Update the counters and the text buffer representation. */
268 buffer = ppc64_pmc_stab(file);
270 /* Put the data into the requestor's buffer. */
271 n = proc_ppc64_pmc_read(page, start, off, count, eof, buffer);
273 spin_unlock(&proc_ppc64_lock);
278 proc_ppc64_pmc_htab_read(char *page, char **start, off_t off,
279 int count, int *eof, void *data)
284 if (count < 0) return 0;
285 spin_lock(&proc_ppc64_lock);
287 /* Figure out which file is being request. */
288 file = proc_ppc64_pmc_find_file(data);
290 /* Update the counters and the text buffer representation. */
291 buffer = ppc64_pmc_htab(file);
293 /* Put the data into the requestor's buffer. */
294 n = proc_ppc64_pmc_read(page, start, off, count, eof, buffer);
296 spin_unlock(&proc_ppc64_lock);
301 proc_ppc64_pmc_hw_read(char *page, char **start, off_t off,
302 int count, int *eof, void *data)
307 if (count < 0) return 0;
308 spin_lock(&proc_ppc64_lock);
310 /* Figure out which file is being request. */
311 file = proc_ppc64_pmc_find_file(data);
313 /* Update the counters and the text buffer representation. */
314 buffer = ppc64_pmc_hw(file);
316 /* Put the data into the requestor's buffer. */
317 n = proc_ppc64_pmc_read(page, start, off, count, eof, buffer);
319 spin_unlock(&proc_ppc64_lock);
324 * DRENG the remainder of these functions still need work ...
326 void pmc_proc_init(struct proc_dir_entry *iSeries_proc)
328 struct proc_dir_entry *ent = NULL;
330 ent = create_proc_entry("lpevents", S_IFREG|S_IRUGO, iSeries_proc);
333 ent->data = (void *)0;
334 ent->read_proc = proc_get_lpevents;
335 ent->write_proc = proc_reset_lpevents;
337 ent = create_proc_entry("titanTod", S_IFREG|S_IRUGO, iSeries_proc);
340 ent->data = (void *)0;
342 ent->read_proc = proc_get_titanTod;
343 ent->write_proc = NULL;
345 pmc_proc_root = proc_mkdir("pmc", iSeries_proc);
346 if (!pmc_proc_root) return;
348 ent = create_proc_entry("control", S_IFREG|S_IRUSR|S_IWUSR, pmc_proc_root);
351 ent->data = (void *)0;
352 ent->read_proc = proc_pmc_get_control;
353 ent->write_proc = proc_pmc_set_control;
357 static int pmc_calc_metrics( char *page, char **start, off_t off, int count, int *eof, int len)
359 if ( len <= off+count)
370 static char * lpEventTypes[9] = {
372 "Machine Facilities\t",
383 int proc_get_lpevents
384 (char *page, char **start, off_t off, int count, int *eof, void *data)
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",
395 (unsigned long)xItLpQueue.xLpIntCountByType[i] );
397 len += sprintf( page+len, "\n events processed by processor:\n" );
398 for (i = 0; i < NR_CPUS; ++i) {
400 len += sprintf( page+len, " CPU%02d %10u\n",
401 i, paca[i].lpEvent_count );
404 return pmc_calc_metrics( page, start, off, count, eof, len );
408 int proc_reset_lpevents( struct file *file, const char *buffer, unsigned long count, void *data )
413 static unsigned long startTitan = 0;
414 static unsigned long startTb = 0;
417 int proc_get_titanTod
418 (char *page, char **start, off_t off, int count, int *eof, void *data)
421 unsigned long tb0, titan_tod;
424 titan_tod = HvCallXm_loadTod();
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 );
435 startTitan = titan_tod;
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;
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 );
458 return pmc_calc_metrics( page, start, off, count, eof, len );
461 int proc_pmc_get_control
462 (char *page, char **start, off_t off, int count, int *eof, void *data)
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;
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 );
482 cpithou = ( remain * 1000 ) / inst_complete;
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 );
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 );
492 len += sprintf( page+len, "thread active run cycles/instructions completed\n" );
493 len += sprintf( page+len, "CPI = %lu.%03lu\n", cpi, cpithou );
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 ) );
508 return pmc_calc_metrics( page, start, off, count, eof, len );
511 unsigned long proc_pmc_conv_int( const char *buf, unsigned count )
515 unsigned v, multiplier, mult, i;
522 if ( ( b0 == '0' ) &&
523 ( ( b1 == 'x' ) || ( b1 == 'X' ) ) ) {
531 for ( i=0; i<count; ++i ) {
535 if ( ( b0 >= '0' ) && ( b0 <= '9' ) )
537 else if ( multiplier == 16 ) {
538 if ( ( b0 >= 'a' ) && ( b0 <= 'f' ) )
540 else if ( ( b0 >= 'A' ) && ( b0 <= 'F' ) )
555 static inline void proc_pmc_stop(void)
557 /* Freeze all counters, leave everything else alone */
558 mtspr( MMCR0, mfspr( MMCR0 ) | 0x80000000 );
561 static inline void proc_pmc_start(void)
563 /* Unfreeze all counters, leave everything else alone */
564 mtspr( MMCR0, mfspr( MMCR0 ) & ~0x80000000 );
568 static inline void proc_pmc_reset(void)
570 /* Clear all the PMCs to zeros
571 * Assume a "stop" has already frozen the counters
585 static inline void proc_pmc_cpi(void)
587 /* Configure the PMC registers to count cycles and instructions */
588 /* so we can compute cpi */
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
600 proc_pmc_control_mode = PMC_CONTROL_CPI;
602 /* Indicate to hypervisor that we are using the PMCs */
603 get_paca()->xLpPacaPtr->xPMCRegsInUse = 1;
605 /* Freeze all counters */
606 mtspr( MMCR0, 0x80000000 );
607 mtspr( MMCR1, 0x00000000 );
609 /* Clear all the PMCs */
619 /* Freeze counters in Wait State (CTRL[31]=0) */
620 mtspr( MMCRA, 0x00000002 );
622 /* PMC3<-0x07, PMC4<-0x03, PMC5<-0x06 */
623 mtspr( MMCR1, 0x38cc0000 );
627 /* PMC1<-0x01, PMC2<-0x05
630 mtspr( MMCR0, 0x02000045 );
634 static inline void proc_pmc_tlb(void)
636 /* Configure the PMC registers to count tlb misses */
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
651 proc_pmc_control_mode = PMC_CONTROL_TLB;
653 /* Indicate to hypervisor that we are using the PMCs */
654 get_paca()->xLpPacaPtr->xPMCRegsInUse = 1;
656 /* Freeze all counters */
657 mtspr( MMCR0, 0x80000000 );
658 mtspr( MMCR1, 0x00000000 );
660 /* Clear all the PMCs */
670 mtspr( MMCRA, 0x00000000 );
677 mtspr( MMCR0, 0x02001540 );
681 int proc_pmc_set_control( struct file *file, const char *buffer, unsigned long count, void *data )
684 if (count > 9) count = 9;
685 if (copy_from_user (stkbuf, buffer, count)) {
690 if ( ! strncmp( stkbuf, "stop", 4 ) )
692 else if ( ! strncmp( stkbuf, "start", 5 ) )
694 else if ( ! strncmp( stkbuf, "reset", 5 ) )
696 else if ( ! strncmp( stkbuf, "cpi", 3 ) )
698 else if ( ! strncmp( stkbuf, "tlb", 3 ) )
705 int proc_pmc_set_mmcr0( struct file *file, const char *buffer, unsigned long count, void *data )
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;
713 get_paca()->xLpPacaPtr->xPMCRegsInUse = 0;
719 int proc_pmc_set_mmcr1( struct file *file, const char *buffer, unsigned long count, void *data )
722 v = proc_pmc_conv_int( buffer, count );
728 int proc_pmc_set_mmcra( struct file *file, const char *buffer, unsigned long count, void *data )
731 v = proc_pmc_conv_int( buffer, count );
732 v = v & ~0x00008000; /* Don't allow interrupts for now */
739 int proc_pmc_set_pmc1( struct file *file, const char *buffer, unsigned long count, void *data )
742 v = proc_pmc_conv_int( buffer, count );
748 int proc_pmc_set_pmc2( struct file *file, const char *buffer, unsigned long count, void *data )
751 v = proc_pmc_conv_int( buffer, count );
757 int proc_pmc_set_pmc3( struct file *file, const char *buffer, unsigned long count, void *data )
760 v = proc_pmc_conv_int( buffer, count );
766 int proc_pmc_set_pmc4( struct file *file, const char *buffer, unsigned long count, void *data )
769 v = proc_pmc_conv_int( buffer, count );
775 int proc_pmc_set_pmc5( struct file *file, const char *buffer, unsigned long count, void *data )
778 v = proc_pmc_conv_int( buffer, count );
784 int proc_pmc_set_pmc6( struct file *file, const char *buffer, unsigned long count, void *data )
787 v = proc_pmc_conv_int( buffer, count );
793 int proc_pmc_set_pmc7( struct file *file, const char *buffer, unsigned long count, void *data )
796 v = proc_pmc_conv_int( buffer, count );
802 int proc_pmc_set_pmc8( struct file *file, const char *buffer, unsigned long count, void *data )
805 v = proc_pmc_conv_int( buffer, count );