【问题标题】:How does qemu-riscv pass the Device Tree Blob to the guest kernel?qemu-riscv 如何将设备树 Blob 传递给来宾内核?
【发布时间】:2021-09-14 23:22:10
【问题描述】:

qemu-system-riscv 中的默认 bios (OpenSBI) 如何将设备树 Blob 传递给来宾?

我可以从documentation for qemu-system-arm 'virt' 平台看到,当使用 Linux 引导协议时,QEMU 将设备树 Blob (dtb) 的地址传递给 r0 中的来宾,或者在硬编码地址用于裸机客户内核。 QEMU repo 中hw/riscv/virt.c 中的源代码显示为 RISC-V 'virt' 平台生成了一个设备树 Blob(通过create_fdt 函数),但是我找不到的文档都没有描述它是如何传递的给客人。任何帮助表示赞赏。

【问题讨论】:

  • 不是一个完整的答案,但从阅读 Qemu 代码看来,设备树 blob 地址被放置在重置向量 https://gitlab.com/qemu-project/qemu/-/blob/master/hw/riscv/boot.c#L275 中。根据 RISC-V Privileged Architecture 规范,重置向量位置(和内容?不太清楚)是实现定义的。我假设引导加载程序读取重置向量并将地址放在a1 中,从那里它最终被放置在a0 中并用作dtb_pa 中的参数setup_vm

标签: qemu riscv device-tree


【解决方案1】:

qemu-system-riscv 中的默认 bios (OpenSBI) 如何将设备树 Blob 传递给来宾?

它没有。该机制类似于所有 qemu“virt”机器。在这种特殊情况下,生成和加载已编译的 dtb 是 qemu 的责任。

实际上你只能依赖 RAM 和 FLASH 地址,所有其他信息都应该从 Qemu 生成的 DTB 中获取。

引用自 qemu/hw/riscv/boot.c:

riscv_load_fdt
/*
* We should put fdt as far as possible to avoid kernel/initrd overwriting
* its content. But it should be addressable by 32 bit system as well.
* Thus, put it at an 16MB aligned address that less than fdt size from the
* end of dram or 3GB whichever is lesser.
*/

OpenSBI 期望 fdt addr 通过“a1”传递,除非您使用 dtb 内置 FW_FDT_PATH 编译 OpenSBI,请参阅:

opensbi/docs/firmware/fw.md

opensbi/docs/firmware/fw_payload.md

目前编译时无法直接设置fdt的地址(OpenSBI v0.9)。

不过,传递到下一个模式的 fdt 的地址可以通过 FW_PAYLOAD_FDT_ADDR 进行更改。

所以 FW_FDT_PATHFW_PAYLOAD_FDT_ADDR 分别影响 fdt。

Qemu 在 riscv_setup_rom_reset_vec 和其他集合中设置重置向量 fdt_load_addr

接下来会发生什么取决于 OpenSBI 模式(dtb 可以由 OpenSBI 重新分配),但您可以查看 opensbi/sbi_hart.c 中的 sbi_hart_switch_mode:

register unsigned long a0 asm("a0") = arg0;
register unsigned long a1 asm("a1") = arg1;
__asm__ __volatile__("mret" : : "r"(a0), "r"(a1));
__builtin_unreachable();

RISC-V 内核启动过程终于看到https://www.sifive.com/blog/all-aboard-part-6-booting-a-risc-v-linux-kernel

Early Boot in Linux
When Linux boots, it expects the system to be in the following state:
a0 contains a unique per-hart ID. We currently map these to Linux CPU IDs, 
so they're expected to be contiguous and close to 0.
a1 contains a pointer to the device tree, represented as a binary flattened
device tree (DTB).

更新:

例如,您可以看到以下内容:

build-qemu/qemu-system-riscv64 -machine virt -m 2G -nographic -bios opensbi/build/platform/generic/firmware/fw_jump.bin

并且使用 FW_OPTIONS=0x2 编译的 OpenSBI:

Domain0 Name              : root
Domain0 Boot HART         : 0
Domain0 HARTs             : 0*
Domain0 Region00          : 0x0000000002000000-0x000000000200ffff (I)
Domain0 Region01          : 0x0000000080000000-0x000000008003ffff ()
Domain0 Region02          : 0x0000000000000000-0xffffffffffffffff (R,W,X)
Domain0 Next Address      : 0x0000000080200000
Domain0 Next Arg1         : 0x0000000082200000
Domain0 Next Mode         : S-mode
Domain0 SysReset          : yes

【讨论】:

  • 感谢您花时间整理这个答案!
猜你喜欢
  • 2020-02-07
  • 2015-04-13
  • 2016-06-03
  • 1970-01-01
  • 2017-10-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-04-14
相关资源
最近更新 更多