time: Add mechanism to recognize clocksource in time_get_snapshot
authorThomas Gleixner <tglx@linutronix.de>
Wed, 9 Dec 2020 06:09:27 +0000 (14:09 +0800)
committerMarc Zyngier <maz@kernel.org>
Wed, 7 Apr 2021 15:33:20 +0000 (16:33 +0100)
System time snapshots are not conveying information about the current
clocksource which was used, but callers like the PTP KVM guest
implementation have the requirement to evaluate the clocksource type to
select the appropriate mechanism.

Introduce a clocksource id field in struct clocksource which is by default
set to CSID_GENERIC (0). Clocksource implementations can set that field to
a value which allows to identify the clocksource.

Store the clocksource id of the current clocksource in the
system_time_snapshot so callers can evaluate which clocksource was used to
take the snapshot and act accordingly.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
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-5-jianyong.wu@arm.com
include/linux/clocksource.h
include/linux/clocksource_ids.h [new file with mode: 0644]
include/linux/timekeeping.h
kernel/time/clocksource.c
kernel/time/timekeeping.c

index 86d143db65231649af215c30dfc24814f0d38349..1290d0dce84084eb730d8b12ed6311e9f7081a4f 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/timer.h>
 #include <linux/init.h>
 #include <linux/of.h>
+#include <linux/clocksource_ids.h>
 #include <asm/div64.h>
 #include <asm/io.h>
 
@@ -62,6 +63,10 @@ struct module;
  *                     400-499: Perfect
  *                             The ideal clocksource. A must-use where
  *                             available.
+ * @id:                        Defaults to CSID_GENERIC. The id value is captured
+ *                     in certain snapshot functions to allow callers to
+ *                     validate the clocksource from which the snapshot was
+ *                     taken.
  * @flags:             Flags describing special properties
  * @enable:            Optional function to enable the clocksource
  * @disable:           Optional function to disable the clocksource
@@ -100,6 +105,7 @@ struct clocksource {
        const char              *name;
        struct list_head        list;
        int                     rating;
+       enum clocksource_ids    id;
        enum vdso_clock_mode    vdso_clock_mode;
        unsigned long           flags;
 
diff --git a/include/linux/clocksource_ids.h b/include/linux/clocksource_ids.h
new file mode 100644 (file)
index 0000000..4d8e19e
--- /dev/null
@@ -0,0 +1,11 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _LINUX_CLOCKSOURCE_IDS_H
+#define _LINUX_CLOCKSOURCE_IDS_H
+
+/* Enum to give clocksources a unique identifier */
+enum clocksource_ids {
+       CSID_GENERIC            = 0,
+       CSID_MAX,
+};
+
+#endif
index c6792cf01bc756715f01202b1ff7504a08bbd51b..78a98bdff76d6a7e9f3ef630e90c2a5176ace9e7 100644 (file)
@@ -3,6 +3,7 @@
 #define _LINUX_TIMEKEEPING_H
 
 #include <linux/errno.h>
+#include <linux/clocksource_ids.h>
 
 /* Included from linux/ktime.h */
 
@@ -243,11 +244,12 @@ struct ktime_timestamps {
  * @cs_was_changed_seq:        The sequence number of clocksource change events
  */
 struct system_time_snapshot {
-       u64             cycles;
-       ktime_t         real;
-       ktime_t         raw;
-       unsigned int    clock_was_set_seq;
-       u8              cs_was_changed_seq;
+       u64                     cycles;
+       ktime_t                 real;
+       ktime_t                 raw;
+       enum clocksource_ids    cs_id;
+       unsigned int            clock_was_set_seq;
+       u8                      cs_was_changed_seq;
 };
 
 /**
index cce484a2cc7ca4b710622435c5fb065d0ef2c61d..4fe1df894ee58f7ab8b7a4da0ba1df077987249e 100644 (file)
@@ -920,6 +920,8 @@ int __clocksource_register_scale(struct clocksource *cs, u32 scale, u32 freq)
 
        clocksource_arch_init(cs);
 
+       if (WARN_ON_ONCE((unsigned int)cs->id >= CSID_MAX))
+               cs->id = CSID_GENERIC;
        if (cs->vdso_clock_mode < 0 ||
            cs->vdso_clock_mode >= VDSO_CLOCKMODE_MAX) {
                pr_warn("clocksource %s registered with invalid VDSO mode %d. Disabling VDSO support.\n",
index 6aee5768c86ff7dbd4acd58cc96d4fac949f9437..06f55f9258bf3751cf2ced995b0874365e0a0188 100644 (file)
@@ -1048,6 +1048,7 @@ void ktime_get_snapshot(struct system_time_snapshot *systime_snapshot)
        do {
                seq = read_seqcount_begin(&tk_core.seq);
                now = tk_clock_read(&tk->tkr_mono);
+               systime_snapshot->cs_id = tk->tkr_mono.clock->id;
                systime_snapshot->cs_was_changed_seq = tk->cs_was_changed_seq;
                systime_snapshot->clock_was_set_seq = tk->clock_was_set_seq;
                base_real = ktime_add(tk->tkr_mono.base,