aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexandru Elisei <alexandru.elisei@arm.com>2020-01-31 16:37:21 +0000
committerAndrew Jones <drjones@redhat.com>2020-04-03 09:40:33 +0200
commit0074eebcb5f40f152b210a9ab6f5394a0ed6e065 (patch)
tree0794ef432c1ebfdd637e8c81f6dc915f4efa77eb
parente14e6ba56f6e9597e774ab0e28f9ba9e5f5a06c9 (diff)
downloadkvm-unit-tests-0074eebcb5f40f152b210a9ab6f5394a0ed6e065.tar.gz
arm64: timer: Add ISB after register writes
From ARM DDI 0487E.a glossary, the section "Context synchronization event": "All direct and indirect writes to System registers that are made before the Context synchronization event affect any instruction, including a direct read, that appears in program order after the instruction causing the Context synchronization event." The ISB instruction is a context synchronization event [1]. Add an ISB after all register writes, to make sure that the writes have been completed when we try to test their effects. [1] ARM DDI 0487E.a, section C6.2.96 Signed-off-by: Alexandru Elisei <alexandru.elisei@arm.com> Signed-off-by: Andrew Jones <drjones@redhat.com>
-rw-r--r--arm/timer.c9
1 files changed, 6 insertions, 3 deletions
diff --git a/arm/timer.c b/arm/timer.c
index f390e8e..c6ea108 100644
--- a/arm/timer.c
+++ b/arm/timer.c
@@ -41,6 +41,7 @@ static u64 read_vtimer_cval(void)
static void write_vtimer_cval(u64 val)
{
write_sysreg(val, cntv_cval_el0);
+ isb();
}
static s32 read_vtimer_tval(void)
@@ -51,6 +52,7 @@ static s32 read_vtimer_tval(void)
static void write_vtimer_tval(s32 val)
{
write_sysreg(val, cntv_tval_el0);
+ isb();
}
static u64 read_vtimer_ctl(void)
@@ -61,6 +63,7 @@ static u64 read_vtimer_ctl(void)
static void write_vtimer_ctl(u64 val)
{
write_sysreg(val, cntv_ctl_el0);
+ isb();
}
static u64 read_ptimer_counter(void)
@@ -76,6 +79,7 @@ static u64 read_ptimer_cval(void)
static void write_ptimer_cval(u64 val)
{
write_sysreg(val, cntp_cval_el0);
+ isb();
}
static s32 read_ptimer_tval(void)
@@ -86,6 +90,7 @@ static s32 read_ptimer_tval(void)
static void write_ptimer_tval(s32 val)
{
write_sysreg(val, cntp_tval_el0);
+ isb();
}
static u64 read_ptimer_ctl(void)
@@ -96,6 +101,7 @@ static u64 read_ptimer_ctl(void)
static void write_ptimer_ctl(u64 val)
{
write_sysreg(val, cntp_ctl_el0);
+ isb();
}
struct timer_info {
@@ -181,7 +187,6 @@ static bool test_cval_10msec(struct timer_info *info)
before_timer = info->read_counter();
info->write_cval(before_timer + time_10ms);
info->write_ctl(ARCH_TIMER_CTL_ENABLE);
- isb();
/* Wait for the timer to fire */
while (!(info->read_ctl() & ARCH_TIMER_CTL_ISTATUS))
@@ -217,11 +222,9 @@ static void test_timer(struct timer_info *info)
/* Enable the timer, but schedule it for much later */
info->write_cval(later);
info->write_ctl(ARCH_TIMER_CTL_ENABLE);
- isb();
report(!gic_timer_pending(info), "not pending before");
info->write_cval(now - 1);
- isb();
report(gic_timer_pending(info), "interrupt signal pending");
/* Disable the timer again and prepare to take interrupts */