[Stable-5.4][PATCH 1/3] arm64: Introduce a way to disable the 32bit vdso

2020-07-15 Thread Marc Zyngier
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
__arch_get_hw_counter() helper.

Signed-off-by: Marc Zyngier 
Acked-by: Mark Rutland 
Cc: sta...@vger.kernel.org
Link: https://lore.kernel.org/r/20200706163802.1836732-2-...@kernel.org
Signed-off-by: Will Deacon 
Signed-off-by: Marc Zyngier 
---
 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(-)
 create mode 100644 arch/arm64/include/asm/vdso/clocksource.h

diff --git a/arch/arm/include/asm/clocksource.h 
b/arch/arm/include/asm/clocksource.h
index 0b350a7e26f3..afb7a59828fe 100644
--- 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
diff --git a/arch/arm/kernel/vdso.c b/arch/arm/kernel/vdso.c
index f00e45fa62c4..6c69a5548ba2 100644
--- a/arch/arm/kernel/vdso.c
+++ b/arch/arm/kernel/vdso.c
@@ -281,7 +281,7 @@ static 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)
+   if (tk->tkr_mono.clock->archdata.clock_mode != VDSO_CLOCKMODE_ARCHTIMER)
return false;
 
return true;
diff --git a/arch/arm64/include/asm/clocksource.h 
b/arch/arm64/include/asm/clocksource.h
index 0ece64a26c8c..0c7910447235 100644
--- 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 
+
 struct arch_clocksource_data {
-   bool vdso_direct;   /* Usable for direct VDSO access? */
+   /* Usable for direct VDSO access? */
+   enum vdso_arch_clockmode clock_mode;
 };
 
 #endif
diff --git a/arch/arm64/include/asm/vdso/clocksource.h 
b/arch/arm64/include/asm/vdso/clocksource.h
new file mode 100644
index ..8019f616e1f7
--- /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
diff --git a/arch/arm64/include/asm/vdso/compat_gettimeofday.h 
b/arch/arm64/include/asm/vdso/compat_gettimeofday.h
index c50ee1b7d5cd..413d42e197c7 100644
--- a/arch/arm64/include/asm/vdso/compat_gettimeofday.h
+++ b/arch/arm64/include/asm/vdso/compat_gettimeofday.h
@@ -10,6 +10,7 @@
 #include 
 #include 
 
+#include 
 #include 
 
 #define __VDSO_USE_SYSCALL ULLONG_MAX
@@ -117,10 +118,10 @@ static __always_inline u64 __arch_get_hw_counter(s32 
clock_mode)
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;
 
