target/sparc/helper.h | 3 ++ target/sparc/ldst_helper.c | 65 ++++++++++++++++++++++++++------------ target/sparc/translate.c | 49 ++++++++++++++++++++++++++-- 3 files changed, 95 insertions(+), 22 deletions(-)
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
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.
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 >
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 > > >
© 2016 - 2025 Red Hat, Inc.