Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 71d65a3f authored by Marc Zyngier's avatar Marc Zyngier Committed by Greg Kroah-Hartman
Browse files

arm64: Introduce a way to disable the 32bit vdso



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: default avatarMarc Zyngier <maz@kernel.org>
Acked-by: default avatarMark 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: default avatarWill Deacon <will@kernel.org>
Signed-off-by: default avatarMarc Zyngier <maz@kernel.org>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 36d60eba
Loading
Loading
Loading
Loading
+10 −1
Original line number Diff line number Diff line
#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
+1 −1
Original line number Diff line number Diff line
@@ -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;
+4 −1
Original line number Diff line number Diff line
@@ -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
+14 −0
Original line number Diff line number Diff line
/* 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
+3 −2
Original line number Diff line number Diff line
@@ -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_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;

	/*
Loading