bool
        default y
        select ARCH_32BIT_OFF_T
-       select ARCH_CLOCKSOURCE_DATA
        select ARCH_HAS_BINFMT_FLAT
        select ARCH_HAS_DEBUG_VIRTUAL if MMU
        select ARCH_HAS_DEVMEM_IS_ALLOWED
 
 #ifndef _ASM_CLOCKSOURCE_H
 #define _ASM_CLOCKSOURCE_H
 
-struct arch_clocksource_data {
-       bool vdso_direct;       /* Usable for direct VDSO access? */
-};
+#define VDSO_ARCH_CLOCKMODES   \
+       VDSO_CLOCKMODE_ARCHTIMER
 
 #endif
 
 #ifdef CONFIG_ARM_ARCH_TIMER
        u64 cycle_now;
 
-       if (!clock_mode)
-               return -EINVAL;
+       /*
+        * Core checks for mode already, so this raced against a concurrent
+        * update. Return something. Core will do another round and then
+        * see the mode change and fallback to the syscall.
+        */
+       if (clock_mode == VDSO_CLOCKMODE_NONE)
+               return 0;
 
        isb();
        cycle_now = read_sysreg(CNTVCT);
 
        return cycle_now;
 #else
-       return -EINVAL; /* use fallback */
+       /* Make GCC happy. This is compiled out anyway */
+       return 0;
 #endif
 }
 
 
 extern struct vdso_data *vdso_data;
 extern bool cntvct_ok;
 
-static __always_inline
-bool tk_is_cntvct(const struct timekeeper *tk)
-{
-       if (!IS_ENABLED(CONFIG_ARM_ARCH_TIMER))
-               return false;
-
-       if (!tk->tkr_mono.clock->archdata.vdso_direct)
-               return false;
-
-       return true;
-}
-
 /*
  * Update the vDSO data page to keep in sync with kernel timekeeping.
  */
 }
 #define __arch_update_vdso_data __arm_update_vdso_data
 
-static __always_inline
-int __arm_get_clock_mode(struct timekeeper *tk)
-{
-       u32 __tk_is_cntvct = tk_is_cntvct(tk);
-
-       return __tk_is_cntvct;
-}
-#define __arch_get_clock_mode __arm_get_clock_mode
-
 static __always_inline
 void __arm_sync_vdso_data(struct vdso_data *vdata)
 {
 
        select GENERIC_TIME_VSYSCALL
        select GENERIC_VDSO_32
        select GENERIC_GETTIMEOFDAY
+       select GENERIC_VDSO_CLOCK_MODE
        help
          Place in the process address space an ELF shared object
          providing fast implementations of gettimeofday and
 
        select ACPI_MCFG if (ACPI && PCI)
        select ACPI_SPCR_TABLE if ACPI
        select ACPI_PPTT if ACPI
-       select ARCH_CLOCKSOURCE_DATA
        select ARCH_HAS_DEBUG_VIRTUAL
        select ARCH_HAS_DEVMEM_IS_ALLOWED
        select ARCH_HAS_DMA_PREP_COHERENT
        select GENERIC_STRNLEN_USER
        select GENERIC_TIME_VSYSCALL
        select GENERIC_GETTIMEOFDAY
+       select GENERIC_VDSO_CLOCK_MODE
        select HANDLE_DOMAIN_IRQ
        select HARDIRQS_SW_RESEND
        select HAVE_PCI
 
 #ifndef _ASM_CLOCKSOURCE_H
 #define _ASM_CLOCKSOURCE_H
 
-struct arch_clocksource_data {
-       bool vdso_direct;       /* Usable for direct VDSO access? */
-};
+#define VDSO_ARCH_CLOCKMODES   \
+       VDSO_CLOCKMODE_ARCHTIMER
 
 #endif
 
 
 #include <asm/vdso/compat_barrier.h>
 
-#define __VDSO_USE_SYSCALL             ULLONG_MAX
-
 #define VDSO_HAS_CLOCK_GETRES          1
 
 #define BUILD_VDSO32                   1
        u64 res;
 
        /*
-        * clock_mode == 0 implies that vDSO are enabled otherwise
-        * fallback on syscall.
+        * Core checks for mode already, so this raced against a concurrent
+        * update. Return something. Core will do another round and then
+        * see the mode change and fallback to the syscall.
         */
-       if (clock_mode)
-               return __VDSO_USE_SYSCALL;
+       if (clock_mode == VDSO_CLOCKMODE_NONE)
+               return 0;
 
        /*
         * This isb() is required to prevent that the counter value
 
 #include <asm/unistd.h>
 #include <uapi/linux/time.h>
 
-#define __VDSO_USE_SYSCALL             ULLONG_MAX
-
 #define VDSO_HAS_CLOCK_GETRES          1
 
 static __always_inline
        u64 res;
 
        /*
-        * clock_mode == 0 implies that vDSO are enabled otherwise
-        * fallback on syscall.
+        * Core checks for mode already, so this raced against a concurrent
+        * update. Return something. Core will do another round and then
+        * see the mode change and fallback to the syscall.
         */
-       if (clock_mode)
-               return __VDSO_USE_SYSCALL;
+       if (clock_mode == VDSO_CLOCKMODE_NONE)
+               return 0;
 
        /*
         * This isb() is required to prevent that the counter value
 
 }
 #define __arch_get_k_vdso_data __arm64_get_k_vdso_data
 
-static __always_inline
-int __arm64_get_clock_mode(struct timekeeper *tk)
-{
-       u32 use_syscall = !tk->tkr_mono.clock->archdata.vdso_direct;
-
-       return use_syscall;
-}
-#define __arch_get_clock_mode __arm64_get_clock_mode
-
 static __always_inline
 void __arm64_update_vsyscall(struct vdso_data *vdata, struct timekeeper *tk)
 {
 
 static bool arch_timer_c3stop;
 static bool arch_timer_mem_use_virtual;
 static bool arch_counter_suspend_stop;
-static bool vdso_default = true;
+static enum vdso_clock_mode vdso_default = VDSO_CLOCKMODE_ARCHTIMER;
 
 static cpumask_t evtstrm_available = CPU_MASK_NONE;
 static bool evtstrm_enable = IS_ENABLED(CONFIG_ARM_ARCH_TIMER_EVTSTREAM);
         * change both the default value and the vdso itself.
         */
        if (wa->read_cntvct_el0) {
-               clocksource_counter.archdata.vdso_direct = false;
-               vdso_default = false;
+               clocksource_counter.vdso_clock_mode = VDSO_CLOCKMODE_NONE;
+               vdso_default = VDSO_CLOCKMODE_NONE;
        }
 }
 
                }
 
                arch_timer_read_counter = rd;
-               clocksource_counter.archdata.vdso_direct = vdso_default;
+               clocksource_counter.vdso_clock_mode = vdso_default;
        } else {
                arch_timer_read_counter = arch_counter_get_cntvct_mem;
        }