Christophe Leroy <christophe.le...@c-s.fr> writes: > Le 03/09/2019 à 07:23, Alastair D'Silva a écrit : >> From: Alastair D'Silva <alast...@d-silva.org> >> >> Similar to commit 22e9c88d486a >> ("powerpc/64: reuse PPC32 static inline flush_dcache_range()") >> this patch converts the following ASM symbols to C: >> flush_icache_range() >> __flush_dcache_icache() >> __flush_dcache_icache_phys() >> >> This was done as we discovered a long-standing bug where the length of the >> range was truncated due to using a 32 bit shift instead of a 64 bit one. >> >> By converting these functions to C, it becomes easier to maintain. >> >> flush_dcache_icache_phys() retains a critical assembler section as we must >> ensure there are no memory accesses while the data MMU is disabled >> (authored by Christophe Leroy). Since this has no external callers, it has >> also been made static, allowing the compiler to inline it within >> flush_dcache_icache_page(). >> >> Signed-off-by: Alastair D'Silva <alast...@d-silva.org> >> Signed-off-by: Christophe Leroy <christophe.le...@c-s.fr> >> --- >> arch/powerpc/include/asm/cache.h | 26 ++--- >> arch/powerpc/include/asm/cacheflush.h | 24 ++-- >> arch/powerpc/kernel/misc_32.S | 117 -------------------- >> arch/powerpc/kernel/misc_64.S | 102 ----------------- >> arch/powerpc/mm/mem.c | 152 +++++++++++++++++++++++++- >> 5 files changed, 173 insertions(+), 248 deletions(-) >> >> diff --git a/arch/powerpc/include/asm/cache.h >> b/arch/powerpc/include/asm/cache.h >> index f852d5cd746c..91c808c6738b 100644 >> --- a/arch/powerpc/include/asm/cache.h >> +++ b/arch/powerpc/include/asm/cache.h >> @@ -98,20 +98,7 @@ static inline u32 l1_icache_bytes(void) >> #endif >> #endif /* ! __ASSEMBLY__ */ >> >> -#if defined(__ASSEMBLY__) >> -/* >> - * For a snooping icache, we still need a dummy icbi to purge all the >> - * prefetched instructions from the ifetch buffers. We also need a sync >> - * before the icbi to order the the actual stores to memory that might >> - * have modified instructions with the icbi. >> - */ >> -#define PURGE_PREFETCHED_INS \ >> - sync; \ >> - icbi 0,r3; \ >> - sync; \ >> - isync >> - >> -#else >> +#if !defined(__ASSEMBLY__) >> #define __read_mostly __attribute__((__section__(".data..read_mostly"))) >> >> #ifdef CONFIG_PPC_BOOK3S_32 >> @@ -145,6 +132,17 @@ static inline void dcbst(void *addr) >> { >> __asm__ __volatile__ ("dcbst %y0" : : "Z"(*(u8 *)addr) : "memory"); >> } >> + >> +static inline void icbi(void *addr) >> +{ >> + __asm__ __volatile__ ("icbi 0, %0" : : "r"(addr) : "memory"); > > I think "__asm__ __volatile__" is deprecated. Use "asm volatile" instead.
Yes please. >> diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c >> index 9191a66b3bc5..cd540123874d 100644 >> --- a/arch/powerpc/mm/mem.c >> +++ b/arch/powerpc/mm/mem.c >> @@ -321,6 +321,105 @@ void free_initmem(void) >> free_initmem_default(POISON_FREE_INITMEM); >> } >> >> +/* >> + * Warning: This macro will perform an early return if the CPU has >> + * a coherent icache. The intent is is call this early in function, >> + * and handle the non-coherent icache variant afterwards. >> + * >> + * For a snooping icache, we still need a dummy icbi to purge all the >> + * prefetched instructions from the ifetch buffers. We also need a sync >> + * before the icbi to order the the actual stores to memory that might >> + * have modified instructions with the icbi. >> + */ >> +#define flush_coherent_icache_or_return(addr) { \ >> + if (cpu_has_feature(CPU_FTR_COHERENT_ICACHE)) { \ >> + mb(); /* sync */ \ >> + icbi(addr); \ >> + mb(); /* sync */ \ >> + isync(); \ >> + return; \ >> + } \ >> +} > > I hate this kind of awful macro which kills code readability. Yes I agree. > Please to something like > > static bool flush_coherent_icache_or_return(unsigned long addr) > { > if (!cpu_has_feature(CPU_FTR_COHERENT_ICACHE)) > return false; > > mb(); /* sync */ > icbi(addr); > mb(); /* sync */ > isync(); > return true; > } > > then callers will do: > > if (flush_coherent_icache_or_return(addr)) > return; I don't think it needs the "_or_return" in the name. eg, it can just be: if (flush_coherent_icache(addr)) return; Which reads fine I think, ie. flush the coherent icache, and if that succeeds return, else continue. cheers