qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Question about RISC-V brom register a1 set value


From: Eric Chan
Subject: Question about RISC-V brom register a1 set value
Date: Sat, 1 Oct 2022 07:48:47 +0800

Hi, qemu

As I know, brom will pass 3 parameters to the next stage bootloader, ex: openSBI.
a0 will pass hartid, a2 will pass fw_dynamic_info start address.
although a1 doesn't use directly in openSBI.
a1 read value is determined in compile time rather than read from the original a1 that passes from brom.
In qemu/hw/riscv/boot.c
both 32bit and 64bit machines read 4byte that offset 32byte from the brom start address.

for 64 bits machine: a1 read low 32bit data member magic of fw_dynamic_info,
the value will same as FW_DYNAMIC_INFO_MAGIC_VALUE because risc-v is little endian.

for 32bits machine: each data member of fw_dynamic_info is 4 bytes, so a1 will read the version rather than magic.

Do the 32bit and 64bit pass different parameters are expected?
If it is not expected, I guess the original version is 64bit machine, and then supports 32bit but misses this detail, I hope I can have an opportunity to fix this problem.
If it is expected, why they must be done?

Thanks,
Eric Chan

qemu/include/hw/riscv/boot_opensbi.h
#define FW_DYNAMIC_INFO_MAGIC_VALUE     0x4942534f
qemu/hw/riscv/boot.c
void riscv_setup_rom_reset_vec(MachineState *machine, RISCVHartArrayState *harts,
                               hwaddr start_addr,
                               hwaddr rom_base, hwaddr rom_size,
                               uint64_t kernel_entry,
                               uint64_t fdt_load_addr)
{
    int i;
    uint32_t start_addr_hi32 = 0x00000000;
    uint32_t fdt_load_addr_hi32 = 0x00000000;

    if (!riscv_is_32bit(harts)) {
        start_addr_hi32 = start_addr >> 32;
        fdt_load_addr_hi32 = fdt_load_addr >> 32;
    }
    /* reset vector */
    uint32_t reset_vec[10] = {
        0x00000297,                  /* 1:  auipc  t0, %pcrel_hi(fw_dyn) */
        0x02828613,                  /*     addi   a2, t0, %pcrel_lo(1b) */
        0xf1402573,                  /*     csrr   a0, mhartid  */
        0,
        0,
        0x00028067,                  /*     jr     t0 */
        start_addr,                  /* start: .dword */
        start_addr_hi32,
        fdt_load_addr,               /* fdt_laddr: .dword */
        fdt_load_addr_hi32,
                                     /* fw_dyn: */
    };
    if (riscv_is_32bit(harts)) {
        reset_vec[3] = 0x0202a583;   /*     lw     a1, 32(t0) */
        reset_vec[4] = 0x0182a283;   /*     lw     t0, 24(t0) */
    } else {
        reset_vec[3] = 0x0202b583;   /*     ld     a1, 32(t0) */
        reset_vec[4] = 0x0182b283;   /*     ld     t0, 24(t0) */
    }

    /* copy in the reset vector in little_endian byte order */
    for (i = 0; i < ARRAY_SIZE(reset_vec); i++) {
        reset_vec[i] = cpu_to_le32(reset_vec[i]);
    }
    rom_add_blob_fixed_as("mrom.reset", reset_vec, sizeof(reset_vec),
                          rom_base, &address_space_memory);
    riscv_rom_copy_firmware_info(machine, rom_base, rom_size, sizeof(reset_vec),
                                 kernel_entry);
}

opensbi/firmware/fw_dynamic.S
fw_boot_hart:
        /* Sanity checks */
        li      a1, FW_DYNAMIC_INFO_MAGIC_VALUE
        REG_L   a0, FW_DYNAMIC_INFO_MAGIC_OFFSET(a2)
        bne     a0, a1, _bad_dynamic_info
        li      a1, FW_DYNAMIC_INFO_VERSION_MAX
        REG_L   a0, FW_DYNAMIC_INFO_VERSION_OFFSET(a2)
        bgt     a0, a1, _bad_dynamic_info

        /* Read boot HART id */
        li      a1, FW_DYNAMIC_INFO_VERSION_2
        blt     a0, a1, 2f
        REG_L   a0, FW_DYNAMIC_INFO_BOOT_HART_OFFSET(a2)
        ret
2:      li      a0, -1
        ret

reply via email to

[Prev in Thread] Current Thread [Next in Thread]