diff --git a/pkgs/os-specific/linux/kernel/patches.nix b/pkgs/os-specific/linux/kernel/patches.nix index cdc67b9a3d5..19c7f06b8f7 100644 --- a/pkgs/os-specific/linux/kernel/patches.nix +++ b/pkgs/os-specific/linux/kernel/patches.nix @@ -214,9 +214,10 @@ in patch = ./guruplug-mach-type.patch; }; - revert_pvclock_sync = - { name = "revert-pvclock-sync"; - patch = ./revert-pvclock-sync.patch; + xen_pvclock_resume = + { # Fix the clock after a DomU restore following a Dom0 reboot or migration. + name = "xen-pvclock-resume"; + patch = ./xen-pvclock-resume.patch; }; } diff --git a/pkgs/os-specific/linux/kernel/revert-pvclock-sync.patch b/pkgs/os-specific/linux/kernel/revert-pvclock-sync.patch deleted file mode 100644 index df29cfbf182..00000000000 --- a/pkgs/os-specific/linux/kernel/revert-pvclock-sync.patch +++ /dev/null @@ -1,46 +0,0 @@ -diff -ru -x '*~' linux-2.6.32.24-orig/arch/x86/kernel/pvclock.c linux-2.6.32.24/arch/x86/kernel/pvclock.c ---- linux-2.6.32.24-orig/arch/x86/kernel/pvclock.c 2010-10-01 22:51:56.000000000 +0200 -+++ linux-2.6.32.24/arch/x86/kernel/pvclock.c 2010-10-25 14:02:14.000000000 +0200 -@@ -109,14 +109,11 @@ - return pv_tsc_khz; - } - --static atomic64_t last_value = ATOMIC64_INIT(0); -- - cycle_t pvclock_clocksource_read(struct pvclock_vcpu_time_info *src) - { - struct pvclock_shadow_time shadow; - unsigned version; - cycle_t ret, offset; -- u64 last; - - do { - version = pvclock_get_time_values(&shadow, src); -@@ -126,27 +123,6 @@ - barrier(); - } while (version != src->version); - -- /* -- * Assumption here is that last_value, a global accumulator, always goes -- * forward. If we are less than that, we should not be much smaller. -- * We assume there is an error marging we're inside, and then the correction -- * does not sacrifice accuracy. -- * -- * For reads: global may have changed between test and return, -- * but this means someone else updated poked the clock at a later time. -- * We just need to make sure we are not seeing a backwards event. -- * -- * For updates: last_value = ret is not enough, since two vcpus could be -- * updating at the same time, and one of them could be slightly behind, -- * making the assumption that last_value always go forward fail to hold. -- */ -- last = atomic64_read(&last_value); -- do { -- if (ret < last) -- return last; -- last = atomic64_cmpxchg(&last_value, last, ret); -- } while (unlikely(last != ret)); -- - return ret; - } - diff --git a/pkgs/os-specific/linux/kernel/xen-pvclock-resume.patch b/pkgs/os-specific/linux/kernel/xen-pvclock-resume.patch new file mode 100644 index 00000000000..b92bb74d30b --- /dev/null +++ b/pkgs/os-specific/linux/kernel/xen-pvclock-resume.patch @@ -0,0 +1,51 @@ +From: Jeremy Fitzhardinge +Date: Mon, 25 Oct 2010 16:53:46 -0700 +Subject: [PATCH] x86/pvclock: zero last_value on resume + +If the guest domain has been suspend/resumed or migrated, then the +system clock backing the pvclock clocksource may revert to a smaller +value (ie, can be non-monotonic across the migration/save-restore). +Make sure we zero last_value in that case so that the domain +continues to see clock updates. + +Signed-off-by: Jeremy Fitzhardinge + +diff --git a/arch/x86/include/asm/pvclock.h b/arch/x86/include/asm/pvclock.h +index cd02f32..6226870 100644 +--- a/arch/x86/include/asm/pvclock.h ++++ b/arch/x86/include/asm/pvclock.h +@@ -11,5 +11,6 @@ unsigned long pvclock_tsc_khz(struct pvclock_vcpu_time_info *src); + void pvclock_read_wallclock(struct pvclock_wall_clock *wall, + struct pvclock_vcpu_time_info *vcpu, + struct timespec *ts); ++void pvclock_resume(void); + + #endif /* _ASM_X86_PVCLOCK_H */ +diff --git a/arch/x86/kernel/pvclock.c b/arch/x86/kernel/pvclock.c +index 239427c..a4f07c1 100644 +--- a/arch/x86/kernel/pvclock.c ++++ b/arch/x86/kernel/pvclock.c +@@ -120,6 +120,11 @@ unsigned long pvclock_tsc_khz(struct pvclock_vcpu_time_info *src) + + static atomic64_t last_value = ATOMIC64_INIT(0); + ++void pvclock_resume(void) ++{ ++ atomic64_set(&last_value, 0); ++} ++ + cycle_t pvclock_clocksource_read(struct pvclock_vcpu_time_info *src) + { + struct pvclock_shadow_time shadow; +diff --git a/arch/x86/xen/time.c b/arch/x86/xen/time.c +index b2bb5aa..5da5e53 100644 +--- a/arch/x86/xen/time.c ++++ b/arch/x86/xen/time.c +@@ -426,6 +426,8 @@ void xen_timer_resume(void) + { + int cpu; + ++ pvclock_resume(); ++ + if (xen_clockevent != &xen_vcpuop_clockevent) + return; diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix index 2cbd7e174e7..2e1dace998d 100644 --- a/pkgs/top-level/all-packages.nix +++ b/pkgs/top-level/all-packages.nix @@ -4582,7 +4582,7 @@ let kernelPatches.cifs_timeout kernelPatches.no_xsave kernelPatches.dell_rfkill - kernelPatches.revert_pvclock_sync + kernelPatches.xen_pvclock_resume ]; };