Message ID | 20240412021509.145502-1-richard.henderson@linaro.org |
---|---|
State | Superseded |
Headers | show |
Series | target/sparc: Use GET_ASI_CODE for ASI_KERNELTXT and ASI_USERTXT | expand |
On Thu, Apr 11, 2024, 10:15 PM Richard Henderson < richard.henderson@linaro.org> wrote: > Reads are done with execute access. It is not clear whether writes > are legal at all -- for now, leave helper_st_asi unchanged, so that > we continue to raise an mmu fault. > > This generalizes the exiting code for ASI_KERNELTXT to be usable for > ASI_USERTXT as well, by passing down the MemOpIdx to use. > > Resolves: https://gitlab.com/qemu-project/qemu/-/issues/2281 > Resolves: https://gitlab.com/qemu-project/qemu/-/issues/2059 > Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1609 > Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1166 > Signed-off-by: Richard Henderson <richard.henderson@linaro.org> > --- > target/sparc/helper.h | 3 ++ > target/sparc/ldst_helper.c | 65 ++++++++++++++++++++++++++------------ > target/sparc/translate.c | 49 ++++++++++++++++++++++++++-- > 3 files changed, 95 insertions(+), 22 deletions(-) > > diff --git a/target/sparc/helper.h b/target/sparc/helper.h > index e55fad5b8c..b8087d0d2b 100644 > --- a/target/sparc/helper.h > +++ b/target/sparc/helper.h > @@ -32,6 +32,9 @@ DEF_HELPER_FLAGS_3(udiv, TCG_CALL_NO_WG, i64, env, tl, > tl) > DEF_HELPER_FLAGS_3(sdiv, TCG_CALL_NO_WG, i64, env, tl, tl) > DEF_HELPER_3(taddcctv, tl, env, tl, tl) > DEF_HELPER_3(tsubcctv, tl, env, tl, tl) > +#if !defined(CONFIG_USER_ONLY) && !defined(TARGET_SPARC64) > +DEF_HELPER_FLAGS_3(ld_code, TCG_CALL_NO_WG, i64, env, tl, i32) > +#endif > #if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64) > DEF_HELPER_FLAGS_4(ld_asi, TCG_CALL_NO_WG, i64, env, tl, int, i32) > DEF_HELPER_FLAGS_5(st_asi, TCG_CALL_NO_WG, void, env, tl, i64, int, i32) > diff --git a/target/sparc/ldst_helper.c b/target/sparc/ldst_helper.c > index e581bb42ac..2846a86cc4 100644 > --- a/target/sparc/ldst_helper.c > +++ b/target/sparc/ldst_helper.c > @@ -585,7 +585,6 @@ uint64_t helper_ld_asi(CPUSPARCState *env, > target_ulong addr, > #if defined(DEBUG_MXCC) || defined(DEBUG_ASI) > uint32_t last_addr = addr; > #endif > - MemOpIdx oi; > > do_check_align(env, addr, size - 1, GETPC()); > switch (asi) { > @@ -684,24 +683,6 @@ uint64_t helper_ld_asi(CPUSPARCState *env, > target_ulong addr, > case ASI_M_DIAGS: /* Turbosparc DTLB Diagnostic */ > case ASI_M_IODIAG: /* Turbosparc IOTLB Diagnostic */ > break; > - case ASI_KERNELTXT: /* Supervisor code access */ > - oi = make_memop_idx(memop, cpu_mmu_index(env_cpu(env), true)); > - switch (size) { > - case 1: > - ret = cpu_ldb_code_mmu(env, addr, oi, GETPC()); > - break; > - case 2: > - ret = cpu_ldw_code_mmu(env, addr, oi, GETPC()); > - break; > - default: > - case 4: > - ret = cpu_ldl_code_mmu(env, addr, oi, GETPC()); > - break; > - case 8: > - ret = cpu_ldq_code_mmu(env, addr, oi, GETPC()); > - break; > - } > - break; > case ASI_M_TXTC_TAG: /* SparcStation 5 I-cache tag */ > case ASI_M_TXTC_DATA: /* SparcStation 5 I-cache data */ > case ASI_M_DATAC_TAG: /* SparcStation 5 D-cache tag */ > @@ -779,7 +760,6 @@ uint64_t helper_ld_asi(CPUSPARCState *env, > target_ulong addr, > case 0x4c: /* SuperSPARC MMU Breakpoint Action */ > ret = env->mmubpaction; > break; > - case ASI_USERTXT: /* User code access, XXX */ > default: > sparc_raise_mmu_fault(cs, addr, false, false, asi, size, GETPC()); > ret = 0; > @@ -787,6 +767,8 @@ uint64_t helper_ld_asi(CPUSPARCState *env, > target_ulong addr, > > case ASI_USERDATA: /* User data access */ > case ASI_KERNELDATA: /* Supervisor data access */ > + case ASI_USERTXT: /* User code access */ > + case ASI_KERNELTXT: /* Supervisor code access */ > case ASI_P: /* Implicit primary context data access (v9 only?) */ > case ASI_M_BYPASS: /* MMU passthrough */ > case ASI_LEON_BYPASS: /* LEON MMU passthrough */ > @@ -1161,6 +1143,49 @@ void helper_st_asi(CPUSPARCState *env, target_ulong > addr, uint64_t val, > #endif > } > > +uint64_t helper_ld_code(CPUSPARCState *env, target_ulong addr, uint32_t > oi) > +{ > + MemOp mop = get_memop(oi); > + uintptr_t ra = GETPC(); > + uint64_t ret; > + > + switch (mop & MO_SIZE) { > + case MO_8: > + ret = cpu_ldb_code_mmu(env, addr, oi, ra); > + if (mop & MO_SIGN) { > + ret = (int8_t)ret; > + } > + break; > + case MO_16: > + ret = cpu_ldw_code_mmu(env, addr, oi, ra); > + if ((mop & MO_BSWAP) != MO_TE) { > + ret = bswap16(ret); > + } > + if (mop & MO_SIGN) { > + ret = (int16_t)ret; > + } > + break; > + case MO_32: > + ret = cpu_ldl_code_mmu(env, addr, oi, ra); > + if ((mop & MO_BSWAP) != MO_TE) { > + ret = bswap32(ret); > + } > + if (mop & MO_SIGN) { > + ret = (int32_t)ret; > + } > + break; > + case MO_64: > + ret = cpu_ldq_code_mmu(env, addr, oi, ra); > + if ((mop & MO_BSWAP) != MO_TE) { > + ret = bswap64(ret); > + } > + break; > + default: > + g_assert_not_reached(); > + } > + return ret; > +} > + > #endif /* CONFIG_USER_ONLY */ > #else /* TARGET_SPARC64 */ > > diff --git a/target/sparc/translate.c b/target/sparc/translate.c > index 319934d9bd..c9b9b047df 100644 > --- a/target/sparc/translate.c > +++ b/target/sparc/translate.c > @@ -1117,6 +1117,7 @@ typedef enum { > GET_ASI_EXCP, > GET_ASI_DIRECT, > GET_ASI_DTWINX, > + GET_ASI_CODE, > GET_ASI_BLOCK, > GET_ASI_SHORT, > GET_ASI_BCOPY, > @@ -1159,14 +1160,22 @@ static DisasASI resolve_asi(DisasContext *dc, int > asi, MemOp memop) > || (asi == ASI_USERDATA > && (dc->def->features & CPU_FEATURE_CASA))) { > switch (asi) { > - case ASI_USERDATA: /* User data access */ > + case ASI_USERDATA: /* User data access */ > mem_idx = MMU_USER_IDX; > type = GET_ASI_DIRECT; > break; > - case ASI_KERNELDATA: /* Supervisor data access */ > + case ASI_KERNELDATA: /* Supervisor data access */ > mem_idx = MMU_KERNEL_IDX; > type = GET_ASI_DIRECT; > break; > + case ASI_USERTXT: /* User text access */ > + mem_idx = MMU_USER_IDX; > + type = GET_ASI_CODE; > + break; > + case ASI_KERNELTXT: /* Supervisor text access */ > + mem_idx = MMU_KERNEL_IDX; > + type = GET_ASI_CODE; > + break; > case ASI_M_BYPASS: /* MMU passthrough */ > case ASI_LEON_BYPASS: /* LEON MMU passthrough */ > mem_idx = MMU_PHYS_IDX; > @@ -1379,6 +1388,22 @@ static void gen_ld_asi(DisasContext *dc, DisasASI > *da, TCGv dst, TCGv addr) > case GET_ASI_DIRECT: > tcg_gen_qemu_ld_tl(dst, addr, da->mem_idx, da->memop | MO_ALIGN); > break; > + > + case GET_ASI_CODE: > +#if !defined(CONFIG_USER_ONLY) && !defined(TARGET_SPARC64) > + { > + MemOpIdx oi = make_memop_idx(da->memop, da->mem_idx); > + TCGv_i32 r_oi = tcg_constant_i32(oi); > + TCGv_i64 t64 = tcg_temp_new_i64(); > + > + gen_helper_ld_code(t64, tcg_env, addr, r_oi); > + tcg_gen_trunc_i64_tl(dst, t64); > + } > + break; > +#else > + g_assert_not_reached(); > +#endif > + > default: > { > TCGv_i32 r_asi = tcg_constant_i32(da->asi); > @@ -1791,6 +1816,26 @@ static void gen_ldda_asi(DisasContext *dc, DisasASI > *da, TCGv addr, int rd) > } > break; > > + case GET_ASI_CODE: > +#if !defined(CONFIG_USER_ONLY) && !defined(TARGET_SPARC64) > + { > + TCGv_i64 tmp = tcg_temp_new_i64(); > + MemOpIdx oi = make_memop_idx(da->memop, da->mem_idx); > + > + gen_helper_ld_code(tmp, tcg_env, addr, tcg_constant_i32(oi)); > + > + /* See above. */ > + if ((da->memop & MO_BSWAP) == MO_TE) { > + tcg_gen_extr_i64_tl(lo, hi, tmp); > + } else { > + tcg_gen_extr_i64_tl(hi, lo, tmp); > + } > + } > + break; > +#else > + g_assert_not_reached(); > +#endif > + > default: > /* ??? In theory we've handled all of the ASIs that are valid > for ldda, and this should raise DAE_invalid_asi. However, > -- > 2.34.1 > Hi Richard, I see this is in your hands now. I agree with your take on leaving writes alone. I'm also grateful for the opportunity to collaborate with you. It brings a smile for the community members who will be touched by this amazing contribution. I see them happily realizing that this perplexing bug has been solved, and in our case finally able to use the debuggers we love! :D Thanks for the proper fix, qemu sensei! -bazz >
Hi Bazz, On 12/4/24 06:18, M Bazz wrote: > On Thu, Apr 11, 2024, 10:15 PM Richard Henderson > <richard.henderson@linaro.org <mailto:richard.henderson@linaro.org>> wrote: > > Reads are done with execute access. It is not clear whether writes > are legal at all -- for now, leave helper_st_asi unchanged, so that > we continue to raise an mmu fault. > > This generalizes the exiting code for ASI_KERNELTXT to be usable for > ASI_USERTXT as well, by passing down the MemOpIdx to use. > > Resolves: https://gitlab.com/qemu-project/qemu/-/issues/2281 > <https://gitlab.com/qemu-project/qemu/-/issues/2281> > Resolves: https://gitlab.com/qemu-project/qemu/-/issues/2059 > <https://gitlab.com/qemu-project/qemu/-/issues/2059> > Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1609 > <https://gitlab.com/qemu-project/qemu/-/issues/1609> > Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1166 > <https://gitlab.com/qemu-project/qemu/-/issues/1166> > Signed-off-by: Richard Henderson <richard.henderson@linaro.org > <mailto:richard.henderson@linaro.org>> > --- > target/sparc/helper.h | 3 ++ > target/sparc/ldst_helper.c | 65 ++++++++++++++++++++++++++------------ > target/sparc/translate.c | 49 ++++++++++++++++++++++++++-- > 3 files changed, 95 insertions(+), 22 deletions(-) > Hi Richard, > > I see this is in your hands now. I agree with your take on leaving > writes alone. I'm also grateful for the opportunity to collaborate with you. > > It brings a smile for the community members who will be touched by this > amazing contribution. I see them happily realizing that this perplexing > bug has been solved, and in our case finally able to use the debuggers > we love! :D Does that mean you tested this patch and it resolves your issues? If so, could you add your 'Tested-by: M Bazz <bazz@bazz1.com>' tag when committing this patch? Regards, Phil. > Thanks for the proper fix, qemu sensei! > > -bazz >
On 12/04/2024 03:15, Richard Henderson wrote: > Reads are done with execute access. It is not clear whether writes > are legal at all -- for now, leave helper_st_asi unchanged, so that > we continue to raise an mmu fault. > > This generalizes the exiting code for ASI_KERNELTXT to be usable for > ASI_USERTXT as well, by passing down the MemOpIdx to use. > > Resolves: https://gitlab.com/qemu-project/qemu/-/issues/2281 > Resolves: https://gitlab.com/qemu-project/qemu/-/issues/2059 > Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1609 > Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1166 > Signed-off-by: Richard Henderson <richard.henderson@linaro.org> > --- > target/sparc/helper.h | 3 ++ > target/sparc/ldst_helper.c | 65 ++++++++++++++++++++++++++------------ > target/sparc/translate.c | 49 ++++++++++++++++++++++++++-- > 3 files changed, 95 insertions(+), 22 deletions(-) > > diff --git a/target/sparc/helper.h b/target/sparc/helper.h > index e55fad5b8c..b8087d0d2b 100644 > --- a/target/sparc/helper.h > +++ b/target/sparc/helper.h > @@ -32,6 +32,9 @@ DEF_HELPER_FLAGS_3(udiv, TCG_CALL_NO_WG, i64, env, tl, tl) > DEF_HELPER_FLAGS_3(sdiv, TCG_CALL_NO_WG, i64, env, tl, tl) > DEF_HELPER_3(taddcctv, tl, env, tl, tl) > DEF_HELPER_3(tsubcctv, tl, env, tl, tl) > +#if !defined(CONFIG_USER_ONLY) && !defined(TARGET_SPARC64) > +DEF_HELPER_FLAGS_3(ld_code, TCG_CALL_NO_WG, i64, env, tl, i32) > +#endif > #if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64) > DEF_HELPER_FLAGS_4(ld_asi, TCG_CALL_NO_WG, i64, env, tl, int, i32) > DEF_HELPER_FLAGS_5(st_asi, TCG_CALL_NO_WG, void, env, tl, i64, int, i32) > diff --git a/target/sparc/ldst_helper.c b/target/sparc/ldst_helper.c > index e581bb42ac..2846a86cc4 100644 > --- a/target/sparc/ldst_helper.c > +++ b/target/sparc/ldst_helper.c > @@ -585,7 +585,6 @@ uint64_t helper_ld_asi(CPUSPARCState *env, target_ulong addr, > #if defined(DEBUG_MXCC) || defined(DEBUG_ASI) > uint32_t last_addr = addr; > #endif > - MemOpIdx oi; > > do_check_align(env, addr, size - 1, GETPC()); > switch (asi) { > @@ -684,24 +683,6 @@ uint64_t helper_ld_asi(CPUSPARCState *env, target_ulong addr, > case ASI_M_DIAGS: /* Turbosparc DTLB Diagnostic */ > case ASI_M_IODIAG: /* Turbosparc IOTLB Diagnostic */ > break; > - case ASI_KERNELTXT: /* Supervisor code access */ > - oi = make_memop_idx(memop, cpu_mmu_index(env_cpu(env), true)); > - switch (size) { > - case 1: > - ret = cpu_ldb_code_mmu(env, addr, oi, GETPC()); > - break; > - case 2: > - ret = cpu_ldw_code_mmu(env, addr, oi, GETPC()); > - break; > - default: > - case 4: > - ret = cpu_ldl_code_mmu(env, addr, oi, GETPC()); > - break; > - case 8: > - ret = cpu_ldq_code_mmu(env, addr, oi, GETPC()); > - break; > - } > - break; > case ASI_M_TXTC_TAG: /* SparcStation 5 I-cache tag */ > case ASI_M_TXTC_DATA: /* SparcStation 5 I-cache data */ > case ASI_M_DATAC_TAG: /* SparcStation 5 D-cache tag */ > @@ -779,7 +760,6 @@ uint64_t helper_ld_asi(CPUSPARCState *env, target_ulong addr, > case 0x4c: /* SuperSPARC MMU Breakpoint Action */ > ret = env->mmubpaction; > break; > - case ASI_USERTXT: /* User code access, XXX */ > default: > sparc_raise_mmu_fault(cs, addr, false, false, asi, size, GETPC()); > ret = 0; > @@ -787,6 +767,8 @@ uint64_t helper_ld_asi(CPUSPARCState *env, target_ulong addr, > > case ASI_USERDATA: /* User data access */ > case ASI_KERNELDATA: /* Supervisor data access */ > + case ASI_USERTXT: /* User code access */ > + case ASI_KERNELTXT: /* Supervisor code access */ > case ASI_P: /* Implicit primary context data access (v9 only?) */ > case ASI_M_BYPASS: /* MMU passthrough */ > case ASI_LEON_BYPASS: /* LEON MMU passthrough */ > @@ -1161,6 +1143,49 @@ void helper_st_asi(CPUSPARCState *env, target_ulong addr, uint64_t val, > #endif > } > > +uint64_t helper_ld_code(CPUSPARCState *env, target_ulong addr, uint32_t oi) > +{ > + MemOp mop = get_memop(oi); > + uintptr_t ra = GETPC(); > + uint64_t ret; > + > + switch (mop & MO_SIZE) { > + case MO_8: > + ret = cpu_ldb_code_mmu(env, addr, oi, ra); > + if (mop & MO_SIGN) { > + ret = (int8_t)ret; > + } > + break; > + case MO_16: > + ret = cpu_ldw_code_mmu(env, addr, oi, ra); > + if ((mop & MO_BSWAP) != MO_TE) { > + ret = bswap16(ret); > + } > + if (mop & MO_SIGN) { > + ret = (int16_t)ret; > + } > + break; > + case MO_32: > + ret = cpu_ldl_code_mmu(env, addr, oi, ra); > + if ((mop & MO_BSWAP) != MO_TE) { > + ret = bswap32(ret); > + } > + if (mop & MO_SIGN) { > + ret = (int32_t)ret; > + } > + break; > + case MO_64: > + ret = cpu_ldq_code_mmu(env, addr, oi, ra); > + if ((mop & MO_BSWAP) != MO_TE) { > + ret = bswap64(ret); > + } > + break; > + default: > + g_assert_not_reached(); > + } > + return ret; > +} > + > #endif /* CONFIG_USER_ONLY */ > #else /* TARGET_SPARC64 */ > > diff --git a/target/sparc/translate.c b/target/sparc/translate.c > index 319934d9bd..c9b9b047df 100644 > --- a/target/sparc/translate.c > +++ b/target/sparc/translate.c > @@ -1117,6 +1117,7 @@ typedef enum { > GET_ASI_EXCP, > GET_ASI_DIRECT, > GET_ASI_DTWINX, > + GET_ASI_CODE, > GET_ASI_BLOCK, > GET_ASI_SHORT, > GET_ASI_BCOPY, > @@ -1159,14 +1160,22 @@ static DisasASI resolve_asi(DisasContext *dc, int asi, MemOp memop) > || (asi == ASI_USERDATA > && (dc->def->features & CPU_FEATURE_CASA))) { > switch (asi) { > - case ASI_USERDATA: /* User data access */ > + case ASI_USERDATA: /* User data access */ > mem_idx = MMU_USER_IDX; > type = GET_ASI_DIRECT; > break; > - case ASI_KERNELDATA: /* Supervisor data access */ > + case ASI_KERNELDATA: /* Supervisor data access */ > mem_idx = MMU_KERNEL_IDX; > type = GET_ASI_DIRECT; > break; > + case ASI_USERTXT: /* User text access */ > + mem_idx = MMU_USER_IDX; > + type = GET_ASI_CODE; > + break; > + case ASI_KERNELTXT: /* Supervisor text access */ > + mem_idx = MMU_KERNEL_IDX; > + type = GET_ASI_CODE; > + break; > case ASI_M_BYPASS: /* MMU passthrough */ > case ASI_LEON_BYPASS: /* LEON MMU passthrough */ > mem_idx = MMU_PHYS_IDX; > @@ -1379,6 +1388,22 @@ static void gen_ld_asi(DisasContext *dc, DisasASI *da, TCGv dst, TCGv addr) > case GET_ASI_DIRECT: > tcg_gen_qemu_ld_tl(dst, addr, da->mem_idx, da->memop | MO_ALIGN); > break; > + > + case GET_ASI_CODE: > +#if !defined(CONFIG_USER_ONLY) && !defined(TARGET_SPARC64) > + { > + MemOpIdx oi = make_memop_idx(da->memop, da->mem_idx); > + TCGv_i32 r_oi = tcg_constant_i32(oi); > + TCGv_i64 t64 = tcg_temp_new_i64(); > + > + gen_helper_ld_code(t64, tcg_env, addr, r_oi); > + tcg_gen_trunc_i64_tl(dst, t64); > + } > + break; > +#else > + g_assert_not_reached(); > +#endif > + > default: > { > TCGv_i32 r_asi = tcg_constant_i32(da->asi); > @@ -1791,6 +1816,26 @@ static void gen_ldda_asi(DisasContext *dc, DisasASI *da, TCGv addr, int rd) > } > break; > > + case GET_ASI_CODE: > +#if !defined(CONFIG_USER_ONLY) && !defined(TARGET_SPARC64) > + { > + TCGv_i64 tmp = tcg_temp_new_i64(); > + MemOpIdx oi = make_memop_idx(da->memop, da->mem_idx); > + > + gen_helper_ld_code(tmp, tcg_env, addr, tcg_constant_i32(oi)); > + > + /* See above. */ > + if ((da->memop & MO_BSWAP) == MO_TE) { > + tcg_gen_extr_i64_tl(lo, hi, tmp); > + } else { > + tcg_gen_extr_i64_tl(hi, lo, tmp); > + } > + } > + break; > +#else > + g_assert_not_reached(); > +#endif > + > default: > /* ??? In theory we've handled all of the ASIs that are valid > for ldda, and this should raise DAE_invalid_asi. However, Thanks for the excellent analysis, and also thanks to Richard for improving the correctness of the patch: Acked-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk> ATB, Mark.
Hi Philippe, On Fri, Apr 12, 2024 at 7:14 AM Philippe Mathieu-Daudé <philmd@linaro.org> wrote: > > Hi Bazz, > > On 12/4/24 06:18, M Bazz wrote: > > On Thu, Apr 11, 2024, 10:15 PM Richard Henderson > > <richard.henderson@linaro.org <mailto:richard.henderson@linaro.org>> wrote: > > > > Reads are done with execute access. It is not clear whether writes > > are legal at all -- for now, leave helper_st_asi unchanged, so that > > we continue to raise an mmu fault. > > > > This generalizes the exiting code for ASI_KERNELTXT to be usable for > > ASI_USERTXT as well, by passing down the MemOpIdx to use. > > > > Resolves: https://gitlab.com/qemu-project/qemu/-/issues/2281 > > <https://gitlab.com/qemu-project/qemu/-/issues/2281> > > Resolves: https://gitlab.com/qemu-project/qemu/-/issues/2059 > > <https://gitlab.com/qemu-project/qemu/-/issues/2059> > > Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1609 > > <https://gitlab.com/qemu-project/qemu/-/issues/1609> > > Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1166 > > <https://gitlab.com/qemu-project/qemu/-/issues/1166> > > Signed-off-by: Richard Henderson <richard.henderson@linaro.org > > <mailto:richard.henderson@linaro.org>> > > --- > > target/sparc/helper.h | 3 ++ > > target/sparc/ldst_helper.c | 65 ++++++++++++++++++++++++++------------ > > target/sparc/translate.c | 49 ++++++++++++++++++++++++++-- > > 3 files changed, 95 insertions(+), 22 deletions(-) > > > Hi Richard, > > > > I see this is in your hands now. I agree with your take on leaving > > writes alone. I'm also grateful for the opportunity to collaborate with you. > > > > It brings a smile for the community members who will be touched by this > > amazing contribution. I see them happily realizing that this perplexing > > bug has been solved, and in our case finally able to use the debuggers > > we love! :D > > Does that mean you tested this patch and it resolves your issues? > > If so, could you add your 'Tested-by: M Bazz <bazz@bazz1.com>' tag > when committing this patch? > > Regards, > > Phil. Yes, I can confirm the issue is resolved. Richard has already made the pull request. I am appreciative of the fast movement on this. I would like to have my "Tested-by" tag added to the PR, if it's no trouble. How might I get it there? Tested-by: M Bazz <bazz@bazz1.com> > > > Thanks for the proper fix, qemu sensei! > > > > -bazz > > >
diff --git a/target/sparc/helper.h b/target/sparc/helper.h index e55fad5b8c..b8087d0d2b 100644 --- a/target/sparc/helper.h +++ b/target/sparc/helper.h @@ -32,6 +32,9 @@ DEF_HELPER_FLAGS_3(udiv, TCG_CALL_NO_WG, i64, env, tl, tl) DEF_HELPER_FLAGS_3(sdiv, TCG_CALL_NO_WG, i64, env, tl, tl) DEF_HELPER_3(taddcctv, tl, env, tl, tl) DEF_HELPER_3(tsubcctv, tl, env, tl, tl) +#if !defined(CONFIG_USER_ONLY) && !defined(TARGET_SPARC64) +DEF_HELPER_FLAGS_3(ld_code, TCG_CALL_NO_WG, i64, env, tl, i32) +#endif #if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64) DEF_HELPER_FLAGS_4(ld_asi, TCG_CALL_NO_WG, i64, env, tl, int, i32) DEF_HELPER_FLAGS_5(st_asi, TCG_CALL_NO_WG, void, env, tl, i64, int, i32) diff --git a/target/sparc/ldst_helper.c b/target/sparc/ldst_helper.c index e581bb42ac..2846a86cc4 100644 --- a/target/sparc/ldst_helper.c +++ b/target/sparc/ldst_helper.c @@ -585,7 +585,6 @@ uint64_t helper_ld_asi(CPUSPARCState *env, target_ulong addr, #if defined(DEBUG_MXCC) || defined(DEBUG_ASI) uint32_t last_addr = addr; #endif - MemOpIdx oi; do_check_align(env, addr, size - 1, GETPC()); switch (asi) { @@ -684,24 +683,6 @@ uint64_t helper_ld_asi(CPUSPARCState *env, target_ulong addr, case ASI_M_DIAGS: /* Turbosparc DTLB Diagnostic */ case ASI_M_IODIAG: /* Turbosparc IOTLB Diagnostic */ break; - case ASI_KERNELTXT: /* Supervisor code access */ - oi = make_memop_idx(memop, cpu_mmu_index(env_cpu(env), true)); - switch (size) { - case 1: - ret = cpu_ldb_code_mmu(env, addr, oi, GETPC()); - break; - case 2: - ret = cpu_ldw_code_mmu(env, addr, oi, GETPC()); - break; - default: - case 4: - ret = cpu_ldl_code_mmu(env, addr, oi, GETPC()); - break; - case 8: - ret = cpu_ldq_code_mmu(env, addr, oi, GETPC()); - break; - } - break; case ASI_M_TXTC_TAG: /* SparcStation 5 I-cache tag */ case ASI_M_TXTC_DATA: /* SparcStation 5 I-cache data */ case ASI_M_DATAC_TAG: /* SparcStation 5 D-cache tag */ @@ -779,7 +760,6 @@ uint64_t helper_ld_asi(CPUSPARCState *env, target_ulong addr, case 0x4c: /* SuperSPARC MMU Breakpoint Action */ ret = env->mmubpaction; break; - case ASI_USERTXT: /* User code access, XXX */ default: sparc_raise_mmu_fault(cs, addr, false, false, asi, size, GETPC()); ret = 0; @@ -787,6 +767,8 @@ uint64_t helper_ld_asi(CPUSPARCState *env, target_ulong addr, case ASI_USERDATA: /* User data access */ case ASI_KERNELDATA: /* Supervisor data access */ + case ASI_USERTXT: /* User code access */ + case ASI_KERNELTXT: /* Supervisor code access */ case ASI_P: /* Implicit primary context data access (v9 only?) */ case ASI_M_BYPASS: /* MMU passthrough */ case ASI_LEON_BYPASS: /* LEON MMU passthrough */ @@ -1161,6 +1143,49 @@ void helper_st_asi(CPUSPARCState *env, target_ulong addr, uint64_t val, #endif } +uint64_t helper_ld_code(CPUSPARCState *env, target_ulong addr, uint32_t oi) +{ + MemOp mop = get_memop(oi); + uintptr_t ra = GETPC(); + uint64_t ret; + + switch (mop & MO_SIZE) { + case MO_8: + ret = cpu_ldb_code_mmu(env, addr, oi, ra); + if (mop & MO_SIGN) { + ret = (int8_t)ret; + } + break; + case MO_16: + ret = cpu_ldw_code_mmu(env, addr, oi, ra); + if ((mop & MO_BSWAP) != MO_TE) { + ret = bswap16(ret); + } + if (mop & MO_SIGN) { + ret = (int16_t)ret; + } + break; + case MO_32: + ret = cpu_ldl_code_mmu(env, addr, oi, ra); + if ((mop & MO_BSWAP) != MO_TE) { + ret = bswap32(ret); + } + if (mop & MO_SIGN) { + ret = (int32_t)ret; + } + break; + case MO_64: + ret = cpu_ldq_code_mmu(env, addr, oi, ra); + if ((mop & MO_BSWAP) != MO_TE) { + ret = bswap64(ret); + } + break; + default: + g_assert_not_reached(); + } + return ret; +} + #endif /* CONFIG_USER_ONLY */ #else /* TARGET_SPARC64 */ diff --git a/target/sparc/translate.c b/target/sparc/translate.c index 319934d9bd..c9b9b047df 100644 --- a/target/sparc/translate.c +++ b/target/sparc/translate.c @@ -1117,6 +1117,7 @@ typedef enum { GET_ASI_EXCP, GET_ASI_DIRECT, GET_ASI_DTWINX, + GET_ASI_CODE, GET_ASI_BLOCK, GET_ASI_SHORT, GET_ASI_BCOPY, @@ -1159,14 +1160,22 @@ static DisasASI resolve_asi(DisasContext *dc, int asi, MemOp memop) || (asi == ASI_USERDATA && (dc->def->features & CPU_FEATURE_CASA))) { switch (asi) { - case ASI_USERDATA: /* User data access */ + case ASI_USERDATA: /* User data access */ mem_idx = MMU_USER_IDX; type = GET_ASI_DIRECT; break; - case ASI_KERNELDATA: /* Supervisor data access */ + case ASI_KERNELDATA: /* Supervisor data access */ mem_idx = MMU_KERNEL_IDX; type = GET_ASI_DIRECT; break; + case ASI_USERTXT: /* User text access */ + mem_idx = MMU_USER_IDX; + type = GET_ASI_CODE; + break; + case ASI_KERNELTXT: /* Supervisor text access */ + mem_idx = MMU_KERNEL_IDX; + type = GET_ASI_CODE; + break; case ASI_M_BYPASS: /* MMU passthrough */ case ASI_LEON_BYPASS: /* LEON MMU passthrough */ mem_idx = MMU_PHYS_IDX; @@ -1379,6 +1388,22 @@ static void gen_ld_asi(DisasContext *dc, DisasASI *da, TCGv dst, TCGv addr) case GET_ASI_DIRECT: tcg_gen_qemu_ld_tl(dst, addr, da->mem_idx, da->memop | MO_ALIGN); break; + + case GET_ASI_CODE: +#if !defined(CONFIG_USER_ONLY) && !defined(TARGET_SPARC64) + { + MemOpIdx oi = make_memop_idx(da->memop, da->mem_idx); + TCGv_i32 r_oi = tcg_constant_i32(oi); + TCGv_i64 t64 = tcg_temp_new_i64(); + + gen_helper_ld_code(t64, tcg_env, addr, r_oi); + tcg_gen_trunc_i64_tl(dst, t64); + } + break; +#else + g_assert_not_reached(); +#endif + default: { TCGv_i32 r_asi = tcg_constant_i32(da->asi); @@ -1791,6 +1816,26 @@ static void gen_ldda_asi(DisasContext *dc, DisasASI *da, TCGv addr, int rd) } break; + case GET_ASI_CODE: +#if !defined(CONFIG_USER_ONLY) && !defined(TARGET_SPARC64) + { + TCGv_i64 tmp = tcg_temp_new_i64(); + MemOpIdx oi = make_memop_idx(da->memop, da->mem_idx); + + gen_helper_ld_code(tmp, tcg_env, addr, tcg_constant_i32(oi)); + + /* See above. */ + if ((da->memop & MO_BSWAP) == MO_TE) { + tcg_gen_extr_i64_tl(lo, hi, tmp); + } else { + tcg_gen_extr_i64_tl(hi, lo, tmp); + } + } + break; +#else + g_assert_not_reached(); +#endif + default: /* ??? In theory we've handled all of the ASIs that are valid for ldda, and this should raise DAE_invalid_asi. However,
Reads are done with execute access. It is not clear whether writes are legal at all -- for now, leave helper_st_asi unchanged, so that we continue to raise an mmu fault. This generalizes the exiting code for ASI_KERNELTXT to be usable for ASI_USERTXT as well, by passing down the MemOpIdx to use. Resolves: https://gitlab.com/qemu-project/qemu/-/issues/2281 Resolves: https://gitlab.com/qemu-project/qemu/-/issues/2059 Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1609 Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1166 Signed-off-by: Richard Henderson <richard.henderson@linaro.org> --- target/sparc/helper.h | 3 ++ target/sparc/ldst_helper.c | 65 ++++++++++++++++++++++++++------------ target/sparc/translate.c | 49 ++++++++++++++++++++++++++-- 3 files changed, 95 insertions(+), 22 deletions(-)