From: Anton Blanchard 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 Signed-off-by: Andrew Morton --- 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); _