[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20170721171542.27639-17-marc.zyngier@arm.com>
Date: Fri, 21 Jul 2017 18:15:42 +0100
From: Marc Zyngier <marc.zyngier@....com>
To: linux-arm-kernel@...ts.infradead.org, linux-kernel@...r.kernel.org
Cc: Mark Rutland <mark.rutland@....com>,
Russell King <linux@...linux.org.uk>,
Catalin Marinas <catalin.marinas@....com>,
Will Deacon <will.deacon@....com>,
Daniel Lezcano <daniel.lezcano@...aro.org>,
Thomas Gleixner <tglx@...utronix.de>
Subject: [PATCH 16/16] clocksource/arm_arch_timer: Trap user access to CNT{VCT,FRQ} if CNTFRQ is invalid
If we end-up in a situation where any of the CPUs doesn't have its
CNTFRQ register correctly programmed, we cannot reliably expose this
register to userspace. It means that in this case, we have to trap
it, and CNTVCT at the same time (since they are controlled by the
same trapping bit).
It also means that there is no point in enabling the VDSO access to
the counter, since we're going to enter the kernel.
Acked-by: Mark Rutland <mark.rutland@....com>
Signed-off-by: Marc Zyngier <marc.zyngier@....com>
---
drivers/clocksource/arm_arch_timer.c | 28 ++++++++++++++++++++++++----
1 file changed, 24 insertions(+), 4 deletions(-)
diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c
index 4f4633157978..37404a6a1bfa 100644
--- a/drivers/clocksource/arm_arch_timer.c
+++ b/drivers/clocksource/arm_arch_timer.c
@@ -759,6 +759,25 @@ static void arch_timer_configure_evtstream(void)
arch_timer_evtstrm_enable(min(pos, 15));
}
+static bool cntfrq_valid(void)
+{
+ u32 freq = arch_timer_get_cntfrq();
+
+ if (freq != arch_timer_rate) {
+ /*
+ * If any of the CPUs disagrees on what CNTFRQ should
+ * actually be, we end-up disabling the vdso fastpath
+ * for the whole system.
+ */
+ pr_warn("CPU%d: Invalid CNTFRQ (%u, expected %u)\n",
+ smp_processor_id(), freq, arch_timer_rate);
+ disable_vdso();
+ return false;
+ }
+
+ return true;
+}
+
static void arch_counter_set_user_access(void)
{
u32 cntkctl = arch_timer_get_cntkctl();
@@ -773,11 +792,12 @@ static void arch_counter_set_user_access(void)
/*
* Enable user access to the virtual counter if it doesn't
- * need to be workaround. The vdso may have been already
- * disabled though.
+ * need to be workaround, and that the frequency has been
+ * correctly set. The vdso may have been already disabled
+ * though.
*/
- if (arch_timer_this_cpu_has_cntvct_wa())
- pr_info("CPU%d: Trapping CNTVCT access\n", smp_processor_id());
+ if (arch_timer_this_cpu_has_cntvct_wa() || !cntfrq_valid())
+ pr_info("CPU%d: Trapping CNTVCT/CNTFRQ access\n", smp_processor_id());
else
cntkctl |= ARCH_TIMER_USR_VCT_ACCESS_EN;
--
2.11.0
Powered by blists - more mailing lists