From: Anton Blanchard <anton@samba.org>

POWER4 oprofile updates from Carl Love.

- Create mmcr0, mmcr1, mmcra oprofilefs files.
- Use kernel and user profile disable bits. (Some modifications by me)

Signed-off-by: Anton Blanchard <anton@samba.org>
Signed-off-by: Andrew Morton <akpm@osdl.org>
---

 25-akpm/arch/ppc64/oprofile/common.c          |   12 ++++++++++
 25-akpm/arch/ppc64/oprofile/op_impl.h         |   15 ++++++++++--
 25-akpm/arch/ppc64/oprofile/op_model_power4.c |   31 +++++++++++++++++++++++---
 3 files changed, 52 insertions(+), 6 deletions(-)

diff -puN arch/ppc64/oprofile/common.c~ppc64-power4-oprofile-update arch/ppc64/oprofile/common.c
--- 25/arch/ppc64/oprofile/common.c~ppc64-power4-oprofile-update	2004-08-16 11:54:59.573258136 -0700
+++ 25-akpm/arch/ppc64/oprofile/common.c	2004-08-16 11:54:59.579257224 -0700
@@ -90,6 +90,14 @@ static int op_ppc64_create_files(struct 
 {
 	int i;
 
+	/*
+	 * There is one mmcr0, mmcr1 and mmcra for setting the events for
+	 * all of the counters.
+	 */
+	oprofilefs_create_ulong(sb, root, "mmcr0", &sys.mmcr0);
+	oprofilefs_create_ulong(sb, root, "mmcr1", &sys.mmcr1);
+	oprofilefs_create_ulong(sb, root, "mmcra", &sys.mmcra);
+
 	for (i = 0; i < model->num_counters; ++i) {
 		struct dentry *dir;
 		char buf[3];
@@ -112,6 +120,10 @@ static int op_ppc64_create_files(struct 
 	oprofilefs_create_ulong(sb, root, "enable_kernel", &sys.enable_kernel);
 	oprofilefs_create_ulong(sb, root, "enable_user", &sys.enable_user);
 
+	/* Default to tracing both kernel and user */
+	sys.enable_kernel = 1;
+	sys.enable_user = 1;
+
 	return 0;
 }
 
diff -puN arch/ppc64/oprofile/op_impl.h~ppc64-power4-oprofile-update arch/ppc64/oprofile/op_impl.h
--- 25/arch/ppc64/oprofile/op_impl.h~ppc64-power4-oprofile-update	2004-08-16 11:54:59.574257984 -0700
+++ 25-akpm/arch/ppc64/oprofile/op_impl.h	2004-08-16 11:54:59.579257224 -0700
@@ -19,6 +19,12 @@
 /* freeze counters. set to 1 on a perfmon exception */
 #define MMCR0_FC	(1UL << (31 - 0))
 
+/* freeze in supervisor state */
+#define MMCR0_KERNEL_DISABLE (1UL << (31 - 1))
+
+/* freeze in problem state */
+#define MMCR0_PROBLEM_DISABLE (1UL << (31 - 2))
+
 /* freeze counters while MSR mark = 1 */
 #define MMCR0_FCM1	(1UL << (31 - 3))
 
@@ -28,15 +34,15 @@
 /* freeze counters on enabled condition or event */
 #define MMCR0_FCECE	(1UL << (31 - 6))
 
-/* performance monitor alert has occurred, set to 0 after handling exception */
-#define MMCR0_PMAO	(1UL << (31 - 24))
-
 /* PMC1 count enable*/
 #define MMCR0_PMC1INTCONTROL	(1UL << (31 - 16))
 
 /* PMCn count enable*/
 #define MMCR0_PMCNINTCONTROL	(1UL << (31 - 17))
 
+/* performance monitor alert has occurred, set to 0 after handling exception */
+#define MMCR0_PMAO	(1UL << (31 - 24))
+
 /* state of MSR HV when SIAR set */
 #define MMCRA_SIHV	(1UL << (63 - 35))
 
@@ -60,6 +66,9 @@ struct op_counter_config {
 
 /* System-wide configuration as set via oprofilefs.  */
 struct op_system_config {
+	unsigned long mmcr0;
+	unsigned long mmcr1;
+	unsigned long mmcra;
 	unsigned long enable_kernel;
 	unsigned long enable_user;
 };
diff -puN arch/ppc64/oprofile/op_model_power4.c~ppc64-power4-oprofile-update arch/ppc64/oprofile/op_model_power4.c
--- 25/arch/ppc64/oprofile/op_model_power4.c~ppc64-power4-oprofile-update	2004-08-16 11:54:59.575257832 -0700
+++ 25-akpm/arch/ppc64/oprofile/op_model_power4.c	2004-08-16 11:54:59.580257072 -0700
@@ -27,6 +27,11 @@ static int num_counters;
 static int oprofile_running;
 static int mmcra_has_sihv;
 
+/* mmcr values are set in power4_reg_setup, used in power4_cpu_setup */
+static u32 mmcr0_val;
+static u64 mmcr1_val;
+static u32 mmcra_val;
+
 static void power4_reg_setup(struct op_counter_config *ctr,
 			     struct op_system_config *sys,
 			     int num_ctrs)
@@ -45,18 +50,36 @@ static void power4_reg_setup(struct op_c
 	if (cur_cpu_spec->cpu_features & CPU_FTR_MMCRA_SIHV)
 		mmcra_has_sihv = 1;
 
+	/*
+	 * The performance counter event settings are given in the mmcr0,
+	 * mmcr1 and mmcra values passed from the user in the
+	 * op_system_config structure (sys variable).
+	 */
+	mmcr0_val = sys->mmcr0;
+	mmcr1_val = sys->mmcr1;
+	mmcra_val = sys->mmcra;
+
 	for (i = 0; i < num_counters; ++i)
 		reset_value[i] = 0x80000000UL - ctr[i].count;
 
-	/* XXX setup user and kernel profiling */
+	/* setup user and kernel profiling */
+	if (sys->enable_kernel)
+		mmcr0_val &= ~MMCR0_KERNEL_DISABLE;
+	else
+		mmcr0_val |= MMCR0_KERNEL_DISABLE;
+
+	if (sys->enable_user)
+		mmcr0_val &= ~MMCR0_PROBLEM_DISABLE;
+	else
+		mmcr0_val |= MMCR0_PROBLEM_DISABLE;
 }
 
 extern void ppc64_enable_pmcs(void);
 
 static void power4_cpu_setup(void *unused)
 {
-	unsigned int mmcr0 = mfspr(SPRN_MMCR0);
-	unsigned long mmcra = mfspr(SPRN_MMCRA);
+	unsigned int mmcr0 = mmcr0_val;
+	unsigned long mmcra = mmcra_val;
 
 	ppc64_enable_pmcs();
 
@@ -68,6 +91,8 @@ static void power4_cpu_setup(void *unuse
 	mmcr0 |= MMCR0_PMC1INTCONTROL|MMCR0_PMCNINTCONTROL;
 	mtspr(SPRN_MMCR0, mmcr0);
 
+	mtspr(SPRN_MMCR1, mmcr1_val);
+
 	mmcra |= MMCRA_SAMPLE_ENABLE;
 	mtspr(SPRN_MMCRA, mmcra);
 
_