Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ARM: avoid unwanted GCC memset()/memcpy() optimisations for IO variants

We don't want GCC optimising our memset_io(), memcpy_fromio() or
memcpy_toio() variants, so we must not call one of the standard
functions. Provide a separate name for our assembly memcpy() and
memset() functions, and use that instead, thereby bypassing GCC's
ability to optimise these operations.

GCCs optimisation may introduce unaligned accesses which are invalid
for device mappings.

Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>

+16 -3
+6 -3
arch/arm/include/asm/io.h
··· 316 316 static inline void memset_io(volatile void __iomem *dst, unsigned c, 317 317 size_t count) 318 318 { 319 - memset((void __force *)dst, c, count); 319 + extern void mmioset(void *, unsigned int, size_t); 320 + mmioset((void __force *)dst, c, count); 320 321 } 321 322 #define memset_io(dst,c,count) memset_io(dst,c,count) 322 323 323 324 static inline void memcpy_fromio(void *to, const volatile void __iomem *from, 324 325 size_t count) 325 326 { 326 - memcpy(to, (const void __force *)from, count); 327 + extern void mmiocpy(void *, const void *, size_t); 328 + mmiocpy(to, (const void __force *)from, count); 327 329 } 328 330 #define memcpy_fromio(to,from,count) memcpy_fromio(to,from,count) 329 331 330 332 static inline void memcpy_toio(volatile void __iomem *to, const void *from, 331 333 size_t count) 332 334 { 333 - memcpy((void __force *)to, from, count); 335 + extern void mmiocpy(void *, const void *, size_t); 336 + mmiocpy((void __force *)to, from, count); 334 337 } 335 338 #define memcpy_toio(to,from,count) memcpy_toio(to,from,count) 336 339
+6
arch/arm/kernel/armksyms.c
··· 50 50 51 51 extern void fpundefinstr(void); 52 52 53 + void mmioset(void *, unsigned int, size_t); 54 + void mmiocpy(void *, const void *, size_t); 55 + 53 56 /* platform dependent support */ 54 57 EXPORT_SYMBOL(arm_delay_ops); 55 58 ··· 90 87 EXPORT_SYMBOL(memmove); 91 88 EXPORT_SYMBOL(memchr); 92 89 EXPORT_SYMBOL(__memzero); 90 + 91 + EXPORT_SYMBOL(mmioset); 92 + EXPORT_SYMBOL(mmiocpy); 93 93 94 94 #ifdef CONFIG_MMU 95 95 EXPORT_SYMBOL(copy_page);
+2
arch/arm/lib/memcpy.S
··· 61 61 62 62 /* Prototype: void *memcpy(void *dest, const void *src, size_t n); */ 63 63 64 + ENTRY(mmiocpy) 64 65 ENTRY(memcpy) 65 66 66 67 #include "copy_template.S" 67 68 68 69 ENDPROC(memcpy) 70 + ENDPROC(mmiocpy)
+2
arch/arm/lib/memset.S
··· 16 16 .text 17 17 .align 5 18 18 19 + ENTRY(mmioset) 19 20 ENTRY(memset) 20 21 UNWIND( .fnstart ) 21 22 ands r3, r0, #3 @ 1 unaligned? ··· 134 133 b 1b 135 134 UNWIND( .fnend ) 136 135 ENDPROC(memset) 136 + ENDPROC(mmioset)