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  * 2001/08/03 : trautman : Added PCI Flight Recorder
25  * End Change Activity
26  */
27 
28 #include <asm/proc_fs.h>
29 #include <asm/paca.h>
30 #include <asm/iSeries/ItLpPaca.h>
31 #include <asm/iSeries/ItLpQueue.h>
32 #include <asm/iSeries/HvCallXm.h>
33 #include <asm/iSeries/IoHriMainStore.h>
34 #include <asm/processor.h>
35 #include <asm/time.h>
36 #include <asm/iSeries/LparData.h>
37 
38 #include <linux/config.h>
39 #include <linux/proc_fs.h>
40 #include <linux/spinlock.h>
41 #include <asm/pmc.h>
42 #include <asm/uaccess.h>
43 #include <asm/naca.h>
44 #include <asm/rtas.h>
45 #include <asm/perfmon.h>
46 
47 /* pci Flight Recorder AHT */
48 extern void proc_pciFr_init(struct proc_dir_entry *proc_ppc64_root);
49 
50 static int proc_pmc_control_mode = 0;
51 
52 struct proc_dir_entry *proc_ppc64_root = NULL;
53 static struct proc_dir_entry *proc_ppc64_pmc_root = NULL;
54 static struct proc_dir_entry *proc_ppc64_pmc_system_root = NULL;
55 static struct proc_dir_entry *proc_ppc64_pmc_cpu_root[NR_CPUS] = {NULL, };
56 
57 spinlock_t proc_ppc64_lock;
58 static int proc_ppc64_page_read(char *page, char **start, off_t off,
59 				int count, int *eof, void *data);
60 static void proc_ppc64_create_paca(int num, struct proc_dir_entry *paca_dir);
61 void proc_ppc64_create_smt(void);
62 
63 int proc_ppc64_pmc_find_file(void *data);
64 int proc_ppc64_pmc_read(char *page, char **start, off_t off,
65 			int count, int *eof, char *buffer);
66 int proc_ppc64_pmc_stab_read(char *page, char **start, off_t off,
67 			     int count, int *eof, void *data);
68 int proc_ppc64_pmc_htab_read(char *page, char **start, off_t off,
69 			     int count, int *eof, void *data);
70 int proc_ppc64_pmc_profile_read(char *page, char **start, off_t off,
71 				int count, int *eof, void *data);
72 int proc_ppc64_pmc_profile_read(char *page, char **start, off_t off,
73 				int count, int *eof, void *data);
74 int proc_ppc64_pmc_hw_read(char *page, char **start, off_t off,
75 			   int count, int *eof, void *data);
76 
77 static struct proc_dir_entry *pmc_proc_root = NULL;
78 
79 int proc_get_lpevents( char *page, char **start, off_t off, int count, int *eof, void *data);
80 int proc_reset_lpevents( struct file *file, const char *buffer, unsigned long count, void *data);
81 
82 int proc_get_titanTod( char *page, char **start, off_t off, int count, int *eof, void *data);
83 
84 int proc_pmc_get_control( char *page, char **start, off_t off, int count, int *eof, void *data);
85 
86 int proc_pmc_set_control( struct file *file, const char *buffer, unsigned long count, void *data);
87 int proc_pmc_set_mmcr0( struct file *file, const char *buffer, unsigned long count, void *data);
88 int proc_pmc_set_mmcr1( struct file *file, const char *buffer, unsigned long count, void *data);
89 int proc_pmc_set_mmcra( struct file *file, const char *buffer, unsigned long count, void *data);
90 int proc_pmc_set_pmc1(  struct file *file, const char *buffer, unsigned long count, void *data);
91 int proc_pmc_set_pmc2(  struct file *file, const char *buffer, unsigned long count, void *data);
92 int proc_pmc_set_pmc3(  struct file *file, const char *buffer, unsigned long count, void *data);
93 int proc_pmc_set_pmc4(  struct file *file, const char *buffer, unsigned long count, void *data);
94 int proc_pmc_set_pmc5(  struct file *file, const char *buffer, unsigned long count, void *data);
95 int proc_pmc_set_pmc6(  struct file *file, const char *buffer, unsigned long count, void *data);
96 int proc_pmc_set_pmc7(  struct file *file, const char *buffer, unsigned long count, void *data);
97 int proc_pmc_set_pmc8(  struct file *file, const char *buffer, unsigned long count, void *data);
98 
99 static loff_t  nacamap_seek( struct file *file, loff_t off, int whence);
100 static ssize_t nacamap_read( struct file *file, char *buf, size_t nbytes, loff_t *ppos);
101 static int     nacamap_mmap( struct file *file, struct vm_area_struct *vma );
102 
103 static struct file_operations nacamap_fops = {
104 	llseek:	nacamap_seek,
105 	read:	nacamap_read,
106 	mmap:	nacamap_mmap
107 };
108 
109 static ssize_t read_profile(struct file *file, char *buf, size_t count, loff_t *ppos);
110 static ssize_t write_profile(struct file * file, const char * buf,
111 			     size_t count, loff_t *ppos);
112 static ssize_t read_trace(struct file *file, char *buf, size_t count, loff_t *ppos);
113 static ssize_t write_trace(struct file * file, const char * buf,
114 			     size_t count, loff_t *ppos);
115 static ssize_t read_timeslice(struct file *file, char *buf, size_t count, loff_t *ppos);
116 static ssize_t write_timeslice(struct file * file, const char * buf,
117 			     size_t count, loff_t *ppos);
118 
119 static struct file_operations proc_profile_operations = {
120 	read:		read_profile,
121 	write:		write_profile,
122 };
123 
124 static struct file_operations proc_trace_operations = {
125 	read:		read_trace,
126 	write:		write_trace,
127 };
128 
129 static struct file_operations proc_timeslice_operations = {
130 	read:		read_timeslice,
131 	write:		write_timeslice,
132 };
133 
134 extern struct perfmon_base_struct perfmon_base;
135 
proc_ppc64_init(void)136 void proc_ppc64_init(void)
137 {
138 	unsigned long i;
139 	struct proc_dir_entry *ent = NULL;
140 	char buf[256];
141 
142 	printk("proc_ppc64: Creating /proc/ppc64/pmc\n");
143 
144 	/*
145 	 * Create the root, system, and cpu directories as follows:
146 	 *   /proc/ppc64/pmc/system
147 	 *   /proc/ppc64/pmc/cpu0
148 	 */
149 	spin_lock(&proc_ppc64_lock);
150 	if (proc_ppc64_root == NULL) {
151 		proc_ppc64_root = proc_mkdir("ppc64", 0);
152 		if (!proc_ppc64_root) {
153 			spin_unlock(&proc_ppc64_lock);
154 			return;
155 		}
156 	}
157 	spin_unlock(&proc_ppc64_lock);
158 
159 	ent = create_proc_entry("naca", S_IFREG|S_IRUGO, proc_ppc64_root);
160 	if ( ent ) {
161 		ent->nlink = 1;
162 		ent->data = naca;
163 		ent->size = 4096;
164 		ent->proc_fops = &nacamap_fops;
165 	}
166 
167 	ent = create_proc_entry("systemcfg", S_IFREG|S_IRUGO, proc_ppc64_root);
168 	if ( ent ) {
169 		ent->nlink = 1;
170 		ent->data = systemcfg;
171 		ent->size = 4096;
172 		ent->proc_fops = &nacamap_fops;
173 	}
174 
175 	/* /proc/ppc64/paca/XX -- raw paca contents.  Only readable to root */
176 	ent = proc_mkdir("paca", proc_ppc64_root);
177 	if (ent) {
178 		for (i = 0; i < systemcfg->processorCount; i++)
179 			proc_ppc64_create_paca(i, ent);
180 	}
181 
182 	/* Placeholder for rtas interfaces. */
183 	if (rtas_proc_dir == NULL) {
184 		rtas_proc_dir = proc_mkdir("rtas", proc_ppc64_root);
185 	}
186 
187 	proc_ppc64_create_smt();
188 
189 	/* Create the /proc/ppc64/pcifr for the Pci Flight Recorder.	 */
190 	proc_pciFr_init(proc_ppc64_root);
191 
192 	proc_ppc64_pmc_root = proc_mkdir("pmc", proc_ppc64_root);
193 
194 	proc_ppc64_pmc_system_root = proc_mkdir("system", proc_ppc64_pmc_root);
195 	for (i = 0; i < systemcfg->processorCount; i++) {
196 		sprintf(buf, "cpu%ld", i);
197 		proc_ppc64_pmc_cpu_root[i] = proc_mkdir(buf, proc_ppc64_pmc_root);
198 	}
199 
200 
201 	/* Create directories for the software counters. */
202 	for (i = 0; i < systemcfg->processorCount; i++) {
203 		ent = create_proc_entry("stab", S_IRUGO | S_IWUSR,
204 					proc_ppc64_pmc_cpu_root[i]);
205 		if (ent) {
206 			ent->nlink = 1;
207 			ent->data = (void *)proc_ppc64_pmc_cpu_root[i];
208 			ent->read_proc = (void *)proc_ppc64_pmc_stab_read;
209 			ent->write_proc = NULL;
210 		}
211 
212 		ent = create_proc_entry("htab", S_IRUGO | S_IWUSR,
213 					proc_ppc64_pmc_cpu_root[i]);
214 		if (ent) {
215 			ent->nlink = 1;
216 			ent->data = (void *)proc_ppc64_pmc_cpu_root[i];
217 			ent->read_proc = (void *)proc_ppc64_pmc_htab_read;
218 			ent->write_proc = NULL;
219 		}
220 	}
221 
222 	ent = create_proc_entry("stab", S_IRUGO | S_IWUSR,
223 				proc_ppc64_pmc_system_root);
224 	if (ent) {
225 		ent->nlink = 1;
226 		ent->data = (void *)proc_ppc64_pmc_system_root;
227 		ent->read_proc = (void *)proc_ppc64_pmc_stab_read;
228 		ent->write_proc = NULL;
229 	}
230 
231 	ent = create_proc_entry("htab", S_IRUGO | S_IWUSR,
232 				proc_ppc64_pmc_system_root);
233 	if (ent) {
234 		ent->nlink = 1;
235 		ent->data = (void *)proc_ppc64_pmc_system_root;
236 		ent->read_proc = (void *)proc_ppc64_pmc_htab_read;
237 		ent->write_proc = NULL;
238 	}
239 
240 	ent = create_proc_entry("profile", S_IWUSR | S_IRUGO, proc_ppc64_pmc_system_root);
241 	if (ent) {
242 		ent->nlink = 1;
243 		ent->proc_fops = &proc_profile_operations;
244 		/* ent->size = (1+prof_len) * sizeof(unsigned int); */
245 	}
246 
247 	ent = create_proc_entry("trace", S_IWUSR | S_IRUGO, proc_ppc64_pmc_system_root);
248 	if (ent) {
249 		ent->nlink = 1;
250 		ent->proc_fops = &proc_trace_operations;
251 		/* ent->size = (1+prof_len) * sizeof(unsigned int); */
252 	}
253 
254 	ent = create_proc_entry("timeslice", S_IWUSR | S_IRUGO, proc_ppc64_pmc_system_root);
255 	if (ent) {
256 		ent->nlink = 1;
257 		ent->proc_fops = &proc_timeslice_operations;
258 	}
259 
260 	/* Create directories for the hardware counters. */
261 	for (i = 0; i < systemcfg->processorCount; i++) {
262 		ent = create_proc_entry("hardware", S_IRUGO | S_IWUSR,
263 					proc_ppc64_pmc_cpu_root[i]);
264 		if (ent) {
265 			ent->nlink = 1;
266 			ent->data = (void *)proc_ppc64_pmc_cpu_root[i];
267 			ent->read_proc = (void *)proc_ppc64_pmc_hw_read;
268 			ent->write_proc = NULL;
269 		}
270 	}
271 
272 	ent = create_proc_entry("hardware", S_IRUGO | S_IWUSR,
273 				proc_ppc64_pmc_system_root);
274 	if (ent) {
275 		ent->nlink = 1;
276 		ent->data = (void *)proc_ppc64_pmc_system_root;
277 		ent->read_proc = (void *)proc_ppc64_pmc_hw_read;
278 		ent->write_proc = NULL;
279 	}
280 }
281 
282 /* Read a page of raw data.  "data" points to the start addr.
283  * Intended as a proc read function.
284  */
proc_ppc64_page_read(char * page,char ** start,off_t off,int count,int * eof,void * data)285 static int proc_ppc64_page_read(char *page, char **start, off_t off,
286 				int count, int *eof, void *data)
287 {
288 	int len = PAGE_SIZE - off;
289 	char *p = (char *)data;
290 
291 	if (len > count)
292 		len = count;
293 	if (len <= 0)
294 		return 0;
295 	/* Rely on a "hack" in fs/proc/generic.c.
296 	 * If we could return a ptr to our own data this would be
297 	 * trivial (currently *start must be either an offset, or
298 	 * point into the given page).
299 	 */
300 	memcpy(page, p+off, len);
301 	*start = (char *)len;
302 	return len;
303 }
304 
305 /* NOTE: since paca data is always in flux the values will never be a consistant set.
306  * In theory it could be made consistent if we made the corresponding cpu
307  * copy the page for us (via an IPI).  Probably not worth it.
308  *
309  */
proc_ppc64_create_paca(int num,struct proc_dir_entry * paca_dir)310 static void proc_ppc64_create_paca(int num, struct proc_dir_entry *paca_dir)
311 {
312 	struct proc_dir_entry *ent;
313 	struct paca_struct *lpaca = paca + num;
314 	char buf[16];
315 
316 	sprintf(buf, "%02x", num);
317 	ent = create_proc_read_entry(buf, S_IRUSR, paca_dir, proc_ppc64_page_read, lpaca);
318 }
319 
320 /*
321  * Find the requested 'file' given a proc token.
322  *
323  * Inputs: void * data: proc token
324  * Output: int        : (0, ..., +N) = CPU number.
325  *                      -1           = System.
326  */
proc_ppc64_pmc_find_file(void * data)327 int proc_ppc64_pmc_find_file(void *data)
328 {
329 	int i;
330 
331 	if ((unsigned long)data ==
332 	   (unsigned long) proc_ppc64_pmc_system_root) {
333 		return(-1);
334 	} else {
335 		for (i = 0; i < systemcfg->processorCount; i++) {
336 			if ((unsigned long)data ==
337 			   (unsigned long)proc_ppc64_pmc_cpu_root[i]) {
338 				return(i);
339 			}
340 		}
341 	}
342 
343 	/* On error, just default to a type of system. */
344 	printk("proc_ppc64_pmc_find_file: failed to find file token.\n");
345 	return(-1);
346 }
347 
348 int
proc_ppc64_pmc_read(char * page,char ** start,off_t off,int count,int * eof,char * buffer)349 proc_ppc64_pmc_read(char *page, char **start, off_t off,
350 		    int count, int *eof, char *buffer)
351 {
352 	int buffer_size, n;
353 
354 	if (count < 0) return 0;
355 
356 	if (buffer == NULL) {
357 		*eof = 1;
358 		return 0;
359 	}
360 
361 	/* Check for read beyond EOF */
362 	buffer_size = n = strlen(buffer);
363 	if (off >= buffer_size) {
364 		*eof = 1;
365 		return 0;
366 	}
367 	if (n > (buffer_size - off)) n = buffer_size - off;
368 
369 	/* Never return more than was requested */
370 	if (n > count) {
371 		n = count;
372 	} else {
373 		*eof = 1;
374 	}
375 
376 	memcpy(page, buffer + off, n);
377 
378 	*start = page;
379 
380 	return n;
381 }
382 
383 int
proc_ppc64_pmc_stab_read(char * page,char ** start,off_t off,int count,int * eof,void * data)384 proc_ppc64_pmc_stab_read(char *page, char **start, off_t off,
385 			 int count, int *eof, void *data)
386 {
387 	int n, file;
388 	char *buffer = NULL;
389 
390 	if (count < 0) return 0;
391 	spin_lock(&proc_ppc64_lock);
392 
393 	/* Figure out which file is being request. */
394 	file = proc_ppc64_pmc_find_file(data);
395 
396 	/* Update the counters and the text buffer representation. */
397 	buffer = ppc64_pmc_stab(file);
398 
399 	/* Put the data into the requestor's buffer. */
400 	n = proc_ppc64_pmc_read(page, start, off, count, eof, buffer);
401 
402 	spin_unlock(&proc_ppc64_lock);
403 	return n;
404 }
405 
406 int
proc_ppc64_pmc_htab_read(char * page,char ** start,off_t off,int count,int * eof,void * data)407 proc_ppc64_pmc_htab_read(char *page, char **start, off_t off,
408 			 int count, int *eof, void *data)
409 {
410 	int n, file;
411 	char *buffer = NULL;
412 
413 	if (count < 0) return 0;
414 	spin_lock(&proc_ppc64_lock);
415 
416 	/* Figure out which file is being request. */
417 	file = proc_ppc64_pmc_find_file(data);
418 
419 	/* Update the counters and the text buffer representation. */
420 	buffer = ppc64_pmc_htab(file);
421 
422 	/* Put the data into the requestor's buffer. */
423 	n = proc_ppc64_pmc_read(page, start, off, count, eof, buffer);
424 
425 	spin_unlock(&proc_ppc64_lock);
426 	return n;
427 }
428 
read_profile(struct file * file,char * buf,size_t count,loff_t * ppos)429 static ssize_t read_profile(struct file *file, char *buf,
430 			    size_t count, loff_t *ppos)
431 {
432 	unsigned long p = *ppos;
433 	ssize_t read;
434 	char * pnt;
435 	unsigned int sample_step = 4;
436 
437 	if (p >= (perfmon_base.profile_length+1)) return 0;
438 	if (count > (perfmon_base.profile_length+1) - p)
439 		count = (perfmon_base.profile_length+1) - p;
440 	read = 0;
441 
442 	while (p < sizeof(unsigned int) && count > 0) {
443 		put_user(*((char *)(&sample_step)+p),buf);
444 		buf++; p++; count--; read++;
445 	}
446 	pnt = (char *)(perfmon_base.profile_buffer) + p - sizeof(unsigned int);
447 	copy_to_user(buf,(void *)pnt,count);
448 	p += count;
449 	read += count;
450 	*ppos = p;
451 	return read;
452 }
453 
write_profile(struct file * file,const char * buf,size_t count,loff_t * ppos)454 static ssize_t write_profile(struct file * file, const char * buf,
455 			     size_t count, loff_t *ppos)
456 {
457 	return(0);
458 }
459 
read_trace(struct file * file,char * buf,size_t count,loff_t * ppos)460 static ssize_t read_trace(struct file *file, char *buf,
461 			    size_t count, loff_t *ppos)
462 {
463 	unsigned long p = *ppos;
464 	char * pnt;
465 
466 	if (p >= (perfmon_base.trace_length)) return 0;
467 	if (count > (perfmon_base.trace_length) - p)
468 		count = (perfmon_base.trace_length) - p;
469 
470 	pnt = (char *)(perfmon_base.trace_buffer) + p;
471 	copy_to_user(buf,(void *)pnt,count);
472 	p += count;
473 	*ppos = p;
474 	return count;
475 }
476 
write_trace(struct file * file,const char * buf,size_t count,loff_t * ppos)477 static ssize_t write_trace(struct file * file, const char * buf,
478 			     size_t count, loff_t *ppos)
479 {
480 	return(0);
481 }
482 
read_timeslice(struct file * file,char * buf,size_t count,loff_t * ppos)483 static ssize_t read_timeslice(struct file *file, char *buf,
484 			      size_t count, loff_t *ppos)
485 {
486 	unsigned long p = *ppos;
487 	ssize_t read;
488 	char * pnt;
489 
490 	if (p >= (perfmon_base.timeslice_length)) return 0;
491 	if (count > (perfmon_base.timeslice_length) - p)
492 		count = (perfmon_base.timeslice_length) - p;
493 
494 	pnt = (char *)(perfmon_base.timeslice_buffer) + p;
495 	copy_to_user(buf,(void *)pnt,count);
496 	*ppos = p + count;
497 	return count;
498 }
499 
write_timeslice(struct file * file,const char * buf,size_t count,loff_t * ppos)500 static ssize_t write_timeslice(struct file * file, const char * buf,
501 			       size_t count, loff_t *ppos)
502 {
503 	return(0);
504 }
505 
506 int
proc_ppc64_pmc_hw_read(char * page,char ** start,off_t off,int count,int * eof,void * data)507 proc_ppc64_pmc_hw_read(char *page, char **start, off_t off,
508 			     int count, int *eof, void *data)
509 {
510 	int n, file;
511 	char *buffer = NULL;
512 
513 	if (count < 0) return 0;
514 	spin_lock(&proc_ppc64_lock);
515 
516 	/* Figure out which file is being request. */
517 	file = proc_ppc64_pmc_find_file(data);
518 
519 	/* Update the counters and the text buffer representation. */
520 	buffer = ppc64_pmc_hw(file);
521 
522 	/* Put the data into the requestor's buffer. */
523 	n = proc_ppc64_pmc_read(page, start, off, count, eof, buffer);
524 
525 	spin_unlock(&proc_ppc64_lock);
526 	return n;
527 }
528 
529 /*
530  * DRENG the remainder of these functions still need work ...
531  */
pmc_proc_init(struct proc_dir_entry * iSeries_proc)532 void pmc_proc_init(struct proc_dir_entry *iSeries_proc)
533 {
534     struct proc_dir_entry *ent = NULL;
535 
536     ent = create_proc_entry("lpevents", S_IFREG|S_IRUGO, iSeries_proc);
537     if (!ent) return;
538     ent->nlink = 1;
539     ent->data = (void *)0;
540     ent->read_proc = proc_get_lpevents;
541     ent->write_proc = proc_reset_lpevents;
542 
543     ent = create_proc_entry("titanTod", S_IFREG|S_IRUGO, iSeries_proc);
544     if (!ent) return;
545     ent->nlink = 1;
546     ent->data = (void *)0;
547     ent->size = 0;
548     ent->read_proc = proc_get_titanTod;
549     ent->write_proc = NULL;
550 
551     pmc_proc_root = proc_mkdir("pmc", iSeries_proc);
552     if (!pmc_proc_root) return;
553 
554     ent = create_proc_entry("control", S_IFREG|S_IRUSR|S_IWUSR, pmc_proc_root);
555     if (!ent) return;
556     ent->nlink = 1;
557     ent->data = (void *)0;
558     ent->read_proc = proc_pmc_get_control;
559     ent->write_proc = proc_pmc_set_control;
560 
561 }
562 
pmc_calc_metrics(char * page,char ** start,off_t off,int count,int * eof,int len)563 static int pmc_calc_metrics( char *page, char **start, off_t off, int count, int *eof, int len)
564 {
565 	if ( len <= off+count)
566 		*eof = 1;
567 	*start = page+off;
568 	len -= off;
569 	if ( len > count )
570 		len = count;
571 	if ( len < 0 )
572 		len = 0;
573 	return len;
574 }
575 
576 static char * lpEventTypes[9] = {
577 	"Hypervisor\t\t",
578 	"Machine Facilities\t",
579 	"Session Manager\t",
580 	"SPD I/O\t\t",
581 	"Virtual Bus\t\t",
582 	"PCI I/O\t\t",
583 	"RIO I/O\t\t",
584 	"Virtual Lan\t\t",
585 	"Virtual I/O\t\t"
586 	};
587 
588 
proc_get_lpevents(char * page,char ** start,off_t off,int count,int * eof,void * data)589 int proc_get_lpevents
590 (char *page, char **start, off_t off, int count, int *eof, void *data)
591 {
592 	unsigned i;
593 	int len = 0;
594 
595 	len += sprintf( page+len, "LpEventQueue 0\n" );
596 	len += sprintf( page+len, "  events processed:\t%lu\n",
597 			(unsigned long)xItLpQueue.xLpIntCount );
598 	for (i=0; i<9; ++i) {
599 		len += sprintf( page+len, "    %s %10lu\n",
600 			lpEventTypes[i],
601 			(unsigned long)xItLpQueue.xLpIntCountByType[i] );
602 	}
603 	len += sprintf( page+len, "\n  events processed by processor:\n" );
604 	for (i=0; i<systemcfg->processorCount; ++i) {
605 		len += sprintf( page+len, "    CPU%02d  %10u\n",
606 			i, paca[i].lpEvent_count );
607 	}
608 
609 	return pmc_calc_metrics( page, start, off, count, eof, len );
610 
611 }
612 
proc_reset_lpevents(struct file * file,const char * buffer,unsigned long count,void * data)613 int proc_reset_lpevents( struct file *file, const char *buffer, unsigned long count, void *data )
614 {
615 	return count;
616 }
617 
618 static unsigned long startTitan = 0;
619 static unsigned long startTb = 0;
620 
621 
proc_get_titanTod(char * page,char ** start,off_t off,int count,int * eof,void * data)622 int proc_get_titanTod
623 (char *page, char **start, off_t off, int count, int *eof, void *data)
624 {
625 	int len = 0;
626 	unsigned long tb0, titan_tod;
627 
628 	tb0 = get_tb();
629 	titan_tod = HvCallXm_loadTod();
630 
631 	len += sprintf( page+len, "Titan\n" );
632 	len += sprintf( page+len, "  time base =          %016lx\n", tb0 );
633 	len += sprintf( page+len, "  titan tod =          %016lx\n", titan_tod );
634 	len += sprintf( page+len, "  xProcFreq =          %016x\n", xIoHriProcessorVpd[0].xProcFreq );
635 	len += sprintf( page+len, "  xTimeBaseFreq =      %016x\n", xIoHriProcessorVpd[0].xTimeBaseFreq );
636 	len += sprintf( page+len, "  tb_ticks_per_jiffy = %lu\n", tb_ticks_per_jiffy );
637 	len += sprintf( page+len, "  tb_ticks_per_usec  = %lu\n", tb_ticks_per_usec );
638 
639 	if ( !startTitan ) {
640 		startTitan = titan_tod;
641 		startTb = tb0;
642 	}
643 	else {
644 		unsigned long titan_usec = (titan_tod - startTitan) >> 12;
645 		unsigned long tb_ticks = (tb0 - startTb);
646 		unsigned long titan_jiffies = titan_usec / (1000000/HZ);
647 		unsigned long titan_jiff_usec = titan_jiffies * (1000000/HZ);
648 		unsigned long titan_jiff_rem_usec = titan_usec - titan_jiff_usec;
649 		unsigned long tb_jiffies = tb_ticks / tb_ticks_per_jiffy;
650 		unsigned long tb_jiff_ticks = tb_jiffies * tb_ticks_per_jiffy;
651 		unsigned long tb_jiff_rem_ticks = tb_ticks - tb_jiff_ticks;
652 		unsigned long tb_jiff_rem_usec = tb_jiff_rem_ticks / tb_ticks_per_usec;
653 		unsigned long new_tb_ticks_per_jiffy = (tb_ticks * (1000000/HZ))/titan_usec;
654 
655 		len += sprintf( page+len, "  titan elapsed = %lu uSec\n", titan_usec);
656 		len += sprintf( page+len, "  tb elapsed    = %lu ticks\n", tb_ticks);
657 		len += sprintf( page+len, "  titan jiffies = %lu.%04lu \n", titan_jiffies, titan_jiff_rem_usec );
658 		len += sprintf( page+len, "  tb jiffies    = %lu.%04lu\n", tb_jiffies, tb_jiff_rem_usec );
659 		len += sprintf( page+len, "  new tb_ticks_per_jiffy = %lu\n", new_tb_ticks_per_jiffy );
660 
661 	}
662 
663 	return pmc_calc_metrics( page, start, off, count, eof, len );
664 }
665 
proc_pmc_get_control(char * page,char ** start,off_t off,int count,int * eof,void * data)666 int proc_pmc_get_control
667 (char *page, char **start, off_t off, int count, int *eof, void *data)
668 {
669 	int len = 0;
670 
671 	if ( proc_pmc_control_mode == PMC_CONTROL_CPI ) {
672 		unsigned long mach_cycles   = mfspr( PMC5 );
673 		unsigned long inst_complete = mfspr( PMC4 );
674 		unsigned long inst_dispatch = mfspr( PMC3 );
675 		unsigned long thread_active_run = mfspr( PMC1 );
676 		unsigned long thread_active  = mfspr( PMC2 );
677 		unsigned long cpi = 0;
678 		unsigned long cpithou = 0;
679 		unsigned long remain;
680 
681 		if ( inst_complete ) {
682 			cpi = thread_active_run / inst_complete;
683 			remain = thread_active_run % inst_complete;
684 			if ( inst_complete > 1000000 )
685 				cpithou = remain / ( inst_complete / 1000 );
686 			else
687 				cpithou = ( remain * 1000 ) / inst_complete;
688 		}
689 		len += sprintf( page+len, "PMC CPI Mode\nRaw Counts\n" );
690 		len += sprintf( page+len, "machine cycles           : %12lu\n", mach_cycles );
691 		len += sprintf( page+len, "thread active cycles     : %12lu\n\n", thread_active );
692 
693 		len += sprintf( page+len, "instructions completed   : %12lu\n", inst_complete );
694 		len += sprintf( page+len, "instructions dispatched  : %12lu\n", inst_dispatch );
695 		len += sprintf( page+len, "thread active run cycles : %12lu\n", thread_active_run );
696 
697 		len += sprintf( page+len, "thread active run cycles/instructions completed\n" );
698 		len += sprintf( page+len, "CPI = %lu.%03lu\n", cpi, cpithou );
699 
700 	}
701 	else if ( proc_pmc_control_mode == PMC_CONTROL_TLB ) {
702 		len += sprintf( page+len, "PMC TLB Mode\n" );
703 		len += sprintf( page+len, "I-miss count             : %12lu\n", mfspr( PMC1 ) );
704 		len += sprintf( page+len, "I-miss latency           : %12lu\n", mfspr( PMC2 ) );
705 		len += sprintf( page+len, "D-miss count             : %12lu\n", mfspr( PMC3 ) );
706 		len += sprintf( page+len, "D-miss latency           : %12lu\n", mfspr( PMC4 ) );
707 		len += sprintf( page+len, "IERAT miss count         : %12lu\n", mfspr( PMC5 ) );
708 		len += sprintf( page+len, "D-reference count        : %12lu\n", mfspr( PMC6 ) );
709 		len += sprintf( page+len, "miss PTEs searched       : %12lu\n", mfspr( PMC7 ) );
710 		len += sprintf( page+len, "miss >8 PTEs searched    : %12lu\n", mfspr( PMC8 ) );
711 	}
712 	/* IMPLEMENT ME */
713 	return pmc_calc_metrics( page, start, off, count, eof, len );
714 }
715 
proc_pmc_conv_int(const char * buf,unsigned count)716 unsigned long proc_pmc_conv_int( const char *buf, unsigned count )
717 {
718 	const char * p;
719 	char b0, b1;
720 	unsigned v, multiplier, mult, i;
721 	unsigned long val;
722 	multiplier = 10;
723 	p = buf;
724 	if ( count >= 3 ) {
725 		b0 = buf[0];
726 		b1 = buf[1];
727 		if ( ( b0 == '0' ) &&
728 		     ( ( b1 == 'x' ) || ( b1 == 'X' ) ) ) {
729 			p = buf + 2;
730 			count -= 2;
731 			multiplier = 16;
732 		}
733 
734 	}
735 	val = 0;
736 	for ( i=0; i<count; ++i ) {
737 		b0 = *p++;
738 		v = 0;
739 		mult = multiplier;
740 		if ( ( b0 >= '0' ) && ( b0 <= '9' ) )
741 			v = b0 - '0';
742 		else if ( multiplier == 16 ) {
743 			if ( ( b0 >= 'a' ) && ( b0 <= 'f' ) )
744 				v = b0 - 'a' + 10;
745 			else if ( ( b0 >= 'A' ) && ( b0 <= 'F' ) )
746 				v = b0 - 'A' + 10;
747 			else
748 				mult = 1;
749 		}
750 		else
751 			mult = 1;
752 		val *= mult;
753 		val += v;
754 	}
755 
756 	return val;
757 
758 }
759 
proc_pmc_stop(void)760 static inline void proc_pmc_stop(void)
761 {
762 	/* Freeze all counters, leave everything else alone */
763 	mtspr( MMCR0, mfspr( MMCR0 ) | 0x80000000 );
764 }
765 
proc_pmc_start(void)766 static inline void proc_pmc_start(void)
767 {
768 	/* Unfreeze all counters, leave everything else alone */
769 	mtspr( MMCR0, mfspr( MMCR0 ) & ~0x80000000 );
770 
771 }
772 
proc_pmc_reset(void)773 static inline void proc_pmc_reset(void)
774 {
775 	/* Clear all the PMCs to zeros
776 	 * Assume a "stop" has already frozen the counters
777 	 * Clear all the PMCs
778 	 */
779 	mtspr( PMC1, 0 );
780 	mtspr( PMC2, 0 );
781 	mtspr( PMC3, 0 );
782 	mtspr( PMC4, 0 );
783 	mtspr( PMC5, 0 );
784 	mtspr( PMC6, 0 );
785 	mtspr( PMC7, 0 );
786 	mtspr( PMC8, 0 );
787 
788 }
789 
proc_pmc_cpi(void)790 static inline void proc_pmc_cpi(void)
791 {
792 	/* Configure the PMC registers to count cycles and instructions */
793 	/* so we can compute cpi */
794 	/*
795 	 * MMCRA[30]    = 1     Don't count in wait state (CTRL[31]=0)
796 	 * MMCR0[6]     = 1     Freeze counters when any overflow
797 	 * MMCR0[19:25] = 0x01  PMC1 counts Thread Active Run Cycles
798 	 * MMCR0[26:31] = 0x05	PMC2 counts Thread Active Cycles
799 	 * MMCR1[0:4]   = 0x07	PMC3 counts Instructions Dispatched
800 	 * MMCR1[5:9]   = 0x03	PMC4 counts Instructions Completed
801 	 * MMCR1[10:14] = 0x06	PMC5 counts Machine Cycles
802 	 *
803 	 */
804 
805 	proc_pmc_control_mode = PMC_CONTROL_CPI;
806 
807 	/* Indicate to hypervisor that we are using the PMCs */
808 	get_paca()->xLpPacaPtr->xPMCRegsInUse = 1;
809 
810 	/* Freeze all counters */
811 	mtspr( MMCR0, 0x80000000 );
812 	mtspr( MMCR1, 0x00000000 );
813 
814 	/* Clear all the PMCs */
815 	mtspr( PMC1, 0 );
816 	mtspr( PMC2, 0 );
817 	mtspr( PMC3, 0 );
818 	mtspr( PMC4, 0 );
819 	mtspr( PMC5, 0 );
820 	mtspr( PMC6, 0 );
821 	mtspr( PMC7, 0 );
822 	mtspr( PMC8, 0 );
823 
824 	/* Freeze counters in Wait State (CTRL[31]=0) */
825 	mtspr( MMCRA, 0x00000002 );
826 
827 	/* PMC3<-0x07, PMC4<-0x03, PMC5<-0x06 */
828 	mtspr( MMCR1, 0x38cc0000 );
829 
830 	mb();
831 
832 	/* PMC1<-0x01, PMC2<-0x05
833 	 * Start all counters
834 	 */
835 	mtspr( MMCR0, 0x02000045 );
836 
837 }
838 
proc_pmc_tlb(void)839 static inline void proc_pmc_tlb(void)
840 {
841 	/* Configure the PMC registers to count tlb misses  */
842 	/*
843 	 * MMCR0[6]     = 1     Freeze counters when any overflow
844 	 * MMCR0[19:25] = 0x55  Group count
845 	 *   PMC1 counts  I misses
846 	 *   PMC2 counts  I miss duration (latency)
847 	 *   PMC3 counts  D misses
848 	 *   PMC4 counts  D miss duration (latency)
849 	 *   PMC5 counts  IERAT misses
850 	 *   PMC6 counts  D references (including PMC7)
851 	 *   PMC7 counts  miss PTEs searched
852 	 *   PMC8 counts  miss >8 PTEs searched
853 	 *
854 	 */
855 
856 	proc_pmc_control_mode = PMC_CONTROL_TLB;
857 
858 	/* Indicate to hypervisor that we are using the PMCs */
859 	get_paca()->xLpPacaPtr->xPMCRegsInUse = 1;
860 
861 	/* Freeze all counters */
862 	mtspr( MMCR0, 0x80000000 );
863 	mtspr( MMCR1, 0x00000000 );
864 
865 	/* Clear all the PMCs */
866 	mtspr( PMC1, 0 );
867 	mtspr( PMC2, 0 );
868 	mtspr( PMC3, 0 );
869 	mtspr( PMC4, 0 );
870 	mtspr( PMC5, 0 );
871 	mtspr( PMC6, 0 );
872 	mtspr( PMC7, 0 );
873 	mtspr( PMC8, 0 );
874 
875 	mtspr( MMCRA, 0x00000000 );
876 
877 	mb();
878 
879 	/* PMC1<-0x55
880 	 * Start all counters
881 	 */
882 	mtspr( MMCR0, 0x02001540 );
883 
884 }
885 
proc_pmc_set_control(struct file * file,const char * buffer,unsigned long count,void * data)886 int proc_pmc_set_control( struct file *file, const char *buffer, unsigned long count, void *data )
887 {
888 	char stkbuf[10];
889 
890 	if (count > 9)
891 		count = 9;
892 	if (copy_from_user (stkbuf, buffer, count))
893 		return -EFAULT;
894 
895 	stkbuf[count] = 0;
896 
897 	if      ( ! strncmp( stkbuf, "stop", 4 ) )
898 		proc_pmc_stop();
899 	else if ( ! strncmp( stkbuf, "start", 5 ) )
900 		proc_pmc_start();
901 	else if ( ! strncmp( stkbuf, "reset", 5 ) )
902 		proc_pmc_reset();
903 	else if ( ! strncmp( stkbuf, "cpi", 3 ) )
904 		proc_pmc_cpi();
905 	else if ( ! strncmp( stkbuf, "tlb", 3 ) )
906 		proc_pmc_tlb();
907 
908 	/* IMPLEMENT ME */
909 	return count;
910 }
911 
proc_pmc_set_mmcr0(struct file * file,const char * buffer,unsigned long count,void * data)912 int proc_pmc_set_mmcr0( struct file *file, const char *buffer, unsigned long count, void *data )
913 {
914 	unsigned long v;
915 	v = proc_pmc_conv_int( buffer, count );
916 	v = v & ~0x04000000;	/* Don't allow interrupts for now */
917 	if ( v & ~0x80000000 ) 	/* Inform hypervisor we are using PMCs */
918 		get_paca()->xLpPacaPtr->xPMCRegsInUse = 1;
919 	else
920 		get_paca()->xLpPacaPtr->xPMCRegsInUse = 0;
921 	mtspr( MMCR0, v );
922 
923 	return count;
924 }
925 
proc_pmc_set_mmcr1(struct file * file,const char * buffer,unsigned long count,void * data)926 int proc_pmc_set_mmcr1( struct file *file, const char *buffer, unsigned long count, void *data )
927 {
928 	unsigned long v;
929 	v = proc_pmc_conv_int( buffer, count );
930 	mtspr( MMCR1, v );
931 
932 	return count;
933 }
934 
proc_pmc_set_mmcra(struct file * file,const char * buffer,unsigned long count,void * data)935 int proc_pmc_set_mmcra( struct file *file, const char *buffer, unsigned long count, void *data )
936 {
937 	unsigned long v;
938 	v = proc_pmc_conv_int( buffer, count );
939 	v = v & ~0x00008000;	/* Don't allow interrupts for now */
940 	mtspr( MMCRA, v );
941 
942 	return count;
943 }
944 
945 
proc_pmc_set_pmc1(struct file * file,const char * buffer,unsigned long count,void * data)946 int proc_pmc_set_pmc1( struct file *file, const char *buffer, unsigned long count, void *data )
947 {
948 	unsigned long v;
949 	v = proc_pmc_conv_int( buffer, count );
950 	mtspr( PMC1, v );
951 
952 	return count;
953 }
954 
proc_pmc_set_pmc2(struct file * file,const char * buffer,unsigned long count,void * data)955 int proc_pmc_set_pmc2( struct file *file, const char *buffer, unsigned long count, void *data )
956 {
957 	unsigned long v;
958 	v = proc_pmc_conv_int( buffer, count );
959 	mtspr( PMC2, v );
960 
961 	return count;
962 }
963 
proc_pmc_set_pmc3(struct file * file,const char * buffer,unsigned long count,void * data)964 int proc_pmc_set_pmc3( struct file *file, const char *buffer, unsigned long count, void *data )
965 {
966 	unsigned long v;
967 	v = proc_pmc_conv_int( buffer, count );
968 	mtspr( PMC3, v );
969 
970 	return count;
971 }
972 
proc_pmc_set_pmc4(struct file * file,const char * buffer,unsigned long count,void * data)973 int proc_pmc_set_pmc4( struct file *file, const char *buffer, unsigned long count, void *data )
974 {
975 	unsigned long v;
976 	v = proc_pmc_conv_int( buffer, count );
977 	mtspr( PMC4, v );
978 
979 	return count;
980 }
981 
proc_pmc_set_pmc5(struct file * file,const char * buffer,unsigned long count,void * data)982 int proc_pmc_set_pmc5( struct file *file, const char *buffer, unsigned long count, void *data )
983 {
984 	unsigned long v;
985 	v = proc_pmc_conv_int( buffer, count );
986 	mtspr( PMC5, v );
987 
988 	return count;
989 }
990 
proc_pmc_set_pmc6(struct file * file,const char * buffer,unsigned long count,void * data)991 int proc_pmc_set_pmc6( struct file *file, const char *buffer, unsigned long count, void *data )
992 {
993 	unsigned long v;
994 	v = proc_pmc_conv_int( buffer, count );
995 	mtspr( PMC6, v );
996 
997 	return count;
998 }
999 
proc_pmc_set_pmc7(struct file * file,const char * buffer,unsigned long count,void * data)1000 int proc_pmc_set_pmc7( struct file *file, const char *buffer, unsigned long count, void *data )
1001 {
1002 	unsigned long v;
1003 	v = proc_pmc_conv_int( buffer, count );
1004 	mtspr( PMC7, v );
1005 
1006 	return count;
1007 }
1008 
proc_pmc_set_pmc8(struct file * file,const char * buffer,unsigned long count,void * data)1009 int proc_pmc_set_pmc8( struct file *file, const char *buffer, unsigned long count, void *data )
1010 {
1011 	unsigned long v;
1012 	v = proc_pmc_conv_int( buffer, count );
1013 	mtspr( PMC8, v );
1014 
1015 	return count;
1016 }
1017 
nacamap_seek(struct file * file,loff_t off,int whence)1018 static loff_t nacamap_seek( struct file *file, loff_t off, int whence)
1019 {
1020 	loff_t new;
1021 	struct proc_dir_entry *dp;
1022 
1023 	dp = file->f_dentry->d_inode->u.generic_ip;
1024 
1025 	switch(whence) {
1026 	case 0:
1027 		new = off;
1028 		break;
1029 	case 1:
1030 		new = file->f_pos + off;
1031 		break;
1032 	case 2:
1033 		new = dp->size + off;
1034 		break;
1035 	default:
1036 		return -EINVAL;
1037 	}
1038 	if ( new < 0 || new > dp->size )
1039 		return -EINVAL;
1040 	return (file->f_pos = new);
1041 }
1042 
nacamap_read(struct file * file,char * buf,size_t nbytes,loff_t * ppos)1043 static ssize_t nacamap_read( struct file *file, char *buf, size_t nbytes, loff_t *ppos)
1044 {
1045 	unsigned pos = *ppos;
1046 	struct proc_dir_entry *dp;
1047 
1048 	dp = file->f_dentry->d_inode->u.generic_ip;
1049 
1050 	if ( pos >= dp->size )
1051 		return 0;
1052 	if ( nbytes >= dp->size )
1053 		nbytes = dp->size;
1054 	if ( pos + nbytes > dp->size )
1055 		nbytes = dp->size - pos;
1056 
1057 	copy_to_user( buf, (char *)dp->data + pos, nbytes );
1058 	*ppos = pos + nbytes;
1059 	return nbytes;
1060 }
1061 
nacamap_mmap(struct file * file,struct vm_area_struct * vma)1062 static int nacamap_mmap( struct file *file, struct vm_area_struct *vma )
1063 {
1064 	struct proc_dir_entry *dp;
1065 
1066 	dp = file->f_dentry->d_inode->u.generic_ip;
1067 
1068 	vma->vm_flags |= VM_SHM | VM_LOCKED;
1069 
1070 	if ((vma->vm_end - vma->vm_start) > dp->size)
1071 		return -EINVAL;
1072 
1073 	remap_page_range( vma->vm_start, __pa(dp->data), dp->size, vma->vm_page_prot );
1074 	return 0;
1075 }
1076 
proc_ppc64_smt_snooze_read(char * page,char ** start,off_t off,int count,int * eof,void * data)1077 static int proc_ppc64_smt_snooze_read(char *page, char **start, off_t off,
1078 				      int count, int *eof, void *data)
1079 {
1080 	if (naca->smt_snooze_delay)
1081 		return sprintf(page, "%lu\n", naca->smt_snooze_delay);
1082 	else
1083 		return sprintf(page, "disabled\n");
1084 }
1085 
proc_ppc64_smt_snooze_write(struct file * file,const char * buffer,unsigned long count,void * data)1086 static int proc_ppc64_smt_snooze_write(struct file* file, const char *buffer,
1087 				       unsigned long count, void *data)
1088 {
1089 	unsigned long val;
1090 	char val_string[22];
1091 
1092 	if (!capable(CAP_SYS_ADMIN))
1093 		return -EACCES;
1094 
1095 	if (count > sizeof(val_string) - 1)
1096 		return -EINVAL;
1097 
1098 	if (copy_from_user(val_string, buffer, count))
1099 		return -EFAULT;
1100 
1101 	val_string[count] = '\0';
1102 
1103 	if (val_string[0] == '0' && (val_string[1] == '\n' || val_string[1] == '\0')) {
1104 		naca->smt_snooze_delay = 0;
1105 		return count;
1106 	}
1107 
1108 	val = simple_strtoul(val_string, NULL, 10);
1109 	if (val != 0)
1110 		naca->smt_snooze_delay = val;
1111 	else
1112 		return -EINVAL;
1113 
1114 	return count;
1115 }
1116 
proc_ppc64_smt_state_read(char * page,char ** start,off_t off,int count,int * eof,void * data)1117 static int proc_ppc64_smt_state_read(char *page, char **start, off_t off,
1118 				      int count, int *eof, void *data)
1119 {
1120 	switch(naca->smt_state) {
1121 	case SMT_OFF:
1122 		return sprintf(page, "off\n");
1123 		break;
1124 	case SMT_ON:
1125 		return sprintf(page, "on\n");
1126 		break;
1127 	case SMT_DYNAMIC:
1128 		return sprintf(page, "dynamic\n");
1129 		break;
1130 	default:
1131 		return sprintf(page, "unknown\n");
1132 		break;
1133 	}
1134 }
1135 
proc_ppc64_create_smt(void)1136 void proc_ppc64_create_smt(void)
1137 {
1138 	struct proc_dir_entry *ent_snooze =
1139 		create_proc_entry("smt-snooze-delay", S_IRUGO | S_IWUSR,
1140 				  proc_ppc64_root);
1141 	struct proc_dir_entry *ent_enabled =
1142 		create_proc_entry("smt-enabled", S_IRUGO | S_IWUSR,
1143 				  proc_ppc64_root);
1144 	if (ent_snooze) {
1145 		ent_snooze->nlink = 1;
1146 		ent_snooze->data = NULL;
1147 		ent_snooze->read_proc = (void *)proc_ppc64_smt_snooze_read;
1148 		ent_snooze->write_proc = (void *)proc_ppc64_smt_snooze_write;
1149 	}
1150 
1151 	if (ent_enabled) {
1152 		ent_enabled->nlink = 1;
1153 		ent_enabled->data = NULL;
1154 		ent_enabled->read_proc = (void *)proc_ppc64_smt_state_read;
1155 		ent_enabled->write_proc = NULL;
1156 	}
1157 }
1158