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

Unverified Commit 93751113 authored by Andreas Schneider's avatar Andreas Schneider Committed by GitHub
Browse files

Merge pull request #95 from derfelot/lineage-17.1_vdso

[lineage-17.1] Add vDSO32 and enable it
parents ef54dc54 bc16f5ae
Loading
Loading
Loading
Loading
+31 −6
Original line number Diff line number Diff line
@@ -24,21 +24,38 @@

#include <asm/page.h>

#ifndef _VDSO_WTM_CLOCK_SEC_T
#define _VDSO_WTM_CLOCK_SEC_T
typedef u32 vdso_wtm_clock_nsec_t;
#endif

#ifndef _VDSO_XTIME_CLOCK_SEC_T
#define _VDSO_XTIME_CLOCK_SEC_T
typedef u32 vdso_xtime_clock_sec_t;
#endif

#ifndef _VDSO_RAW_TIME_SEC_T
#define _VDSO_RAW_TIME_SEC_T
typedef u32 vdso_raw_time_sec_t;
#endif

/* Try to be cache-friendly on systems that don't implement the
 * generic timer: fit the unconditionally updated fields in the first
 * 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;

	u32 wtm_clock_sec;	/* wall to monotonic offset */
	u32 wtm_clock_nsec;
	u32 xtime_clock_sec;	/* CLOCK_REALTIME - seconds */
	u32 cs_mult;		/* clocksource multiplier */
	/* wall to monotonic offset */
	u32 wtm_clock_sec;
	vdso_wtm_clock_nsec_t	wtm_clock_nsec;
	/* CLOCK_REALTIME - seconds */
	vdso_xtime_clock_sec_t	xtime_clock_sec;
	u32 cs_mono_mult;	/* clocksource multiplier */

	u64 cs_cycle_last;	/* last cycle value */
	u64 cs_mask;		/* clocksource mask */
@@ -46,6 +63,14 @@ struct vdso_data {
	u64 xtime_clock_snsec;	/* CLOCK_REALTIME sub-ns base */
	u32 tz_minuteswest;	/* timezone info for gettimeofday(2) */
	u32 tz_dsttime;

	u32 btm_sec;		/* monotonic to boot time */
	u32 btm_nsec;
	/* Raw clocksource multipler */
	u32 cs_raw_mult;
	/* Raw time */
	vdso_raw_time_sec_t raw_time_sec;
	u32 raw_time_nsec;
};

union vdso_data_store {
+18 −8
Original line number Diff line number Diff line
@@ -173,6 +173,8 @@ static void __init patch_vdso(void *ehdr)
	if (!cntvct_ok) {
		vdso_nullpatch_one(&einfo, "__vdso_gettimeofday");
		vdso_nullpatch_one(&einfo, "__vdso_clock_gettime");
		vdso_nullpatch_one(&einfo, "__vdso_clock_getres");
		/* do not zero out __vdso_time, no cntvct_ok dependency */
	}
}

@@ -258,14 +260,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 +291,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,20 +312,28 @@ 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) {
		struct timespec btm = ktime_to_timespec(tk->offs_boot);

		vdso_data->cs_cycle_last	= tk->tkr_mono.cycle_last;
		vdso_data->raw_time_sec		= tk->raw_sec;
		vdso_data->raw_time_nsec	= tk->tkr_raw.xtime_nsec;
		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;
		vdso_data->cs_raw_mult		= tk->tkr_raw.mult;
		/* tkr_mono.shift == tkr_raw.shift */
		vdso_data->cs_shift		= tk->tkr_mono.shift;
		vdso_data->cs_mask		= tk->tkr_mono.mask;
		vdso_data->btm_sec		= btm.tv_sec;
		vdso_data->btm_nsec		= btm.tv_nsec;
	}

	vdso_write_end(vdso_data);
+4 −1
Original line number Diff line number Diff line
@@ -26,8 +26,11 @@ CFLAGS_REMOVE_vdso.o = -pg
CFLAGS_REMOVE_vgettimeofday.o = -pg -Os
CFLAGS_vgettimeofday.o = -O2

# Disable gcov profiling for VDSO code
# Disable gcov, kasan, ubsan and kcov profiling for VDSO code
GCOV_PROFILE := n
KASAN_SANITIZE := n
UBSAN_SANITIZE := n
KCOV_INSTRUMENT := n

# Force dependency
$(obj)/vdso.o : $(obj)/vdso.so
+75 −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>
#include <linux/hrtimer.h>	/* for LOW_RES_NSEC and MONOTONIC_RES_NSEC */
#include <linux/time.h>		/* for NSEC_PER_SEC			*/

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

#ifdef CONFIG_ARM_ARCH_TIMER
#define ARCH_PROVIDES_TIMER
#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 */
+25 −0
Original line number Diff line number Diff line
/*
 * Userspace implementations of __get_datapage
 *
 * 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/>.
 */

#ifndef __VDSO_DATAPAGE_H
#define __VDSO_DATAPAGE_H

#include <linux/types.h>
#include <asm/vdso_datapage.h>

extern const struct vdso_data *__get_datapage(void);

#endif /* __VDSO_DATAPAGE_H */
Loading