diff --git a/kernel/configs/arm64_kata_kvm_4.19.x b/kernel/configs/arm64_kata_kvm_4.19.x index e8d23cc932..95a0c83ea8 100644 --- a/kernel/configs/arm64_kata_kvm_4.19.x +++ b/kernel/configs/arm64_kata_kvm_4.19.x @@ -1572,13 +1572,24 @@ CONFIG_HW_RANDOM_VIRTIO=y # CONFIG_SPI is not set # CONFIG_SPMI is not set # CONFIG_HSI is not set -# CONFIG_PPS is not set +CONFIG_PPS=y +# CONFIG_PPS_DEBUG is not set + +# +# PPS clients support +# +# CONFIG_PPS_CLIENT_KTIMER is not set +# CONFIG_PPS_CLIENT_LDISC is not set +# CONFIG_PPS_CLIENT_GPIO is not set +# +# PPS generators support +# # # PTP clock support # -# CONFIG_PTP_1588_CLOCK is not set - +CONFIG_PTP_1588_CLOCK=y +CONFIG_PTP_1588_CLOCK_KVM=y # # Enable PHYLIB and NETWORK_PHY_TIMESTAMPING to see the additional clocks. # diff --git a/kernel/kata_config_version b/kernel/kata_config_version index 59343b09ec..fb1e7bc869 100644 --- a/kernel/kata_config_version +++ b/kernel/kata_config_version @@ -1 +1 @@ -53 +54 diff --git a/kernel/patches/4.19.x/0001-4.19-enable-ptp_kvm-for-arm64-in-kata.patch b/kernel/patches/4.19.x/0001-4.19-enable-ptp_kvm-for-arm64-in-kata.patch new file mode 100644 index 0000000000..6aca37969c --- /dev/null +++ b/kernel/patches/4.19.x/0001-4.19-enable-ptp_kvm-for-arm64-in-kata.patch @@ -0,0 +1,457 @@ +From bee1ae5587a7427dbb9e9e313f6d0a43a9e0ec2e Mon Sep 17 00:00:00 2001 +From: Jianyong Wu +Date: Mon, 30 Sep 2019 09:26:22 +0800 +Subject: [PATCH] 4.19: enable ptp_kvm for arm64 in kata + +--- + drivers/clocksource/arm_arch_timer.c | 25 ++++++ + drivers/ptp/Kconfig | 2 +- + drivers/ptp/Makefile | 1 + + drivers/ptp/ptp_kvm_arm64.c | 59 ++++++++++++++ + drivers/ptp/{ptp_kvm.c => ptp_kvm_common.c} | 89 +++++---------------- + drivers/ptp/ptp_kvm_x86.c | 87 ++++++++++++++++++++ + include/asm-generic/ptp_kvm.h | 12 +++ + include/linux/arm-smccc.h | 5 ++ + virt/kvm/arm/psci.c | 12 +++ + 9 files changed, 221 insertions(+), 71 deletions(-) + create mode 100644 drivers/ptp/ptp_kvm_arm64.c + rename drivers/ptp/{ptp_kvm.c => ptp_kvm_common.c} (56%) + create mode 100644 drivers/ptp/ptp_kvm_x86.c + create mode 100644 include/asm-generic/ptp_kvm.h + +diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c +index d8c7f5750cdb..84ba8f9e57be 100644 +--- a/drivers/clocksource/arm_arch_timer.c ++++ b/drivers/clocksource/arm_arch_timer.c +@@ -1571,3 +1571,28 @@ static int __init arch_timer_acpi_init(struct acpi_table_header *table) + } + TIMER_ACPI_DECLARE(arch_timer, ACPI_SIG_GTDT, arch_timer_acpi_init); + #endif ++ ++#if IS_ENABLED(CONFIG_PTP_1588_CLOCK_KVM) ++#include ++int kvm_arch_ptp_get_clock_fn(long *cycle, struct timespec64 *ts, ++ struct clocksource **cs) ++{ ++ struct arm_smccc_res hvc_res; ++ ktime_t ktime_overall; ++ struct arm_smccc_quirk hvc_quirk; ++ ++ __arm_smccc_hvc(ARM_SMCCC_VENDOR_HYP_KVM_PTP_FUNC_ID, 0, 0, 0, 0, 0, 0, 0, &hvc_res, &hvc_quirk); ++ ++ if ((long)(hvc_res.a0) < 0) ++ return -EOPNOTSUPP; ++ ++ ts->tv_sec = hvc_res.a0; ++ ts->tv_nsec = hvc_res.a1; ++ *cycle = hvc_res.a2 << 32 | hvc_res.a3; ++ *cs = &clocksource_counter; ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(kvm_arch_ptp_get_clock_fn); ++#endif ++ +diff --git a/drivers/ptp/Kconfig b/drivers/ptp/Kconfig +index d137c480db46..318b3f5df1ea 100644 +--- a/drivers/ptp/Kconfig ++++ b/drivers/ptp/Kconfig +@@ -109,7 +109,7 @@ config PTP_1588_CLOCK_PCH + config PTP_1588_CLOCK_KVM + tristate "KVM virtual PTP clock" + depends on PTP_1588_CLOCK +- depends on KVM_GUEST && X86 ++ depends on KVM_GUEST && X86 || ARM64 + default y + help + This driver adds support for using kvm infrastructure as a PTP +diff --git a/drivers/ptp/Makefile b/drivers/ptp/Makefile +index 19efa9cfa950..1bf4940a88a6 100644 +--- a/drivers/ptp/Makefile ++++ b/drivers/ptp/Makefile +@@ -4,6 +4,7 @@ + # + + ptp-y := ptp_clock.o ptp_chardev.o ptp_sysfs.o ++ptp_kvm-y := ptp_kvm_common.o ptp_kvm_$(ARCH).o + obj-$(CONFIG_PTP_1588_CLOCK) += ptp.o + obj-$(CONFIG_PTP_1588_CLOCK_DTE) += ptp_dte.o + obj-$(CONFIG_PTP_1588_CLOCK_IXP46X) += ptp_ixp46x.o +diff --git a/drivers/ptp/ptp_kvm_arm64.c b/drivers/ptp/ptp_kvm_arm64.c +new file mode 100644 +index 000000000000..fcd83324c7e1 +--- /dev/null ++++ b/drivers/ptp/ptp_kvm_arm64.c +@@ -0,0 +1,59 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * Virtual PTP 1588 clock for use with KVM guests ++ * Copyright (C) 2019 ARM Ltd. ++ * All Rights Reserved ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++ ++void arm_smccc_1_1_invoke(u32 id, struct arm_smccc_res *res) ++{ ++ struct arm_smccc_quirk hvc_quirk; ++ ++ __arm_smccc_hvc(id, 0, 0, 0, 0, 0, 0, 0, res, &hvc_quirk); ++} ++ ++int kvm_arch_ptp_init(void) ++{ ++ struct arm_smccc_res hvc_res; ++ ++ arm_smccc_1_1_invoke(ARM_SMCCC_VENDOR_HYP_KVM_PTP_FUNC_ID, ++ &hvc_res); ++ if ((long)(hvc_res.a0) < 0) ++ return -EOPNOTSUPP; ++ ++ return 0; ++} ++ ++int kvm_arch_ptp_get_clock_generic(struct timespec64 *ts, ++ struct arm_smccc_res *hvc_res) ++{ ++ arm_smccc_1_1_invoke(ARM_SMCCC_VENDOR_HYP_KVM_PTP_FUNC_ID, ++ hvc_res); ++ if ((long)(hvc_res->a0) < 0) ++ return -EOPNOTSUPP; ++ ++ ts->tv_sec = hvc_res->a0; ++ ts->tv_nsec = hvc_res->a1; ++ ++ return 0; ++} ++ ++int kvm_arch_ptp_get_clock(struct timespec64 *ts) ++{ ++ struct arm_smccc_res hvc_res; ++ ++ kvm_arch_ptp_get_clock_generic(ts, &hvc_res); ++ ++ return 0; ++} +diff --git a/drivers/ptp/ptp_kvm.c b/drivers/ptp/ptp_kvm_common.c +similarity index 56% +rename from drivers/ptp/ptp_kvm.c +rename to drivers/ptp/ptp_kvm_common.c +index c67dd11e08b1..c0b445fa6144 100644 +--- a/drivers/ptp/ptp_kvm.c ++++ b/drivers/ptp/ptp_kvm_common.c +@@ -1,29 +1,19 @@ ++// SPDX-License-Identifier: GPL-2.0-or-later + /* + * Virtual PTP 1588 clock for use with KVM guests + * + * Copyright (C) 2017 Red Hat Inc. +- * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License as published by +- * the Free Software Foundation; either version 2 of the License, or +- * (at your option) any later version. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * + */ + #include + #include + #include + #include ++#include + #include + #include + #include +-#include +-#include + #include ++#include + + #include + +@@ -34,56 +24,29 @@ struct kvm_ptp_clock { + + DEFINE_SPINLOCK(kvm_ptp_lock); + +-static struct pvclock_vsyscall_time_info *hv_clock; +- +-static struct kvm_clock_pairing clock_pair; +-static phys_addr_t clock_pair_gpa; +- + static int ptp_kvm_get_time_fn(ktime_t *device_time, + struct system_counterval_t *system_counter, + void *ctx) + { +- unsigned long ret; ++ unsigned long ret, cycle; + struct timespec64 tspec; +- unsigned version; +- int cpu; +- struct pvclock_vcpu_time_info *src; ++ struct clocksource *cs; + + spin_lock(&kvm_ptp_lock); + + preempt_disable_notrace(); +- cpu = smp_processor_id(); +- src = &hv_clock[cpu].pvti; +- +- do { +- /* +- * We are using a TSC value read in the hosts +- * kvm_hc_clock_pairing handling. +- * So any changes to tsc_to_system_mul +- * and tsc_shift or any other pvclock +- * data invalidate that measurement. +- */ +- version = pvclock_read_begin(src); +- +- ret = kvm_hypercall2(KVM_HC_CLOCK_PAIRING, +- clock_pair_gpa, +- KVM_CLOCK_PAIRING_WALLCLOCK); +- if (ret != 0) { +- pr_err_ratelimited("clock pairing hypercall ret %lu\n", ret); +- spin_unlock(&kvm_ptp_lock); +- preempt_enable_notrace(); +- return -EOPNOTSUPP; +- } +- +- tspec.tv_sec = clock_pair.sec; +- tspec.tv_nsec = clock_pair.nsec; +- ret = __pvclock_read_cycles(src, clock_pair.tsc); +- } while (pvclock_read_retry(src, version)); ++ ret = kvm_arch_ptp_get_clock_fn(&cycle, &tspec, &cs); ++ if (ret != 0) { ++ pr_err_ratelimited("clock pairing hypercall ret %lu\n", ret); ++ spin_unlock(&kvm_ptp_lock); ++ preempt_enable_notrace(); ++ return -EOPNOTSUPP; ++ } + + preempt_enable_notrace(); + +- system_counter->cycles = ret; +- system_counter->cs = &kvm_clock; ++ system_counter->cycles = cycle; ++ system_counter->cs = cs; + + *device_time = timespec64_to_ktime(tspec); + +@@ -126,17 +89,13 @@ static int ptp_kvm_gettime(struct ptp_clock_info *ptp, struct timespec64 *ts) + + spin_lock(&kvm_ptp_lock); + +- ret = kvm_hypercall2(KVM_HC_CLOCK_PAIRING, +- clock_pair_gpa, +- KVM_CLOCK_PAIRING_WALLCLOCK); ++ ret = kvm_arch_ptp_get_clock(&tspec); + if (ret != 0) { + pr_err_ratelimited("clock offset hypercall ret %lu\n", ret); + spin_unlock(&kvm_ptp_lock); + return -EOPNOTSUPP; + } + +- tspec.tv_sec = clock_pair.sec; +- tspec.tv_nsec = clock_pair.nsec; + spin_unlock(&kvm_ptp_lock); + + memcpy(ts, &tspec, sizeof(struct timespec64)); +@@ -176,21 +135,11 @@ static void __exit ptp_kvm_exit(void) + + static int __init ptp_kvm_init(void) + { +- long ret; +- +- if (!kvm_para_available()) +- return -ENODEV; ++ int ret; + +- clock_pair_gpa = slow_virt_to_phys(&clock_pair); +- hv_clock = pvclock_get_pvti_cpu0_va(); +- +- if (!hv_clock) +- return -ENODEV; +- +- ret = kvm_hypercall2(KVM_HC_CLOCK_PAIRING, clock_pair_gpa, +- KVM_CLOCK_PAIRING_WALLCLOCK); +- if (ret == -KVM_ENOSYS || ret == -KVM_EOPNOTSUPP) +- return -ENODEV; ++ ret = kvm_arch_ptp_init(); ++ if (ret) ++ return -EOPNOTSUPP; + + kvm_ptp_clock.caps = ptp_kvm_caps; + +diff --git a/drivers/ptp/ptp_kvm_x86.c b/drivers/ptp/ptp_kvm_x86.c +new file mode 100644 +index 000000000000..a52cf1c2990c +--- /dev/null ++++ b/drivers/ptp/ptp_kvm_x86.c +@@ -0,0 +1,87 @@ ++// SPDX-License-Identifier: GPL-2.0-or-later ++/* ++ * Virtual PTP 1588 clock for use with KVM guests ++ * ++ * Copyright (C) 2017 Red Hat Inc. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++phys_addr_t clock_pair_gpa; ++struct kvm_clock_pairing clock_pair; ++struct pvclock_vsyscall_time_info *hv_clock; ++ ++int kvm_arch_ptp_init(void) ++{ ++ int ret; ++ ++ if (!kvm_para_available()) ++ return -ENODEV; ++ ++ clock_pair_gpa = slow_virt_to_phys(&clock_pair); ++ hv_clock = pvclock_get_pvti_cpu0_va(); ++ if (!hv_clock) ++ return -ENODEV; ++ ++ ret = kvm_hypercall2(KVM_HC_CLOCK_PAIRING, clock_pair_gpa, ++ KVM_CLOCK_PAIRING_WALLCLOCK); ++ if (ret == -KVM_ENOSYS || ret == -KVM_EOPNOTSUPP) ++ return -ENODEV; ++ ++ return 0; ++} ++ ++int kvm_arch_ptp_get_clock(struct timespec64 *ts) ++{ ++ long ret; ++ ++ ret = kvm_hypercall2(KVM_HC_CLOCK_PAIRING, ++ clock_pair_gpa, ++ KVM_CLOCK_PAIRING_WALLCLOCK); ++ if (ret != 0) ++ return -EOPNOTSUPP; ++ ++ ts->tv_sec = clock_pair.sec; ++ ts->tv_nsec = clock_pair.nsec; ++ ++ return 0; ++} ++ ++int kvm_arch_ptp_get_clock_fn(unsigned long *cycle, struct timespec64 *tspec, ++ struct clocksource **cs) ++{ ++ unsigned long ret; ++ unsigned int version; ++ int cpu; ++ struct pvclock_vcpu_time_info *src; ++ ++ cpu = smp_processor_id(); ++ src = &hv_clock[cpu].pvti; ++ ++ do { ++ /* ++ * We are using a TSC value read in the hosts ++ * kvm_hc_clock_pairing handling. ++ * So any changes to tsc_to_system_mul ++ * and tsc_shift or any other pvclock ++ * data invalidate that measurement. ++ */ ++ version = pvclock_read_begin(src); ++ ++ ret = kvm_hypercall2(KVM_HC_CLOCK_PAIRING, ++ clock_pair_gpa, ++ KVM_CLOCK_PAIRING_WALLCLOCK); ++ tspec->tv_sec = clock_pair.sec; ++ tspec->tv_nsec = clock_pair.nsec; ++ *cycle = __pvclock_read_cycles(src, clock_pair.tsc); ++ } while (pvclock_read_retry(src, version)); ++ ++ *cs = &kvm_clock; ++ ++ return 0; ++} +diff --git a/include/asm-generic/ptp_kvm.h b/include/asm-generic/ptp_kvm.h +new file mode 100644 +index 000000000000..883eea494a80 +--- /dev/null ++++ b/include/asm-generic/ptp_kvm.h +@@ -0,0 +1,12 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * linux/drivers/clocksource/arm_arch_timer.c ++ * ++ * Copyright (C) 2019 ARM Ltd. ++ * All Rights Reserved ++ */ ++ ++int kvm_arch_ptp_init(void); ++int kvm_arch_ptp_get_clock(struct timespec64 *ts); ++int kvm_arch_ptp_get_clock_fn(unsigned long *cycle, ++ struct timespec64 *tspec, void *cs); +diff --git a/include/linux/arm-smccc.h b/include/linux/arm-smccc.h +index 18863d56273c..10e99c82d098 100644 +--- a/include/linux/arm-smccc.h ++++ b/include/linux/arm-smccc.h +@@ -75,6 +75,11 @@ + ARM_SMCCC_SMC_32, \ + 0, 1) + ++#define ARM_SMCCC_VENDOR_HYP_KVM_PTP_FUNC_ID \ ++ ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \ ++ ARM_SMCCC_SMC_32, \ ++ 0, 2) ++ + #define ARM_SMCCC_ARCH_WORKAROUND_1 \ + ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \ + ARM_SMCCC_SMC_32, \ +diff --git a/virt/kvm/arm/psci.c b/virt/kvm/arm/psci.c +index 9b73d3ad918a..9b9999bdeab7 100644 +--- a/virt/kvm/arm/psci.c ++++ b/virt/kvm/arm/psci.c +@@ -407,6 +407,9 @@ int kvm_hvc_call_handler(struct kvm_vcpu *vcpu) + u32 func_id = smccc_get_function(vcpu); + u32 val = SMCCC_RET_NOT_SUPPORTED; + u32 feature; ++ struct timespec64 ts; ++ u64 cycles, cycle_high, cycle_low; ++ struct system_time_snapshot systime_snapshot; + + switch (func_id) { + case ARM_SMCCC_VERSION_FUNC_ID: +@@ -435,6 +438,15 @@ int kvm_hvc_call_handler(struct kvm_vcpu *vcpu) + break; + } + break; ++ case ARM_SMCCC_VENDOR_HYP_KVM_PTP_FUNC_ID: ++ ktime_get_real_ts64(&ts); ++ ktime_get_snapshot(&systime_snapshot); ++ cycles = systime_snapshot.cycles - vcpu_vtimer(vcpu)->cntvoff; ++ cycle_high = cycles >> 32; ++ cycle_low = cycles << 32 >> 32; ++ ++ smccc_set_retval(vcpu, ts.tv_sec, ts.tv_nsec, cycle_high, cycle_low); ++ return 1; + default: + return kvm_psci_call(vcpu); + } +-- +2.17.1 +