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

Commit 0d18e171 authored by Mark Salyzyn's avatar Mark Salyzyn Committed by Gagan Malvi
Browse files

FROMLIST: [PATCH v5 03/12] arm: vdso: inline assembler operations to compiler.h

(cherry picked from commit https://patchwork.kernel.org/patch/10044507/

)

Take an effort to recode the arm64 vdso code from assembler to C
previously submitted by Andrew Pinski <apinski@cavium.com>, rework
it for use in both arm and arm64, overlapping any optimizations
for each architecture. But instead of landing it in arm64, land the
result into lib/vdso and unify both implementations to simplify
future maintenance.

Move compiler-specific code to a local compiler.h file:

- CONFIG_AEABI dependency check.
- System call fallback functions standardized into a
  DEFINE_FALLBACK macro.
- Replace arch_counter_get_cntvct() with arch_vdso_read_counter.
- Deal with architecture specific unresolved references emitted
  by GCC.
- Optimize handling of fallback calls in callers.
- For time functions that always return success, do not waste time
  checking return value for switch to fallback.
- Optimize unlikely nullptr checking in __vdso_gettimeofday,
  if tv null no need to proceed to fallback, as vdso is still
  capable of filling in the tv values.

Signed-off-by: default avatarMark Salyzyn <salyzyn@android.com>
Cc: James Morse <james.morse@arm.com>
Cc: Russell King <linux@armlinux.org.uk>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Will Deacon <will.deacon@arm.com>
Cc: Andy Lutomirski <luto@amacapital.net>
Cc: Dmitry Safonov <dsafonov@virtuozzo.com>
Cc: John Stultz <john.stultz@linaro.org>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Laura Abbott <labbott@redhat.com>
Cc: Kees Cook <keescook@chromium.org>
Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: Andy Gross <andy.gross@linaro.org>
Cc: Kevin Brodsky <kevin.brodsky@arm.com>
Cc: Andrew Pinski <apinski@cavium.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: linux-kernel@vger.kernel.org
Cc: linux-arm-kernel@lists.infradead.org
Bug: 63737556
Bug: 20045882
Change-Id: I468e4c32b5136d199982bf25df8967321e384d90

Signed-off-by: default avatarstarlight5234 <ifist2834@gmail.com>
Signed-off-by: default avatarTheSync <repo-sync@outlook.com>
parent 2b09e58a
Loading
Loading
Loading
Loading
+69 −0
Original line number Diff line number Diff line
/*
 * Userspace implementations of fallback calls
 *
 * Copyright (C) 2017 Cavium, Inc.
 * Copyright (C) 2012 ARM Limited
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 * Author: Will Deacon <will.deacon@arm.com>
 * Rewriten into C by: Andrew Pinski <apinski@cavium.com>
 */

#ifndef __VDSO_COMPILER_H
#define __VDSO_COMPILER_H

#include <asm/arch_timer.h>	/* for arch_counter_get_cntvct()	*/
#include <asm/processor.h>	/* for cpu_relax()			*/
#include <asm/unistd.h>
#include <linux/compiler.h>

#ifndef CONFIG_AEABI
#error This code depends on AEABI system call conventions
#endif

#define DEFINE_FALLBACK(name, type_arg1, name_arg1, type_arg2, name_arg2) \
static notrace long name##_fallback(type_arg1 _##name_arg1,		  \
				    type_arg2 _##name_arg2)		  \
{									  \
	register type_arg1 name_arg1 asm("r0") = _##name_arg1;		  \
	register type_arg2 name_arg2 asm("r1") = _##name_arg2;		  \
	register long ret asm ("r0");					  \
	register long nr asm("r7") = __NR_##name;			  \
									  \
	asm volatile(							  \
	"	swi #0\n"						  \
	: "=r" (ret)							  \
	: "r" (name_arg1), "r" (name_arg2), "r" (nr)			  \
	: "memory");							  \
									  \
	return ret;							  \
}

#define arch_vdso_read_counter() arch_counter_get_cntvct()

/* Avoid unresolved references emitted by GCC */

void __aeabi_unwind_cpp_pr0(void)
{
}

void __aeabi_unwind_cpp_pr1(void)
{
}

void __aeabi_unwind_cpp_pr2(void)
{
}

#endif /* __VDSO_COMPILER_H */
+27 −82
Original line number Diff line number Diff line
@@ -22,21 +22,16 @@
 * Reworked and rebased over arm version by: Mark Salyzyn <salyzyn@android.com>
 */

#include <linux/compiler.h>
#include <linux/hrtimer.h>
#include <linux/time.h>
#include <asm/arch_timer.h>
#include <asm/barrier.h>
#include <asm/bug.h>
#include <asm/page.h>
#include <asm/unistd.h>

