Unverified Commit 7f55dbd9 authored by openeuler-ci-bot's avatar openeuler-ci-bot Committed by Gitee
Browse files

!3306 improve gettimeofday() performance in user space

Merge Pull Request from: @ci-robot 
 
PR sync from: Yang Yingliang <yangyingliang@huawei.com>
https://mailweb.openeuler.org/hyperkitty/list/kernel@openeuler.org/message/YHKNSX4KKFYDIZG6PFMBJYN2PUPIOMV4/ 
Don't trap kernel to read the counter register, do this in userspace to
improve performance.

Yang Yingliang (3):
  arm64: arch_timer: Disable CNTVCT_EL0 trap if workaround is enabled
  vdso: do cntvct workaround in the VDSO
  arm64: arch_timer: disable
    CONFIG_ARM_ARCH_TIMER_WORKAROUND_IN_USERSPACE


-- 
2.25.1
 
https://gitee.com/openeuler/kernel/issues/I8LFBU 
 
Link:https://gitee.com/openeuler/kernel/pulls/3306

 

Reviewed-by: default avatarWei Li <liwei391@huawei.com>
Reviewed-by: default avatarZhang Jianhua <chris.zjh@huawei.com>
Reviewed-by: default avatarXie XiuQi <xiexiuqi@huawei.com>
Signed-off-by: default avatarZheng Zengkai <zhengzengkai@huawei.com>
parents b91e04ba be898f9a
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -6406,6 +6406,7 @@ CONFIG_FSL_ERRATUM_A008585=y
CONFIG_HISILICON_ERRATUM_161010101=y
CONFIG_ARM64_ERRATUM_858921=y
CONFIG_ARM_TIMER_SP804=y
# CONFIG_ARM_ARCH_TIMER_WORKAROUND_IN_USERSPACE is not set
# end of Clock Source drivers

CONFIG_MAILBOX=y
+32 −0
Original line number Diff line number Diff line
@@ -94,6 +94,38 @@ static __always_inline u64 __arch_get_hw_counter(s32 clock_mode,
	:
	: "memory");

#ifdef CONFIG_ARM_ARCH_TIMER_WORKAROUND_IN_USERSPACE
	if (vd->vdso_fix) {
		u64 new;
		int retries = 50;

		asm volatile(
		ALTERNATIVE("mrs %0, cntvct_el0",
			    __mrs_s("%0", SYS_CNTVCTSS_EL0),
			    ARM64_HAS_ECV)
		: "=r" (new)
		:
		: "memory");
		while (unlikely((new - res) >> vd->vdso_shift) && retries) {
			asm volatile(
			ALTERNATIVE("mrs %0, cntvct_el0",
				    __mrs_s("%0", SYS_CNTVCTSS_EL0),
				    ARM64_HAS_ECV)
			: "=r" (res)
			:
			: "memory");

			asm volatile(
			ALTERNATIVE("mrs %0, cntvct_el0",
				    __mrs_s("%0", SYS_CNTVCTSS_EL0),
				    ARM64_HAS_ECV)
			: "=r" (new)
			:
			: "memory");
			retries--;
		}
	}
#endif
	arch_counter_enforce_ordering(res);

	return res;
+5 −0
Original line number Diff line number Diff line
@@ -732,4 +732,9 @@ config GOLDFISH_TIMER
	help
	  Support for the timer/counter of goldfish-rtc

config ARM_ARCH_TIMER_WORKAROUND_IN_USERSPACE
	bool "Enable arch timer workaround in vdso"
	default y
	depends on ARM_ARCH_TIMER_OOL_WORKAROUND

endmenu
+27 −0
Original line number Diff line number Diff line
@@ -92,6 +92,10 @@ static enum vdso_clock_mode vdso_default = VDSO_CLOCKMODE_ARCHTIMER;
#else
static enum vdso_clock_mode vdso_default = VDSO_CLOCKMODE_NONE;
#endif /* CONFIG_GENERIC_GETTIMEOFDAY */
#ifdef CONFIG_ARM_ARCH_TIMER_WORKAROUND_IN_USERSPACE
static bool vdso_fix;
static u16 vdso_shift;
#endif

static cpumask_t evtstrm_available = CPU_MASK_NONE;
static bool evtstrm_enable __ro_after_init = IS_ENABLED(CONFIG_ARM_ARCH_TIMER_EVTSTREAM);
@@ -599,8 +603,23 @@ void arch_timer_enable_workaround(const struct arch_timer_erratum_workaround *wa
	 * change both the default value and the vdso itself.
	 */
	if (wa->read_cntvct_el0) {
#ifdef CONFIG_ARM_ARCH_TIMER_WORKAROUND_IN_USERSPACE
		if (!strncmp(wa->desc, "HiSilicon erratum 161010101",
			     strlen("HiSilicon erratum 161010101"))) {
			vdso_fix = true;
			vdso_shift = 5;
		} else if (!strncmp(wa->desc, "Freescale erratum a005858",
				    strlen("Freescale erratum a005858"))) {
			vdso_fix = true;
			vdso_shift = 0;
		} else {
			clocksource_counter.vdso_clock_mode = VDSO_CLOCKMODE_NONE;
			vdso_default = VDSO_CLOCKMODE_NONE;
		}
#else
		clocksource_counter.vdso_clock_mode = VDSO_CLOCKMODE_NONE;
		vdso_default = VDSO_CLOCKMODE_NONE;
#endif
	} else if (wa->disable_compat_vdso && vdso_default != VDSO_CLOCKMODE_NONE) {
		vdso_default = VDSO_CLOCKMODE_ARCHTIMER_NOCOMPAT;
		clocksource_counter.vdso_clock_mode = vdso_default;
@@ -973,7 +992,11 @@ static void arch_counter_set_user_access(void)
	 * need to be workaround. The vdso may have been already
	 * disabled though.
	 */
#ifdef CONFIG_ARM_ARCH_TIMER_WORKAROUND_IN_USERSPACE
	if (arch_timer_this_cpu_has_cntvct_wa() && !vdso_fix)
#else
	if (arch_timer_this_cpu_has_cntvct_wa())
#endif
		pr_info("CPU%d: Trapping CNTVCT access\n", smp_processor_id());
	else
		cntkctl |= ARCH_TIMER_USR_VCT_ACCESS_EN;
@@ -1129,6 +1152,10 @@ static void __init arch_counter_register(unsigned type)

		arch_timer_read_counter = rd;
		clocksource_counter.vdso_clock_mode = vdso_default;
#ifdef CONFIG_ARM_ARCH_TIMER_WORKAROUND_IN_USERSPACE
		clocksource_counter.vdso_fix = vdso_fix;
		clocksource_counter.vdso_shift = vdso_shift;
#endif
	} else {
		arch_timer_read_counter = arch_counter_get_cntvct_mem;
		scr = arch_counter_get_cntvct_mem;
+4 −0
Original line number Diff line number Diff line
@@ -110,6 +110,10 @@ struct clocksource {
	int			rating;
	enum clocksource_ids	id;
	enum vdso_clock_mode	vdso_clock_mode;
#ifdef CONFIG_ARM_ARCH_TIMER_WORKAROUND_IN_USERSPACE
	u16			vdso_fix;
	u16			vdso_shift;
#endif
	unsigned long		flags;

	int			(*enable)(struct clocksource *cs);
Loading