Make the RTAS call to reset the debug-bus signals any time a context is
removed from the PMU. This way other contexts don't need to worry about
what state the bus is in when they get loaded onto the PMU.
For self-monitored or system-wide contexts, reset the bus during the
unload-context call. Externally monitored contexts don't need to call the
bus-reset, since they must already have been context-switched off the CPU
(or have already exited).
For self-monitored or externally-monitored contexts, reset the bus when the
monitored thread is context-switched out. System-wide contexts are not
attached to a specific process, so they never get switched out.
Signed-off-by: Kevin Corry <[EMAIL PROTECTED]>
Signed-off-by: Carl Love <[EMAIL PROTECTED]>
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
@@ -137,9 +137,6 @@ struct cell_rtas_arg {
*
* Set up the RTAS arguments for a RESET command. The buffer will be only
* the first entry in the rtas_args[cpu].signal[] array.
- *
- * FIX: When are we going to call this routine? Before each context-switch-out?
- * After each context-switch-in?
**/
static int rtas_reset_signals(u32 cpu)
{
@@ -357,6 +354,38 @@ void pfm_cell_restore_pmcs(struct pfm_ev
}
/**
+ * pfm_cell_unload_context
+ *
+ * For system-wide contexts and self-monitored contexts, make the RTAS call
+ * to reset the debug-bus signals.
+ *
+ * For non-self-monitored contexts, the monitored thread will already have
+ * been taken off the CPU and we don't need to do anything additional.
+ **/
+static int pfm_cell_unload_context(struct pfm_context *ctx,
+ struct task_struct *task)
+{
+ if (task == current || ctx->flags.system) {
+ rtas_reset_signals(smp_processor_id());
+ }
+ return 0;
+}
+
+/**
+ * pfm_cell_ctxswout_thread
+ *
+ * When a monitored thread is switched out (self-monitored or externally
+ * monitored) we need to reset the debug-bus signals so the next context that
+ * gets switched in can start from a clean set of signals.
+ **/
+int pfm_cell_ctxswout_thread(struct task_struct *task,
+ struct pfm_context *ctx, struct pfm_event_set *set)
+{
+ rtas_reset_signals(smp_processor_id());
+ return 0;
+}
+
+/**
* pfm_cell_get_ovfl_pmds
*
* Determine which counters in this set have overflowed and fill in the
@@ -506,6 +535,7 @@ static struct pfm_arch_pmu_info pfm_cell
.irq_handler = pfm_cell_irq_handler,
.get_ovfl_pmds = pfm_cell_get_ovfl_pmds,
.restore_pmcs = pfm_cell_restore_pmcs,
+ .ctxswout_thread = pfm_cell_ctxswout_thread,
};
static struct pfm_pmu_config pfm_cell_pmu_conf = {
@@ -516,6 +546,7 @@ static struct pfm_pmu_config pfm_cell_pm
.pmc_desc = pfm_cell_pmc_desc,
.num_pmc_entries = PFM_PM_NUM_PMCS,
.num_pmd_entries = PFM_PM_NUM_PMDS,
+ .unload_context = pfm_cell_unload_context,
.probe_pmu = pfm_cell_probe_pmu,
.arch_info = &pfm_cell_pmu_info,
.flags = PFM_PMU_BUILTIN_FLAG,
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
@@ -57,9 +57,16 @@ struct pfm_arch_pmu_info {
void (*get_ovfl_pmds)(struct pfm_context *ctx,
struct pfm_event_set *set);
- /* These two are optional. */
+ /* The following routines are optional. */
void (*restore_pmcs)(struct pfm_event_set *set);
void (*restore_pmds)(struct pfm_event_set *set);
+
+ int (*ctxswout_thread)(struct task_struct *task,
+ struct pfm_context *ctx,
+ struct pfm_event_set *set);
+ void (*ctxswin_thread)(struct task_struct *task,
+ struct pfm_context *ctx,
+ struct pfm_event_set *set);
};
#ifdef CONFIG_PPC32
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
@@ -54,6 +54,8 @@ static void pfm_stop_active(struct task_
int pfm_arch_ctxswout_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;
+
/*
* disable lazy restore of PMC registers.
*/
@@ -61,6 +63,10 @@ int pfm_arch_ctxswout_thread(struct task
pfm_stop_active(task, ctx, set);
+ if (arch_info->ctxswout_thread) {
+ arch_info->ctxswout_thread(task, ctx, set);
+ }
+
return 1;
}
@@ -71,8 +77,13 @@ void pfm_arch_ctxswin_thread(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);
+
+ if (arch_info->ctxswin_thread) {
+ arch_info->ctxswin_thread(task, ctx, set);
+ }
}
/*
Index: linux-2.6.21-perfmon1/arch/x86_64/perfmon/perfmon_k8.c
===================================================================
--- linux-2.6.21-perfmon1.orig/arch/x86_64/perfmon/perfmon_k8.c
+++ linux-2.6.21-perfmon1/arch/x86_64/perfmon/perfmon_k8.c
@@ -166,7 +166,8 @@ static int pfm_k8_pmc_write_check(struct
* invoked on pfm_load_context().
* context is locked, interrupts are masked
*/
-static int pfm_k8_load_context(struct pfm_context *ctx)
+static int pfm_k8_load_context(struct pfm_context *ctx,
+ struct task_struct *task)
{
struct pfm_event_set *set;
unsigned int i, n;
@@ -192,7 +193,8 @@ found:
/*
* invoked on pfm_unload_context()
*/
-static int pfm_k8_unload_context(struct pfm_context *ctx)
+static int pfm_k8_unload_context(struct pfm_context *ctx,
+ struct task_struct *task)
{
struct pfm_context **entry, *old;
int proc_id;
Index: linux-2.6.21-perfmon1/include/linux/perfmon_pmu.h
===================================================================
--- linux-2.6.21-perfmon1.orig/include/linux/perfmon_pmu.h
+++ linux-2.6.21-perfmon1/include/linux/perfmon_pmu.h
@@ -91,7 +91,8 @@ typedef int (*pfm_pmd_check_t)(struct pf
typedef u64 (*pfm_pmd_sread_t)(struct pfm_context *ctx, unsigned int cnum);
typedef void (*pfm_pmd_swrite_t)(struct pfm_context *ctx, unsigned int cnum,
u64 val);
-typedef int (*pfm_check_session_t)(struct pfm_context *ctx);
+typedef int (*pfm_check_session_t)(struct pfm_context *ctx,
+ struct task_struct *task);
/*
* _pfm_pmu_config is for perfmon core/arch specific use only.
Index: linux-2.6.21-perfmon1/perfmon/perfmon.c
===================================================================
--- linux-2.6.21-perfmon1.orig/perfmon/perfmon.c
+++ linux-2.6.21-perfmon1/perfmon/perfmon.c
@@ -1293,7 +1293,7 @@ int __pfm_load_context(struct pfm_contex
* invoke PMU-model specific load context handler
*/
if (pfm_pmu_conf->load_context) {
- ret = pfm_pmu_conf->load_context(ctx);
+ ret = pfm_pmu_conf->load_context(ctx, ctx->task);
if (ret)
goto error_arch_loaded;
}
@@ -1379,7 +1379,7 @@ int __pfm_load_context(struct pfm_contex
error:
if (pfm_pmu_conf->unload_context)
- ret = pfm_pmu_conf->unload_context(ctx);
+ ret = pfm_pmu_conf->unload_context(ctx, ctx->task);
error_arch_loaded:
pfm_arch_unload_context(ctx, task);
error_noload:
@@ -1468,7 +1468,7 @@ int __pfm_unload_context(struct pfm_cont
*can_release = 1;
if (pfm_pmu_conf->unload_context)
- pfm_pmu_conf->unload_context(ctx);
+ pfm_pmu_conf->unload_context(ctx, task);
return 0;
}
_______________________________________________
perfmon mailing list
[email protected]
http://www.hpl.hp.com/hosted/linux/mail-archives/perfmon/