From 5fe48c913d05538bf7c5920b93b36443ca7da495 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 12 Feb 2014 10:21:12 -0500 Subject: [PATCH] Fix backtrace in amd_e400_idle (rhbz 1031296) --- kernel.spec | 9 ++ ...ending-bit-when-switching-to-oneshot.patch | 88 +++++++++++++++++++ 2 files changed, 97 insertions(+) create mode 100644 tick-Clear-broadcast-pending-bit-when-switching-to-oneshot.patch diff --git a/kernel.spec b/kernel.spec index cd09f8e65..4b98a9e8c 100644 --- a/kernel.spec +++ b/kernel.spec @@ -626,6 +626,9 @@ Patch25189: ath9k-fix-bad-udelay.patch Patch25192: imx-hdmi-fix.patch Patch25193: fix-exynos-hdmi-build.patch +#rhbz 1031296 +Patch25194: tick-Clear-broadcast-pending-bit-when-switching-to-oneshot.patch + # END OF PATCH DEFINITIONS %endif @@ -1274,6 +1277,9 @@ ApplyPatch ath9k-fix-bad-udelay.patch ApplyPatch imx-hdmi-fix.patch ApplyPatch fix-exynos-hdmi-build.patch +#rhbz 1031296 +ApplyPatch tick-Clear-broadcast-pending-bit-when-switching-to-oneshot.patch + # END OF PATCH APPLICATIONS %endif @@ -2053,6 +2059,9 @@ fi # ||----w | # || || %changelog +* Wed Feb 12 2014 Josh Boyer +- Fix backtrace in amd_e400_idle (rhbz 1031296) + * Tue Feb 11 2014 Josh Boyer - 3.14.0-0.rc2.git1.1 - Linux v3.14-rc2-26-g6792dfe - Reenable debugging options. diff --git a/tick-Clear-broadcast-pending-bit-when-switching-to-oneshot.patch b/tick-Clear-broadcast-pending-bit-when-switching-to-oneshot.patch new file mode 100644 index 000000000..a0d58cf4d --- /dev/null +++ b/tick-Clear-broadcast-pending-bit-when-switching-to-oneshot.patch @@ -0,0 +1,88 @@ +On Mon, 10 Feb 2014, Thomas Gleixner wrote: +> On Mon, 10 Feb 2014, poma wrote: +> +> > [ 83.558551] [] amd_e400_idle+0x87/0x130 +> +> So this seems to happen only on AMD machines which use that e400 idle +> mode. I have no idea at the moment whats wrong there. I'll find one of +> those machines and try to reproduce. + +Found it. Patch below. + +Thanks, + + tglx +---- +Subject: tick: Clear broadcast pending bit when switching to oneshot +From: Thomas Gleixner +Date: Tue, 11 Feb 2014 14:35:40 +0100 + +AMD systems which use the C1E workaround in the amd_e400_idle routine +trigger the WARN_ON_ONCE in the broadcast code when onlining a CPU. + +The reason is that the idle routine of those AMD systems switches the +cpu into forced broadcast mode early on before the newly brought up +CPU can switch over to high resolution / NOHZ mode. The timer related +CPU1 bringup looks like this: + + clockevent_register_device(local_apic); + tick_setup(local_apic); + ... + idle() + tick_broadcast_on_off(FORCE); + tick_broadcast_oneshot_control(ENTER) + cpumask_set(cpu, broadcast_oneshot_mask); + halt(); + +Now the broadcast interrupt on CPU0 sets CPU1 in the +broadcast_pending_mask and wakes CPU1. So CPU1 continues: + + local_apic_timer_interrupt() + tick_handle_periodic(); + softirq() + tick_init_highres(); + cpumask_clr(cpu, broadcast_oneshot_mask); + + tick_broadcast_oneshot_control(ENTER) + WARN_ON(cpumask_test(cpu, broadcast_pending_mask); + +So while we remove CPU1 from the broadcast_oneshot_mask when we switch +over to highres mode, we do not clear the pending bit, which then +triggers the warning when we go back to idle. + +The reason why this is only visible on C1E affected AMD systems is +that the other machines enter the deep sleep states via +acpi_idle/intel_idle and exit the broadcast mode before executing the +remote triggered local_apic_timer_interrupt. So the pending bit is +already cleared when the switch over to highres mode is clearing the +oneshot mask. + +The solution is simple: Clear the pending bit together with the mask +bit when we switch over to highres mode. + +Reported-by: poma +Cc: stable@vger.kernel.org # 3.10+ +Signed-off-by: Thomas Gleixner +--- + kernel/time/tick-broadcast.c | 1 + + 1 file changed, 1 insertion(+) + +Index: linux-2.6/kernel/time/tick-broadcast.c +=================================================================== +--- linux-2.6.orig/kernel/time/tick-broadcast.c ++++ linux-2.6/kernel/time/tick-broadcast.c +@@ -756,6 +756,7 @@ out: + static void tick_broadcast_clear_oneshot(int cpu) + { + cpumask_clear_cpu(cpu, tick_broadcast_oneshot_mask); ++ cpumask_clear_cpu(cpu, tick_broadcast_pending_mask); + } + + static void tick_broadcast_init_next_event(struct cpumask *mask, + + +-- +To unsubscribe from this list: send the line "unsubscribe linux-kernel" in +the body of a message to majordomo@vger.kernel.org +More majordomo info at http://vger.kernel.org/majordomo-info.html +Please read the FAQ at http://www.tux.org/lkml/ \ No newline at end of file