Add "enable_counters" and "disable_counters" function pointers to the
pfm_arch_pmu_info structure. Implement these routines in all of the powerpc
model-specific modules.
enable_counters is called from pfm_arch_start(), and disable_counters is
called from pfm_stop_active(). The existing code from those two routines
was moved to the power5 and ppc32 modules.
Calls to enable_counters are also added to pfm_arch_ctxswin_thread() and
to pfm_arch_intr_unfreeze_pmu().
Signed-off-by: Kevin Corry <[EMAIL PROTECTED]>
Signed-off-by: Carl Love <[EMAIL PROTECTED]>
Index: linux-2.6.21-perfmon1/arch/powerpc/perfmon/perfmon.c
===================================================================
--- linux-2.6.21-perfmon1.orig/arch/powerpc/perfmon/perfmon.c
+++ linux-2.6.21-perfmon1/arch/powerpc/perfmon/perfmon.c
@@ -64,15 +64,11 @@ static void __pfm_get_ovfl_pmds(struct p
static void pfm_stop_active(struct task_struct *task,
struct pfm_context *ctx, struct pfm_event_set *set)
{
- unsigned int i, max;
+ struct pfm_arch_pmu_info *arch_info = pfm_pmu_conf->arch_info;
- max = pfm_pmu_conf->max_pmc;
- /*
- * clear enable bits
- */
- for (i = 0; i < max; i++)
- if (test_bit(i, set->used_pmcs))
- pfm_arch_write_pmc(ctx, i,0);
+ BUG_ON(!arch_info->disable_counters);
+
+ arch_info->disable_counters(set);
if (set->npend_ovfls)
return;
@@ -105,6 +101,17 @@ int pfm_arch_ctxswout_thread(struct task
}
/*
+ * Called from pfm_ctxsw
+ */
+void pfm_arch_ctxswin_thread(struct task_struct *task,
+ struct pfm_context *ctx, struct pfm_event_set *set)
+{
+ struct pfm_arch_pmu_info *arch_info = pfm_pmu_conf->arch_info;
+ BUG_ON(!arch_info->enable_counters);
+ arch_info->enable_counters(set);
+}
+
+/*
* Called from pfm_stop() and idle notifier
*
* Interrupts are masked. Context is locked. Set is the active set.
@@ -155,16 +162,14 @@ void pfm_arch_stop(struct task_struct *t
void pfm_arch_start(struct task_struct *task,
struct pfm_context *ctx, struct pfm_event_set *set)
{
- unsigned int i, max_pmc;
+ struct pfm_arch_pmu_info *arch_info = pfm_pmu_conf->arch_info;
if (task != current)
return;
- max_pmc = pfm_pmu_conf->max_pmc;
+ BUG_ON(!arch_info->enable_counters);
- for (i = 0; i < max_pmc; i++)
- if (test_bit(i,set->used_pmcs))
- pfm_arch_write_pmc(ctx, i, set->pmcs[i]);
+ arch_info->enable_counters(set);
}
/*
@@ -267,9 +272,12 @@ void pfm_arch_intr_freeze_pmu(struct pfm
*/
void pfm_arch_intr_unfreeze_pmu(struct pfm_context *ctx)
{
- if (!ctx)
- return;
- pfm_arch_restore_pmcs(ctx, ctx->active_set);
+ struct pfm_arch_pmu_info *arch_info;
+ if (ctx) {
+ arch_info = pfm_pmu_conf->arch_info;
+ BUG_ON(!arch_info->enable_counters);
+ arch_info->enable_counters(ctx->active_set);
+ }
}
char *pfm_arch_get_pmu_module_name(void)
Index: linux-2.6.21-perfmon1/arch/powerpc/perfmon/perfmon_cell.c
===================================================================
--- linux-2.6.21-perfmon1.orig/arch/powerpc/perfmon/perfmon_cell.c
+++ linux-2.6.21-perfmon1/arch/powerpc/perfmon/perfmon_cell.c
@@ -269,11 +269,33 @@ static u64 pfm_cell_read_pmd(unsigned in
return -EINVAL;
}
+/**
+ * pfm_cell_enable_counters
+ *
+ * Just need to turn on the global disable bit in pm_control.
+ **/
+static void pfm_cell_enable_counters(struct pfm_event_set *set)
+{
+ cbe_enable_pm(smp_processor_id());
+}
+
+/**
+ * pfm_cell_disable_counters
+ *
+ * Just need to turn off the global disable bit in pm_control.
+ **/
+static void pfm_cell_disable_counters(struct pfm_event_set *set)
+{
+ cbe_disable_pm(smp_processor_id());
+}
+
static struct pfm_arch_pmu_info pfm_cell_pmu_info = {
- .pmu_style = PFM_POWERPC_PMU_CELL,
- .write_pmc = pfm_cell_write_pmc,
- .write_pmd = pfm_cell_write_pmd,
- .read_pmd = pfm_cell_read_pmd,
+ .pmu_style = PFM_POWERPC_PMU_CELL,
+ .write_pmc = pfm_cell_write_pmc,
+ .write_pmd = pfm_cell_write_pmd,
+ .read_pmd = pfm_cell_read_pmd,
+ .enable_counters = pfm_cell_enable_counters,
+ .disable_counters = pfm_cell_disable_counters,
};
static struct pfm_pmu_config pfm_cell_pmu_conf = {
Index: linux-2.6.21-perfmon1/arch/powerpc/perfmon/perfmon_power5.c
===================================================================
--- linux-2.6.21-perfmon1.orig/arch/powerpc/perfmon/perfmon_power5.c
+++ linux-2.6.21-perfmon1/arch/powerpc/perfmon/perfmon_power5.c
@@ -146,11 +146,45 @@ static u64 pfm_power5_read_pmd(unsigned
}
}
+/**
+ * pfm_power5_enable_counters
+ *
+ * Just need to load the current values into the control registers.
+ **/
+static void pfm_power5_enable_counters(struct pfm_event_set *set)
+{
+ unsigned int i, max_pmc;
+
+ max_pmc = pfm_pmu_conf->max_pmc;
+
+ for (i = 0; i < max_pmc; i++)
+ if (test_bit(i, set->used_pmcs))
+ pfm_power5_write_pmc(i, set->pmcs[i]);
+}
+
+/**
+ * pfm_power5_disable_counters
+ *
+ * Just need to zero all the control registers.
+ **/
+static void pfm_power5_disable_counters(struct pfm_event_set *set)
+{
+ unsigned int i, max;
+
+ max = pfm_pmu_conf->max_pmc;
+
+ for (i = 0; i < max; i++)
+ if (test_bit(i, set->used_pmcs))
+ pfm_power5_write_pmc(i, 0);
+}
+
struct pfm_arch_pmu_info pfm_power5_pmu_info = {
- .pmu_style = PFM_POWERPC_PMU_POWER5,
- .write_pmc = pfm_power5_write_pmc,
- .write_pmd = pfm_power5_write_pmd,
- .read_pmd = pfm_power5_read_pmd,
+ .pmu_style = PFM_POWERPC_PMU_POWER5,
+ .write_pmc = pfm_power5_write_pmc,
+ .write_pmd = pfm_power5_write_pmd,
+ .read_pmd = pfm_power5_read_pmd,
+ .enable_counters = pfm_power5_enable_counters,
+ .disable_counters = pfm_power5_disable_counters,
};
/*
Index: linux-2.6.21-perfmon1/arch/powerpc/perfmon/perfmon_ppc32.c
===================================================================
--- linux-2.6.21-perfmon1.orig/arch/powerpc/perfmon/perfmon_ppc32.c
+++ linux-2.6.21-perfmon1/arch/powerpc/perfmon/perfmon_ppc32.c
@@ -240,11 +240,45 @@ static u64 pfm_ppc32_read_pmd(unsigned i
}
}
+/**
+ * pfm_ppc32_enable_counters
+ *
+ * Just need to load the current values into the control registers.
+ **/
+static void pfm_ppc32_enable_counters(struct pfm_event_set *set)
+{
+ unsigned int i, max_pmc;
+
+ max_pmc = pfm_pmu_conf->max_pmc;
+
+ for (i = 0; i < max_pmc; i++)
+ if (test_bit(i, set->used_pmcs))
+ pfm_ppc32_write_pmc(i, set->pmcs[i]);
+}
+
+/**
+ * pfm_ppc32_disable_counters
+ *
+ * Just need to zero all the control registers.
+ **/
+static void pfm_ppc32_disable_counters(struct pfm_event_set *set)
+{
+ unsigned int i, max;
+
+ max = pfm_pmu_conf->max_pmc;
+
+ for (i = 0; i < max; i++)
+ if (test_bit(i, set->used_pmcs))
+ pfm_ppc32_write_pmc(ctx, 0);
+}
+
struct pfm_arch_pmu_info pfm_ppc32_pmu_info = {
- .pmu_style = PFM_POWERPC_PMU_NONE,
- .write_pmc = pfm_ppc32_write_pmc,
- .write_pmd = pfm_ppc32_write_pmd,
- .read_pmd = pfm_ppc32_read_pmd,
+ .pmu_style = PFM_POWERPC_PMU_NONE,
+ .write_pmc = pfm_ppc32_write_pmc,
+ .write_pmd = pfm_ppc32_write_pmd,
+ .read_pmd = pfm_ppc32_read_pmd,
+ .enable_counters = pfm_ppc32_enable_counters,
+ .disable_counters = pfm_ppc32_disable_counters,
};
static struct pfm_pmu_config pfm_ppc32_pmu_conf = {
Index: linux-2.6.21-perfmon1/include/asm-powerpc/perfmon.h
===================================================================
--- linux-2.6.21-perfmon1.orig/include/asm-powerpc/perfmon.h
+++ linux-2.6.21-perfmon1/include/asm-powerpc/perfmon.h
@@ -49,6 +49,9 @@ struct pfm_arch_pmu_info {
void (*write_pmd)(unsigned int cnum, u64 value);
u64 (*read_pmd)(unsigned int cnum);
+
+ void (*enable_counters)(struct pfm_event_set *set);
+ void (*disable_counters)(struct pfm_event_set *set);
};
#ifdef CONFIG_PPC32
@@ -142,15 +145,12 @@ static inline void pfm_arch_ctxswin_sys(
struct pfm_event_set *set)
{}
-static inline void pfm_arch_ctxswin_thread(struct task_struct *task,
- struct pfm_context *ctx,
- struct pfm_event_set *set)
-{}
-
void pfm_arch_init_percpu(void);
int pfm_arch_is_monitoring_active(struct pfm_context *ctx);
int pfm_arch_ctxswout_thread(struct task_struct *task, struct pfm_context
*ctx,
struct pfm_event_set *set);
+void pfm_arch_ctxswin_thread(struct task_struct *task, struct pfm_context *ctx,
+ struct pfm_event_set *set);
void pfm_arch_stop(struct task_struct *task, struct pfm_context *ctx,
struct pfm_event_set *set);
void pfm_arch_start(struct task_struct *task, struct pfm_context *ctx,
_______________________________________________
perfmon mailing list
[email protected]
http://www.hpl.hp.com/hosted/linux/mail-archives/perfmon/