From 2c160f9660455930eca7510b5e12af73fec87846 Mon Sep 17 00:00:00 2001 From: whensun Date: Fri, 19 Jun 2026 15:45:44 -0700 Subject: [PATCH] riscv: Fix LR/SC alignment checks --- arch/riscv/translate.c | 45 +++++++++++++++++++++++++++++++++++++++--- 1 file changed, 42 insertions(+), 3 deletions(-) diff --git a/arch/riscv/translate.c b/arch/riscv/translate.c index 7d873ee17..f60a71620 100644 --- a/arch/riscv/translate.c +++ b/arch/riscv/translate.c @@ -2781,6 +2781,45 @@ static void gen_atomic_compare_and_swap(DisasContext *dc, uint32_t opc, TCGv res } } +static void gen_atomic_alignment_check(DisasContext *dc, uint32_t opc, TCGv address) +{ + int aligned = gen_new_label(); + TCGv misalignment = tcg_temp_new(); + int exception = RISCV_EXCP_STORE_AMO_ADDR_MIS; + target_ulong alignment_mask = 0; + + switch(opc) { + case OPC_RISC_LR_W: + exception = RISCV_EXCP_LOAD_ADDR_MIS; + alignment_mask = 0x3; + break; + case OPC_RISC_SC_W: + exception = RISCV_EXCP_STORE_AMO_ADDR_MIS; + alignment_mask = 0x3; + break; +#if defined(TARGET_RISCV64) + case OPC_RISC_LR_D: + exception = RISCV_EXCP_LOAD_ADDR_MIS; + alignment_mask = 0x7; + break; + case OPC_RISC_SC_D: + exception = RISCV_EXCP_STORE_AMO_ADDR_MIS; + alignment_mask = 0x7; + break; +#endif + default: + tcg_temp_free(misalignment); + return; + } + + tcg_gen_andi_tl(misalignment, address, alignment_mask); + tcg_gen_brcondi_tl(TCG_COND_EQ, misalignment, 0, aligned); + generate_exception_mbadaddr(dc, exception); + gen_set_label(aligned); + + tcg_temp_free(misalignment); +} + static void gen_atomic(CPUState *env, DisasContext *dc, uint32_t opc, int rd, int rs1, int rs2) { if(!ensure_extension(dc, RISCV_FEATURE_RVA)) { @@ -2801,8 +2840,10 @@ static void gen_atomic(CPUState *env, DisasContext *dc, uint32_t opc, int rd, in gen_get_gpr(source2, rs2); gen_get_gpr(result, rd); + gen_atomic_alignment_check(dc, opc, source1); + if(rs1 == SP) { - // LR is the only pure read atomic instruciton + // LR is the only pure read atomic instruciton bool is_write = MASK_FUNCT5(opc) != FUNCT5_LR; switch(MASK_FUNCT3(opc)) { case FUNCT3_WORD: @@ -2815,8 +2856,6 @@ static void gen_atomic(CPUState *env, DisasContext *dc, uint32_t opc, int rd, in try_run_pre_stack_access_hook(source1, 128, is_write); break; default: - // Can only happen if the instruction is malformed somehow - // so it will throw an illegal instruction exception later break; } }