summaryrefslogtreecommitdiff
path: root/arch/arm64/include/asm/arch_timer.h
diff options
context:
space:
mode:
authorStefan Agner <stefan.agner@toradex.com>2019-06-03 10:59:09 +0200
committerStefan Agner <stefan.agner@toradex.com>2019-06-03 10:59:09 +0200
commit2115c1bc6e396d5ffe9ecbe394d1c50a6e25c404 (patch)
tree20fff445991414f23c0a29237940b75cd756de86 /arch/arm64/include/asm/arch_timer.h
parentb794ea49ba3816c0d5cf05506964a8e69ce4efa3 (diff)
parent3f7c1cab1a61108821cf47dda8a32ed25cc3588b (diff)
Merge tag 'v5.0.19' into toradex_5.0.ytoradex_5.0.y
This is the 5.0.19 stable release
Diffstat (limited to 'arch/arm64/include/asm/arch_timer.h')
-rw-r--r--arch/arm64/include/asm/arch_timer.h33
1 files changed, 31 insertions, 2 deletions
diff --git a/arch/arm64/include/asm/arch_timer.h b/arch/arm64/include/asm/arch_timer.h
index f2a234d6516c..93e07512b4b6 100644
--- a/arch/arm64/include/asm/arch_timer.h
+++ b/arch/arm64/include/asm/arch_timer.h
@@ -148,18 +148,47 @@ static inline void arch_timer_set_cntkctl(u32 cntkctl)
isb();
}
+/*
+ * Ensure that reads of the counter are treated the same as memory reads
+ * for the purposes of ordering by subsequent memory barriers.
+ *
+ * This insanity brought to you by speculative system register reads,
+ * out-of-order memory accesses, sequence locks and Thomas Gleixner.
+ *
+ * http://lists.infradead.org/pipermail/linux-arm-kernel/2019-February/631195.html
+ */
+#define arch_counter_enforce_ordering(val) do { \
+ u64 tmp, _val = (val); \
+ \
+ asm volatile( \
+ " eor %0, %1, %1\n" \
+ " add %0, sp, %0\n" \
+ " ldr xzr, [%0]" \
+ : "=r" (tmp) : "r" (_val)); \
+} while (0)
+
static inline u64 arch_counter_get_cntpct(void)
{
+ u64 cnt;
+
isb();
- return arch_timer_reg_read_stable(cntpct_el0);
+ cnt = arch_timer_reg_read_stable(cntpct_el0);
+ arch_counter_enforce_ordering(cnt);
+ return cnt;
}
static inline u64 arch_counter_get_cntvct(void)
{
+ u64 cnt;
+
isb();
- return arch_timer_reg_read_stable(cntvct_el0);
+ cnt = arch_timer_reg_read_stable(cntvct_el0);
+ arch_counter_enforce_ordering(cnt);
+ return cnt;
}
+#undef arch_counter_enforce_ordering
+
static inline int arch_timer_arch_init(void)
{
return 0;