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

Commit 3158d448 authored by Marc Zyngier's avatar Marc Zyngier Committed by Gerrit - the friendly Code Review server
Browse files

BACKPORT: arm64: Add CNTFRQ_EL0 trap handler



We now trap accesses to CNTVCT_EL0 when the counter is broken
enough to require the kernel to mediate the access. But it
turns out that some existing userspace (such as OpenMPI) do
probe for the counter frequency, leading to an UNDEF exception
as CNTVCT_EL0 and CNTFRQ_EL0 share the same control bit.

The fix is to handle the exception the same way we do for CNTVCT_EL0.

Fixes: a86bd139f2ae ("arm64: arch_timer: Enable CNTVCT_EL0 trap if workaround is enabled")
Reported-by: default avatarHanjun Guo <guohanjun@huawei.com>
Tested-by: default avatarHanjun Guo <guohanjun@huawei.com>
Reviewed-by: default avatarHanjun Guo <guohanjun@huawei.com>
Signed-off-by: default avatarMarc Zyngier <marc.zyngier@arm.com>
Signed-off-by: default avatarCatalin Marinas <catalin.marinas@arm.com>
(cherry picked from commit 9842119a238bfb92cbab63258dabb54f0e7b111b)

Change-Id: I1bde5dc8f2fbdc94f66bc6606b88ad1817788080
Signed-off-by: default avatarNeeraj Upadhyay <neeraju@codeaurora.org>
parent d74d8eb4
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -171,6 +171,9 @@
#define ESR_ELx_SYS64_ISS_SYS_CNTVCT	(ESR_ELx_SYS64_ISS_SYS_VAL(3, 3, 2, 14, 0) | \
					 ESR_ELx_SYS64_ISS_DIR_READ)

#define ESR_ELx_SYS64_ISS_SYS_CNTFRQ	(ESR_ELx_SYS64_ISS_SYS_VAL(3, 3, 0, 14, 0) | \
					 ESR_ELx_SYS64_ISS_DIR_READ)

#ifndef __ASSEMBLY__
#include <asm/types.h>

+12 −0
Original line number Diff line number Diff line
@@ -408,11 +408,23 @@ static void cntvct_read_handler(unsigned int esr, struct pt_regs *regs)
	regs->pc += 4;
}

static void cntfrq_read_handler(unsigned int esr, struct pt_regs *regs)
{
	int rt = (esr & ESR_ELx_SYS64_ISS_RT_MASK) >> ESR_ELx_SYS64_ISS_RT_SHIFT;

	if (rt != 31)
		regs->regs[rt] = read_sysreg(cntfrq_el0);
	regs->pc += 4;
}

asmlinkage void __exception do_sysinstr(unsigned int esr, struct pt_regs *regs)
{
	if ((esr & ESR_ELx_SYS64_ISS_SYS_OP_MASK) == ESR_ELx_SYS64_ISS_SYS_CNTVCT) {
		cntvct_read_handler(esr, regs);
		return;
	} else if ((esr & ESR_ELx_SYS64_ISS_SYS_OP_MASK) == ESR_ELx_SYS64_ISS_SYS_CNTFRQ) {
		cntfrq_read_handler(esr, regs);
		return;
	}

	do_undefinstr(regs);