From: John Villalovos <jvillalo@redhat.com> Date: Wed, 16 Sep 2009 13:54:48 -0400 Subject: [x86] oprofile: fix K8/core2 on multiple cpus Message-id: 20090916175447.GB5238@linuxjohn.usersys.redhat.com O-Subject: [RHEL 5.5 BZ523479 Patch 2/3] Support arch perfmon in oprofile Bugzilla: 523479 RH-Acked-by: Prarit Bhargava <prarit@redhat.com> RH-Acked-by: Markus Armbruster <armbru@redhat.com> [RHEL 5.5 BZ523479 Patch 2/3] Support arch perfmon in oprofile https://bugzilla.redhat.com/show_bug.cgi?id=523479 This second patch is some fixes that were needed for the performance counter reservation system, before applying the third set of patches. commit 3f85f9b0c07ea02cdaf19c46539175f360ffe97c Author: John L. Villalovos <jvillalo@redhat.com> Date: Tue Sep 15 13:35:33 2009 -0400 Backport of the following commits: Upstream commit 6c977aad03a18019015035958c65b6729cd0574c Upstream Author: Andi Kleen <ak@suse.de> Upstream Date: Mon May 21 14:31:45 2007 +0200 i386: Fix K8/core2 oprofile on multiple CPUs Only try to allocate MSRs once instead of for every CPU. This assumes the MSRs are the same on all CPUs which is currently true. P4-HT is a special case for different SMT threads, but the code always saves/restores all MSRs so it works identical. Upstream commit 0939c17c7bcf1c838bea4445b80a6966809a438f Upstream Author: Chris Wright <chrisw@sous-sol.org> Upstream Date: Fri Jun 1 00:46:39 2007 -0700 x86: fix oprofile double free Chuck reports that the recent fix from Andi to oprofile 6c977aad03a18019015035958c65b6729cd0574c introduces a double free. Each cpu's cpu_msrs is setup to point to cpu 0's, which causes free_msrs to free cpu 0's pointers for_each_possible_cpu. Rather than copy the pointers, do a deep copy instead. Upstream commit 0f8e45a288991ff24951b83fe83cf3eb011bbaed Upstream Author: Stephane Eranian <eranian@hpl.hp.com> Upstream Date: Wed Oct 17 18:04:32 2007 +0200 i386: make Oprofile call shutdown() only once per session Oprofile: call model->shutdown() only once to avoid calling release_ev*() multiple times diff --git a/arch/i386/oprofile/nmi_int.c b/arch/i386/oprofile/nmi_int.c index 6889f03..fc98c05 100644 --- a/arch/i386/oprofile/nmi_int.c +++ b/arch/i386/oprofile/nmi_int.c @@ -121,7 +121,6 @@ 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); } @@ -145,7 +144,7 @@ static int allocate_msrs(void) size_t counters_size = sizeof(struct op_msr) * model->num_counters; int i; - for_each_online_cpu(i) { + for_each_possible_cpu(i) { cpu_msrs[i].counters = kmalloc(counters_size, GFP_KERNEL); if (!cpu_msrs[i].counters) { success = 0; @@ -179,6 +178,8 @@ static void nmi_cpu_setup(void * dummy) static int nmi_setup(void) { + int cpu; + if (!allocate_msrs()) return -ENOMEM; @@ -199,6 +200,19 @@ static int nmi_setup(void) /* 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(&cpu_msrs[0]); + for_each_possible_cpu(cpu) { + if (cpu != 0) { + memcpy(cpu_msrs[cpu].counters, cpu_msrs[0].counters, + sizeof(struct op_msr) * model->num_counters); + + memcpy(cpu_msrs[cpu].controls, cpu_msrs[0].controls, + sizeof(struct op_msr) * model->num_controls); + } + + } on_each_cpu(nmi_save_registers, NULL, 0, 1); on_each_cpu(nmi_cpu_setup, NULL, 0, 1); set_nmi_callback(nmi_callback); @@ -249,7 +263,6 @@ static void nmi_cpu_shutdown(void * dummy) apic_write(APIC_LVTPC, saved_lvtpc[cpu]); apic_write(APIC_LVTERR, v); nmi_restore_registers(msrs); - model->shutdown(msrs); } @@ -258,6 +271,7 @@ static void nmi_shutdown(void) nmi_enabled = 0; on_each_cpu(nmi_cpu_shutdown, NULL, 0, 1); unset_nmi_callback(); + model->shutdown(cpu_msrs); release_lapic_nmi(); free_msrs();