@ -7,12 +7,81 @@
# include "qemu/osdep.h"
# include "qemu/cacheflush.h"
# include "qemu/bitops.h"
# if defined(__i386__) || defined(__x86_64__) || defined(__s390__)
/* Caches are coherent and do not require flushing; symbol inline. */
# elif defined(__aarch64__)
# ifdef CONFIG_DARWIN
/* Apple does not expose CTR_EL0, so we must use system interfaces. */
extern void sys_icache_invalidate ( void * start , size_t len ) ;
extern void sys_dcache_flush ( void * start , size_t len ) ;
void flush_idcache_range ( uintptr_t rx , uintptr_t rw , size_t len )
{
sys_dcache_flush ( ( void * ) rw , len ) ;
sys_icache_invalidate ( ( void * ) rx , len ) ;
}
# else
/*
* TODO : unify this with cacheinfo . c .
* We want to save the whole contents of CTR_EL0 , so that we
* have more than the linesize , but also IDC and DIC .
*/
static unsigned int save_ctr_el0 ;
static void __attribute__ ( ( constructor ) ) init_ctr_el0 ( void )
{
asm volatile ( " mrs \t %0, ctr_el0 " : " =r " ( save_ctr_el0 ) ) ;
}
/*
* This is a copy of gcc ' s __aarch64_sync_cache_range , modified
* to fit this three - operand interface .
*/
void flush_idcache_range ( uintptr_t rx , uintptr_t rw , size_t len )
{
const unsigned CTR_IDC = 1u < < 28 ;
const unsigned CTR_DIC = 1u < < 29 ;
const unsigned int ctr_el0 = save_ctr_el0 ;
const uintptr_t icache_lsize = 4 < < extract32 ( ctr_el0 , 0 , 4 ) ;
const uintptr_t dcache_lsize = 4 < < extract32 ( ctr_el0 , 16 , 4 ) ;
uintptr_t p ;
/*
* If CTR_EL0 . IDC is enabled , Data cache clean to the Point of Unification
* is not required for instruction to data coherence .
*/
if ( ! ( ctr_el0 & CTR_IDC ) ) {
/*
* Loop over the address range , clearing one cache line at once .
* Data cache must be flushed to unification first to make sure
* the instruction cache fetches the updated data .
*/
for ( p = rw & - dcache_lsize ; p < rw + len ; p + = dcache_lsize ) {
asm volatile ( " dc \t cvau, %0 " : : " r " ( p ) : " memory " ) ;
}
asm volatile ( " dsb \t ish " : : : " memory " ) ;
}
/*
* If CTR_EL0 . DIC is enabled , Instruction cache cleaning to the Point
* of Unification is not required for instruction to data coherence .
*/
if ( ! ( ctr_el0 & CTR_DIC ) ) {
for ( p = rx & - icache_lsize ; p < rx + len ; p + = icache_lsize ) {
asm volatile ( " ic \t ivau, %0 " : : " r " ( p ) : " memory " ) ;
}
asm volatile ( " dsb \t ish " : : : " memory " ) ;
}
asm volatile ( " isb " : : : " memory " ) ;
}
# endif /* CONFIG_DARWIN */
# elif defined(__mips__)
# ifdef __OpenBSD__