mirror of https://github.com/xemu-project/xemu.git
hw/intc: Support 32/64-bit mtimecmp and mtime accesses in RISC-V ACLINT
RISC-V privilege spec defines that: * In RV32, memory-mapped writes to mtimecmp modify only one 32-bit part of the register. * For RV64, naturally aligned 64-bit memory accesses to the mtime and mtimecmp registers are additionally supported and are atomic. It's possible to perform both 32/64-bit read/write accesses to both mtimecmp and mtime registers. Signed-off-by: Frank Chang <frank.chang@sifive.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Reviewed-by: Jim Shu <jim.shu@sifive.com> Message-Id: <20220420080901.14655-3-frank.chang@sifive.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
This commit is contained in:
parent
231a90c085
commit
d42df0ea5d
hw/intc
|
@ -126,9 +126,9 @@ static uint64_t riscv_aclint_mtimer_read(void *opaque, hwaddr addr,
|
|||
qemu_log_mask(LOG_GUEST_ERROR,
|
||||
"aclint-mtimer: invalid hartid: %zu", hartid);
|
||||
} else if ((addr & 0x7) == 0) {
|
||||
/* timecmp_lo */
|
||||
/* timecmp_lo for RV32/RV64 or timecmp for RV64 */
|
||||
uint64_t timecmp = env->timecmp;
|
||||
return timecmp & 0xFFFFFFFF;
|
||||
return (size == 4) ? (timecmp & 0xFFFFFFFF) : timecmp;
|
||||
} else if ((addr & 0x7) == 4) {
|
||||
/* timecmp_hi */
|
||||
uint64_t timecmp = env->timecmp;
|
||||
|
@ -139,8 +139,9 @@ static uint64_t riscv_aclint_mtimer_read(void *opaque, hwaddr addr,
|
|||
return 0;
|
||||
}
|
||||
} else if (addr == mtimer->time_base) {
|
||||
/* time_lo */
|
||||
return cpu_riscv_read_rtc(mtimer->timebase_freq) & 0xFFFFFFFF;
|
||||
/* time_lo for RV32/RV64 or timecmp for RV64 */
|
||||
uint64_t rtc = cpu_riscv_read_rtc(mtimer->timebase_freq);
|
||||
return (size == 4) ? (rtc & 0xFFFFFFFF) : rtc;
|
||||
} else if (addr == mtimer->time_base + 4) {
|
||||
/* time_hi */
|
||||
return (cpu_riscv_read_rtc(mtimer->timebase_freq) >> 32) & 0xFFFFFFFF;
|
||||
|
@ -167,18 +168,29 @@ static void riscv_aclint_mtimer_write(void *opaque, hwaddr addr,
|
|||
qemu_log_mask(LOG_GUEST_ERROR,
|
||||
"aclint-mtimer: invalid hartid: %zu", hartid);
|
||||
} else if ((addr & 0x7) == 0) {
|
||||
/* timecmp_lo */
|
||||
uint64_t timecmp_hi = env->timecmp >> 32;
|
||||
riscv_aclint_mtimer_write_timecmp(mtimer, RISCV_CPU(cpu), hartid,
|
||||
timecmp_hi << 32 | (value & 0xFFFFFFFF),
|
||||
mtimer->timebase_freq);
|
||||
return;
|
||||
if (size == 4) {
|
||||
/* timecmp_lo for RV32/RV64 */
|
||||
uint64_t timecmp_hi = env->timecmp >> 32;
|
||||
riscv_aclint_mtimer_write_timecmp(mtimer, RISCV_CPU(cpu), hartid,
|
||||
timecmp_hi << 32 | (value & 0xFFFFFFFF),
|
||||
mtimer->timebase_freq);
|
||||
} else {
|
||||
/* timecmp for RV64 */
|
||||
riscv_aclint_mtimer_write_timecmp(mtimer, RISCV_CPU(cpu), hartid,
|
||||
value, mtimer->timebase_freq);
|
||||
}
|
||||
} else if ((addr & 0x7) == 4) {
|
||||
/* timecmp_hi */
|
||||
uint64_t timecmp_lo = env->timecmp;
|
||||
riscv_aclint_mtimer_write_timecmp(mtimer, RISCV_CPU(cpu), hartid,
|
||||
value << 32 | (timecmp_lo & 0xFFFFFFFF),
|
||||
mtimer->timebase_freq);
|
||||
if (size == 4) {
|
||||
/* timecmp_hi for RV32/RV64 */
|
||||
uint64_t timecmp_lo = env->timecmp;
|
||||
riscv_aclint_mtimer_write_timecmp(mtimer, RISCV_CPU(cpu), hartid,
|
||||
value << 32 | (timecmp_lo & 0xFFFFFFFF),
|
||||
mtimer->timebase_freq);
|
||||
} else {
|
||||
qemu_log_mask(LOG_GUEST_ERROR,
|
||||
"aclint-mtimer: invalid timecmp_hi write: %08x",
|
||||
(uint32_t)addr);
|
||||
}
|
||||
} else {
|
||||
qemu_log_mask(LOG_UNIMP,
|
||||
"aclint-mtimer: invalid timecmp write: %08x",
|
||||
|
|
Loading…
Reference in New Issue