| @@ -1142,6 +1142,7 @@ struct pvclock_gtod_data { · 1141 unmodified lines |
| 1142 | 1142 | |
| 1143 | 1143 | u64 boot_ns; |
| 1144 | 1144 | u64 nsec_base; |
| 1145 | + u64 wall_time_sec; |
| 1145 | 1146 | }; |
| 1146 | 1147 | |
| 1147 | 1148 | static struct pvclock_gtod_data pvclock_gtod_data; |
| @@ -1165,6 +1166,8 @@ static void update_pvclock_gtod(struct timekeeper *tk) · 17 unmodified lines |
| 1165 | 1166 | vdata->boot_ns = boot_ns; |
| 1166 | 1167 | vdata->nsec_base = tk->tkr_mono.xtime_nsec; |
| 1167 | 1168 | |
| 1169 | + vdata->wall_time_sec = tk->xtime_sec; |
| 1170 | + |
| 1168 | 1171 | write_seqcount_end(&vdata->seq); |
| 1169 | 1172 | } |
| 1170 | 1173 | #endif |
| @@ -1626,6 +1629,28 @@ static int do_monotonic_boot(s64 *t, u64 *cycle_now) · 455 unmodified lines |
| 1626 | 1629 | return mode; |
| 1627 | 1630 | } |
| 1628 | 1631 | |
| 1632 | +static int do_realtime(struct timespec *ts, u64 *cycle_now) |
| 1633 | +{ |
| 1634 | + struct pvclock_gtod_data *gtod = &pvclock_gtod_data; |
| 1635 | + unsigned long seq; |
| 1636 | + int mode; |
| 1637 | + u64 ns; |
| 1638 | + |
| 1639 | + do { |
| 1640 | + seq = read_seqcount_begin(>od->seq); |
| 1641 | + mode = gtod->clock.vclock_mode; |
| 1642 | + ts->tv_sec = gtod->wall_time_sec; |
| 1643 | + ns = gtod->nsec_base; |
| 1644 | + ns += vgettsc(cycle_now); |
| 1645 | + ns >>= gtod->clock.shift; |
| 1646 | + } while (unlikely(read_seqcount_retry(>od->seq, seq))); |
| 1647 | + |
| 1648 | + ts->tv_sec += __iter_div_u64_rem(ns, NSEC_PER_SEC, &ns); |
| 1649 | + ts->tv_nsec = ns; |
| 1650 | + |
| 1651 | + return mode; |
| 1652 | +} |
| 1653 | + |
| 1629 | 1654 | /* returns true if host is using tsc clocksource */ |
| 1630 | 1655 | static bool kvm_get_time_and_clockread(s64 *kernel_ns, u64 *cycle_now) |
| 1631 | 1656 | { |
| @@ -1635,6 +1660,17 @@ static bool kvm_get_time_and_clockread(s64 *kernel_ns, u64 *cycle_now) · 3 unmodified lines |
| 1635 | 1660 | |
| 1636 | 1661 | return do_monotonic_boot(kernel_ns, cycle_now) == VCLOCK_TSC; |
| 1637 | 1662 | } |
| 1663 | + |
| 1664 | +/* returns true if host is using tsc clocksource */ |
| 1665 | +static bool kvm_get_walltime_and_clockread(struct timespec *ts, |
| 1666 | + u64 *cycle_now) |
| 1667 | +{ |
| 1668 | + /* checked again under seqlock below */ |
| 1669 | + if (pvclock_gtod_data.clock.vclock_mode != VCLOCK_TSC) |
| 1670 | + return false; |
| 1671 | + |
| 1672 | + return do_realtime(ts, cycle_now) == VCLOCK_TSC; |
| 1673 | +} |
| 1638 | 1674 | #endif |
| 1639 | 1675 | |
| 1640 | 1676 | /* |
| @@ -6112,6 +6148,33 @@ int kvm_emulate_halt(struct kvm_vcpu *vcpu) · 4471 unmodified lines |
| 6112 | 6148 | } |
| 6113 | 6149 | EXPORT_SYMBOL_GPL(kvm_emulate_halt); |
| 6114 | 6150 | |
| 6151 | +static int kvm_pv_clock_pairing(struct kvm_vcpu *vcpu, gpa_t paddr, |
| 6152 | + unsigned long clock_type) |
| 6153 | +{ |
| 6154 | + struct kvm_clock_pairing clock_pairing; |
| 6155 | + struct timespec ts; |
| 6156 | + cycle_t cycle; |
| 6157 | + int ret; |
| 6158 | + |
| 6159 | + if (clock_type != KVM_CLOCK_PAIRING_WALLCLOCK) |
| 6160 | + return -KVM_EOPNOTSUPP; |
| 6161 | + |
| 6162 | + if (kvm_get_walltime_and_clockread(&ts, &cycle) == false) |
| 6163 | + return -KVM_EOPNOTSUPP; |
| 6164 | + |
| 6165 | + clock_pairing.sec = ts.tv_sec; |
| 6166 | + clock_pairing.nsec = ts.tv_nsec; |
| 6167 | + clock_pairing.tsc = kvm_read_l1_tsc(vcpu, cycle); |
| 6168 | + clock_pairing.flags = 0; |
| 6169 | + |
| 6170 | + ret = 0; |
| 6171 | + if (kvm_write_guest(vcpu->kvm, paddr, &clock_pairing, |
| 6172 | + sizeof(struct kvm_clock_pairing))) |
| 6173 | + ret = -KVM_EFAULT; |
| 6174 | + |
| 6175 | + return ret; |
| 6176 | +} |
| 6177 | + |
| 6115 | 6178 | /* |
| 6116 | 6179 | * kvm_pv_kick_cpu_op: Kick a vcpu. |
| 6117 | 6180 | * |
| @@ -6176,6 +6239,9 @@ int kvm_emulate_hypercall(struct kvm_vcpu *vcpu) · 58 unmodified lines |
| 6176 | 6239 | kvm_pv_kick_cpu_op(vcpu->kvm, a0, a1); |
| 6177 | 6240 | ret = 0; |
| 6178 | 6241 | break; |
| 6242 | + case KVM_HC_CLOCK_PAIRING: |
| 6243 | + ret = kvm_pv_clock_pairing(vcpu, a0, a1); |
| 6244 | + break; |
| 6179 | 6245 | default: |
| 6180 | 6246 | ret = -KVM_ENOSYS; |
| 6181 | 6247 | break; |