diff options
Diffstat (limited to 'arch/x86/kvm')
-rw-r--r-- | arch/x86/kvm/x86.c | 62 |
1 files changed, 21 insertions, 41 deletions
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index b86d329b953a..ca3d760dd581 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c | |||
@@ -1020,9 +1020,8 @@ struct pvclock_gtod_data { | |||
1020 | u32 shift; | 1020 | u32 shift; |
1021 | } clock; | 1021 | } clock; |
1022 | 1022 | ||
1023 | /* open coded 'struct timespec' */ | 1023 | u64 boot_ns; |
1024 | u64 monotonic_time_snsec; | 1024 | u64 nsec_base; |
1025 | time_t monotonic_time_sec; | ||
1026 | }; | 1025 | }; |
1027 | 1026 | ||
1028 | static struct pvclock_gtod_data pvclock_gtod_data; | 1027 | static struct pvclock_gtod_data pvclock_gtod_data; |
@@ -1030,27 +1029,21 @@ static struct pvclock_gtod_data pvclock_gtod_data; | |||
1030 | static void update_pvclock_gtod(struct timekeeper *tk) | 1029 | static void update_pvclock_gtod(struct timekeeper *tk) |
1031 | { | 1030 | { |
1032 | struct pvclock_gtod_data *vdata = &pvclock_gtod_data; | 1031 | struct pvclock_gtod_data *vdata = &pvclock_gtod_data; |
1032 | u64 boot_ns; | ||
1033 | |||
1034 | boot_ns = ktime_to_ns(ktime_add(tk->tkr.base_mono, tk->offs_boot)); | ||
1033 | 1035 | ||
1034 | write_seqcount_begin(&vdata->seq); | 1036 | write_seqcount_begin(&vdata->seq); |
1035 | 1037 | ||
1036 | /* copy pvclock gtod data */ | 1038 | /* copy pvclock gtod data */ |
1037 | vdata->clock.vclock_mode = tk->clock->archdata.vclock_mode; | 1039 | vdata->clock.vclock_mode = tk->tkr.clock->archdata.vclock_mode; |
1038 | vdata->clock.cycle_last = tk->clock->cycle_last; | 1040 | vdata->clock.cycle_last = tk->tkr.cycle_last; |
1039 | vdata->clock.mask = tk->clock->mask; | 1041 | vdata->clock.mask = tk->tkr.mask; |
1040 | vdata->clock.mult = tk->mult; | 1042 | vdata->clock.mult = tk->tkr.mult; |
1041 | vdata->clock.shift = tk->shift; | 1043 | vdata->clock.shift = tk->tkr.shift; |
1042 | 1044 | ||
1043 | vdata->monotonic_time_sec = tk->xtime_sec | 1045 | vdata->boot_ns = boot_ns; |
1044 | + tk->wall_to_monotonic.tv_sec; | 1046 | vdata->nsec_base = tk->tkr.xtime_nsec; |
1045 | vdata->monotonic_time_snsec = tk->xtime_nsec | ||
1046 | + (tk->wall_to_monotonic.tv_nsec | ||
1047 | << tk->shift); | ||
1048 | while (vdata->monotonic_time_snsec >= | ||
1049 | (((u64)NSEC_PER_SEC) << tk->shift)) { | ||
1050 | vdata->monotonic_time_snsec -= | ||
1051 | ((u64)NSEC_PER_SEC) << tk->shift; | ||
1052 | vdata->monotonic_time_sec++; | ||
1053 | } | ||
1054 | 1047 | ||
1055 | write_seqcount_end(&vdata->seq); | 1048 | write_seqcount_end(&vdata->seq); |
1056 | } | 1049 | } |
@@ -1145,11 +1138,7 @@ static void kvm_get_time_scale(uint32_t scaled_khz, uint32_t base_khz, | |||
1145 | 1138 | ||
1146 | static inline u64 get_kernel_ns(void) | 1139 | static inline u64 get_kernel_ns(void) |
1147 | { | 1140 | { |
1148 | struct timespec ts; | 1141 | return ktime_get_boot_ns(); |
1149 | |||
1150 | ktime_get_ts(&ts); | ||
1151 | monotonic_to_bootbased(&ts); | ||
1152 | return timespec_to_ns(&ts); | ||
1153 | } | 1142 | } |
1154 | 1143 | ||
1155 | #ifdef CONFIG_X86_64 | 1144 | #ifdef CONFIG_X86_64 |
@@ -1414,23 +1403,22 @@ static inline u64 vgettsc(cycle_t *cycle_now) | |||
1414 | return v * gtod->clock.mult; | 1403 | return v * gtod->clock.mult; |
1415 | } | 1404 | } |
1416 | 1405 | ||
1417 | static int do_monotonic(struct timespec *ts, cycle_t *cycle_now) | 1406 | static int do_monotonic_boot(s64 *t, cycle_t *cycle_now) |
1418 | { | 1407 | { |
1408 | struct pvclock_gtod_data *gtod = &pvclock_gtod_data; | ||
1419 | unsigned long seq; | 1409 | unsigned long seq; |
1420 | u64 ns; | ||
1421 | int mode; | 1410 | int mode; |
1422 | struct pvclock_gtod_data *gtod = &pvclock_gtod_data; | 1411 | u64 ns; |
1423 | 1412 | ||
1424 | ts->tv_nsec = 0; | ||
1425 | do { | 1413 | do { |
1426 | seq = read_seqcount_begin(>od->seq); | 1414 | seq = read_seqcount_begin(>od->seq); |
1427 | mode = gtod->clock.vclock_mode; | 1415 | mode = gtod->clock.vclock_mode; |
1428 | ts->tv_sec = gtod->monotonic_time_sec; | 1416 | ns = gtod->nsec_base; |
1429 | ns = gtod->monotonic_time_snsec; | ||
1430 | ns += vgettsc(cycle_now); | 1417 | ns += vgettsc(cycle_now); |
1431 | ns >>= gtod->clock.shift; | 1418 | ns >>= gtod->clock.shift; |
1419 | ns += gtod->boot_ns; | ||
1432 | } while (unlikely(read_seqcount_retry(>od->seq, seq))); | 1420 | } while (unlikely(read_seqcount_retry(>od->seq, seq))); |
1433 | timespec_add_ns(ts, ns); | 1421 | *t = ns; |
1434 | 1422 | ||
1435 | return mode; | 1423 | return mode; |
1436 | } | 1424 | } |
@@ -1438,19 +1426,11 @@ static int do_monotonic(struct timespec *ts, cycle_t *cycle_now) | |||
1438 | /* returns true if host is using tsc clocksource */ | 1426 | /* returns true if host is using tsc clocksource */ |
1439 | static bool kvm_get_time_and_clockread(s64 *kernel_ns, cycle_t *cycle_now) | 1427 | static bool kvm_get_time_and_clockread(s64 *kernel_ns, cycle_t *cycle_now) |
1440 | { | 1428 | { |
1441 | struct timespec ts; | ||
1442 | |||
1443 | /* checked again under seqlock below */ | 1429 | /* checked again under seqlock below */ |
1444 | if (pvclock_gtod_data.clock.vclock_mode != VCLOCK_TSC) | 1430 | if (pvclock_gtod_data.clock.vclock_mode != VCLOCK_TSC) |
1445 | return false; | 1431 | return false; |
1446 | 1432 | ||
1447 | if (do_monotonic(&ts, cycle_now) != VCLOCK_TSC) | 1433 | return do_monotonic_boot(kernel_ns, cycle_now) == VCLOCK_TSC; |
1448 | return false; | ||
1449 | |||
1450 | monotonic_to_bootbased(&ts); | ||
1451 | *kernel_ns = timespec_to_ns(&ts); | ||
1452 | |||
1453 | return true; | ||
1454 | } | 1434 | } |
1455 | #endif | 1435 | #endif |
1456 | 1436 | ||