0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/device.h>
0009 #include <linux/kernel.h>
0010 #include <asm/pvclock.h>
0011 #include <asm/kvmclock.h>
0012 #include <linux/module.h>
0013 #include <uapi/asm/kvm_para.h>
0014 #include <uapi/linux/kvm_para.h>
0015 #include <linux/ptp_clock_kernel.h>
0016 #include <linux/ptp_kvm.h>
0017
0018 static phys_addr_t clock_pair_gpa;
0019 static struct kvm_clock_pairing clock_pair;
0020
0021 int kvm_arch_ptp_init(void)
0022 {
0023 long ret;
0024
0025 if (!kvm_para_available())
0026 return -ENODEV;
0027
0028 clock_pair_gpa = slow_virt_to_phys(&clock_pair);
0029 if (!pvclock_get_pvti_cpu0_va())
0030 return -ENODEV;
0031
0032 ret = kvm_hypercall2(KVM_HC_CLOCK_PAIRING, clock_pair_gpa,
0033 KVM_CLOCK_PAIRING_WALLCLOCK);
0034 if (ret == -KVM_ENOSYS)
0035 return -ENODEV;
0036
0037 return ret;
0038 }
0039
0040 int kvm_arch_ptp_get_clock(struct timespec64 *ts)
0041 {
0042 long ret;
0043
0044 ret = kvm_hypercall2(KVM_HC_CLOCK_PAIRING,
0045 clock_pair_gpa,
0046 KVM_CLOCK_PAIRING_WALLCLOCK);
0047 if (ret != 0) {
0048 pr_err_ratelimited("clock offset hypercall ret %lu\n", ret);
0049 return -EOPNOTSUPP;
0050 }
0051
0052 ts->tv_sec = clock_pair.sec;
0053 ts->tv_nsec = clock_pair.nsec;
0054
0055 return 0;
0056 }
0057
0058 int kvm_arch_ptp_get_crosststamp(u64 *cycle, struct timespec64 *tspec,
0059 struct clocksource **cs)
0060 {
0061 struct pvclock_vcpu_time_info *src;
0062 unsigned int version;
0063 long ret;
0064
0065 src = this_cpu_pvti();
0066
0067 do {
0068
0069
0070
0071
0072
0073
0074
0075 version = pvclock_read_begin(src);
0076
0077 ret = kvm_hypercall2(KVM_HC_CLOCK_PAIRING,
0078 clock_pair_gpa,
0079 KVM_CLOCK_PAIRING_WALLCLOCK);
0080 if (ret != 0) {
0081 pr_err_ratelimited("clock pairing hypercall ret %lu\n", ret);
0082 return -EOPNOTSUPP;
0083 }
0084 tspec->tv_sec = clock_pair.sec;
0085 tspec->tv_nsec = clock_pair.nsec;
0086 *cycle = __pvclock_read_cycles(src, clock_pair.tsc);
0087 } while (pvclock_read_retry(src, version));
0088
0089 *cs = &kvm_clock;
0090
0091 return 0;
0092 }