1084cfca1SRichard Henderson /* 2084cfca1SRichard Henderson * Flush the host cpu caches. 3084cfca1SRichard Henderson * 4084cfca1SRichard Henderson * This work is licensed under the terms of the GNU GPL, version 2 or later. 5084cfca1SRichard Henderson * See the COPYING file in the top-level directory. 6084cfca1SRichard Henderson */ 7084cfca1SRichard Henderson 8084cfca1SRichard Henderson #include "qemu/osdep.h" 9084cfca1SRichard Henderson #include "qemu/cacheflush.h" 10084cfca1SRichard Henderson 11084cfca1SRichard Henderson 12084cfca1SRichard Henderson #if defined(__i386__) || defined(__x86_64__) || defined(__s390__) 13084cfca1SRichard Henderson 14084cfca1SRichard Henderson /* Caches are coherent and do not require flushing; symbol inline. */ 15084cfca1SRichard Henderson 16084cfca1SRichard Henderson #elif defined(__mips__) 17084cfca1SRichard Henderson 18084cfca1SRichard Henderson #ifdef __OpenBSD__ 19084cfca1SRichard Henderson #include <machine/sysarch.h> 20084cfca1SRichard Henderson #else 21084cfca1SRichard Henderson #include <sys/cachectl.h> 22084cfca1SRichard Henderson #endif 23084cfca1SRichard Henderson 24*1da8de39SRichard Henderson void flush_idcache_range(uintptr_t rx, uintptr_t rw, size_t len) 25084cfca1SRichard Henderson { 26*1da8de39SRichard Henderson if (rx != rw) { 27*1da8de39SRichard Henderson cacheflush((void *)rw, len, DCACHE); 28*1da8de39SRichard Henderson } 29*1da8de39SRichard Henderson cacheflush((void *)rx, len, ICACHE); 30084cfca1SRichard Henderson } 31084cfca1SRichard Henderson 32084cfca1SRichard Henderson #elif defined(__powerpc__) 33084cfca1SRichard Henderson 34*1da8de39SRichard Henderson void flush_idcache_range(uintptr_t rx, uintptr_t rw, size_t len) 35084cfca1SRichard Henderson { 36*1da8de39SRichard Henderson uintptr_t p, b, e; 37084cfca1SRichard Henderson size_t dsize = qemu_dcache_linesize; 38084cfca1SRichard Henderson size_t isize = qemu_icache_linesize; 39084cfca1SRichard Henderson 40*1da8de39SRichard Henderson b = rw & ~(dsize - 1); 41*1da8de39SRichard Henderson e = (rw + len + dsize - 1) & ~(dsize - 1); 42*1da8de39SRichard Henderson for (p = b; p < e; p += dsize) { 43084cfca1SRichard Henderson asm volatile ("dcbst 0,%0" : : "r"(p) : "memory"); 44084cfca1SRichard Henderson } 45084cfca1SRichard Henderson asm volatile ("sync" : : : "memory"); 46084cfca1SRichard Henderson 47*1da8de39SRichard Henderson b = rx & ~(isize - 1); 48*1da8de39SRichard Henderson e = (rx + len + isize - 1) & ~(isize - 1); 49*1da8de39SRichard Henderson for (p = b; p < e; p += isize) { 50084cfca1SRichard Henderson asm volatile ("icbi 0,%0" : : "r"(p) : "memory"); 51084cfca1SRichard Henderson } 52084cfca1SRichard Henderson asm volatile ("sync" : : : "memory"); 53084cfca1SRichard Henderson asm volatile ("isync" : : : "memory"); 54084cfca1SRichard Henderson } 55084cfca1SRichard Henderson 56084cfca1SRichard Henderson #elif defined(__sparc__) 57084cfca1SRichard Henderson 58*1da8de39SRichard Henderson void flush_idcache_range(uintptr_t rx, uintptr_t rw, size_t len) 59084cfca1SRichard Henderson { 60*1da8de39SRichard Henderson /* No additional data flush to the RW virtual address required. */ 61*1da8de39SRichard Henderson uintptr_t p, end = (rx + len + 7) & -8; 62*1da8de39SRichard Henderson for (p = rx & -8; p < end; p += 8) { 63084cfca1SRichard Henderson __asm__ __volatile__("flush\t%0" : : "r" (p)); 64084cfca1SRichard Henderson } 65084cfca1SRichard Henderson } 66084cfca1SRichard Henderson 67084cfca1SRichard Henderson #else 68084cfca1SRichard Henderson 69*1da8de39SRichard Henderson void flush_idcache_range(uintptr_t rx, uintptr_t rw, size_t len) 70084cfca1SRichard Henderson { 71*1da8de39SRichard Henderson if (rw != rx) { 72*1da8de39SRichard Henderson __builtin___clear_cache((char *)rw, (char *)rw + len); 73*1da8de39SRichard Henderson } 74*1da8de39SRichard Henderson __builtin___clear_cache((char *)rx, (char *)rx + len); 75084cfca1SRichard Henderson } 76084cfca1SRichard Henderson 77084cfca1SRichard Henderson #endif 78