RISC-V: Fix CLINT timecmp low 32-bit writes

A missing shift made updates to the low order bits
of timecmp erroneously copy the old low order bits
into the high order bits of the 64-bit timecmp
register. Add the missing shift and rename timecmp
local variables to timecmp_hi and timecmp_lo.

This bug didn't show up as the low order bits are
usually written first followed by the high order
bits meaning the high order bits contained an invalid
value between the timecmp_lo and timecmp_hi update.

Cc: Palmer Dabbelt <palmer@sifive.com>
Cc: Sagar Karandikar <sagark@eecs.berkeley.edu>
Cc: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
Cc: Alistair Francis <Alistair.Francis@wdc.com>
Co-Authored-by: Johannes Haring <johannes.haring@gmx.net>
Signed-off-by: Michael Clark <mjc@sifive.com>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
Signed-off-by: Palmer Dabbelt <palmer@sifive.com>
This commit is contained in:
Michael Clark 2018-12-14 00:18:39 +00:00 committed by Palmer Dabbelt
parent 9543fdaf22
commit ef9e41df68
No known key found for this signature in database
GPG Key ID: EF4CA1502CCBAB41
1 changed files with 4 additions and 4 deletions

View File

@ -146,15 +146,15 @@ static void sifive_clint_write(void *opaque, hwaddr addr, uint64_t value,
error_report("clint: invalid timecmp hartid: %zu", hartid);
} else if ((addr & 0x7) == 0) {
/* timecmp_lo */
uint64_t timecmp = env->timecmp;
uint64_t timecmp_hi = env->timecmp >> 32;
sifive_clint_write_timecmp(RISCV_CPU(cpu),
timecmp << 32 | (value & 0xFFFFFFFF));
timecmp_hi << 32 | (value & 0xFFFFFFFF));
return;
} else if ((addr & 0x7) == 4) {
/* timecmp_hi */
uint64_t timecmp = env->timecmp;
uint64_t timecmp_lo = env->timecmp;
sifive_clint_write_timecmp(RISCV_CPU(cpu),
value << 32 | (timecmp & 0xFFFFFFFF));
value << 32 | (timecmp_lo & 0xFFFFFFFF));
} else {
error_report("clint: invalid timecmp write: %08x", (uint32_t)addr);
}