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:
parent
973104ba1f
commit
127a79e0b6
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue