qemu-riscv
[Top][All Lists]
Advanced

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

Re: Question about RISC-V brom register a1 set value


From: Philippe Mathieu-Daudé
Subject: Re: Question about RISC-V brom register a1 set value
Date: Mon, 3 Oct 2022 14:37:30 +0200
User-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:91.0) Gecko/20100101 Thunderbird/91.13.1

Cc'ing the RISC-V specific mailing list.

On 1/10/22 01:48, Eric Chan wrote:
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]