new file mode 100644
@@ -0,0 +1,64 @@
+/*
+ * icache flush for QEMU (both TCG or virtualized)
+ *
+ * Copyright (c) 2003-2020 QEMU contributors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef FLUSH_ICACHE_H
+#define FLUSH_ICACHE_H
+
+#if defined HOST_I386 || defined HOST_X86_64 || defined HOST_S390 || defined HOST_S390X
+static inline void flush_icache_range(uintptr_t start, uintptr_t stop)
+{
+}
+
+#elif defined HOST_MIPS
+#ifdef __OpenBSD__
+#include <machine/sysarch.h>
+#else
+#include <sys/cachectl.h>
+#endif
+
+static inline void flush_icache_range(uintptr_t start, uintptr_t stop)
+{
+ cacheflush ((void *)start, stop-start, ICACHE);
+}
+
+#elif defined HOST_PPC || defined HOST_PPC64
+extern void flush_icache_range(uintptr_t start, uintptr_t stop);
+
+#elif defined HOST_SPARC
+static inline void flush_icache_range(uintptr_t start, uintptr_t stop)
+{
+ uintptr_t p;
+ for (p = start & -8; p < ((stop + 7) & -8); p += 8) {
+ __asm__ __volatile__("flush\t%0" : : "r" (p));
+ }
+}
+
+#elif defined HOST_AARCH64 || defined HOST_ARM || defined HOST_RISCV
+static inline void flush_icache_range(uintptr_t start, uintptr_t stop)
+{
+ __builtin___clear_cache((char *)start, (char *)stop);
+}
+#elif defined CONFIG_TCG_INTERPRETER
+static inline void flush_icache_range(uintptr_t start, uintptr_t stop)
+{
+ assert(tcg_enabled());
+}
+#endif
+
+#endif
@@ -53,6 +53,7 @@
#include "qemu/rcu_queue.h"
#include "qemu/main-loop.h"
#include "exec/translate-all.h"
+#include "exec/flush-icache.h"
#include "sysemu/replay.h"
#include "exec/memory-internal.h"
@@ -148,11 +148,6 @@ typedef enum {
#define TCG_TARGET_DEFAULT_MO (0)
#define TCG_TARGET_HAS_MEMORY_BSWAP 1
-static inline void flush_icache_range(uintptr_t start, uintptr_t stop)
-{
- __builtin___clear_cache((char *)start, (char *)stop);
-}
-
void tb_target_set_jmp_target(uintptr_t, uintptr_t, uintptr_t);
#ifdef CONFIG_SOFTMMU
@@ -134,11 +134,6 @@ enum {
#define TCG_TARGET_DEFAULT_MO (0)
#define TCG_TARGET_HAS_MEMORY_BSWAP 1
-static inline void flush_icache_range(uintptr_t start, uintptr_t stop)
-{
- __builtin___clear_cache((char *) start, (char *) stop);
-}
-
/* not defined -- call should be eliminated at compile time */
void tb_target_set_jmp_target(uintptr_t, uintptr_t, uintptr_t);
@@ -206,10 +206,6 @@ extern bool have_avx2;
#define TCG_TARGET_extract_i64_valid(ofs, len) \
(((ofs) == 8 && (len) == 8) || ((ofs) + (len)) == 32)
-static inline void flush_icache_range(uintptr_t start, uintptr_t stop)
-{
-}
-
static inline void tb_target_set_jmp_target(uintptr_t tc_ptr,
uintptr_t jmp_addr, uintptr_t addr)
{
@@ -198,20 +198,9 @@ extern bool use_mips32r2_instructions;
#define TCG_TARGET_HAS_ext16u_i64 0 /* andi rt, rs, 0xffff */
#endif
-#ifdef __OpenBSD__
-#include <machine/sysarch.h>
-#else
-#include <sys/cachectl.h>
-#endif
-
#define TCG_TARGET_DEFAULT_MO (0)
#define TCG_TARGET_HAS_MEMORY_BSWAP 1
-static inline void flush_icache_range(uintptr_t start, uintptr_t stop)
-{
- cacheflush ((void *)start, stop-start, ICACHE);
-}
-
void tb_target_set_jmp_target(uintptr_t, uintptr_t, uintptr_t);
#ifdef CONFIG_SOFTMMU
@@ -3863,25 +3863,3 @@ void tcg_register_jit(void *buf, size_t buf_size)
tcg_register_jit_int(buf, buf_size, &debug_frame, sizeof(debug_frame));
}
#endif /* __ELF__ */
-
-void flush_icache_range(uintptr_t start, uintptr_t stop)
-{
- uintptr_t p, start1, stop1;
- size_t dsize = qemu_dcache_linesize;
- size_t isize = qemu_icache_linesize;
-
- start1 = start & ~(dsize - 1);
- stop1 = (stop + dsize - 1) & ~(dsize - 1);
- for (p = start1; p < stop1; p += dsize) {
- asm volatile ("dcbst 0,%0" : : "r"(p) : "memory");
- }
- asm volatile ("sync" : : : "memory");
-
- start &= start & ~(isize - 1);
- stop1 = (stop + isize - 1) & ~(isize - 1);
- for (p = start1; p < stop1; p += isize) {
- asm volatile ("icbi 0,%0" : : "r"(p) : "memory");
- }
- asm volatile ("sync" : : : "memory");
- asm volatile ("isync" : : : "memory");
-}
@@ -175,7 +175,6 @@ extern bool have_vsx;
#define TCG_TARGET_HAS_bitsel_vec have_vsx
#define TCG_TARGET_HAS_cmpsel_vec 0
-void flush_icache_range(uintptr_t start, uintptr_t stop);
void tb_target_set_jmp_target(uintptr_t, uintptr_t, uintptr_t);
#define TCG_TARGET_DEFAULT_MO (0)
@@ -159,11 +159,6 @@ typedef enum {
#define TCG_TARGET_HAS_mulsh_i64 1
#endif
-static inline void flush_icache_range(uintptr_t start, uintptr_t stop)
-{
- __builtin___clear_cache((char *)start, (char *)stop);
-}
-
/* not defined -- call should be eliminated at compile time */
void tb_target_set_jmp_target(uintptr_t, uintptr_t, uintptr_t);
@@ -145,10 +145,6 @@ enum {
TCG_AREG0 = TCG_REG_R10,
};
-static inline void flush_icache_range(uintptr_t start, uintptr_t stop)
-{
-}
-
static inline void tb_target_set_jmp_target(uintptr_t tc_ptr,
uintptr_t jmp_addr, uintptr_t addr)
{
@@ -168,14 +168,6 @@ extern bool use_vis3_instructions;
#define TCG_TARGET_DEFAULT_MO (0)
#define TCG_TARGET_HAS_MEMORY_BSWAP 1
-static inline void flush_icache_range(uintptr_t start, uintptr_t stop)
-{
- uintptr_t p;
- for (p = start & -8; p < ((stop + 7) & -8); p += 8) {
- __asm__ __volatile__("flush\t%0" : : "r" (p));
- }
-}
-
void tb_target_set_jmp_target(uintptr_t, uintptr_t, uintptr_t);
#define TCG_TARGET_NEED_POOL_LABELS
@@ -43,6 +43,7 @@
#include "cpu.h"
#include "exec/exec-all.h"
+#include "exec/flush-icache.h"
#if !defined(CONFIG_USER_ONLY)
#include "hw/boards.h"
@@ -191,10 +191,6 @@ void tci_disas(uint8_t opc);
#define HAVE_TCG_QEMU_TB_EXEC
-static inline void flush_icache_range(uintptr_t start, uintptr_t stop)
-{
-}
-
/* We could notice __i386__ or __s390x__ and reduce the barriers depending
on the host. But if you want performance, you use the normal backend.
We prefer consistency across hosts on this. */
@@ -9,6 +9,7 @@
#include "qemu/osdep.h"
#include "qemu/host-utils.h"
#include "qemu/atomic.h"
+#include "exec/flush-icache.h"
int qemu_icache_linesize = 0;
int qemu_icache_linesize_log;
@@ -177,6 +178,30 @@ static void fallback_cache_info(int *isize, int *dsize)
}
}
+#if defined HOST_PPC || defined HOST_PPC64
+void flush_icache_range(uintptr_t start, uintptr_t stop)
+{
+ uintptr_t p, start1, stop1;
+ size_t dsize = qemu_dcache_linesize;
+ size_t isize = qemu_icache_linesize;
+
+ start1 = start & ~(dsize - 1);
+ stop1 = (stop + dsize - 1) & ~(dsize - 1);
+ for (p = start1; p < stop1; p += dsize) {
+ asm volatile ("dcbst 0,%0" : : "r"(p) : "memory");
+ }
+ asm volatile ("sync" : : : "memory");
+
+ start &= start & ~(isize - 1);
+ stop1 = (stop + isize - 1) & ~(isize - 1);
+ for (p = start1; p < stop1; p += isize) {
+ asm volatile ("icbi 0,%0" : : "r"(p) : "memory");
+ }
+ asm volatile ("sync" : : : "memory");
+ asm volatile ("isync" : : : "memory");
+}
+#endif
+
static void __attribute__((constructor)) init_cache_info(void)
{
int isize = 0, dsize = 0;
icache flush is also used by non-TCG accelerators. Do not require users such as physmem.c to include tcg/tcg.h. Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> --- include/exec/flush-icache.h | 64 ++++++++++++++++++++++++++++++++++++++++ softmmu/physmem.c | 1 + tcg/aarch64/tcg-target.h | 5 ---- tcg/arm/tcg-target.h | 5 ---- tcg/i386/tcg-target.h | 4 --- tcg/mips/tcg-target.h | 11 ------- tcg/ppc/tcg-target.c.inc | 22 -------------- tcg/ppc/tcg-target.h | 1 - tcg/riscv/tcg-target.h | 5 ---- tcg/s390/tcg-target.h | 4 --- tcg/sparc/tcg-target.h | 8 ----- tcg/tcg.c | 1 + tcg/tci/tcg-target.h | 4 --- util/cacheinfo.c | 25 ++++++++++++++++ 14 files changed, 91 insertions(+), 69 deletions(-) create mode 100644 include/exec/flush-icache.h