cbmem: Add custom aligned memcpy() implementation

On some architectures (like AArch64), /dev/mem mappings outside of the
area marked as normal RAM use a memory type that does not support
unaligned accesses. The libc memcpy() implementation on these
architectures may not know or expect that and make an unaligned access
for certain source/dest/length alignments. Add a custom memcpy()
implementation that takes these restrictions into account and use it
anywhere we copy straight out of /dev/mem memory.

Change-Id: I03eece380a14a69d4be3805ed72fba640f6f7d9c
Signed-off-by: Julius Werner <jwerner@chromium.org>
Reviewed-on: https://review.coreboot.org/18300
Tested-by: build bot (Jenkins)
Reviewed-by: Aaron Durbin <adurbin@chromium.org>
This commit is contained in:
Julius Werner 2017-02-03 12:50:03 -08:00 committed by Martin Roth
parent 973104ba1f
commit 127a79e0b6
1 changed files with 31 additions and 1 deletions

View File

@ -60,6 +60,36 @@ static int mem_fd;
static uint64_t lbtable_address;
static size_t lbtable_size;
/*
* Some architectures map /dev/mem memory in a way that doesn't support
* unaligned accesses. Most normal libc memcpy()s aren't safe to use in this
* case, so build our own which makes sure to never do unaligned accesses on
* *src (*dest is fine since we never map /dev/mem for writing).
*/
static void *aligned_memcpy(void *dest, const void *src, size_t n)
{
u8 *d = dest;
const volatile u8 *s = src; /* volatile to prevent optimization */
while ((uintptr_t)s & (sizeof(size_t) - 1)) {
if (n-- == 0)
return dest;
*d++ = *s++;
}
while (n >= sizeof(size_t)) {
*(size_t *)d = *(const volatile size_t *)s;
d += sizeof(size_t);
s += sizeof(size_t);
n -= sizeof(size_t);
}
while (n-- > 0)
*d++ = *s++;
return dest;
}
/*
* calculate ip checksum (16 bit quantities) on a passed in buffer. In case
* the buffer length is odd last byte is excluded from the calculation
@ -608,7 +638,7 @@ static void dump_console(void)
console_p = map_memory_size((unsigned long)console.cbmem_addr,
size + sizeof(size) + sizeof(cursor), 1);
memcpy(console_c, console_p + 8, size);
aligned_memcpy(console_c, console_p + 8, size);
printf("%s\n", console_c);
if (size < cursor)