| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * This file is subject to the terms and conditions of the GNU General Public | 
					
						
							|  |  |  |  * License.  See the file "COPYING" in the main directory of this archive | 
					
						
							|  |  |  |  * for more details. | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2005-02-07 02:54:29 +00:00
										 |  |  |  * Copyright (C) 2004, 2005 Ralf Baechle | 
					
						
							|  |  |  |  * Copyright (C) 2005 MIPS Technologies, Inc. | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  |  */ | 
					
						
							| 
									
										
										
										
											2010-01-26 23:02:34 +08:00
										 |  |  | #include <linux/compiler.h>
 | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | #include <linux/errno.h>
 | 
					
						
							|  |  |  | #include <linux/init.h>
 | 
					
						
							|  |  |  | #include <linux/oprofile.h>
 | 
					
						
							|  |  |  | #include <linux/smp.h>
 | 
					
						
							|  |  |  | #include <asm/cpu-info.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "op_impl.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-26 23:02:34 +08:00
										 |  |  | extern struct op_mips_model op_model_mipsxx_ops __weak; | 
					
						
							|  |  |  | extern struct op_mips_model op_model_loongson2_ops __weak; | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | static struct op_mips_model *model; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static struct op_counter_config ctr[20]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int op_mips_setup(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	/* Pre-compute the values to stuff in the hardware registers.  */ | 
					
						
							|  |  |  | 	model->reg_setup(ctr); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-22 12:59:30 +01:00
										 |  |  | 	/* Configure the registers on all cpus.	 */ | 
					
						
							| 
									
										
										
										
											2008-05-09 09:39:44 +02:00
										 |  |  | 	on_each_cpu(model->cpu_setup, NULL, 1); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-22 12:59:30 +01:00
										 |  |  | 	return 0; | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-07-19 15:52:42 +04:00
										 |  |  | static int op_mips_create_files(struct dentry *root) | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | { | 
					
						
							|  |  |  | 	int i; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for (i = 0; i < model->num_counters; ++i) { | 
					
						
							|  |  |  | 		struct dentry *dir; | 
					
						
							| 
									
										
										
										
											2006-06-26 00:24:34 -07:00
										 |  |  | 		char buf[4]; | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		snprintf(buf, sizeof buf, "%d", i); | 
					
						
							| 
									
										
										
										
											2013-07-19 15:58:27 +04:00
										 |  |  | 		dir = oprofilefs_mkdir(root, buf); | 
					
						
							| 
									
										
										
										
											2013-07-19 15:52:42 +04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-07-19 16:10:36 +04:00
										 |  |  | 		oprofilefs_create_ulong(dir, "enabled", &ctr[i].enabled); | 
					
						
							|  |  |  | 		oprofilefs_create_ulong(dir, "event", &ctr[i].event); | 
					
						
							|  |  |  | 		oprofilefs_create_ulong(dir, "count", &ctr[i].count); | 
					
						
							|  |  |  | 		oprofilefs_create_ulong(dir, "kernel", &ctr[i].kernel); | 
					
						
							|  |  |  | 		oprofilefs_create_ulong(dir, "user", &ctr[i].user); | 
					
						
							|  |  |  | 		oprofilefs_create_ulong(dir, "exl", &ctr[i].exl); | 
					
						
							| 
									
										
										
										
											2005-02-07 02:54:29 +00:00
										 |  |  | 		/* Dummy.  */ | 
					
						
							| 
									
										
										
										
											2013-07-19 16:10:36 +04:00
										 |  |  | 		oprofilefs_create_ulong(dir, "unit_mask", &ctr[i].unit_mask); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int op_mips_start(void) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2008-05-09 09:39:44 +02:00
										 |  |  | 	on_each_cpu(model->cpu_start, NULL, 1); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void op_mips_stop(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	/* Disable performance monitoring for all counters.  */ | 
					
						
							| 
									
										
										
										
											2008-05-09 09:39:44 +02:00
										 |  |  | 	on_each_cpu(model->cpu_stop, NULL, 1); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-02-07 02:54:29 +00:00
										 |  |  | int __init oprofile_arch_init(struct oprofile_operations *ops) | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | { | 
					
						
							|  |  |  | 	struct op_mips_model *lmodel = NULL; | 
					
						
							| 
									
										
										
										
											2005-02-07 02:54:29 +00:00
										 |  |  | 	int res; | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-10-11 23:46:15 +01:00
										 |  |  | 	switch (current_cpu_type()) { | 
					
						
							| 
									
										
										
										
											2005-12-09 12:42:13 +00:00
										 |  |  | 	case CPU_5KC: | 
					
						
							| 
									
										
										
										
											2012-07-06 23:56:00 +02:00
										 |  |  | 	case CPU_M14KC: | 
					
						
							| 
									
										
										
										
											2012-12-07 03:51:35 +00:00
										 |  |  | 	case CPU_M14KEC: | 
					
						
							| 
									
										
										
										
											2005-12-09 12:42:13 +00:00
										 |  |  | 	case CPU_20KC: | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	case CPU_24K: | 
					
						
							| 
									
										
										
										
											2005-12-09 12:42:13 +00:00
										 |  |  | 	case CPU_25KF: | 
					
						
							| 
									
										
										
										
											2006-02-01 17:54:30 +00:00
										 |  |  | 	case CPU_34K: | 
					
						
							| 
									
										
										
										
											2008-04-28 17:14:26 +01:00
										 |  |  | 	case CPU_1004K: | 
					
						
							| 
									
										
										
										
											2006-05-02 14:08:46 +01:00
										 |  |  | 	case CPU_74K: | 
					
						
							| 
									
										
										
										
											2012-06-20 20:05:32 +01:00
										 |  |  | 	case CPU_LOONGSON1: | 
					
						
							| 
									
										
										
										
											2006-01-17 12:06:32 -08:00
										 |  |  | 	case CPU_SB1: | 
					
						
							|  |  |  | 	case CPU_SB1A: | 
					
						
							| 
									
										
										
										
											2006-10-23 00:44:02 +01:00
										 |  |  | 	case CPU_R10000: | 
					
						
							|  |  |  | 	case CPU_R12000: | 
					
						
							|  |  |  | 	case CPU_R14000: | 
					
						
							| 
									
										
										
										
											2012-10-31 12:01:27 +00:00
										 |  |  | 	case CPU_XLR: | 
					
						
							| 
									
										
										
										
											2006-05-23 16:42:38 +09:00
										 |  |  | 		lmodel = &op_model_mipsxx_ops; | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 		break; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-07-02 23:25:46 +08:00
										 |  |  | 	case CPU_LOONGSON2: | 
					
						
							|  |  |  | 		lmodel = &op_model_loongson2_ops; | 
					
						
							|  |  |  | 		break; | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!lmodel) | 
					
						
							| 
									
										
										
										
											2005-02-07 02:54:29 +00:00
										 |  |  | 		return -ENODEV; | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-02-07 02:54:29 +00:00
										 |  |  | 	res = lmodel->init(); | 
					
						
							|  |  |  | 	if (res) | 
					
						
							|  |  |  | 		return res; | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	model = lmodel; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-02-07 02:54:29 +00:00
										 |  |  | 	ops->create_files	= op_mips_create_files; | 
					
						
							|  |  |  | 	ops->setup		= op_mips_setup; | 
					
						
							| 
									
										
										
										
											2013-01-22 12:59:30 +01:00
										 |  |  | 	//ops->shutdown		= op_mips_shutdown;
 | 
					
						
							| 
									
										
										
										
											2005-02-07 02:54:29 +00:00
										 |  |  | 	ops->start		= op_mips_start; | 
					
						
							|  |  |  | 	ops->stop		= op_mips_stop; | 
					
						
							|  |  |  | 	ops->cpu_type		= lmodel->cpu_type; | 
					
						
							| 
									
										
										
										
											2011-05-13 08:38:05 -04:00
										 |  |  | 	ops->backtrace		= op_mips_backtrace; | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	printk(KERN_INFO "oprofile: using %s performance monitoring.\n", | 
					
						
							|  |  |  | 	       lmodel->cpu_type); | 
					
						
							| 
									
										
										
										
											2005-02-07 02:54:29 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void oprofile_arch_exit(void) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2006-04-24 10:48:54 +01:00
										 |  |  | 	if (model) | 
					
						
							|  |  |  | 		model->exit(); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | } |