Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ptp: Reorganize ptp_kvm.c to make it arch-independent

Currently, the ptp_kvm module contains a lot of x86-specific code.
Let's move this code into a new arch-specific file in the same directory,
and rename the arch-independent file to ptp_kvm_common.c.

Acked-by: Richard Cochran <richardcochran@gmail.com>
Reviewed-by: Andre Przywara <andre.przywara@arm.com>
Signed-off-by: Jianyong Wu <jianyong.wu@arm.com>
Signed-off-by: Marc Zyngier <maz@kernel.org>
Link: https://lore.kernel.org/r/20201209060932.212364-4-jianyong.wu@arm.com

authored by

Jianyong Wu and committed by
Marc Zyngier
a8cf291b 923961a7

+139 -62
+1
drivers/ptp/Makefile
··· 4 4 # 5 5 6 6 ptp-y := ptp_clock.o ptp_chardev.o ptp_sysfs.o 7 + ptp_kvm-$(CONFIG_X86) := ptp_kvm_x86.o ptp_kvm_common.o 7 8 obj-$(CONFIG_PTP_1588_CLOCK) += ptp.o 8 9 obj-$(CONFIG_PTP_1588_CLOCK_DTE) += ptp_dte.o 9 10 obj-$(CONFIG_PTP_1588_CLOCK_INES) += ptp_ines.o
+22 -62
drivers/ptp/ptp_kvm.c drivers/ptp/ptp_kvm_common.c
··· 8 8 #include <linux/err.h> 9 9 #include <linux/init.h> 10 10 #include <linux/kernel.h> 11 + #include <linux/slab.h> 11 12 #include <linux/module.h> 13 + #include <linux/ptp_kvm.h> 12 14 #include <uapi/linux/kvm_para.h> 13 15 #include <asm/kvm_para.h> 14 - #include <asm/pvclock.h> 15 - #include <asm/kvmclock.h> 16 16 #include <uapi/asm/kvm_para.h> 17 17 18 18 #include <linux/ptp_clock_kernel.h> ··· 24 24 25 25 static DEFINE_SPINLOCK(kvm_ptp_lock); 26 26 27 - static struct pvclock_vsyscall_time_info *hv_clock; 28 - 29 - static struct kvm_clock_pairing clock_pair; 30 - static phys_addr_t clock_pair_gpa; 31 - 32 27 static int ptp_kvm_get_time_fn(ktime_t *device_time, 33 28 struct system_counterval_t *system_counter, 34 29 void *ctx) 35 30 { 36 - unsigned long ret; 31 + long ret; 32 + u64 cycle; 37 33 struct timespec64 tspec; 38 - unsigned version; 39 - int cpu; 40 - struct pvclock_vcpu_time_info *src; 34 + struct clocksource *cs; 41 35 42 36 spin_lock(&kvm_ptp_lock); 43 37 44 38 preempt_disable_notrace(); 45 - cpu = smp_processor_id(); 46 - src = &hv_clock[cpu].pvti; 47 - 48 - do { 49 - /* 50 - * We are using a TSC value read in the hosts 51 - * kvm_hc_clock_pairing handling. 52 - * So any changes to tsc_to_system_mul 53 - * and tsc_shift or any other pvclock 54 - * data invalidate that measurement. 55 - */ 56 - version = pvclock_read_begin(src); 57 - 58 - ret = kvm_hypercall2(KVM_HC_CLOCK_PAIRING, 59 - clock_pair_gpa, 60 - KVM_CLOCK_PAIRING_WALLCLOCK); 61 - if (ret != 0) { 62 - pr_err_ratelimited("clock pairing hypercall ret %lu\n", ret); 63 - spin_unlock(&kvm_ptp_lock); 64 - preempt_enable_notrace(); 65 - return -EOPNOTSUPP; 66 - } 67 - 68 - tspec.tv_sec = clock_pair.sec; 69 - tspec.tv_nsec = clock_pair.nsec; 70 - ret = __pvclock_read_cycles(src, clock_pair.tsc); 71 - } while (pvclock_read_retry(src, version)); 39 + ret = kvm_arch_ptp_get_crosststamp(&cycle, &tspec, &cs); 40 + if (ret) { 41 + spin_unlock(&kvm_ptp_lock); 42 + preempt_enable_notrace(); 43 + return ret; 44 + } 72 45 73 46 preempt_enable_notrace(); 74 47 75 - system_counter->cycles = ret; 76 - system_counter->cs = &kvm_clock; 48 + system_counter->cycles = cycle; 49 + system_counter->cs = cs; 77 50 78 51 *device_time = timespec64_to_ktime(tspec); 79 52 ··· 84 111 85 112 static int ptp_kvm_gettime(struct ptp_clock_info *ptp, struct timespec64 *ts) 86 113 { 87 - unsigned long ret; 114 + long ret; 88 115 struct timespec64 tspec; 89 116 90 117 spin_lock(&kvm_ptp_lock); 91 118 92 - ret = kvm_hypercall2(KVM_HC_CLOCK_PAIRING, 93 - clock_pair_gpa, 94 - KVM_CLOCK_PAIRING_WALLCLOCK); 95 - if (ret != 0) { 96 - pr_err_ratelimited("clock offset hypercall ret %lu\n", ret); 119 + ret = kvm_arch_ptp_get_clock(&tspec); 120 + if (ret) { 97 121 spin_unlock(&kvm_ptp_lock); 98 - return -EOPNOTSUPP; 122 + return ret; 99 123 } 100 124 101 - tspec.tv_sec = clock_pair.sec; 102 - tspec.tv_nsec = clock_pair.nsec; 103 125 spin_unlock(&kvm_ptp_lock); 104 126 105 127 memcpy(ts, &tspec, sizeof(struct timespec64)); ··· 136 168 { 137 169 long ret; 138 170 139 - if (!kvm_para_available()) 140 - return -ENODEV; 141 - 142 - clock_pair_gpa = slow_virt_to_phys(&clock_pair); 143 - hv_clock = pvclock_get_pvti_cpu0_va(); 144 - 145 - if (!hv_clock) 146 - return -ENODEV; 147 - 148 - ret = kvm_hypercall2(KVM_HC_CLOCK_PAIRING, clock_pair_gpa, 149 - KVM_CLOCK_PAIRING_WALLCLOCK); 150 - if (ret == -KVM_ENOSYS || ret == -KVM_EOPNOTSUPP) 151 - return -ENODEV; 171 + ret = kvm_arch_ptp_init(); 172 + if (ret) { 173 + pr_err("fail to initialize ptp_kvm"); 174 + return ret; 175 + } 152 176 153 177 kvm_ptp_clock.caps = ptp_kvm_caps; 154 178
+97
drivers/ptp/ptp_kvm_x86.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-or-later 2 + /* 3 + * Virtual PTP 1588 clock for use with KVM guests 4 + * 5 + * Copyright (C) 2017 Red Hat Inc. 6 + */ 7 + 8 + #include <linux/device.h> 9 + #include <linux/kernel.h> 10 + #include <asm/pvclock.h> 11 + #include <asm/kvmclock.h> 12 + #include <linux/module.h> 13 + #include <uapi/asm/kvm_para.h> 14 + #include <uapi/linux/kvm_para.h> 15 + #include <linux/ptp_clock_kernel.h> 16 + #include <linux/ptp_kvm.h> 17 + 18 + struct pvclock_vsyscall_time_info *hv_clock; 19 + 20 + static phys_addr_t clock_pair_gpa; 21 + static struct kvm_clock_pairing clock_pair; 22 + 23 + int kvm_arch_ptp_init(void) 24 + { 25 + long ret; 26 + 27 + if (!kvm_para_available()) 28 + return -ENODEV; 29 + 30 + clock_pair_gpa = slow_virt_to_phys(&clock_pair); 31 + hv_clock = pvclock_get_pvti_cpu0_va(); 32 + if (!hv_clock) 33 + return -ENODEV; 34 + 35 + ret = kvm_hypercall2(KVM_HC_CLOCK_PAIRING, clock_pair_gpa, 36 + KVM_CLOCK_PAIRING_WALLCLOCK); 37 + if (ret == -KVM_ENOSYS || ret == -KVM_EOPNOTSUPP) 38 + return -ENODEV; 39 + 40 + return 0; 41 + } 42 + 43 + int kvm_arch_ptp_get_clock(struct timespec64 *ts) 44 + { 45 + long ret; 46 + 47 + ret = kvm_hypercall2(KVM_HC_CLOCK_PAIRING, 48 + clock_pair_gpa, 49 + KVM_CLOCK_PAIRING_WALLCLOCK); 50 + if (ret != 0) { 51 + pr_err_ratelimited("clock offset hypercall ret %lu\n", ret); 52 + return -EOPNOTSUPP; 53 + } 54 + 55 + ts->tv_sec = clock_pair.sec; 56 + ts->tv_nsec = clock_pair.nsec; 57 + 58 + return 0; 59 + } 60 + 61 + int kvm_arch_ptp_get_crosststamp(u64 *cycle, struct timespec64 *tspec, 62 + struct clocksource **cs) 63 + { 64 + struct pvclock_vcpu_time_info *src; 65 + unsigned int version; 66 + long ret; 67 + int cpu; 68 + 69 + cpu = smp_processor_id(); 70 + src = &hv_clock[cpu].pvti; 71 + 72 + do { 73 + /* 74 + * We are using a TSC value read in the hosts 75 + * kvm_hc_clock_pairing handling. 76 + * So any changes to tsc_to_system_mul 77 + * and tsc_shift or any other pvclock 78 + * data invalidate that measurement. 79 + */ 80 + version = pvclock_read_begin(src); 81 + 82 + ret = kvm_hypercall2(KVM_HC_CLOCK_PAIRING, 83 + clock_pair_gpa, 84 + KVM_CLOCK_PAIRING_WALLCLOCK); 85 + if (ret != 0) { 86 + pr_err_ratelimited("clock pairing hypercall ret %lu\n", ret); 87 + return -EOPNOTSUPP; 88 + } 89 + tspec->tv_sec = clock_pair.sec; 90 + tspec->tv_nsec = clock_pair.nsec; 91 + *cycle = __pvclock_read_cycles(src, clock_pair.tsc); 92 + } while (pvclock_read_retry(src, version)); 93 + 94 + *cs = &kvm_clock; 95 + 96 + return 0; 97 + }
+19
include/linux/ptp_kvm.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0-or-later */ 2 + /* 3 + * Virtual PTP 1588 clock for use with KVM guests 4 + * 5 + * Copyright (C) 2017 Red Hat Inc. 6 + */ 7 + 8 + #ifndef _PTP_KVM_H_ 9 + #define _PTP_KVM_H_ 10 + 11 + struct timespec64; 12 + struct clocksource; 13 + 14 + int kvm_arch_ptp_init(void); 15 + int kvm_arch_ptp_get_clock(struct timespec64 *ts); 16 + int kvm_arch_ptp_get_crosststamp(u64 *cycle, 17 + struct timespec64 *tspec, struct clocksource **cs); 18 + 19 + #endif /* _PTP_KVM_H_ */