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

Commit 4b4fd1fc authored by Mark Salyzyn's avatar Mark Salyzyn Committed by Gagan Malvi
Browse files

FROMLIST: [PATCH v5 01/12] arm: vdso: rename vdso_datapage variables

(cherry picked from url https://patchwork.kernel.org/patch/10044505/

)

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.

Rename seq_count to tb_seq_count. Rename tk_is_cntvct to use_syscall.
Rename cs_mult to cs_mono_mult. All to align with the variables in the
arm64 vdso datapage. Rework vdso_read_begin() and vdso_read_retry()
functions to reflect modern access patterns for tb_seq_count field.

Update copyright message to reflect the start of the contributions in
this series.

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: I13f16e71b1ecba3d72b999caafef72e3c7f48dfe

Signed-off-by: default avatarstarlight5234 <ifist2834@gmail.com>
Signed-off-by: default avatarTheSync <repo-sync@outlook.com>
parent 288f781e
Loading
Loading
Loading
Loading
+3 −3
Original line number Diff line number Diff line
@@ -29,8 +29,8 @@
 * 32 bytes.
 */
struct vdso_data {
	u32 seq_count;		/* sequence count - odd during updates */
	u16 tk_is_cntvct;	/* fall back to syscall if false */
	u32 tb_seq_count;	/* sequence count - odd during updates */
	u16 use_syscall;	/* fall back to syscall if true */
	u16 cs_shift;		/* clocksource shift */
	u32 xtime_coarse_sec;	/* coarse time */
	u32 xtime_coarse_nsec;
@@ -38,7 +38,7 @@ struct vdso_data {
	u32 wtm_clock_sec;	/* wall to monotonic offset */
	u32 wtm_clock_nsec;
	u32 xtime_clock_sec;	/* CLOCK_REALTIME - seconds */
	u32 cs_mult;		/* clocksource multiplier */
	u32 cs_mono_mult;	/* clocksource multiplier */

	u64 cs_cycle_last;	/* last cycle value */
	u64 cs_mask;		/* clocksource mask */
+9 −8
Original line number Diff line number Diff line
@@ -258,14 +258,14 @@ void arm_install_vdso(struct mm_struct *mm, unsigned long addr)

static void vdso_write_begin(struct vdso_data *vdata)
{
	++vdso_data->seq_count;
	++vdso_data->tb_seq_count;
	smp_wmb(); /* Pairs with smp_rmb in vdso_read_retry */
}

static void vdso_write_end(struct vdso_data *vdata)
{
	smp_wmb(); /* Pairs with smp_rmb in vdso_read_begin */
	++vdso_data->seq_count;
	++vdso_data->tb_seq_count;
}

static bool tk_is_cntvct(const struct timekeeper *tk)
@@ -289,10 +289,10 @@ static bool tk_is_cntvct(const struct timekeeper *tk)
 * counter again, making it even, indicating to userspace that the
 * update is finished.
 *
 * Userspace is expected to sample seq_count before reading any other
 * fields from the data page.  If seq_count is odd, userspace is
 * Userspace is expected to sample tb_seq_count before reading any other
 * fields from the data page.  If tb_seq_count is odd, userspace is
 * expected to wait until it becomes even.  After copying data from
 * the page, userspace must sample seq_count again; if it has changed
 * the page, userspace must sample tb_seq_count again; if it has changed
 * from its previous value, userspace must retry the whole sequence.
 *
 * Calls to update_vsyscall are serialized by the timekeeping core.
@@ -310,18 +310,19 @@ void update_vsyscall(struct timekeeper *tk)

	vdso_write_begin(vdso_data);

	vdso_data->tk_is_cntvct			= tk_is_cntvct(tk);
	vdso_data->use_syscall			= !tk_is_cntvct(tk);
	vdso_data->xtime_coarse_sec		= tk->xtime_sec;
	vdso_data->xtime_coarse_nsec		= (u32)(tk->tkr_mono.xtime_nsec >>
							tk->tkr_mono.shift);
	vdso_data->wtm_clock_sec		= wtm->tv_sec;
	vdso_data->wtm_clock_nsec		= wtm->tv_nsec;

	if (vdso_data->tk_is_cntvct) {
	if (!vdso_data->use_syscall) {
		vdso_data->cs_cycle_last	= tk->tkr_mono.cycle_last;
		vdso_data->xtime_clock_sec	= tk->xtime_sec;
		vdso_data->xtime_clock_snsec	= tk->tkr_mono.xtime_nsec;
		vdso_data->cs_mult		= tk->tkr_mono.mult;
		vdso_data->cs_mono_mult		= tk->tkr_mono.mult;
		/* tkr_mono.shift == tkr_raw.shift */
		vdso_data->cs_shift		= tk->tkr_mono.shift;
		vdso_data->cs_mask		= tk->tkr_mono.mask;
	}
+33 −28
Original line number Diff line number Diff line
/*
 * Copyright 2015 Mentor Graphics Corporation.
 * Userspace implementations of gettimeofday() and friends.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; version 2 of the
 * License.
 * Copyright (C) 2017 Cavium, Inc.
 * Copyright (C) 2015 Mentor Graphics Corporation
 * Copyright (C) 2012 ARM Limited
 *
 * 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.
 * 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 from arch64 version into C by: Andrew Pinski <apinski@cavium.com>
 * Reworked and rebased over arm version by: Mark Salyzyn <salyzyn@android.com>
 */

#include <linux/compiler.h>
@@ -31,32 +38,30 @@

extern struct vdso_data *__get_datapage(void);

static notrace u32 __vdso_read_begin(const struct vdso_data *vdata)
{
	u32 seq;
repeat:
	seq = ACCESS_ONCE(vdata->seq_count);
	if (seq & 1) {
		cpu_relax();
		goto repeat;
	}
	return seq;
}

static notrace u32 vdso_read_begin(const struct vdso_data *vdata)
{
	u32 seq;

	seq = __vdso_read_begin(vdata);
	do {
		seq = READ_ONCE(vdata->tb_seq_count);

		if ((seq & 1) == 0)
			break;

		cpu_relax();
	} while (true);

	smp_rmb(); /* Pairs with smp_wmb in vdso_write_end */
	smp_rmb(); /* Pairs with second smp_wmb in update_vsyscall */
	return seq;
}

static notrace int vdso_read_retry(const struct vdso_data *vdata, u32 start)
{
	smp_rmb(); /* Pairs with smp_wmb in vdso_write_begin */
	return vdata->seq_count != start;
	u32 seq;

	smp_rmb(); /* Pairs with first smp_wmb in update_vsyscall */
	seq = READ_ONCE(vdata->tb_seq_count);
	return seq != start;
}

static notrace long clock_gettime_fallback(clockid_t _clkid,
@@ -127,7 +132,7 @@ static notrace u64 get_ns(struct vdso_data *vdata)

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

	nsec = (cycle_delta * vdata->cs_mult) + vdata->xtime_clock_snsec;
	nsec = (cycle_delta * vdata->cs_mono_mult) + vdata->xtime_clock_snsec;
	nsec >>= vdata->cs_shift;

	return nsec;
@@ -141,7 +146,7 @@ static notrace int do_realtime(struct timespec *ts, struct vdso_data *vdata)
	do {
		seq = vdso_read_begin(vdata);

		if (!vdata->tk_is_cntvct)
		if (vdata->use_syscall)
			return -1;

		ts->tv_sec = vdata->xtime_clock_sec;
@@ -164,7 +169,7 @@ static notrace int do_monotonic(struct timespec *ts, struct vdso_data *vdata)
	do {
		seq = vdso_read_begin(vdata);

		if (!vdata->tk_is_cntvct)
		if (vdata->use_syscall)
			return -1;

		ts->tv_sec = vdata->xtime_clock_sec;