Skip to content

Commit

Permalink
ARM: avoid unwanted GCC memset()/memcpy() optimisations for IO variants
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Russell King committed Jul 3, 2015
1 parent 9ab79bb commit 1bd4678
Show file tree
Hide file tree
Showing 4 changed files with 16 additions and 3 deletions.
9 changes: 6 additions & 3 deletions arch/arm/include/asm/io.h
Original file line number Diff line number Diff line change
Expand Up @@ -316,21 +316,24 @@ extern void _memset_io(volatile void __iomem *, int, size_t);
static inline void memset_io(volatile void __iomem *dst, unsigned c,
size_t count)
{
memset((void __force *)dst, c, count);
extern void mmioset(void *, unsigned int, size_t);
mmioset((void __force *)dst, c, count);
}
#define memset_io(dst,c,count) memset_io(dst,c,count)

static inline void memcpy_fromio(void *to, const volatile void __iomem *from,
size_t count)
{
memcpy(to, (const void __force *)from, count);
extern void mmiocpy(void *, const void *, size_t);
mmiocpy(to, (const void __force *)from, count);
}
#define memcpy_fromio(to,from,count) memcpy_fromio(to,from,count)

static inline void memcpy_toio(volatile void __iomem *to, const void *from,
size_t count)
{
memcpy((void __force *)to, from, count);
extern void mmiocpy(void *, const void *, size_t);
mmiocpy((void __force *)to, from, count);
}
#define memcpy_toio(to,from,count) memcpy_toio(to,from,count)

Expand Down
6 changes: 6 additions & 0 deletions arch/arm/kernel/armksyms.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@ extern void __aeabi_ulcmp(void);

extern void fpundefinstr(void);

void mmioset(void *, unsigned int, size_t);
void mmiocpy(void *, const void *, size_t);

/* platform dependent support */
EXPORT_SYMBOL(arm_delay_ops);

Expand Down Expand Up @@ -88,6 +91,9 @@ EXPORT_SYMBOL(memmove);
EXPORT_SYMBOL(memchr);
EXPORT_SYMBOL(__memzero);

EXPORT_SYMBOL(mmioset);
EXPORT_SYMBOL(mmiocpy);

#ifdef CONFIG_MMU
EXPORT_SYMBOL(copy_page);

Expand Down
2 changes: 2 additions & 0 deletions arch/arm/lib/memcpy.S
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,10 @@

/* Prototype: void *memcpy(void *dest, const void *src, size_t n); */

ENTRY(mmiocpy)
ENTRY(memcpy)

#include "copy_template.S"

ENDPROC(memcpy)
ENDPROC(mmiocpy)
2 changes: 2 additions & 0 deletions arch/arm/lib/memset.S
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
.text
.align 5

ENTRY(mmioset)
ENTRY(memset)
UNWIND( .fnstart )
ands r3, r0, #3 @ 1 unaligned?
Expand Down Expand Up @@ -133,3 +134,4 @@ UNWIND( .fnstart )
b 1b
UNWIND( .fnend )
ENDPROC(memset)
ENDPROC(mmioset)

0 comments on commit 1bd4678

Please sign in to comment.