--- /dev/null
+From c1fbec4ac0d701f350a581941d35643d5a9cd184 Mon Sep 17 00:00:00 2001
+From: Marc Zyngier <maz@kernel.org>
+Date: Mon, 6 Jul 2020 17:38:00 +0100
+Subject: arm64: arch_timer: Allow an workaround descriptor to disable compat vdso
+
+From: Marc Zyngier <maz@kernel.org>
+
+commit c1fbec4ac0d701f350a581941d35643d5a9cd184 upstream.
+
+As we are about to disable the vdso for compat tasks in some circumstances,
+let's allow a workaround descriptor to express exactly that.
+
+Signed-off-by: Marc Zyngier <maz@kernel.org>
+Acked-by: Mark Rutland <mark.rutland@arm.com>
+Cc: stable@vger.kernel.org
+Link: https://lore.kernel.org/r/20200706163802.1836732-3-maz@kernel.org
+Signed-off-by: Will Deacon <will@kernel.org>
+Signed-off-by: Marc Zyngier <maz@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/arm64/include/asm/arch_timer.h | 1 +
+ drivers/clocksource/arm_arch_timer.c | 3 +++
+ 2 files changed, 4 insertions(+)
+
+--- a/arch/arm64/include/asm/arch_timer.h
++++ b/arch/arm64/include/asm/arch_timer.h
+@@ -58,6 +58,7 @@ struct arch_timer_erratum_workaround {
+ u64 (*read_cntvct_el0)(void);
+ int (*set_next_event_phys)(unsigned long, struct clock_event_device *);
+ int (*set_next_event_virt)(unsigned long, struct clock_event_device *);
++ bool disable_compat_vdso;
+ };
+
+ DECLARE_PER_CPU(const struct arch_timer_erratum_workaround *,
+--- a/drivers/clocksource/arm_arch_timer.c
++++ b/drivers/clocksource/arm_arch_timer.c
+@@ -562,6 +562,9 @@ void arch_timer_enable_workaround(const
+ if (wa->read_cntvct_el0) {
+ clocksource_counter.archdata.clock_mode = VDSO_CLOCKMODE_NONE;
+ vdso_default = VDSO_CLOCKMODE_NONE;
++ } else if (wa->disable_compat_vdso && vdso_default != VDSO_CLOCKMODE_NONE) {
++ vdso_default = VDSO_CLOCKMODE_ARCHTIMER_NOCOMPAT;
++ clocksource_counter.vdso_clock_mode = vdso_default;
+ }
+ }
+
--- /dev/null
+From 4b661d6133c5d3a7c9aca0b4ee5a78c7766eff3f Mon Sep 17 00:00:00 2001
+From: Marc Zyngier <maz@kernel.org>
+Date: Mon, 6 Jul 2020 17:38:01 +0100
+Subject: arm64: arch_timer: Disable the compat vdso for cores affected by ARM64_WORKAROUND_1418040
+
+From: Marc Zyngier <maz@kernel.org>
+
+commit 4b661d6133c5d3a7c9aca0b4ee5a78c7766eff3f upstream.
+
+ARM64_WORKAROUND_1418040 requires that AArch32 EL0 accesses to
+the virtual counter register are trapped and emulated by the kernel.
+This makes the vdso pretty pointless, and in some cases livelock
+prone.
+
+Provide a workaround entry that limits the vdso to 64bit tasks.
+
+Signed-off-by: Marc Zyngier <maz@kernel.org>
+Acked-by: Mark Rutland <mark.rutland@arm.com>
+Cc: stable@vger.kernel.org
+Link: https://lore.kernel.org/r/20200706163802.1836732-4-maz@kernel.org
+Signed-off-by: Will Deacon <will@kernel.org>
+Signed-off-by: Marc Zyngier <maz@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/clocksource/arm_arch_timer.c | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+--- a/drivers/clocksource/arm_arch_timer.c
++++ b/drivers/clocksource/arm_arch_timer.c
+@@ -476,6 +476,14 @@ static const struct arch_timer_erratum_w
+ .set_next_event_virt = erratum_set_next_event_tval_virt,
+ },
+ #endif
++#ifdef CONFIG_ARM64_ERRATUM_1418040
++ {
++ .match_type = ate_match_local_cap_id,
++ .id = (void *)ARM64_WORKAROUND_1418040,
++ .desc = "ARM erratum 1418040",
++ .disable_compat_vdso = true,
++ },
++#endif
+ };
+
+ typedef bool (*ate_match_fn_t)(const struct arch_timer_erratum_workaround *,
--- /dev/null
+From 97884ca8c2925d14c32188e865069f21378b4b4f Mon Sep 17 00:00:00 2001
+From: Marc Zyngier <maz@kernel.org>
+Date: Mon, 6 Jul 2020 17:37:59 +0100
+Subject: arm64: Introduce a way to disable the 32bit vdso
+
+From: Marc Zyngier <maz@kernel.org>
+
+commit 97884ca8c2925d14c32188e865069f21378b4b4f upstream.
+
+[this is a redesign rather than a backport]
+
+We have a class of errata (grouped under the ARM64_WORKAROUND_1418040
+banner) that force the trapping of counter access from 32bit EL0.
+
+We would normally disable the whole vdso for such defect, except that
+it would disable it for 64bit userspace as well, which is a shame.
+
+Instead, add a new vdso_clock_mode, which signals that the vdso
+isn't usable for compat tasks. This gets checked in the new
+vdso_clocksource_ok() helper, now provided for the 32bit vdso.
+
+Signed-off-by: Marc Zyngier <maz@kernel.org>
+Acked-by: Mark Rutland <mark.rutland@arm.com>
+Cc: stable@vger.kernel.org
+Link: https://lore.kernel.org/r/20200706163802.1836732-2-maz@kernel.org
+Signed-off-by: Will Deacon <will@kernel.org>
+Signed-off-by: Marc Zyngier <maz@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/arm/include/asm/clocksource.h | 11 ++++++++++-
+ arch/arm/kernel/vdso.c | 2 +-
+ arch/arm64/include/asm/clocksource.h | 5 ++++-
+ arch/arm64/include/asm/vdso/clocksource.h | 14 ++++++++++++++
+ arch/arm64/include/asm/vdso/compat_gettimeofday.h | 5 +++--
+ arch/arm64/include/asm/vdso/gettimeofday.h | 6 ++++--
+ arch/arm64/include/asm/vdso/vsyscall.h | 4 +---
+ drivers/clocksource/arm_arch_timer.c | 8 ++++----
+ 8 files changed, 41 insertions(+), 14 deletions(-)
+
+--- a/arch/arm/include/asm/clocksource.h
++++ b/arch/arm/include/asm/clocksource.h
+@@ -1,8 +1,17 @@
+ #ifndef _ASM_CLOCKSOURCE_H
+ #define _ASM_CLOCKSOURCE_H
+
++enum vdso_arch_clockmode {
++ /* vdso clocksource not usable */
++ VDSO_CLOCKMODE_NONE,
++ /* vdso clocksource usable */
++ VDSO_CLOCKMODE_ARCHTIMER,
++ VDSO_CLOCKMODE_ARCHTIMER_NOCOMPAT = VDSO_CLOCKMODE_ARCHTIMER,
++};
++
+ struct arch_clocksource_data {
+- bool vdso_direct; /* Usable for direct VDSO access? */
++ /* Usable for direct VDSO access? */
++ enum vdso_arch_clockmode clock_mode;
+ };
+
+ #endif
+--- a/arch/arm/kernel/vdso.c
++++ b/arch/arm/kernel/vdso.c
+@@ -281,7 +281,7 @@ static bool tk_is_cntvct(const struct ti
+ if (!IS_ENABLED(CONFIG_ARM_ARCH_TIMER))
+ return false;
+
+- if (!tk->tkr_mono.clock->archdata.vdso_direct)
++ if (tk->tkr_mono.clock->archdata.clock_mode != VDSO_CLOCKMODE_ARCHTIMER)
+ return false;
+
+ return true;
+--- a/arch/arm64/include/asm/clocksource.h
++++ b/arch/arm64/include/asm/clocksource.h
+@@ -2,8 +2,11 @@
+ #ifndef _ASM_CLOCKSOURCE_H
+ #define _ASM_CLOCKSOURCE_H
+
++#include <asm/vdso/clocksource.h>
++
+ struct arch_clocksource_data {
+- bool vdso_direct; /* Usable for direct VDSO access? */
++ /* Usable for direct VDSO access? */
++ enum vdso_arch_clockmode clock_mode;
+ };
+
+ #endif
+--- /dev/null
++++ b/arch/arm64/include/asm/vdso/clocksource.h
+@@ -0,0 +1,14 @@
++/* SPDX-License-Identifier: GPL-2.0 */
++#ifndef __ASM_VDSOCLOCKSOURCE_H
++#define __ASM_VDSOCLOCKSOURCE_H
++
++enum vdso_arch_clockmode {
++ /* vdso clocksource not usable */
++ VDSO_CLOCKMODE_NONE,
++ /* vdso clocksource for both 32 and 64bit tasks */
++ VDSO_CLOCKMODE_ARCHTIMER,
++ /* vdso clocksource for 64bit tasks only */
++ VDSO_CLOCKMODE_ARCHTIMER_NOCOMPAT,
++};
++
++#endif
+--- a/arch/arm64/include/asm/vdso/compat_gettimeofday.h
++++ b/arch/arm64/include/asm/vdso/compat_gettimeofday.h
+@@ -10,6 +10,7 @@
+ #include <asm/unistd.h>
+ #include <uapi/linux/time.h>
+
++#include <asm/vdso/clocksource.h>
+ #include <asm/vdso/compat_barrier.h>
+
+ #define __VDSO_USE_SYSCALL ULLONG_MAX
+@@ -117,10 +118,10 @@ static __always_inline u64 __arch_get_hw
+ u64 res;
+
+ /*
+- * clock_mode == 0 implies that vDSO are enabled otherwise
++ * clock_mode == ARCHTIMER implies that vDSO are enabled otherwise
+ * fallback on syscall.
+ */
+- if (clock_mode)
++ if (clock_mode != VDSO_CLOCKMODE_ARCHTIMER)
+ return __VDSO_USE_SYSCALL;
+
+ /*
+--- a/arch/arm64/include/asm/vdso/gettimeofday.h
++++ b/arch/arm64/include/asm/vdso/gettimeofday.h
+@@ -10,6 +10,8 @@
+ #include <asm/unistd.h>
+ #include <uapi/linux/time.h>
+
++#include <asm/vdso/clocksource.h>
++
+ #define __VDSO_USE_SYSCALL ULLONG_MAX
+
+ #define VDSO_HAS_CLOCK_GETRES 1
+@@ -71,10 +73,10 @@ static __always_inline u64 __arch_get_hw
+ u64 res;
+
+ /*
+- * clock_mode == 0 implies that vDSO are enabled otherwise
++ * clock_mode != NONE implies that vDSO are enabled otherwise
+ * fallback on syscall.
+ */
+- if (clock_mode)
++ if (clock_mode == VDSO_CLOCKMODE_NONE)
+ return __VDSO_USE_SYSCALL;
+
+ /*
+--- a/arch/arm64/include/asm/vdso/vsyscall.h
++++ b/arch/arm64/include/asm/vdso/vsyscall.h
+@@ -24,9 +24,7 @@ struct vdso_data *__arm64_get_k_vdso_dat
+ static __always_inline
+ int __arm64_get_clock_mode(struct timekeeper *tk)
+ {
+- u32 use_syscall = !tk->tkr_mono.clock->archdata.vdso_direct;
+-
+- return use_syscall;
++ return tk->tkr_mono.clock->archdata.clock_mode;
+ }
+ #define __arch_get_clock_mode __arm64_get_clock_mode
+
+--- a/drivers/clocksource/arm_arch_timer.c
++++ b/drivers/clocksource/arm_arch_timer.c
+@@ -69,7 +69,7 @@ static enum arch_timer_ppi_nr arch_timer
+ 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_arch_clockmode vdso_default = VDSO_CLOCKMODE_ARCHTIMER;
+
+ static cpumask_t evtstrm_available = CPU_MASK_NONE;
+ static bool evtstrm_enable = IS_ENABLED(CONFIG_ARM_ARCH_TIMER_EVTSTREAM);
+@@ -560,8 +560,8 @@ void arch_timer_enable_workaround(const
+ * 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.archdata.clock_mode = VDSO_CLOCKMODE_NONE;
++ vdso_default = VDSO_CLOCKMODE_NONE;
+ }
+ }
+
+@@ -979,7 +979,7 @@ static void __init arch_counter_register
+ }
+
+ arch_timer_read_counter = rd;
+- clocksource_counter.archdata.vdso_direct = vdso_default;
++ clocksource_counter.archdata.clock_mode = vdso_default;
+ } else {
+ arch_timer_read_counter = arch_counter_get_cntvct_mem;
+ }