On 11/3/26 12:59, Djordje Todorovic wrote:
Add riscv_is_big_endian() helper that checks the hart's big-endian CPU
property and use it throughout the boot code:
- ELF loading: pass ELFDATA2MSB or ELFDATA2LSB based on endianness
- Firmware dynamic info: use cpu_to_be* or cpu_to_le* based on endianness
- Reset vector: instructions (entries 0-5) remain always little-endian,
data words (entries 6-9) use target data endianness. For RV64 BE, the
hi/lo word pairs within each dword are swapped since LD reads as BE.
This is part of the runtime big-endian support series which avoids
separate BE binaries by handling endianness as a CPU property.
---
hw/riscv/boot.c | 68 +++++++++++++++++++++++++++++++++--------
include/hw/riscv/boot.h | 2 ++
2 files changed, 58 insertions(+), 12 deletions(-)
@@ -474,10 +493,35 @@ void riscv_setup_rom_reset_vec(MachineState *machine,
RISCVHartArrayState *harts
reset_vec[2] = 0x00000013; /* addi x0, x0, 0 */
}
- /* copy in the reset vector in little_endian byte order */
- for (i = 0; i < ARRAY_SIZE(reset_vec); i++) {
+ /* RISC-V instructions are always little-endian */
+ for (i = 0; i < 6; i++) {
reset_vec[i] = cpu_to_le32(reset_vec[i]);
}
+
+ /*
+ * Data words (addresses at entries 6-9) must match the firmware's data
+ * endianness. For 64-bit big-endian, the high/low word order within
+ * each dword must also be swapped since LD interprets bytes as BE.
+ */
+ if (riscv_is_big_endian(harts)) {
Do not consider endianness as an exceptional case. Please re-order
as:
for(...) {
if (32bit) {
if (big_endian) {
Even clearer if you add a riscv_boot_swap_data64() helper:
for(...) {
riscv_boot_swap_data64();
}
+ if (!riscv_is_32bit(harts)) {
+ uint32_t tmp;
+ tmp = reset_vec[6];
+ reset_vec[6] = cpu_to_be32(reset_vec[7]);
+ reset_vec[7] = cpu_to_be32(tmp);
+ tmp = reset_vec[8];
+ reset_vec[8] = cpu_to_be32(reset_vec[9]);
+ reset_vec[9] = cpu_to_be32(tmp);
+ } else {
+ for (i = 6; i < ARRAY_SIZE(reset_vec); i++) {
+ reset_vec[i] = cpu_to_be32(reset_vec[i]);
+ }
+ }
+ } else {
+ for (i = 6; i < ARRAY_SIZE(reset_vec); i++) {
+ reset_vec[i] = cpu_to_le32(reset_vec[i]);
+ }
+ }