Skip to content

Commit c444d16

Browse files
CodingVoidMrChromebox
authored andcommitted
include/endian.h: Add 'always aligned access' support
RISC-V doesn't support unaligned access, so check for that before decoding and encoding. It is not perfectly performant, but still much better then invoking the misaligned exception handler every time there is a misaligned access. We can't modify our whole codebase to always do aligned access, because it is neither feasible in long term nor is fair to add that performance penalty onto other architectures that do support unaligned access. So this is the next best thing. On architectures that do support unaligned access the compiler will just optimize the RISCV_ENV part out and should result in the exact same binary. tested: identical binary on QEMU-aarch64 and QEMU-q35. Change-Id: I4dfccfdc2b302dd30b7ce5a29520c86add13169d Signed-off-by: Maximilian Brune <[email protected]> Reviewed-on: https://review.coreboot.org/c/coreboot/+/86609 Tested-by: build bot (Jenkins) <[email protected]> Reviewed-by: Julius Werner <[email protected]>
1 parent dcd07b3 commit c444d16

File tree

1 file changed

+24
-4
lines changed

1 file changed

+24
-4
lines changed

src/include/endian.h

+24-4
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
#include <arch/byteorder.h>
77
#include <stdint.h>
8+
#include <string.h>
89
#include <swab.h>
910

1011
#if defined(__LITTLE_ENDIAN)
@@ -67,25 +68,44 @@
6768
#define clrsetbits_le16(addr, clear, set) __clrsetbits(le, 16, addr, clear, set)
6869
#define clrsetbits_be16(addr, clear, set) __clrsetbits(be, 16, addr, clear, set)
6970

70-
/* be16dec/be32dec/be64dec/le16dec/le32dec/le64dec family of functions. */
71+
/*
72+
* be16dec/be32dec/be64dec/le16dec/le32dec/le64dec family of functions.
73+
* RISC-V doesn't support misaligned access so decode it byte by byte.
74+
*/
7175
#define DEFINE_ENDIAN_DEC(endian, width) \
7276
static inline uint##width##_t endian##width##dec(const void *p) \
7377
{ \
74-
return endian##width##_to_cpu(*(uint##width##_t *)p); \
78+
if (ENV_RISCV) { \
79+
uint##width##_t val; \
80+
memcpy(&val, p, sizeof(val)); \
81+
return endian##width##_to_cpu(val); \
82+
} else { \
83+
return endian##width##_to_cpu(*(uint##width##_t *)p); \
84+
} \
7585
}
86+
7687
DEFINE_ENDIAN_DEC(be, 16)
7788
DEFINE_ENDIAN_DEC(be, 32)
7889
DEFINE_ENDIAN_DEC(be, 64)
7990
DEFINE_ENDIAN_DEC(le, 16)
8091
DEFINE_ENDIAN_DEC(le, 32)
8192
DEFINE_ENDIAN_DEC(le, 64)
8293

83-
/* be16enc/be32enc/be64enc/le16enc/le32enc/le64enc family of functions. */
94+
/*
95+
* be16enc/be32enc/be64enc/le16enc/le32enc/le64enc family of functions.
96+
* RISC-V doesn't support misaligned access so encode it byte by byte.
97+
*/
8498
#define DEFINE_ENDIAN_ENC(endian, width) \
8599
static inline void endian##width##enc(void *p, uint##width##_t u) \
86100
{ \
87-
*(uint##width##_t *)p = cpu_to_##endian##width(u); \
101+
if (ENV_RISCV) { \
102+
uint##width##_t val = cpu_to_##endian##width(u); \
103+
memcpy(p, &val, sizeof(val)); \
104+
} else { \
105+
*(uint##width##_t *)p = cpu_to_##endian##width(u); \
106+
} \
88107
}
108+
89109
DEFINE_ENDIAN_ENC(be, 16)
90110
DEFINE_ENDIAN_ENC(be, 32)
91111
DEFINE_ENDIAN_ENC(be, 64)

0 commit comments

Comments
 (0)