41f2467ce8
OBS-URL: https://build.opensuse.org/package/show/Virtualization/xen?expand=0&rev=09344c5eaa8b11326333fb14f09b2a45
68 lines
2.0 KiB
Diff
68 lines
2.0 KiB
Diff
# HG changeset patch
|
|
# User Keir Fraser <keir.fraser@citrix.com>
|
|
# Date 1273573287 -3600
|
|
# Node ID 7d4deb86b9661b8585fc2b5c41334f2b34b0922b
|
|
# Parent 2077d6ad60780bbe0631c0dee1ef2e2b8eb03867
|
|
x86: Detect and handle unexpected platform-timer counter wrap.
|
|
|
|
Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
|
|
|
|
--- a/xen/arch/x86/time.c
|
|
+++ b/xen/arch/x86/time.c
|
|
@@ -571,26 +571,48 @@ static u64 plt_stamp64; /* 64-b
|
|
static u64 plt_stamp; /* hardware-width platform counter stamp */
|
|
static struct timer plt_overflow_timer;
|
|
|
|
+static s_time_t __read_platform_stime(u64 platform_time)
|
|
+{
|
|
+ u64 diff = platform_time - platform_timer_stamp;
|
|
+ ASSERT(spin_is_locked(&platform_timer_lock));
|
|
+ return (stime_platform_stamp + scale_delta(diff, &plt_scale));
|
|
+}
|
|
+
|
|
static void plt_overflow(void *unused)
|
|
{
|
|
+ int i;
|
|
u64 count;
|
|
+ s_time_t now, plt_now, plt_wrap;
|
|
|
|
spin_lock_irq(&platform_timer_lock);
|
|
+
|
|
count = plt_src.read_counter();
|
|
plt_stamp64 += (count - plt_stamp) & plt_mask;
|
|
plt_stamp = count;
|
|
+
|
|
+ now = NOW();
|
|
+ plt_wrap = __read_platform_stime(plt_stamp64);
|
|
+ for ( i = 0; i < 10; i++ )
|
|
+ {
|
|
+ plt_now = plt_wrap;
|
|
+ plt_wrap = __read_platform_stime(plt_stamp64 + plt_mask + 1);
|
|
+ if ( __builtin_llabs(plt_wrap - now) > __builtin_llabs(plt_now - now) )
|
|
+ break;
|
|
+ plt_stamp64 += plt_mask + 1;
|
|
+ }
|
|
+ if ( i != 0 )
|
|
+ {
|
|
+ static bool_t warned_once;
|
|
+ if ( !test_and_set_bool(warned_once) )
|
|
+ printk("Platform timer appears to have unexpectedly wrapped "
|
|
+ "%u%s times.\n", i, (i == 10) ? " or more" : "");
|
|
+ }
|
|
+
|
|
spin_unlock_irq(&platform_timer_lock);
|
|
|
|
set_timer(&plt_overflow_timer, NOW() + plt_overflow_period);
|
|
}
|
|
|
|
-static s_time_t __read_platform_stime(u64 platform_time)
|
|
-{
|
|
- u64 diff = platform_time - platform_timer_stamp;
|
|
- ASSERT(spin_is_locked(&platform_timer_lock));
|
|
- return (stime_platform_stamp + scale_delta(diff, &plt_scale));
|
|
-}
|
|
-
|
|
static s_time_t read_platform_stime(void)
|
|
{
|
|
u64 count;
|