Commit 9da452d862 for qemu.org
commit 9da452d862753b41e42efbdb4724c9a4fc77dfa0
Author: Brian Cain <brian.cain@oss.qualcomm.com>
Date: Tue Aug 18 21:53:39 2026 -0700
tests/tcg/hexagon: add icinva test
Reviewed-by: Pierrick Bouvier <pierrick.bouvier@oss.qualcomm.com>
Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
diff --git a/tests/tcg/hexagon/Makefile.target b/tests/tcg/hexagon/Makefile.target
index 641f6bc10e..f72bb8a6b4 100644
--- a/tests/tcg/hexagon/Makefile.target
+++ b/tests/tcg/hexagon/Makefile.target
@@ -61,6 +61,7 @@ HEX_TESTS += multiple-writes
HEX_TESTS += privileged-insn
HEX_TESTS += unaligned_pc
HEX_TESTS += unaligned_data
+HEX_TESTS += icinva
HEX_TESTS += test_abs
HEX_TESTS += test_bitcnt
@@ -104,6 +105,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
diff --git a/tests/tcg/hexagon/icinva.c b/tests/tcg/hexagon/icinva.c
new file mode 100644
index 0000000000..c75adec677
--- /dev/null
+++ b/tests/tcg/hexagon/icinva.c
@@ -0,0 +1,70 @@
+/*
+ * 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 <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)
+{
+ int pagesize = 4096;
+ 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;
+}