Commit 6a59dff3 authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] oprofile: fix P4 HT msr sharing

From: Philippe Elie <phil.el@wanadoo.fr>

When I debugged P4 ht oprofile a few month ago I noticed that but though it
wasn't a problem...  The fix I propose is not completely clean.

With P4 HT we split msr in two subset, one for each logical processor.  The
msrs subset used in op_model_p4.c at save and setup point of view are
distinct (*), it means we must serialize setup and save operation else a
logical processor can save some msr value already setup by the other thread
then when oprofile shutdown we restore wrong msrs values.

Nobody noticed the problem because after restoring the msrs we call
enable_lapic_nmi_watchdog() -> setup_p4_watchdog() wich clear all the msrs
but it's a bit fragile.  If nmi watchdog is not enabled nothing bad occurs
because the LVTPC remains disabled.

(*) this is done in this way because it allows a lot of simplification in
op_model_p4.c, yes it isn't clean but it's not fixable w/o rewriting 75% of
op_model_p4.c and I think the code will be bigger and more complex.
parent b7d83b8c
...@@ -88,7 +88,7 @@ static int nmi_callback(struct pt_regs * regs, int cpu) ...@@ -88,7 +88,7 @@ static int nmi_callback(struct pt_regs * regs, int cpu)
} }
static void nmi_save_registers(struct op_msrs * msrs) static void nmi_cpu_save_registers(struct op_msrs * msrs)
{ {
unsigned int const nr_ctrs = model->num_counters; unsigned int const nr_ctrs = model->num_counters;
unsigned int const nr_ctrls = model->num_controls; unsigned int const nr_ctrls = model->num_controls;
...@@ -110,6 +110,15 @@ static void nmi_save_registers(struct op_msrs * msrs) ...@@ -110,6 +110,15 @@ static void nmi_save_registers(struct op_msrs * msrs)
} }
static void nmi_save_registers(void * dummy)
{
int cpu = smp_processor_id();
struct op_msrs * msrs = &cpu_msrs[cpu];
model->fill_in_addresses(msrs);
nmi_cpu_save_registers(msrs);
}
static void free_msrs(void) static void free_msrs(void)
{ {
int i; int i;
...@@ -156,8 +165,6 @@ static void nmi_cpu_setup(void * dummy) ...@@ -156,8 +165,6 @@ static void nmi_cpu_setup(void * dummy)
{ {
int cpu = smp_processor_id(); int cpu = smp_processor_id();
struct op_msrs * msrs = &cpu_msrs[cpu]; struct op_msrs * msrs = &cpu_msrs[cpu];
model->fill_in_addresses(msrs);
nmi_save_registers(msrs);
spin_lock(&oprofilefs_lock); spin_lock(&oprofilefs_lock);
model->setup_ctrs(msrs); model->setup_ctrs(msrs);
spin_unlock(&oprofilefs_lock); spin_unlock(&oprofilefs_lock);
...@@ -177,6 +184,10 @@ static int nmi_setup(void) ...@@ -177,6 +184,10 @@ static int nmi_setup(void)
* break the core code horrifically. * break the core code horrifically.
*/ */
disable_lapic_nmi_watchdog(); disable_lapic_nmi_watchdog();
/* We need to serialize save and setup for HT because the subset
* of msrs are distinct for save and setup operations
*/
on_each_cpu(nmi_save_registers, NULL, 0, 1);
on_each_cpu(nmi_cpu_setup, NULL, 0, 1); on_each_cpu(nmi_cpu_setup, NULL, 0, 1);
set_nmi_callback(nmi_callback); set_nmi_callback(nmi_callback);
nmi_enabled = 1; nmi_enabled = 1;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment