* [PATCH 0/2] Hexagon: fix icinva
@ 2026-08-19 4:53 Brian Cain
2026-08-19 4:53 ` [PATCH 1/2] target/hexagon: invalidate translated code for user icinva Brian Cain
2026-08-19 4:53 ` [PATCH 2/2] tests/tcg/hexagon: add icinva test Brian Cain
0 siblings, 2 replies; 8+ messages in thread
From: Brian Cain @ 2026-08-19 4:53 UTC (permalink / raw)
To: qemu-devel; +Cc: Pierrick Bouvier, Brian Cain
icinva (icache invalidate addr) instruction was a nop, but this behavior
is not correct for userspace.
Also note that this checkpatch issue was bypassed because I believe
it's appropriate/acceptable to check the "guest" page size in a TCG test
case.
Patch 1/2 has no obvious style problems and is ready for submission.
2/2 Checking commit ea94abbfc875 (tests/tcg/hexagon: add icinva test)
ERROR: use qemu_real_host_page_size() instead of sysconf(_SC_PAGESIZE)
#74: FILE: tests/tcg/hexagon/icinva.c:56:
+ long pagesize = sysconf(_SC_PAGESIZE);
Brian Cain (2):
target/hexagon: invalidate translated code for user icinva
tests/tcg/hexagon: add icinva test
target/hexagon/gen_tcg.h | 9 ++++
target/hexagon/helper.h | 4 ++
target/hexagon/op_helper.c | 15 +++++++
target/hexagon/translate.c | 3 ++
tests/tcg/hexagon/icinva.c | 71 +++++++++++++++++++++++++++++++
tests/tcg/hexagon/Makefile.target | 2 +
6 files changed, 104 insertions(+)
create mode 100644 tests/tcg/hexagon/icinva.c
--
2.34.1
^ permalink raw reply [flat|nested] 8+ messages in thread* [PATCH 1/2] target/hexagon: invalidate translated code for user icinva 2026-08-19 4:53 [PATCH 0/2] Hexagon: fix icinva Brian Cain @ 2026-08-19 4:53 ` Brian Cain 2026-08-20 18:37 ` Pierrick Bouvier 2026-08-19 4:53 ` [PATCH 2/2] tests/tcg/hexagon: add icinva test Brian Cain 1 sibling, 1 reply; 8+ messages in thread From: Brian Cain @ 2026-08-19 4:53 UTC (permalink / raw) To: qemu-devel; +Cc: Pierrick Bouvier, Brian Cain Route linux-user icinva through a helper that invalidates the addressed icache line under mmap_lock For system mode icinva has nothing left to do, so it stays a nop. Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com> --- target/hexagon/gen_tcg.h | 9 +++++++++ target/hexagon/helper.h | 4 ++++ target/hexagon/op_helper.c | 15 +++++++++++++++ target/hexagon/translate.c | 3 +++ 4 files changed, 31 insertions(+) diff --git a/target/hexagon/gen_tcg.h b/target/hexagon/gen_tcg.h index 40e03781d36..1d25391282a 100644 --- a/target/hexagon/gen_tcg.h +++ b/target/hexagon/gen_tcg.h @@ -497,8 +497,17 @@ do { RsV = RsV; } while (0) #define fGEN_TCG_Y2_dccleana(SHORTCODE) \ do { RsV = RsV; } while (0) + +#ifdef CONFIG_USER_ONLY +#define fGEN_TCG_Y2_icinva(SHORTCODE) \ + gen_helper_insn_cache_op(tcg_env, RsV, \ + tcg_constant_tl(insn->slot), \ + tcg_constant_tl(ctx->mem_idx), \ + tcg_constant_tl(ctx->pkt.pc)) +#else #define fGEN_TCG_Y2_icinva(SHORTCODE) \ do { RsV = RsV; } while (0) +#endif /* * allocframe(#uiV) diff --git a/target/hexagon/helper.h b/target/hexagon/helper.h index 78dc28ca9e5..a5a5c123533 100644 --- a/target/hexagon/helper.h +++ b/target/hexagon/helper.h @@ -113,6 +113,10 @@ DEF_HELPER_FLAGS_4(gvec_sabsdiff_w, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) DEF_HELPER_FLAGS_4(gvec_uabsdiff_b, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) DEF_HELPER_FLAGS_4(gvec_uabsdiff_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) +#if defined(CONFIG_USER_ONLY) +DEF_HELPER_5(insn_cache_op, void, env, i32, int, int, i32) +#endif + #if !defined(CONFIG_USER_ONLY) DEF_HELPER_3(raise_stack_overflow, void, env, i32, i32) DEF_HELPER_2(swi, void, env, i32) diff --git a/target/hexagon/op_helper.c b/target/hexagon/op_helper.c index 23894ff3d28..84f5564b1e6 100644 --- a/target/hexagon/op_helper.c +++ b/target/hexagon/op_helper.c @@ -23,6 +23,9 @@ #include "qemu/main-loop.h" #include "cpu.h" #include "exec/helper-proto.h" +#include "exec/mmap-lock.h" +#include "exec/target_page.h" +#include "exec/translation-block.h" #include "fpu/softfloat.h" #include "exec/cpu-interrupt.h" #include "internal.h" @@ -311,6 +314,18 @@ int32_t HELPER(vacsh_pred)(CPUHexagonState *env, return PeV; } +#ifdef CONFIG_USER_ONLY +void HELPER(insn_cache_op)(CPUHexagonState *env, target_ulong RsV, + int slot, int mmu_idx, target_ulong PC) +{ + target_ulong start = RsV & ~31; + + mmap_lock(); + tb_invalidate_phys_range(env_cpu(env), start, start + 31); + mmap_unlock(); +} +#endif + int64_t HELPER(cabacdecbin_val)(int64_t RssV, int64_t RttV) { int64_t RddV = 0; diff --git a/target/hexagon/translate.c b/target/hexagon/translate.c index 06a8159d283..1560c412732 100644 --- a/target/hexagon/translate.c +++ b/target/hexagon/translate.c @@ -354,6 +354,9 @@ static bool pkt_ends_tb(Packet *pkt) if (pkt->pkt_has_cof) { return true; } + if (check_for_attrib(pkt, A_ICFLUSHOP)) { + return true; + } #ifndef CONFIG_USER_ONLY /* System mode instructions that end TLB */ if (check_for_opcode(pkt, Y2_swi) || -- 2.34.1 ^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH 1/2] target/hexagon: invalidate translated code for user icinva 2026-08-19 4:53 ` [PATCH 1/2] target/hexagon: invalidate translated code for user icinva Brian Cain @ 2026-08-20 18:37 ` Pierrick Bouvier 2026-08-20 19:00 ` Brian Cain 0 siblings, 1 reply; 8+ messages in thread From: Pierrick Bouvier @ 2026-08-20 18:37 UTC (permalink / raw) To: Brian Cain, qemu-devel On 8/18/2026 9:53 PM, Brian Cain wrote: > Route linux-user icinva through a helper that invalidates the addressed > icache line under mmap_lock > > For system mode icinva has nothing left to do, so it stays a nop. > Why does system mode icinva is a nop? Shouldn't we invalidate translated code also? > Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com> > --- > target/hexagon/gen_tcg.h | 9 +++++++++ > target/hexagon/helper.h | 4 ++++ > target/hexagon/op_helper.c | 15 +++++++++++++++ > target/hexagon/translate.c | 3 +++ > 4 files changed, 31 insertions(+) > > diff --git a/target/hexagon/gen_tcg.h b/target/hexagon/gen_tcg.h > index 40e03781d36..1d25391282a 100644 > --- a/target/hexagon/gen_tcg.h > +++ b/target/hexagon/gen_tcg.h > @@ -497,8 +497,17 @@ > do { RsV = RsV; } while (0) > #define fGEN_TCG_Y2_dccleana(SHORTCODE) \ > do { RsV = RsV; } while (0) > + > +#ifdef CONFIG_USER_ONLY > +#define fGEN_TCG_Y2_icinva(SHORTCODE) \ > + gen_helper_insn_cache_op(tcg_env, RsV, \ > + tcg_constant_tl(insn->slot), \ > + tcg_constant_tl(ctx->mem_idx), \ > + tcg_constant_tl(ctx->pkt.pc)) > +#else > #define fGEN_TCG_Y2_icinva(SHORTCODE) \ > do { RsV = RsV; } while (0) > +#endif > > /* > * allocframe(#uiV) > diff --git a/target/hexagon/helper.h b/target/hexagon/helper.h > index 78dc28ca9e5..a5a5c123533 100644 > --- a/target/hexagon/helper.h > +++ b/target/hexagon/helper.h > @@ -113,6 +113,10 @@ DEF_HELPER_FLAGS_4(gvec_sabsdiff_w, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) > DEF_HELPER_FLAGS_4(gvec_uabsdiff_b, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) > DEF_HELPER_FLAGS_4(gvec_uabsdiff_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) > > +#if defined(CONFIG_USER_ONLY) > +DEF_HELPER_5(insn_cache_op, void, env, i32, int, int, i32) > +#endif > + > #if !defined(CONFIG_USER_ONLY) > DEF_HELPER_3(raise_stack_overflow, void, env, i32, i32) > DEF_HELPER_2(swi, void, env, i32) > diff --git a/target/hexagon/op_helper.c b/target/hexagon/op_helper.c > index 23894ff3d28..84f5564b1e6 100644 > --- a/target/hexagon/op_helper.c > +++ b/target/hexagon/op_helper.c > @@ -23,6 +23,9 @@ > #include "qemu/main-loop.h" > #include "cpu.h" > #include "exec/helper-proto.h" > +#include "exec/mmap-lock.h" > +#include "exec/target_page.h" > +#include "exec/translation-block.h" > #include "fpu/softfloat.h" > #include "exec/cpu-interrupt.h" > #include "internal.h" > @@ -311,6 +314,18 @@ int32_t HELPER(vacsh_pred)(CPUHexagonState *env, > return PeV; > } > > +#ifdef CONFIG_USER_ONLY > +void HELPER(insn_cache_op)(CPUHexagonState *env, target_ulong RsV, > + int slot, int mmu_idx, target_ulong PC) > +{ > + target_ulong start = RsV & ~31; > + > + mmap_lock(); > + tb_invalidate_phys_range(env_cpu(env), start, start + 31); > + mmap_unlock(); > +} > +#endif > + > int64_t HELPER(cabacdecbin_val)(int64_t RssV, int64_t RttV) > { > int64_t RddV = 0; > diff --git a/target/hexagon/translate.c b/target/hexagon/translate.c > index 06a8159d283..1560c412732 100644 > --- a/target/hexagon/translate.c > +++ b/target/hexagon/translate.c > @@ -354,6 +354,9 @@ static bool pkt_ends_tb(Packet *pkt) > if (pkt->pkt_has_cof) { > return true; > } > + if (check_for_attrib(pkt, A_ICFLUSHOP)) { > + return true; > + } > #ifndef CONFIG_USER_ONLY > /* System mode instructions that end TLB */ > if (check_for_opcode(pkt, Y2_swi) || ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 1/2] target/hexagon: invalidate translated code for user icinva 2026-08-20 18:37 ` Pierrick Bouvier @ 2026-08-20 19:00 ` Brian Cain 2026-08-20 19:10 ` Pierrick Bouvier 2026-08-20 23:40 ` Richard Henderson 0 siblings, 2 replies; 8+ messages in thread From: Brian Cain @ 2026-08-20 19:00 UTC (permalink / raw) To: Pierrick Bouvier, qemu-devel On 8/20/2026 1:37 PM, Pierrick Bouvier wrote: > On 8/18/2026 9:53 PM, Brian Cain wrote: >> Route linux-user icinva through a helper that invalidates the addressed >> icache line under mmap_lock >> >> For system mode icinva has nothing left to do, so it stays a nop. >> > Why does system mode icinva is a nop? > Shouldn't we invalidate translated code also? The normal behavior of instruction translation in QEMU is conservative relative to the ISA constraint. QEMU will invalidate translated blocks that become dirty/stale from a store instruction, so icinva can't flush anything: it's already flushed. >> Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com> >> --- >> target/hexagon/gen_tcg.h | 9 +++++++++ >> target/hexagon/helper.h | 4 ++++ >> target/hexagon/op_helper.c | 15 +++++++++++++++ >> target/hexagon/translate.c | 3 +++ >> 4 files changed, 31 insertions(+) >> >> diff --git a/target/hexagon/gen_tcg.h b/target/hexagon/gen_tcg.h >> index 40e03781d36..1d25391282a 100644 >> --- a/target/hexagon/gen_tcg.h >> +++ b/target/hexagon/gen_tcg.h >> @@ -497,8 +497,17 @@ >> do { RsV = RsV; } while (0) >> #define fGEN_TCG_Y2_dccleana(SHORTCODE) \ >> do { RsV = RsV; } while (0) >> + >> +#ifdef CONFIG_USER_ONLY >> +#define fGEN_TCG_Y2_icinva(SHORTCODE) \ >> + gen_helper_insn_cache_op(tcg_env, RsV, \ >> + tcg_constant_tl(insn->slot), \ >> + tcg_constant_tl(ctx->mem_idx), \ >> + tcg_constant_tl(ctx->pkt.pc)) >> +#else >> #define fGEN_TCG_Y2_icinva(SHORTCODE) \ >> do { RsV = RsV; } while (0) >> +#endif >> >> /* >> * allocframe(#uiV) >> diff --git a/target/hexagon/helper.h b/target/hexagon/helper.h >> index 78dc28ca9e5..a5a5c123533 100644 >> --- a/target/hexagon/helper.h >> +++ b/target/hexagon/helper.h >> @@ -113,6 +113,10 @@ DEF_HELPER_FLAGS_4(gvec_sabsdiff_w, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) >> DEF_HELPER_FLAGS_4(gvec_uabsdiff_b, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) >> DEF_HELPER_FLAGS_4(gvec_uabsdiff_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) >> >> +#if defined(CONFIG_USER_ONLY) >> +DEF_HELPER_5(insn_cache_op, void, env, i32, int, int, i32) >> +#endif >> + >> #if !defined(CONFIG_USER_ONLY) >> DEF_HELPER_3(raise_stack_overflow, void, env, i32, i32) >> DEF_HELPER_2(swi, void, env, i32) >> diff --git a/target/hexagon/op_helper.c b/target/hexagon/op_helper.c >> index 23894ff3d28..84f5564b1e6 100644 >> --- a/target/hexagon/op_helper.c >> +++ b/target/hexagon/op_helper.c >> @@ -23,6 +23,9 @@ >> #include "qemu/main-loop.h" >> #include "cpu.h" >> #include "exec/helper-proto.h" >> +#include "exec/mmap-lock.h" >> +#include "exec/target_page.h" >> +#include "exec/translation-block.h" >> #include "fpu/softfloat.h" >> #include "exec/cpu-interrupt.h" >> #include "internal.h" >> @@ -311,6 +314,18 @@ int32_t HELPER(vacsh_pred)(CPUHexagonState *env, >> return PeV; >> } >> >> +#ifdef CONFIG_USER_ONLY >> +void HELPER(insn_cache_op)(CPUHexagonState *env, target_ulong RsV, >> + int slot, int mmu_idx, target_ulong PC) >> +{ >> + target_ulong start = RsV & ~31; >> + >> + mmap_lock(); >> + tb_invalidate_phys_range(env_cpu(env), start, start + 31); >> + mmap_unlock(); >> +} >> +#endif >> + >> int64_t HELPER(cabacdecbin_val)(int64_t RssV, int64_t RttV) >> { >> int64_t RddV = 0; >> diff --git a/target/hexagon/translate.c b/target/hexagon/translate.c >> index 06a8159d283..1560c412732 100644 >> --- a/target/hexagon/translate.c >> +++ b/target/hexagon/translate.c >> @@ -354,6 +354,9 @@ static bool pkt_ends_tb(Packet *pkt) >> if (pkt->pkt_has_cof) { >> return true; >> } >> + if (check_for_attrib(pkt, A_ICFLUSHOP)) { >> + return true; >> + } >> #ifndef CONFIG_USER_ONLY >> /* System mode instructions that end TLB */ >> if (check_for_opcode(pkt, Y2_swi) || ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 1/2] target/hexagon: invalidate translated code for user icinva 2026-08-20 19:00 ` Brian Cain @ 2026-08-20 19:10 ` Pierrick Bouvier 2026-08-20 23:40 ` Richard Henderson 1 sibling, 0 replies; 8+ messages in thread From: Pierrick Bouvier @ 2026-08-20 19:10 UTC (permalink / raw) To: Brian Cain, qemu-devel On 8/20/2026 12:00 PM, Brian Cain wrote: > > On 8/20/2026 1:37 PM, Pierrick Bouvier wrote: >> On 8/18/2026 9:53 PM, Brian Cain wrote: >>> Route linux-user icinva through a helper that invalidates the addressed >>> icache line under mmap_lock >>> >>> For system mode icinva has nothing left to do, so it stays a nop. >>> >> Why does system mode icinva is a nop? >> Shouldn't we invalidate translated code also? > > The normal behavior of instruction translation in QEMU is conservative > relative to the ISA constraint. QEMU will invalidate translated blocks > that become dirty/stale from a store instruction, so icinva can't flush > anything: it's already flushed. > I see, it's related to the fact we emulate mmu in system mode. >>> Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com> >>> --- >>> target/hexagon/gen_tcg.h | 9 +++++++++ >>> target/hexagon/helper.h | 4 ++++ >>> target/hexagon/op_helper.c | 15 +++++++++++++++ >>> target/hexagon/translate.c | 3 +++ >>> 4 files changed, 31 insertions(+) >>> >>> diff --git a/target/hexagon/gen_tcg.h b/target/hexagon/gen_tcg.h >>> index 40e03781d36..1d25391282a 100644 >>> --- a/target/hexagon/gen_tcg.h >>> +++ b/target/hexagon/gen_tcg.h >>> @@ -497,8 +497,17 @@ >>> do { RsV = RsV; } while (0) >>> #define fGEN_TCG_Y2_dccleana(SHORTCODE) \ >>> do { RsV = RsV; } while (0) >>> + >>> +#ifdef CONFIG_USER_ONLY >>> +#define fGEN_TCG_Y2_icinva(SHORTCODE) \ >>> + gen_helper_insn_cache_op(tcg_env, RsV, \ >>> + tcg_constant_tl(insn->slot), \ >>> + tcg_constant_tl(ctx->mem_idx), \ >>> + tcg_constant_tl(ctx->pkt.pc)) >>> +#else >>> #define fGEN_TCG_Y2_icinva(SHORTCODE) \ >>> do { RsV = RsV; } while (0) >>> +#endif >>> /* >>> * allocframe(#uiV) >>> diff --git a/target/hexagon/helper.h b/target/hexagon/helper.h >>> index 78dc28ca9e5..a5a5c123533 100644 >>> --- a/target/hexagon/helper.h >>> +++ b/target/hexagon/helper.h >>> @@ -113,6 +113,10 @@ DEF_HELPER_FLAGS_4(gvec_sabsdiff_w, >>> TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) >>> DEF_HELPER_FLAGS_4(gvec_uabsdiff_b, TCG_CALL_NO_RWG, void, ptr, >>> ptr, ptr, i32) >>> DEF_HELPER_FLAGS_4(gvec_uabsdiff_h, TCG_CALL_NO_RWG, void, ptr, >>> ptr, ptr, i32) >>> +#if defined(CONFIG_USER_ONLY) >>> +DEF_HELPER_5(insn_cache_op, void, env, i32, int, int, i32) >>> +#endif >>> + >>> #if !defined(CONFIG_USER_ONLY) >>> DEF_HELPER_3(raise_stack_overflow, void, env, i32, i32) >>> DEF_HELPER_2(swi, void, env, i32) >>> diff --git a/target/hexagon/op_helper.c b/target/hexagon/op_helper.c >>> index 23894ff3d28..84f5564b1e6 100644 >>> --- a/target/hexagon/op_helper.c >>> +++ b/target/hexagon/op_helper.c >>> @@ -23,6 +23,9 @@ >>> #include "qemu/main-loop.h" >>> #include "cpu.h" >>> #include "exec/helper-proto.h" >>> +#include "exec/mmap-lock.h" >>> +#include "exec/target_page.h" >>> +#include "exec/translation-block.h" >>> #include "fpu/softfloat.h" >>> #include "exec/cpu-interrupt.h" >>> #include "internal.h" >>> @@ -311,6 +314,18 @@ int32_t HELPER(vacsh_pred)(CPUHexagonState *env, >>> return PeV; >>> } >>> +#ifdef CONFIG_USER_ONLY >>> +void HELPER(insn_cache_op)(CPUHexagonState *env, target_ulong RsV, >>> + int slot, int mmu_idx, target_ulong PC) >>> +{ >>> + target_ulong start = RsV & ~31; >>> + >>> + mmap_lock(); >>> + tb_invalidate_phys_range(env_cpu(env), start, start + 31); >>> + mmap_unlock(); >>> +} >>> +#endif >>> + >>> int64_t HELPER(cabacdecbin_val)(int64_t RssV, int64_t RttV) >>> { >>> int64_t RddV = 0; >>> diff --git a/target/hexagon/translate.c b/target/hexagon/translate.c >>> index 06a8159d283..1560c412732 100644 >>> --- a/target/hexagon/translate.c >>> +++ b/target/hexagon/translate.c >>> @@ -354,6 +354,9 @@ static bool pkt_ends_tb(Packet *pkt) >>> if (pkt->pkt_has_cof) { >>> return true; >>> } >>> + if (check_for_attrib(pkt, A_ICFLUSHOP)) { >>> + return true; >>> + } >>> #ifndef CONFIG_USER_ONLY >>> /* System mode instructions that end TLB */ >>> if (check_for_opcode(pkt, Y2_swi) || Reviewed-by: Pierrick Bouvier <pierrick.bouvier@oss.qualcomm.com> Regards, Pierrick ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 1/2] target/hexagon: invalidate translated code for user icinva 2026-08-20 19:00 ` Brian Cain 2026-08-20 19:10 ` Pierrick Bouvier @ 2026-08-20 23:40 ` Richard Henderson 1 sibling, 0 replies; 8+ messages in thread From: Richard Henderson @ 2026-08-20 23:40 UTC (permalink / raw) To: qemu-devel On 8/20/26 12:00, Brian Cain wrote: > > On 8/20/2026 1:37 PM, Pierrick Bouvier wrote: >> On 8/18/2026 9:53 PM, Brian Cain wrote: >>> Route linux-user icinva through a helper that invalidates the addressed >>> icache line under mmap_lock >>> >>> For system mode icinva has nothing left to do, so it stays a nop. >>> >> Why does system mode icinva is a nop? >> Shouldn't we invalidate translated code also? > > The normal behavior of instruction translation in QEMU is conservative relative to the ISA > constraint. QEMU will invalidate translated blocks that become dirty/stale from a store > instruction, so icinva can't flush anything: it's already flushed. We do the same in user mode, trapping the stores via read-only pages. See handle_sigsegv_accerr_write and page_unprotect. So why do you believe that you need to invalidate pages manually here? r~ ^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH 2/2] tests/tcg/hexagon: add icinva test 2026-08-19 4:53 [PATCH 0/2] Hexagon: fix icinva Brian Cain 2026-08-19 4:53 ` [PATCH 1/2] target/hexagon: invalidate translated code for user icinva Brian Cain @ 2026-08-19 4:53 ` Brian Cain 2026-08-20 19:11 ` Pierrick Bouvier 1 sibling, 1 reply; 8+ messages in thread From: Brian Cain @ 2026-08-19 4:53 UTC (permalink / raw) To: qemu-devel; +Cc: Pierrick Bouvier, Brian Cain Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com> --- tests/tcg/hexagon/icinva.c | 71 +++++++++++++++++++++++++++++++ tests/tcg/hexagon/Makefile.target | 2 + 2 files changed, 73 insertions(+) create mode 100644 tests/tcg/hexagon/icinva.c diff --git a/tests/tcg/hexagon/icinva.c b/tests/tcg/hexagon/icinva.c new file mode 100644 index 00000000000..0252e0f899d --- /dev/null +++ b/tests/tcg/hexagon/icinva.c @@ -0,0 +1,71 @@ +/* + * Test that icinva ends the current translation block. + * + * icinva only invalidates the emulator's cached translation for a + * code range; it doesn't retroactively fix up code that has already + * been decoded as part of the still-executing translation block. If + * icinva doesn't force a new TB to start right after it, a packet + * patched via a store immediately before icinva (with no + * change-of-flow in between) still runs the stale decode baked into + * the current TB instead of the freshly-patched instruction. + * + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include <stdio.h> +#include <stdint.h> +#include <unistd.h> +#include <sys/mman.h> + +int err; + +#include "hex_test.h" + +/* Encoding of "r0 = #99" */ +#define ICINVA_NEW_INSN 0x7800cc60 + +static uint32_t __attribute__((noinline)) test_icinva_smc(void) +{ + uint32_t result; + + /* + * r1 = address of the "patch_slot" packet below (1:) + * Overwrite it with the "r0 = #99" encoding, invalidate the + * icache for that address, then fall straight through into it + * with no intervening jump/call. + */ + asm volatile( + "r1 = ##1f\n" + "r2 = ##%[newinsn]\n" + "memw(r1) = r2\n" + "icinva(r1)\n" + "1:\n" + " r0 = #11\n" + "%[out] = r0\n" + : [out] "=r"(result) + : [newinsn] "i"(ICINVA_NEW_INSN) + : "r0", "r1", "r2", "memory" + ); + + return result; +} + +int main(void) +{ + long pagesize = sysconf(_SC_PAGESIZE); + uintptr_t page = (uintptr_t)test_icinva_smc & ~(pagesize - 1); + uint32_t result; + + if (mprotect((void *)page, 2 * pagesize, + PROT_READ | PROT_WRITE | PROT_EXEC) != 0) { + perror("mprotect"); + return 1; + } + + result = test_icinva_smc(); + check32(result, 99); + + puts(err ? "FAIL" : "PASS"); + return err; +} diff --git a/tests/tcg/hexagon/Makefile.target b/tests/tcg/hexagon/Makefile.target index 61adf6356e4..27268e66b7a 100644 --- a/tests/tcg/hexagon/Makefile.target +++ b/tests/tcg/hexagon/Makefile.target @@ -60,6 +60,7 @@ HEX_TESTS += invalid-encoding HEX_TESTS += multiple-writes HEX_TESTS += unaligned_pc HEX_TESTS += unaligned_data +HEX_TESTS += icinva HEX_TESTS += test_abs HEX_TESTS += test_bitcnt @@ -103,6 +104,7 @@ circ: circ.c hex_test.h dual_stores: dual_stores.c hex_test.h fpstuff: fpstuff.c hex_test.h hex_sigsegv: hex_sigsegv.c hex_test.h +icinva: icinva.c hex_test.h load_align: load_align.c hex_test.h load_unpack: load_unpack.c hex_test.h mem_noshuf_exception: mem_noshuf_exception.c hex_test.h -- 2.34.1 ^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH 2/2] tests/tcg/hexagon: add icinva test 2026-08-19 4:53 ` [PATCH 2/2] tests/tcg/hexagon: add icinva test Brian Cain @ 2026-08-20 19:11 ` Pierrick Bouvier 0 siblings, 0 replies; 8+ messages in thread From: Pierrick Bouvier @ 2026-08-20 19:11 UTC (permalink / raw) To: Brian Cain, qemu-devel On 8/18/2026 9:53 PM, Brian Cain wrote: > Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com> > --- > tests/tcg/hexagon/icinva.c | 71 +++++++++++++++++++++++++++++++ > tests/tcg/hexagon/Makefile.target | 2 + > 2 files changed, 73 insertions(+) > create mode 100644 tests/tcg/hexagon/icinva.c > Reviewed-by: Pierrick Bouvier <pierrick.bouvier@oss.qualcomm.com> ^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2026-08-20 23:41 UTC | newest] Thread overview: 8+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2026-08-19 4:53 [PATCH 0/2] Hexagon: fix icinva Brian Cain 2026-08-19 4:53 ` [PATCH 1/2] target/hexagon: invalidate translated code for user icinva Brian Cain 2026-08-20 18:37 ` Pierrick Bouvier 2026-08-20 19:00 ` Brian Cain 2026-08-20 19:10 ` Pierrick Bouvier 2026-08-20 23:40 ` Richard Henderson 2026-08-19 4:53 ` [PATCH 2/2] tests/tcg/hexagon: add icinva test Brian Cain 2026-08-20 19:11 ` Pierrick Bouvier
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.