From 8380b3a453c38f040e7ca2105418802344cc23d0 Mon Sep 17 00:00:00 2001 From: Jessica Clarke Date: Sat, 18 Jul 2020 01:49:34 +0100 Subject: [PATCH 1/5] goldfish_rtc: Fix non-atomic read behaviour of TIME_LOW/TIME_HIGH The specification says: 0x00 TIME_LOW R: Get current time, then return low-order 32-bits. 0x04 TIME_HIGH R: Return high 32-bits from previous TIME_LOW read. ... To read the value, the kernel must perform an IO_READ(TIME_LOW), which returns an unsigned 32-bit value, before an IO_READ(TIME_HIGH), which returns a signed 32-bit value, corresponding to the higher half of the full value. However, we were just returning the current time for both. If the guest is unlucky enough to read TIME_LOW and TIME_HIGH either side of an overflow of the lower half, it will see time be in the future, before jumping backwards on the next read, and Linux currently relies on the atomicity guaranteed by the spec so is affected by this. Fix this violation of the spec by caching the correct value for TIME_HIGH whenever TIME_LOW is read, and returning that value for any TIME_HIGH read. Signed-off-by: Jessica Clarke Reviewed-by: Peter Maydell Reviewed-by: Richard Henderson Message-Id: <20200718004934.83174-1-jrtc27@jrtc27.com> Signed-off-by: Alistair Francis --- hw/rtc/goldfish_rtc.c | 17 ++++++++++++++--- include/hw/rtc/goldfish_rtc.h | 1 + 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/hw/rtc/goldfish_rtc.c b/hw/rtc/goldfish_rtc.c index 01e9d2b083..6ddd45cce0 100644 --- a/hw/rtc/goldfish_rtc.c +++ b/hw/rtc/goldfish_rtc.c @@ -94,12 +94,22 @@ static uint64_t goldfish_rtc_read(void *opaque, hwaddr offset, GoldfishRTCState *s = opaque; uint64_t r = 0; + /* + * From the documentation linked at the top of the file: + * + * To read the value, the kernel must perform an IO_READ(TIME_LOW), which + * returns an unsigned 32-bit value, before an IO_READ(TIME_HIGH), which + * returns a signed 32-bit value, corresponding to the higher half of the + * full value. + */ switch (offset) { case RTC_TIME_LOW: - r = goldfish_rtc_get_count(s) & 0xffffffff; + r = goldfish_rtc_get_count(s); + s->time_high = r >> 32; + r &= 0xffffffff; break; case RTC_TIME_HIGH: - r = goldfish_rtc_get_count(s) >> 32; + r = s->time_high; break; case RTC_ALARM_LOW: r = s->alarm_next & 0xffffffff; @@ -216,7 +226,7 @@ static const MemoryRegionOps goldfish_rtc_ops = { static const VMStateDescription goldfish_rtc_vmstate = { .name = TYPE_GOLDFISH_RTC, - .version_id = 1, + .version_id = 2, .pre_save = goldfish_rtc_pre_save, .post_load = goldfish_rtc_post_load, .fields = (VMStateField[]) { @@ -225,6 +235,7 @@ static const VMStateDescription goldfish_rtc_vmstate = { VMSTATE_UINT32(alarm_running, GoldfishRTCState), VMSTATE_UINT32(irq_pending, GoldfishRTCState), VMSTATE_UINT32(irq_enabled, GoldfishRTCState), + VMSTATE_UINT32(time_high, GoldfishRTCState), VMSTATE_END_OF_LIST() } }; diff --git a/include/hw/rtc/goldfish_rtc.h b/include/hw/rtc/goldfish_rtc.h index 16f9f9e29d..9bd8924f5f 100644 --- a/include/hw/rtc/goldfish_rtc.h +++ b/include/hw/rtc/goldfish_rtc.h @@ -41,6 +41,7 @@ typedef struct GoldfishRTCState { uint32_t alarm_running; uint32_t irq_pending; uint32_t irq_enabled; + uint32_t time_high; } GoldfishRTCState; #endif From eabfeb0cb9e054108b3e29a3a85363b3d80d9c38 Mon Sep 17 00:00:00 2001 From: LIU Zhiwei Date: Tue, 21 Jul 2020 21:37:41 +0800 Subject: [PATCH 2/5] target/riscv: Quiet Coverity complains about vamo* Signed-off-by: LIU Zhiwei Reviewed-by: Alistair Francis Message-Id: <20200721133742.2298-1-zhiwei_liu@c-sky.com> Signed-off-by: Alistair Francis --- target/riscv/insn_trans/trans_rvv.inc.c | 1 + 1 file changed, 1 insertion(+) diff --git a/target/riscv/insn_trans/trans_rvv.inc.c b/target/riscv/insn_trans/trans_rvv.inc.c index c0b7375927..7b4752b911 100644 --- a/target/riscv/insn_trans/trans_rvv.inc.c +++ b/target/riscv/insn_trans/trans_rvv.inc.c @@ -733,6 +733,7 @@ static bool amo_op(DisasContext *s, arg_rwdvm *a, uint8_t seq) g_assert_not_reached(); #endif } else { + assert(seq < ARRAY_SIZE(fnsw)); fn = fnsw[seq]; } } From 3e09396e36dff4234afd6f6fd51861949be383e1 Mon Sep 17 00:00:00 2001 From: LIU Zhiwei Date: Tue, 21 Jul 2020 21:37:42 +0800 Subject: [PATCH 3/5] target/riscv: fix vector index load/store constraints Although not explicitly specified that the the destination vector register groups cannot overlap the source vector register group, it is still necessary. And this constraint has been added to the v0.8 spec. Signed-off-by: LIU Zhiwei Reviewed-by: Alistair Francis Message-Id: <20200721133742.2298-2-zhiwei_liu@c-sky.com> Signed-off-by: Alistair Francis --- target/riscv/insn_trans/trans_rvv.inc.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/target/riscv/insn_trans/trans_rvv.inc.c b/target/riscv/insn_trans/trans_rvv.inc.c index 7b4752b911..887c6b8883 100644 --- a/target/riscv/insn_trans/trans_rvv.inc.c +++ b/target/riscv/insn_trans/trans_rvv.inc.c @@ -513,13 +513,21 @@ static bool ld_index_op(DisasContext *s, arg_rnfvm *a, uint8_t seq) return ldst_index_trans(a->rd, a->rs1, a->rs2, data, fn, s); } +/* + * For vector indexed segment loads, the destination vector register + * groups cannot overlap the source vector register group (specified by + * `vs2`), else an illegal instruction exception is raised. + */ static bool ld_index_check(DisasContext *s, arg_rnfvm* a) { return (vext_check_isa_ill(s) && vext_check_overlap_mask(s, a->rd, a->vm, false) && vext_check_reg(s, a->rd, false) && vext_check_reg(s, a->rs2, false) && - vext_check_nf(s, a->nf)); + vext_check_nf(s, a->nf) && + ((a->nf == 1) || + vext_check_overlap_group(a->rd, a->nf << s->lmul, + a->rs2, 1 << s->lmul))); } GEN_VEXT_TRANS(vlxb_v, 0, rnfvm, ld_index_op, ld_index_check) From e79d27cb322b60b460b709d2c74ff7d77cde0565 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Thu, 16 Jul 2020 02:30:56 -0700 Subject: [PATCH 4/5] hw/riscv: sifive_e: Correct debug block size Currently the debug region size is set to 0x100, but according to FE310-G000 and FE310-G002 manuals: FE310-G000: 0x100 - 0xFFF FE310-G002: 0x0 - 0xFFF Change the size to 0x1000 that applies to both. Signed-off-by: Bin Meng Reviewed-by: Alistair Francis Message-Id: <1594891856-15474-1-git-send-email-bmeng.cn@gmail.com> Signed-off-by: Alistair Francis --- hw/riscv/sifive_e.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/riscv/sifive_e.c b/hw/riscv/sifive_e.c index 7bb97b463d..c8b060486a 100644 --- a/hw/riscv/sifive_e.c +++ b/hw/riscv/sifive_e.c @@ -54,7 +54,7 @@ static const struct MemmapEntry { hwaddr base; hwaddr size; } sifive_e_memmap[] = { - [SIFIVE_E_DEBUG] = { 0x0, 0x100 }, + [SIFIVE_E_DEBUG] = { 0x0, 0x1000 }, [SIFIVE_E_MROM] = { 0x1000, 0x2000 }, [SIFIVE_E_OTP] = { 0x20000, 0x2000 }, [SIFIVE_E_CLINT] = { 0x2000000, 0x10000 }, From 8ba26b0b2b00dd5849a6c0981e358dc7a7cc315d Mon Sep 17 00:00:00 2001 From: Zong Li Date: Tue, 21 Jul 2020 20:40:50 +0800 Subject: [PATCH 5/5] target/riscv: Fix the range of pmpcfg of CSR funcion table The range of Physical Memory Protection should be from CSR_PMPCFG0 to CSR_PMPCFG3, not to CSR_PMPADDR9. Signed-off-by: Zong Li Reviewed-by: Alistair Francis Reviewed-by: Bin Meng Message-Id: Signed-off-by: Alistair Francis --- target/riscv/csr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target/riscv/csr.c b/target/riscv/csr.c index ac01c835e1..6a96a01b1c 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -1353,7 +1353,7 @@ static riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = { [CSR_MTINST] = { hmode, read_mtinst, write_mtinst }, /* Physical Memory Protection */ - [CSR_PMPCFG0 ... CSR_PMPADDR9] = { pmp, read_pmpcfg, write_pmpcfg }, + [CSR_PMPCFG0 ... CSR_PMPCFG3] = { pmp, read_pmpcfg, write_pmpcfg }, [CSR_PMPADDR0 ... CSR_PMPADDR15] = { pmp, read_pmpaddr, write_pmpaddr }, /* Performance Counters */