#ifndef CONFIG_AEABI
#error This code depends on AEABI system call conventions
#endif
#include <linux/compiler.h>	/* for notrace				*/
#include <linux/time.h>

#include "compiler.h"
#include "datapage.h"

DEFINE_FALLBACK(gettimeofday, struct timeval *, tv, struct timezone *, tz)
DEFINE_FALLBACK(clock_gettime, clockid_t, clock, struct timespec *, ts)

static notrace u32 vdso_read_begin(const struct vdso_data *vd)
{
	u32 seq;
@@ -63,23 +58,6 @@ static notrace int vdso_read_retry(const struct vdso_data *vd, u32 start)
	return seq != start;
}

static notrace long clock_gettime_fallback(clockid_t _clkid,
					   struct timespec *_ts)
{
	register struct timespec *ts asm("r1") = _ts;
	register clockid_t clkid asm("r0") = _clkid;
	register long ret asm ("r0");
	register long nr asm("r7") = __NR_clock_gettime;

	asm volatile(
	"	swi #0\n"
	: "=r" (ret)
	: "r" (clkid), "r" (ts), "r" (nr)
	: "memory");

	return ret;
}

static notrace int do_realtime_coarse(const struct vdso_data *vd,
				      struct timespec *ts)
{
@@ -127,7 +105,7 @@ static notrace u64 get_ns(const struct vdso_data *vd)
	u64 cycle_now;
	u64 nsec;

	cycle_now = arch_counter_get_cntvct();
	cycle_now = arch_vdso_read_counter();

	cycle_delta = (cycle_now - vd->cs_cycle_last) & vd->cs_mask;

@@ -200,85 +178,52 @@ static notrace int do_monotonic(const struct vdso_data *vd, struct timespec *ts)

#endif /* CONFIG_ARM_ARCH_TIMER */

notrace int __vdso_clock_gettime(clockid_t clkid, struct timespec *ts)
notrace int __vdso_clock_gettime(clockid_t clock, struct timespec *ts)
{
	int ret = -1;

	const struct vdso_data *vd = __get_datapage();

	switch (clkid) {
	switch (clock) {
	case CLOCK_REALTIME_COARSE:
		ret = do_realtime_coarse(vd, ts);
		do_realtime_coarse(vd, ts);
		break;
	case CLOCK_MONOTONIC_COARSE:
		ret = do_monotonic_coarse(vd, ts);
		do_monotonic_coarse(vd, ts);
		break;
	case CLOCK_REALTIME:
		ret = do_realtime(vd, ts);
		if (do_realtime(vd, ts))
			goto fallback;
		break;
	case CLOCK_MONOTONIC:
		ret = do_monotonic(vd, ts);
		if (do_monotonic(vd, ts))
			goto fallback;
		break;
	default:
		break;
	}

	if (ret)
		ret = clock_gettime_fallback(clkid, ts);

	return ret;
		goto fallback;
	}

static notrace long gettimeofday_fallback(struct timeval *_tv,
					  struct timezone *_tz)
{
	register struct timezone *tz asm("r1") = _tz;
	register struct timeval *tv asm("r0") = _tv;
	register long ret asm ("r0");
	register long nr asm("r7") = __NR_gettimeofday;

	asm volatile(
	"	swi #0\n"
	: "=r" (ret)
	: "r" (tv), "r" (tz), "r" (nr)
	: "memory");

	return ret;
	return 0;
fallback:
	return clock_gettime_fallback(clock, ts);
}

notrace int __vdso_gettimeofday(struct timeval *tv, struct timezone *tz)
{
	struct timespec ts;
	int ret;

	const struct vdso_data *vd = __get_datapage();

	ret = do_realtime(vd, &ts);
	if (ret)
	if (likely(tv != NULL)) {
		struct timespec ts;

		if (do_realtime(vd, &ts))
			return gettimeofday_fallback(tv, tz);

	if (tv) {
		tv->tv_sec = ts.tv_sec;
		tv->tv_usec = ts.tv_nsec / 1000;
	}
	if (tz) {

	if (unlikely(tz != NULL)) {
		tz->tz_minuteswest = vd->tz_minuteswest;
		tz->tz_dsttime = vd->tz_dsttime;
	}

	return ret;
}

/* Avoid unresolved references emitted by GCC */

void __aeabi_unwind_cpp_pr0(void)
{
}

void __aeabi_unwind_cpp_pr1(void)
{
}

void __aeabi_unwind_cpp_pr2(void)
{
	return 0;
}