]> git.karo-electronics.de Git - mv-sheeva.git/blobdiff - arch/x86/oprofile/nmi_int.c
oprofile/x86: fix uninitialized counter usage during cpu hotplug
[mv-sheeva.git] / arch / x86 / oprofile / nmi_int.c
index 2c505ee7101488b7032aad6f89d15ddb134457aa..24582040b718ac274858ca65d9861a0a367ba203 100644 (file)
@@ -95,7 +95,10 @@ static void nmi_cpu_save_registers(struct op_msrs *msrs)
 static void nmi_cpu_start(void *dummy)
 {
        struct op_msrs const *msrs = &__get_cpu_var(cpu_msrs);
-       model->start(msrs);
+       if (!msrs->controls)
+               WARN_ON_ONCE(1);
+       else
+               model->start(msrs);
 }
 
 static int nmi_start(void)
@@ -107,7 +110,10 @@ static int nmi_start(void)
 static void nmi_cpu_stop(void *dummy)
 {
        struct op_msrs const *msrs = &__get_cpu_var(cpu_msrs);
-       model->stop(msrs);
+       if (!msrs->controls)
+               WARN_ON_ONCE(1);
+       else
+               model->stop(msrs);
 }
 
 static void nmi_stop(void)
@@ -295,6 +301,7 @@ static void free_msrs(void)
                kfree(per_cpu(cpu_msrs, i).controls);
                per_cpu(cpu_msrs, i).controls = NULL;
        }
+       nmi_shutdown_mux();
 }
 
 static int allocate_msrs(void)
@@ -307,14 +314,21 @@ static int allocate_msrs(void)
                per_cpu(cpu_msrs, i).counters = kzalloc(counters_size,
                                                        GFP_KERNEL);
                if (!per_cpu(cpu_msrs, i).counters)
-                       return 0;
+                       goto fail;
                per_cpu(cpu_msrs, i).controls = kzalloc(controls_size,
                                                        GFP_KERNEL);
                if (!per_cpu(cpu_msrs, i).controls)
-                       return 0;
+                       goto fail;
        }
 
+       if (!nmi_setup_mux())
+               goto fail;
+
        return 1;
+
+fail:
+       free_msrs();
+       return 0;
 }
 
 static void nmi_cpu_setup(void *dummy)
@@ -342,24 +356,17 @@ static int nmi_setup(void)
        int cpu;
 
        if (!allocate_msrs())
-               err = -ENOMEM;
-       else if (!nmi_setup_mux())
-               err = -ENOMEM;
-       else
-               err = register_die_notifier(&profile_exceptions_nb);
-
-       if (err) {
-               free_msrs();
-               nmi_shutdown_mux();
-               return err;
-       }
+               return -ENOMEM;
 
        /* We need to serialize save and setup for HT because the subset
         * of msrs are distinct for save and setup operations
         */
 
        /* Assume saved/restored counters are the same on all CPUs */
-       model->fill_in_addresses(&per_cpu(cpu_msrs, 0));
+       err = model->fill_in_addresses(&per_cpu(cpu_msrs, 0));
+       if (err)
+               goto fail;
+
        for_each_possible_cpu(cpu) {
                if (!cpu)
                        continue;
@@ -374,9 +381,17 @@ static int nmi_setup(void)
 
                mux_clone(cpu);
        }
+
+       err = register_die_notifier(&profile_exceptions_nb);
+       if (err)
+               goto fail;
+
        on_each_cpu(nmi_cpu_setup, NULL, 1);
        nmi_enabled = 1;
        return 0;
+fail:
+       free_msrs();
+       return err;
 }
 
 static void nmi_cpu_restore_registers(struct op_msrs *msrs)
@@ -421,7 +436,6 @@ static void nmi_shutdown(void)
        nmi_enabled = 0;
        on_each_cpu(nmi_cpu_shutdown, NULL, 1);
        unregister_die_notifier(&profile_exceptions_nb);
-       nmi_shutdown_mux();
        msrs = &get_cpu_var(cpu_msrs);
        model->shutdown(msrs);
        free_msrs();