Merge tag 'for-linus' of git://git.kernel.org/pub/scm/virt/kvm/kvm
[linux-2.6-microblaze.git] / drivers / clocksource / arm_arch_timer.c
index 4fb1f4d..fe1a826 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/cpu_pm.h>
 #include <linux/clockchips.h>
 #include <linux/clocksource.h>
+#include <linux/clocksource_ids.h>
 #include <linux/interrupt.h>
 #include <linux/of_irq.h>
 #include <linux/of_address.h>
@@ -24,6 +25,8 @@
 #include <linux/sched/clock.h>
 #include <linux/sched_clock.h>
 #include <linux/acpi.h>
+#include <linux/arm-smccc.h>
+#include <linux/ptp_kvm.h>
 
 #include <asm/arch_timer.h>
 #include <asm/virt.h>
@@ -200,6 +203,7 @@ static u64 arch_counter_read_cc(const struct cyclecounter *cc)
 
 static struct clocksource clocksource_counter = {
        .name   = "arch_sys_counter",
+       .id     = CSID_ARM_ARCH_COUNTER,
        .rating = 400,
        .read   = arch_counter_read,
        .mask   = CLOCKSOURCE_MASK(56),
@@ -1676,3 +1680,35 @@ 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
+
+int kvm_arch_ptp_get_crosststamp(u64 *cycle, struct timespec64 *ts,
+                                struct clocksource **cs)
+{
+       struct arm_smccc_res hvc_res;
+       u32 ptp_counter;
+       ktime_t ktime;
+
+       if (!IS_ENABLED(CONFIG_HAVE_ARM_SMCCC_DISCOVERY))
+               return -EOPNOTSUPP;
+
+       if (arch_timer_uses_ppi == ARCH_TIMER_VIRT_PPI)
+               ptp_counter = KVM_PTP_VIRT_COUNTER;
+       else
+               ptp_counter = KVM_PTP_PHYS_COUNTER;
+
+       arm_smccc_1_1_invoke(ARM_SMCCC_VENDOR_HYP_KVM_PTP_FUNC_ID,
+                            ptp_counter, &hvc_res);
+
+       if ((int)(hvc_res.a0) < 0)
+               return -EOPNOTSUPP;
+
+       ktime = (u64)hvc_res.a0 << 32 | hvc_res.a1;
+       *ts = ktime_to_timespec64(ktime);
+       if (cycle)
+               *cycle = (u64)hvc_res.a2 << 32 | hvc_res.a3;
+       if (cs)
+               *cs = &clocksource_counter;
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(kvm_arch_ptp_get_crosststamp);