diff options
author | Richard Henderson <richard.henderson@linaro.org> | 2025-03-11 18:34:58 -0700 |
---|---|---|
committer | Richard Henderson <richard.henderson@linaro.org> | 2025-04-23 14:08:17 -0700 |
commit | 6a9dfe1984b0c593fb0ddb52d4e70832e6201dd6 (patch) | |
tree | 07a85614c4d3da1c1733303b014474dd06263b73 | |
parent | 4ba597c138306450e7fcc50d2dba3bfdad8478c8 (diff) | |
download | qemu-6a9dfe1984b0c593fb0ddb52d4e70832e6201dd6.zip qemu-6a9dfe1984b0c593fb0ddb52d4e70832e6201dd6.tar.gz qemu-6a9dfe1984b0c593fb0ddb52d4e70832e6201dd6.tar.bz2 |
accel/tcg: Perform aligned atomic reads in translator_ld
Perform aligned atomic reads in translator_ld, if possible.
According to
https://lore.kernel.org/qemu-devel/20240607101403.1109-1-jim.shu@sifive.com/
this is required for RISC-V Ziccif.
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
-rw-r--r-- | accel/tcg/translator.c | 42 |
1 files changed, 38 insertions, 4 deletions
diff --git a/accel/tcg/translator.c b/accel/tcg/translator.c index ef1538b..157be33 100644 --- a/accel/tcg/translator.c +++ b/accel/tcg/translator.c @@ -265,12 +265,14 @@ static bool translator_ld(CPUArchState *env, DisasContextBase *db, if (likely(((base ^ last) & TARGET_PAGE_MASK) == 0)) { /* Entire read is from the first page. */ - memcpy(dest, host + (pc - base), len); - return true; + goto do_read; } if (unlikely(((base ^ pc) & TARGET_PAGE_MASK) == 0)) { - /* Read begins on the first page and extends to the second. */ + /* + * Read begins on the first page and extends to the second. + * The unaligned read is never atomic. + */ size_t len0 = -(pc | TARGET_PAGE_MASK); memcpy(dest, host + (pc - base), len0); pc += len0; @@ -329,7 +331,39 @@ static bool translator_ld(CPUArchState *env, DisasContextBase *db, host = db->host_addr[1]; } - memcpy(dest, host + (pc - base), len); + do_read: + /* + * Assume aligned reads should be atomic, if possible. + * We're not in a position to jump out with EXCP_ATOMIC. + */ + host += pc - base; + switch (len) { + case 2: + if (QEMU_IS_ALIGNED(pc, 2)) { + uint16_t t = qatomic_read((uint16_t *)host); + stw_he_p(dest, t); + return true; + } + break; + case 4: + if (QEMU_IS_ALIGNED(pc, 4)) { + uint32_t t = qatomic_read((uint32_t *)host); + stl_he_p(dest, t); + return true; + } + break; +#ifdef CONFIG_ATOMIC64 + case 8: + if (QEMU_IS_ALIGNED(pc, 8)) { + uint64_t t = qatomic_read__nocheck((uint64_t *)host); + stq_he_p(dest, t); + return true; + } + break; +#endif + } + /* Unaligned or partial read from the second page is not atomic. */ + memcpy(dest, host, len); return true; } |