From fb84bd51fb5e4e7dc601d4702979243c817a3208 Mon Sep 17 00:00:00 2001 From: Chuck Ebbert Date: Sun, 5 Sep 2010 06:07:58 -0400 Subject: [PATCH] x86-tsc-sched-recompute-cyc2ns_offset-s-during-resume-from-sleep-states.patch Fix load balancing after suspend/resume cycle (taken from 2.6.32 stable queue) --- kernel.spec | 5 + ...et-s-during-resume-from-sleep-states.patch | 115 ++++++++++++++++++ 2 files changed, 120 insertions(+) create mode 100644 x86-tsc-sched-recompute-cyc2ns_offset-s-during-resume-from-sleep-states.patch diff --git a/kernel.spec b/kernel.spec index b6bf610ad..e39d4fa79 100644 --- a/kernel.spec +++ b/kernel.spec @@ -787,6 +787,7 @@ Patch12523: keys-fix-rcu-no-lock-warning-in-keyctl-session-to-parent.patch Patch12530: pci-msi-remove-unsafe-and-unnecessary-hardware-access.patch Patch12531: pci-msi-restore-read_msi_msg_desc-add-get_cached_msi_msg_desc.patch +Patch12532: x86-tsc-sched-recompute-cyc2ns_offset-s-during-resume-from-sleep-states.patch %endif @@ -1487,6 +1488,8 @@ ApplyPatch keys-fix-rcu-no-lock-warning-in-keyctl-session-to-parent.patch # Fix unsafe access to MSI registers during suspend ApplyPatch pci-msi-remove-unsafe-and-unnecessary-hardware-access.patch ApplyPatch pci-msi-restore-read_msi_msg_desc-add-get_cached_msi_msg_desc.patch +# Fix scheduler load balancing after suspend/resume cycle +ApplyPatch x86-tsc-sched-recompute-cyc2ns_offset-s-during-resume-from-sleep-states.patch # END OF PATCH APPLICATIONS @@ -2114,6 +2117,8 @@ fi - Fix unsafe access to MSI registers during suspend (pci-msi-remove-unsafe-and-unnecessary-hardware-access.patch, pci-msi-restore-read_msi_msg_desc-add-get_cached_msi_msg_desc.patch) +- x86-tsc-sched-recompute-cyc2ns_offset-s-during-resume-from-sleep-states.patch + Fix load balancing after suspend/resume cycle (taken from 2.6.32 stable queue) * Fri Sep 03 2010 Chuck Ebbert 2.6.34.6-52 - acpi-ec-pm-fix-race-between-ec-transactions-and-system-suspend.patch: diff --git a/x86-tsc-sched-recompute-cyc2ns_offset-s-during-resume-from-sleep-states.patch b/x86-tsc-sched-recompute-cyc2ns_offset-s-during-resume-from-sleep-states.patch new file mode 100644 index 000000000..c0d1e8604 --- /dev/null +++ b/x86-tsc-sched-recompute-cyc2ns_offset-s-during-resume-from-sleep-states.patch @@ -0,0 +1,115 @@ +From cd7240c0b900eb6d690ccee088a6c9b46dae815a Mon Sep 17 00:00:00 2001 +From: Suresh Siddha +Date: Thu, 19 Aug 2010 17:03:38 -0700 +Subject: x86, tsc, sched: Recompute cyc2ns_offset's during resume from sleep states + +From: Suresh Siddha + +commit cd7240c0b900eb6d690ccee088a6c9b46dae815a upstream. + +TSC's get reset after suspend/resume (even on cpu's with invariant TSC +which runs at a constant rate across ACPI P-, C- and T-states). And in +some systems BIOS seem to reinit TSC to arbitrary large value (still +sync'd across cpu's) during resume. + +This leads to a scenario of scheduler rq->clock (sched_clock_cpu()) less +than rq->age_stamp (introduced in 2.6.32). This leads to a big value +returned by scale_rt_power() and the resulting big group power set by the +update_group_power() is causing improper load balancing between busy and +idle cpu's after suspend/resume. + +This resulted in multi-threaded workloads (like kernel-compilation) go +slower after suspend/resume cycle on core i5 laptops. + +Fix this by recomputing cyc2ns_offset's during resume, so that +sched_clock() continues from the point where it was left off during +suspend. + +Reported-by: Florian Pritz +Signed-off-by: Suresh Siddha +Signed-off-by: Peter Zijlstra +LKML-Reference: <1282262618.2675.24.camel@sbsiddha-MOBL3.sc.intel.com> +Signed-off-by: Ingo Molnar +Signed-off-by: Greg Kroah-Hartman + +--- + arch/x86/include/asm/tsc.h | 2 ++ + arch/x86/kernel/tsc.c | 38 ++++++++++++++++++++++++++++++++++++++ + arch/x86/power/cpu.c | 2 ++ + 3 files changed, 42 insertions(+) + +--- a/arch/x86/include/asm/tsc.h ++++ b/arch/x86/include/asm/tsc.h +@@ -59,5 +59,7 @@ extern void check_tsc_sync_source(int cp + extern void check_tsc_sync_target(void); + + extern int notsc_setup(char *); ++extern void save_sched_clock_state(void); ++extern void restore_sched_clock_state(void); + + #endif /* _ASM_X86_TSC_H */ +--- a/arch/x86/kernel/tsc.c ++++ b/arch/x86/kernel/tsc.c +@@ -626,6 +626,44 @@ static void set_cyc2ns_scale(unsigned lo + local_irq_restore(flags); + } + ++static unsigned long long cyc2ns_suspend; ++ ++void save_sched_clock_state(void) ++{ ++ if (!sched_clock_stable) ++ return; ++ ++ cyc2ns_suspend = sched_clock(); ++} ++ ++/* ++ * Even on processors with invariant TSC, TSC gets reset in some the ++ * ACPI system sleep states. And in some systems BIOS seem to reinit TSC to ++ * arbitrary value (still sync'd across cpu's) during resume from such sleep ++ * states. To cope up with this, recompute the cyc2ns_offset for each cpu so ++ * that sched_clock() continues from the point where it was left off during ++ * suspend. ++ */ ++void restore_sched_clock_state(void) ++{ ++ unsigned long long offset; ++ unsigned long flags; ++ int cpu; ++ ++ if (!sched_clock_stable) ++ return; ++ ++ local_irq_save(flags); ++ ++ get_cpu_var(cyc2ns_offset) = 0; ++ offset = cyc2ns_suspend - sched_clock(); ++ ++ for_each_possible_cpu(cpu) ++ per_cpu(cyc2ns_offset, cpu) = offset; ++ ++ local_irq_restore(flags); ++} ++ + #ifdef CONFIG_CPU_FREQ + + /* Frequency scaling support. Adjust the TSC based timer when the cpu frequency +--- a/arch/x86/power/cpu.c ++++ b/arch/x86/power/cpu.c +@@ -112,6 +112,7 @@ static void __save_processor_state(struc + void save_processor_state(void) + { + __save_processor_state(&saved_context); ++ save_sched_clock_state(); + } + #ifdef CONFIG_X86_32 + EXPORT_SYMBOL(save_processor_state); +@@ -253,6 +254,7 @@ static void __restore_processor_state(st + void restore_processor_state(void) + { + __restore_processor_state(&saved_context); ++ restore_sched_clock_state(); + } + #ifdef CONFIG_X86_32 + EXPORT_SYMBOL(restore_processor_state);