/*
diff --git a/arch/arm64/include/asm/vdso/gettimeofday.h 
b/arch/arm64/include/asm/vdso/gettimeofday.h
index b08f476b72b4..ff83b8b574fc 100644
--- a/arch/arm64/include/asm/vdso/gettimeofday.h
+++ b/arch/arm64/include/asm/vdso/gettimeofday.h
@@ -10,6 +10,8 @@
 #include 
 #include 
 
+#include 
+
 #define __VDSO_USE_SYSCALL ULLONG_MAX
 
 #define VDSO_HAS_CLOCK_GETRES  1
@@ -71,10 +73,10 @@ static 

Re: [PATCH 1/3] arm64: Introduce a way to disable the 32bit vdso

2020-07-02 Thread Mark Rutland
On Wed, Jul 01, 2020 at 05:18:22PM +0100, Marc Zyngier wrote:
> 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 

As-is this looks sound to me. It's not entirely clear to me how this
will compose with VDSO_CLOCKMODE_TIMENS, but given this series is fixing
an existing brokenness I think this has higher priority.

Minor comment below, but regardless:

Acked-by: Mark Rutland 

> ---
>  arch/arm64/include/asm/vdso/clocksource.h | 7 +--
>  arch/arm64/include/asm/vdso/compat_gettimeofday.h | 8 +++-
>  2 files changed, 12 insertions(+), 3 deletions(-)
> 
> diff --git a/arch/arm64/include/asm/vdso/clocksource.h 
> b/arch/arm64/include/asm/vdso/clocksource.h
> index df6ea65c1dec..b054d9febfb5 100644
> --- a/arch/arm64/include/asm/vdso/clocksource.h
> +++ b/arch/arm64/include/asm/vdso/clocksource.h
> @@ -2,7 +2,10 @@
>  #ifndef __ASM_VDSOCLOCKSOURCE_H
>  #define __ASM_VDSOCLOCKSOURCE_H
>  
> -#define VDSO_ARCH_CLOCKMODES \
> - VDSO_CLOCKMODE_ARCHTIMER
> +#define VDSO_ARCH_CLOCKMODES \
> + /* vdso clocksource for both 32 and 64bit tasks */  \
> + VDSO_CLOCKMODE_ARCHTIMER,   \
> + /* vdso clocksource for 64bit tasks only */ \
> + VDSO_CLOCKMODE_ARCHTIMER_NOCOMPAT
>  
>  #endif
> diff --git a/arch/arm64/include/asm/vdso/compat_gettimeofday.h 
> b/arch/arm64/include/asm/vdso/compat_gettimeofday.h
> index b6907ae78e53..9a625e8947ff 100644
> --- a/arch/arm64/include/asm/vdso/compat_gettimeofday.h
> +++ b/arch/arm64/include/asm/vdso/compat_gettimeofday.h
> @@ -111,7 +111,7 @@ static __always_inline u64 __arch_get_hw_counter(s32 
> clock_mode)
>* 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)
> + if (clock_mode != VDSO_CLOCKMODE_ARCHTIMER)
>   return 0;
>  
>   /*
> @@ -152,6 +152,12 @@ static __always_inline const struct vdso_data 
> *__arch_get_vdso_data(void)
>   return ret;
>  }
>  
> +static inline bool vdso_clocksource_ok(const struct vdso_data *vd)
> +{
> + return vd->clock_mode == VDSO_CLOCKMODE_ARCHTIMER;
> +}
> +#define vdso_clocksource_ok  vdso_clocksource_ok

Existing issue, but it's a shame this doesn't take the clock mode
directly, then we wouldn't have to duplicate the conditions (as above,
inverted).

Mark.


[PATCH 1/3] arm64: Introduce a way to disable the 32bit vdso

2020-07-01 Thread Marc Zyngier
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 
---
 arch/arm64/include/asm/vdso/clocksource.h | 7 +--
 arch/arm64/include/asm/vdso/compat_gettimeofday.h | 8 +++-
 2 files changed, 12 insertions(+), 3 deletions(-)

diff --git a/arch/arm64/include/asm/vdso/clocksource.h 
b/arch/arm64/include/asm/vdso/clocksource.h
index df6ea65c1dec..b054d9febfb5 100644
--- a/arch/arm64/include/asm/vdso/clocksource.h
+++ b/arch/arm64/include/asm/vdso/clocksource.h
@@ -2,7 +2,10 @@
 #ifndef __ASM_VDSOCLOCKSOURCE_H
 #define __ASM_VDSOCLOCKSOURCE_H
 
-#define VDSO_ARCH_CLOCKMODES   \
-   VDSO_CLOCKMODE_ARCHTIMER
+#define VDSO_ARCH_CLOCKMODES   \
+   /* vdso clocksource for both 32 and 64bit tasks */  \
+   VDSO_CLOCKMODE_ARCHTIMER,   \
+   /* vdso clocksource for 64bit tasks only */ \
+   VDSO_CLOCKMODE_ARCHTIMER_NOCOMPAT
 
 #endif
diff --git a/arch/arm64/include/asm/vdso/compat_gettimeofday.h 
b/arch/arm64/include/asm/vdso/compat_gettimeofday.h
index b6907ae78e53..9a625e8947ff 100644
--- a/arch/arm64/include/asm/vdso/compat_gettimeofday.h
+++ b/arch/arm64/include/asm/vdso/compat_gettimeofday.h
@@ -111,7 +111,7 @@ static __always_inline u64 __arch_get_hw_counter(s32 
clock_mode)
 * 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)
+   if (clock_mode != VDSO_CLOCKMODE_ARCHTIMER)
return 0;
 
/*
@@ -152,6 +152,12 @@ static __always_inline const struct vdso_data 
*__arch_get_vdso_data(void)
return ret;
 }
 
+static inline bool vdso_clocksource_ok(const struct vdso_data *vd)
+{
+   return vd->clock_mode == VDSO_CLOCKMODE_ARCHTIMER;
+}
+#define vdso_clocksource_okvdso_clocksource_ok
+
 #endif /* !__ASSEMBLY__ */
 
 #endif /* __ASM_VDSO_GETTIMEOFDAY_H */
-- 
2.27.0