泰晓科技 -- 聚焦 Linux - 追本溯源,见微知著!
网站地址:https://tinylab.org

泰晓Linux知识星球:1300+知识点,520+用户
请稍侯

QEMU 启动方式分析(1):QEMU 及 RISC-V 启动流程简介

ysyx 创作于 2022/11/08

Corrector: TinyCorrect v0.1-rc3 - [epw] Author: YJMSTR jay1273062855@outlook.com Date: 2022/08/16 Revisor: Bin Meng, Falcon Project: RISC-V Linux 内核剖析 Sponsor: PLCT Lab, ISCAS

使用软件版本如下:

QEMU: v7.0.0

OpenSBI: v1.1

U-Boot: v2022.04

Linux Kernel: v5.18

1 QEMU 简介

1.1 什么是 QEMU

QEMU (Quick Emulator) 是一个开源的通用机器仿真器与虚拟化工具,主要支持以下使用方式:

  • 用户模式仿真(User Mode Emulation):在该仿真方式下,QEMU 可以在一种架构的 CPU 上运行为另一种架构的 CPU 编译的程序。
  • 系统仿真(System Emulation):在该仿真方式下,QEMU 提供运行客户机所需的完整环境,包括 CPU,内存和外围设备。

当使用 QEMU 模拟 RISC-V 架构时,QEMU 能够提供 virt 虚拟开发板,它不对应现实中的任何硬件,但它支持模拟多种硬件设备。在接下来分析 QEMU 的启动方式时,本系列文章均以 QEMU ‘virt’ 机器作为实验平台。Linux Lab 中也提供了 riscv32/virtriscv64/virt 这两个虚拟开发板,可以用于 RISC-V 的学习。

1.2 QEMU RISC-V 环境构建

Linux Lab 中集成了 QEMU,支持一键自动编译等功能,具体可以参考 Linux Lab 官方手册,当前的 Linux Lab 版本是 v1.0。

下载并构建支持 RISC-V 的 QEMU 的流程如下:

  1. $ wget https://download.qemu.org/qemu-7.0.0.tar.xz
  2. $ tar xvJf qemu-7.0.0.tar.xz
  3. $ cd qemu-7.0.0
  4. $ ./configure --target-list="riscv32-softmmu riscv64-softmmu"
  5. $ make -j $(nproc)
  6. $ make install

安装完成后在终端中输入 qemu-system-riscv64 --version,如果显示以下文字,则说明安装成功:

  1. QEMU emulator version 7.0.0
  2. Copyright (c) 2003-2022 Fabrice Bellard and the QEMU Project developers

2 RISC-V 启动流程简介

如下图所示,RISC-V 引导流程分为多个阶段,我们重点关注 OpenSBI 与 U-Boot。

RISC-V 引导流程图

2.1 ZSBL

ZSBL (Zero Stage Boot Loader) 从 ROM 中获取核心代码。

2.2 FSBL:U-Boot SPL

FSBL (First Stage Boot Loader) 由 Soc 指定,可能是 CoreBoot 或 U-Boot SPL。这一阶段将会完成 DDR 的初始化,并载入运行时环境(runtime)与引导加载器(bootloader)。

其中,U-Boot SPL 是一个非常小的 loader 程序,其主要功能是加载真正的 U-Boot 并运行。具体的加载过程可以参考 RISC-V UEFI 架构支持详解,第 1 部分 - OpenSBI/U-Boot/UEFI 简介 - 泰晓科技(tinylab.org) 中 U-Boot 相关部分。在编译 U-Boot 之前需要先编译 OpenSBI。

2.3 Runtime:OpenSBI

RISC-V 的 Runtime 通常是 OpenSBI,它是运行在 M 模式下的程序,但能够为 S 模式提供一些特定的服务,这些服务由 SBI (Supervisor Binary Interface) 规范定义。

SBI 是指 Supervisor Binary Interface,它是运行在 M 模式下的程序,操作系统通过 SBI 来调用 M 模式的硬件资源。而 OpenSBI 是指西数开发的一种开源 SBI 实现。RISC-V OpenSBI 快速上手 - 泰晓科技(tinylab.org) 这篇文章给出了在 Linux Lab 中编译运行 OpenSBI 的教程。

OpenSBI 有三种 Firmware:

  • FW_PAYLOAD:下一引导阶段被作为 payload 打包进来,通常是 U-Boot 或 Linux。这是兼容 Linux 的 RISC-V 硬件所使用的默认 firmware。
  • FW_JUMP:跳转到一个固定地址,该地址上需存有下一个加载器。QEMU 的早期版本曾经使用过它。
  • FW_DYNAMIC:根据前一个阶段传入的信息加载下一个阶段。通常是 U-Boot SPL 使用它。现在 QEMU 默认使用 FW_DYNAMIC。

下载并编译 OpenSBI 的流程如下:

  1. $ git clone https://gitee.com/tinylab/qemu-opensbi.git
  2. $ cd qemu-opensbi/
  3. $ export CROSS_COMPILE=riscv64-linux-gnu-
  4. $ make all PLATFORM=generic PLATFORM_RISCV_XLEN=64

其中 PLATFORM 选择 qemu_virt 所需的 generic 平台。

2.4 Bootloader:U-Boot

Bootloader 是嵌入式系统在加电后执行的较为早期的代码,这段程序将会完成硬件的初始化与环境设置等操作,再将操作系统映像或嵌入式应用程序载入内存,然后跳转到操作系统所在空间,启动操作系统。

U-Boot 指 Universal Boot Loader,是一种流行的嵌入式 Linux 系统引导加载程序。它分为 U-Boot SPL 与 U-Boot 两部分,其中 SPL 指第二阶段程序加载器(Secondary Program Loader)。

U-Boot SPL 在之前的 “FSBL/U-Boot SPL” 小节已经介绍过,这里主要谈谈 U-Boot 本身。它被 U-Boot SPL 加载进内存后,将会发挥 Bootloader 的作用。在 这篇文章 中有对 U-Boot 加载过程以及代码的分析。

下载 U-Boot:

  1. $ git clone https://gitee.com/mirrors/u-boot.git
  2. $ cd u-boot
  3. $ git checkout v2022.04

为了通过 U-Boot 启动 RISC-V 64 架构的 Linux,我们需要在编译时选择交叉编译工具链 riscv64-linux-gnu-gcc。在 U-Boot 目录下执行以下命令:

  1. $ export CROSS_COMPILE=riscv64-linux-gnu-
  2. $ make qemu-riscv64_smode_defconfig
  3. $ make -j $(nproc)

如果想直接引导 S 模式下的 U-Boot 镜像,使用以下命令:

  1. $ qemu-system-riscv64 -M virt -smp 4 -m 2G \
  2. -display none -serial stdio \
  3. -kernel /path/to/u-boot.bin

其中 /path/to/u-boot.bin 指之前编译出的 u-boot.bin 所在路径。

如需启动 U-Boot 或 Linux,需要在 OpenSBI 编译时指定 U-Boot 或 Linux 的 payload 路径。以 U-Boot 为例,切换到 OpenSBI 目录下,编译命令如下:

  1. $ export CROSS_COMPILE=riscv64-linux-gnu-
  2. $ make PLATFORM=generic FW_PAYLOAD_PATH=<uboot_build_directory>/u-boot.bin

运行:

  1. $ qemu-system-riscv64 -M virt -m 256M -nographic \
  2. -bios build/platform/generic/firmware/fw_payload.elf

或是使用以下命令运行:

  1. $ qemu-system-riscv64 -M virt -m 256M -nographic \
  2. -bios build/platform/generic/firmware/fw_jump.bin \
  3. -kernel <uboot_build_directory>/u-boot.bin

如果要使用 U-Boot SPL,使用如下命令:

  1. $ export CROSS_COMPILE=riscv64-linux-gnu-
  2. $ cd /path/to/u-boot
  3. $ export OPENSBI=/path/to/opensbi/build/platform/generic/firmware/fw_dynamic.bin
  4. $ make qemu-riscv64_spl_defconfig
  5. $ make -j $(nproc)
  6. $ qemu-system-riscv64 -M virt -smp 4 -m 2G \
  7. -display none -serial stdio \
  8. -bios /path/to/u-boot-spl \
  9. -device loader,file=/path/to/u-boot.itb,addr=0x80200000

2.5 OS:Linux

编译内核需要使用交叉编译工具链。

在终端中执行以下命令:

  1. $ mkdir linux-kernel
  2. $ cd linux-kernel
  3. $ git init
  4. $ git fetch git@gitee.com:mirrors/linux_old1.git
  5. // 如果断了,可以多次执行 git fetch,以便实现续传
  6. $ git checkout v5.18

随后进行内核的配置与编译:

  1. $ make ARCH=riscv CROSS_COMPILE=riscv64-linux-gnu- defconfig
  2. $ make ARCH=riscv CROSS_COMPILE=riscv64-linux-gnu- -j $(nproc)

编译出的 kernel image 位于 arch/riscv/boot/Image.

随后我们用 busybox 构建根文件系统 rootfs,首先下载编译 busybox:

  1. $ git clone https://gitee.com/mirrors/busyboxsource
  2. $ cd busyboxsource
  3. $ export CROSS_COMPILE=riscv64-linux-gnu-
  4. $ make defconfig
  5. $ make menuconfig
  6. # 这里启用了 Settings-->Build Options 里的 Build static binary (no shared libs) 选项
  7. $ make -j $(nproc)
  8. $ make install

制作文件系统并新建一个启动脚本:

  1. $ cd ~
  2. $ qemu-img create rootfs.img 1g
  3. $ mkfs.ext4 rootfs.img
  4. $ mkdir rootfs
  5. $ sudo mount -o loop rootfs.img rootfs
  6. $ cd rootfs
  7. $ sudo cp -r ../busyboxsource/_install/* .
  8. $ sudo mkdir proc sys dev etc etc/init.d
  9. $ cd etc/init.d/
  10. $ sudo touch rcS
  11. $ sudo vi rcS

编辑启动脚本 rcS 中的内容如下:

  1. #!/bin/sh
  2. mount -t proc none /proc
  3. mount -t sysfs none /sys
  4. /sbin/mdev -s

并修改文件权限:

  1. $ sudo chmod +x rcS
  2. $ cd ~
  3. $ sudo umount rootfs

随后尝试直接引导内核:

  1. $ qemu-system-riscv64 -M virt -m 256M -nographic \
  2. -kernel linux-kernel/arch/riscv/boot/Image \
  3. -drive file=rootfs.img,format=raw,id=hd0 \
  4. -device virtio-blk-device,drive=hd0 \
  5. -append "root=/dev/vda rw console=ttyS0"

启动日志如下:

  1. OpenSBI v1.0
  2. ____ _____ ____ _____
  3. / __ \ / ____| _ \_ _|
  4. | | | |_ __ ___ _ __ | (___ | |_) || |
  5. | | | | '_ \ / _ \ '_ \ \___ \| _ < | |
  6. | |__| | |_) | __/ | | |____) | |_) || |_
  7. \____/| .__/ \___|_| |_|_____/|____/_____|
  8. | |
  9. |_|
  10. Platform Name : riscv-virtio,qemu
  11. Platform Features : medeleg
  12. Platform HART Count : 1
  13. Platform IPI Device : aclint-mswi
  14. Platform Timer Device : aclint-mtimer @ 10000000Hz
  15. Platform Console Device : uart8250
  16. Platform HSM Device : ---
  17. Platform Reboot Device : sifive_test
  18. Platform Shutdown Device : sifive_test
  19. Firmware Base : 0x80000000
  20. Firmware Size : 252 KB
  21. Runtime SBI Version : 0.3
  22. Domain0 Name : root
  23. Domain0 Boot HART : 0
  24. Domain0 HARTs : 0*
  25. Domain0 Region00 : 0x0000000002000000-0x000000000200ffff (I)
  26. Domain0 Region01 : 0x0000000080000000-0x000000008003ffff ()
  27. Domain0 Region02 : 0x0000000000000000-0xffffffffffffffff (R,W,X)
  28. Domain0 Next Address : 0x0000000080200000
  29. Domain0 Next Arg1 : 0x000000008f000000
  30. Domain0 Next Mode : S-mode
  31. Domain0 SysReset : yes
  32. Boot HART ID : 0
  33. Boot HART Domain : root
  34. Boot HART ISA : rv64imafdcsuh
  35. Boot HART Features : scounteren,mcounteren,time
  36. Boot HART PMP Count : 16
  37. Boot HART PMP Granularity : 4
  38. Boot HART PMP Address Bits: 54
  39. Boot HART MHPM Count : 0
  40. Boot HART MIDELEG : 0x0000000000001666
  41. Boot HART MEDELEG : 0x0000000000f0b509
  42. [ 0.000000] Linux version 5.18.0 (yjmstr@yjmstr) (riscv64-linux-gnu-gcc (Ubuntu 11.2.0-16ubuntu1) 11.2.0, GNU ld (GNU Binutils for Ubuntu) 2.38) #2 SMP Sun Aug 14 13:14:26 CST 2022
  43. [ 0.000000] OF: fdt: Ignoring memory range 0x80000000 - 0x80200000
  44. [ 0.000000] Machine model: riscv-virtio,qemu
  45. [ 0.000000] efi: UEFI not found.
  46. [ 0.000000] Zone ranges:
  47. [ 0.000000] DMA32 [mem 0x0000000080200000-0x000000008fffffff]
  48. [ 0.000000] Normal empty
  49. [ 0.000000] Movable zone start for each node
  50. [ 0.000000] Early memory node ranges
  51. [ 0.000000] node 0: [mem 0x0000000080200000-0x000000008fffffff]
  52. [ 0.000000] Initmem setup node 0 [mem 0x0000000080200000-0x000000008fffffff]
  53. [ 0.000000] SBI specification v0.3 detected
  54. [ 0.000000] SBI implementation ID=0x1 Version=0x10000
  55. [ 0.000000] SBI TIME extension detected
  56. [ 0.000000] SBI IPI extension detected
  57. [ 0.000000] SBI RFENCE extension detected
  58. [ 0.000000] SBI SRST extension detected
  59. [ 0.000000] SBI HSM extension detected
  60. [ 0.000000] riscv: base ISA extensions acdfhim
  61. [ 0.000000] riscv: ELF capabilities acdfim
  62. [ 0.000000] percpu: Embedded 18 pages/cpu s34040 r8192 d31496 u73728
  63. [ 0.000000] Built 1 zonelists, mobility grouping on. Total pages: 64135
  64. [ 0.000000] Kernel command line: root=/dev/vda rw console=ttyS0
  65. [ 0.000000] Dentry cache hash table entries: 32768 (order: 6, 262144 bytes, linear)
  66. [ 0.000000] Inode-cache hash table entries: 16384 (order: 5, 131072 bytes, linear)
  67. [ 0.000000] mem auto-init: stack:off, heap alloc:off, heap free:off
  68. [ 0.000000] Virtual kernel memory layout:
  69. [ 0.000000] fixmap : 0xff1bfffffee00000 - 0xff1bffffff000000 (2048 kB)
  70. [ 0.000000] pci io : 0xff1bffffff000000 - 0xff1c000000000000 ( 16 MB)
  71. [ 0.000000] vmemmap : 0xff1c000000000000 - 0xff20000000000000 (1073741824 MB)
  72. [ 0.000000] vmalloc : 0xff20000000000000 - 0xff60000000000000 (17179869184 MB)
  73. [ 0.000000] lowmem : 0xff60000000000000 - 0xff6000000fe00000 ( 254 MB)
  74. [ 0.000000] kernel : 0xffffffff80000000 - 0xffffffffffffffff (2047 MB)
  75. [ 0.000000] Memory: 237564K/260096K available (6460K kernel code, 4865K rwdata, 2048K rodata, 2165K init, 334K bss, 22532K reserved, 0K cma-reserved)
  76. [ 0.000000] SLUB: HWalign=64, Order=0-3, MinObjects=0, CPUs=1, Nodes=1
  77. [ 0.000000] rcu: Hierarchical RCU implementation.
  78. [ 0.000000] rcu: RCU restricting CPUs from NR_CPUS=8 to nr_cpu_ids=1.
  79. [ 0.000000] rcu: RCU debug extended QS entry/exit.
  80. [ 0.000000] Tracing variant of Tasks RCU enabled.
  81. [ 0.000000] rcu: RCU calculated value of scheduler-enlistment delay is 25 jiffies.
  82. [ 0.000000] rcu: Adjusting geometry for rcu_fanout_leaf=16, nr_cpu_ids=1
  83. [ 0.000000] NR_IRQS: 64, nr_irqs: 64, preallocated irqs: 0
  84. [ 0.000000] riscv-intc: 64 local interrupts mapped
  85. [ 0.000000] plic: plic@c000000: mapped 53 interrupts with 1 handlers for 2 contexts.
  86. [ 0.000000] random: get_random_bytes called from start_kernel+0x4be/0x71a with crng_init=0
  87. [ 0.000000] riscv_timer_init_dt: Registering clocksource cpuid [0] hartid [0]
  88. [ 0.000000] clocksource: riscv_clocksource: mask: 0xffffffffffffffff max_cycles: 0x24e6a1710, max_idle_ns: 440795202120 ns
  89. [ 0.000110] sched_clock: 64 bits at 10MHz, resolution 100ns, wraps every 4398046511100ns
  90. [ 0.005548] Console: colour dummy device 80x25
  91. [ 0.010694] Calibrating delay loop (skipped), value calculated using timer frequency.. 20.00 BogoMIPS (lpj=40000)
  92. [ 0.010903] pid_max: default: 32768 minimum: 301
  93. [ 0.014081] Mount-cache hash table entries: 512 (order: 0, 4096 bytes, linear)
  94. [ 0.014137] Mountpoint-cache hash table entries: 512 (order: 0, 4096 bytes, linear)
  95. [ 0.045919] cblist_init_generic: Setting adjustable number of callback queues.
  96. [ 0.046122] cblist_init_generic: Setting shift to 0 and lim to 1.
  97. [ 0.046833] ASID allocator using 16 bits (65536 entries)
  98. [ 0.048191] rcu: Hierarchical SRCU implementation.
  99. [ 0.050214] EFI services will not be available.
  100. [ 0.052914] smp: Bringing up secondary CPUs ...
  101. [ 0.053035] smp: Brought up 1 node, 1 CPU
  102. [ 0.064892] devtmpfs: initialized
  103. [ 0.072338] clocksource: jiffies: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 7645041785100000 ns
  104. [ 0.072854] futex hash table entries: 256 (order: 2, 16384 bytes, linear)
  105. [ 0.078634] NET: Registered PF_NETLINK/PF_ROUTE protocol family
  106. [ 0.084802] cpuidle: using governor menu
  107. [ 0.116094] HugeTLB registered 2.00 MiB page size, pre-allocated 0 pages
  108. [ 0.121303] iommu: Default domain type: Translated
  109. [ 0.121359] iommu: DMA domain TLB invalidation policy: strict mode
  110. [ 0.122808] SCSI subsystem initialized
  111. [ 0.124731] usbcore: registered new interface driver usbfs
  112. [ 0.125085] usbcore: registered new interface driver hub
  113. [ 0.125244] usbcore: registered new device driver usb
  114. [ 0.139845] vgaarb: loaded
  115. [ 0.141481] clocksource: Switched to clocksource riscv_clocksource
  116. [ 0.160052] NET: Registered PF_INET protocol family
  117. [ 0.161357] IP idents hash table entries: 4096 (order: 3, 32768 bytes, linear)
  118. [ 0.165568] tcp_listen_portaddr_hash hash table entries: 128 (order: 0, 5120 bytes, linear)
  119. [ 0.165859] TCP established hash table entries: 2048 (order: 2, 16384 bytes, linear)
  120. [ 0.166095] TCP bind hash table entries: 2048 (order: 4, 65536 bytes, linear)
  121. [ 0.166331] TCP: Hash tables configured (established 2048 bind 2048)
  122. [ 0.168312] UDP hash table entries: 256 (order: 2, 24576 bytes, linear)
  123. [ 0.168666] UDP-Lite hash table entries: 256 (order: 2, 24576 bytes, linear)
  124. [ 0.170129] NET: Registered PF_UNIX/PF_LOCAL protocol family
  125. [ 0.173256] RPC: Registered named UNIX socket transport module.
  126. [ 0.173403] RPC: Registered udp transport module.
  127. [ 0.173427] RPC: Registered tcp transport module.
  128. [ 0.173453] RPC: Registered tcp NFSv4.1 backchannel transport module.
  129. [ 0.173613] PCI: CLS 0 bytes, default 64
  130. [ 0.180799] workingset: timestamp_bits=62 max_order=16 bucket_order=0
  131. [ 0.195702] NFS: Registering the id_resolver key type
  132. [ 0.196803] Key type id_resolver registered
  133. [ 0.196859] Key type id_legacy registered
  134. [ 0.197434] nfs4filelayout_init: NFSv4 File Layout Driver Registering...
  135. [ 0.197557] nfs4flexfilelayout_init: NFSv4 Flexfile Layout Driver Registering...
  136. [ 0.198259] 9p: Installing v9fs 9p2000 file system support
  137. [ 0.199780] NET: Registered PF_ALG protocol family
  138. [ 0.200339] Block layer SCSI generic (bsg) driver version 0.4 loaded (major 250)
  139. [ 0.200507] io scheduler mq-deadline registered
  140. [ 0.200597] io scheduler kyber registered
  141. [ 0.210780] pci-host-generic 30000000.pci: host bridge /soc/pci@30000000 ranges:
  142. [ 0.211790] pci-host-generic 30000000.pci: IO 0x0003000000..0x000300ffff -> 0x0000000000
  143. [ 0.212339] pci-host-generic 30000000.pci: MEM 0x0040000000..0x007fffffff -> 0x0040000000
  144. [ 0.212418] pci-host-generic 30000000.pci: MEM 0x0400000000..0x07ffffffff -> 0x0400000000
  145. [ 0.213009] pci-host-generic 30000000.pci: Memory resource size exceeds max for 32 bits
  146. [ 0.214178] pci-host-generic 30000000.pci: ECAM at [mem 0x30000000-0x3fffffff] for [bus 00-ff]
  147. [ 0.215635] pci-host-generic 30000000.pci: PCI host bridge to bus 0000:00
  148. [ 0.215922] pci_bus 0000:00: root bus resource [bus 00-ff]
  149. [ 0.216027] pci_bus 0000:00: root bus resource [io 0x0000-0xffff]
  150. [ 0.216104] pci_bus 0000:00: root bus resource [mem 0x40000000-0x7fffffff]
  151. [ 0.216122] pci_bus 0000:00: root bus resource [mem 0x400000000-0x7ffffffff]
  152. [ 0.217645] pci 0000:00:00.0: [1b36:0008] type 00 class 0x060000
  153. [ 0.293879] Serial: 8250/16550 driver, 4 ports, IRQ sharing disabled
  154. [ 0.302601] printk: console [ttyS0] disabled
  155. [ 0.304582] 10000000.uart: ttyS0 at MMIO 0x10000000 (irq = 2, base_baud = 230400) is a 16550A
  156. [ 0.327092] printk: console [ttyS0] enabled
  157. [ 0.343852] loop: module loaded
  158. [ 0.347926] virtio_blk virtio0: [vda] 2097152 512-byte logical blocks (1.07 GB/1.00 GiB)
  159. [ 0.372012] e1000e: Intel(R) PRO/1000 Network Driver
  160. [ 0.372155] e1000e: Copyright(c) 1999 - 2015 Intel Corporation.
  161. [ 0.372587] ehci_hcd: USB 2.0 'Enhanced' Host Controller (EHCI) Driver
  162. [ 0.372811] ehci-pci: EHCI PCI platform driver
  163. [ 0.373121] ehci-platform: EHCI generic platform driver
  164. [ 0.373489] ohci_hcd: USB 1.1 'Open' Host Controller (OHCI) Driver
  165. [ 0.373714] ohci-pci: OHCI PCI platform driver
  166. [ 0.374048] ohci-platform: OHCI generic platform driver
  167. [ 0.375168] usbcore: registered new interface driver uas
  168. [ 0.375509] usbcore: registered new interface driver usb-storage
  169. [ 0.376576] mousedev: PS/2 mouse device common for all mice
  170. [ 0.380046] goldfish_rtc 101000.rtc: registered as rtc0
  171. [ 0.380819] goldfish_rtc 101000.rtc: setting system clock to 2022-08-19T12:22:18 UTC (1660911738)
  172. [ 0.383918] syscon-poweroff soc:poweroff: pm_power_off already claimed for sbi_srst_power_off
  173. [ 0.384279] syscon-poweroff: probe of soc:poweroff failed with error -16
  174. [ 0.385888] sdhci: Secure Digital Host Controller Interface driver
  175. [ 0.386097] sdhci: Copyright(c) Pierre Ossman
  176. [ 0.386425] sdhci-pltfm: SDHCI platform and OF driver helper
  177. [ 0.387522] usbcore: registered new interface driver usbhid
  178. [ 0.387713] usbhid: USB HID core driver
  179. [ 0.388131] riscv-pmu-sbi: SBI PMU extension is available
  180. [ 0.388784] riscv-pmu-sbi: 15 firmware and 2 hardware counters
  181. [ 0.389008] riscv-pmu-sbi: Perf sampling/filtering is not supported as sscof extension is not available
  182. [ 0.393847] NET: Registered PF_INET6 protocol family
  183. [ 0.400899] Segment Routing with IPv6
  184. [ 0.401209] In-situ OAM (IOAM) with IPv6
  185. [ 0.401878] sit: IPv6, IPv4 and MPLS over IPv4 tunneling driver
  186. [ 0.405085] NET: Registered PF_PACKET protocol family
  187. [ 0.406670] 9pnet: Installing 9P2000 support
  188. [ 0.407129] Key type dns_resolver registered
  189. [ 0.409166] debug_vm_pgtable: [debug_vm_pgtable ]: Validating architecture page table helpers
  190. [ 0.473625] EXT4-fs (vda): mounted filesystem with ordered data mode. Quota mode: disabled.
  191. [ 0.474143] VFS: Mounted root (ext4 filesystem) on device 254:0.
  192. [ 0.477311] devtmpfs: mounted
  193. [ 0.507212] Freeing unused kernel image (initmem) memory: 2164K
  194. [ 0.508186] Run /sbin/init as init process
  195. Please press Enter to activate this console.

可以看见打印出的启动信息中的 OpenSBI 版本是 v1.0,这是 QEMU v7.0.0 自带的 OpenSBI 版本。根据 QEMU 官方文档,当没有 -bios 这一启动参数时,QEMU 将会加载自带的 OpenSBI firmware。而当使用 -bios none 作为启动参数时,QEMU 就不会自动加载任何 firmware。当使用 -bios <file> 指定了特定文件作为 firmware 时,QEMU 就会加载我们指定的那个 firmware。

使用我们自己编译的 OpenSBI 引导内核的命令如下:

  1. $ qemu-system-riscv64 -M virt -m 256M -nographic \
  2. -bios qemu-opensbi/build/platform/generic/firmware/fw_jump.bin \
  3. -kernel linux-kernel/arch/riscv/boot/Image \
  4. -drive file=rootfs.img,format=raw,id=hd0 \
  5. -device virtio-blk-device,drive=hd0 \
  6. -append "root=/dev/vda rw console=ttyS0"

此处通过 -bios 参数指定了 OpenSBI 编译出的 fw_jump 类型的 firmware。启动日志如下:

  1. OpenSBI v1.1
  2. ____ _____ ____ _____
  3. / __ \ / ____| _ \_ _|
  4. | | | |_ __ ___ _ __ | (___ | |_) || |
  5. | | | | '_ \ / _ \ '_ \ \___ \| _ < | |
  6. | |__| | |_) | __/ | | |____) | |_) || |_
  7. \____/| .__/ \___|_| |_|_____/|____/_____|
  8. | |
  9. |_|
  10. Platform Name : riscv-virtio,qemu
  11. Platform Features : medeleg
  12. Platform HART Count : 1
  13. Platform IPI Device : aclint-mswi
  14. Platform Timer Device : aclint-mtimer @ 10000000Hz
  15. Platform Console Device : uart8250
  16. Platform HSM Device : ---
  17. Platform Reboot Device : sifive_test
  18. Platform Shutdown Device : sifive_test
  19. Firmware Base : 0x80000000
  20. Firmware Size : 288 KB
  21. Runtime SBI Version : 1.0
  22. Domain0 Name : root
  23. Domain0 Boot HART : 0
  24. Domain0 HARTs : 0*
  25. Domain0 Region00 : 0x0000000002000000-0x000000000200ffff (I)
  26. Domain0 Region01 : 0x0000000080000000-0x000000008007ffff ()
  27. Domain0 Region02 : 0x0000000000000000-0xffffffffffffffff (R,W,X)
  28. Domain0 Next Address : 0x0000000080200000
  29. Domain0 Next Arg1 : 0x0000000082200000
  30. Domain0 Next Mode : S-mode
  31. Domain0 SysReset : yes
  32. Boot HART ID : 0
  33. Boot HART Domain : root
  34. Boot HART Priv Version : v1.10
  35. Boot HART Base ISA : rv64imafdch
  36. Boot HART ISA Extensions : time
  37. Boot HART PMP Count : 16
  38. Boot HART PMP Granularity : 4
  39. Boot HART PMP Address Bits: 54
  40. Boot HART MHPM Count : 0
  41. Boot HART MIDELEG : 0x0000000000001666
  42. Boot HART MEDELEG : 0x0000000000f0b509
  43. [ 0.000000] Linux version 5.18.0 (yjmstr@yjmstr) (riscv64-linux-gnu-gcc (Ubuntu 11.2.0-16ubuntu1) 11.2.0, GNU ld (GNU Binutils for Ubuntu) 2.38) #2 SMP Sun Aug 14 13:14:26 CST 2022
  44. [ 0.000000] OF: fdt: Ignoring memory range 0x80000000 - 0x80200000
  45. [ 0.000000] Machine model: riscv-virtio,qemu
  46. [ 0.000000] efi: UEFI not found.
  47. [ 0.000000] Zone ranges:
  48. [ 0.000000] DMA32 [mem 0x0000000080200000-0x000000008fffffff]
  49. [ 0.000000] Normal empty
  50. [ 0.000000] Movable zone start for each node
  51. [ 0.000000] Early memory node ranges
  52. [ 0.000000] node 0: [mem 0x0000000080200000-0x000000008fffffff]
  53. [ 0.000000] Initmem setup node 0 [mem 0x0000000080200000-0x000000008fffffff]
  54. [ 0.000000] SBI specification v1.0 detected
  55. [ 0.000000] SBI implementation ID=0x1 Version=0x10001
  56. [ 0.000000] SBI TIME extension detected
  57. [ 0.000000] SBI IPI extension detected
  58. [ 0.000000] SBI RFENCE extension detected
  59. [ 0.000000] SBI SRST extension detected
  60. [ 0.000000] SBI HSM extension detected
  61. [ 0.000000] riscv: base ISA extensions acdfhim
  62. [ 0.000000] riscv: ELF capabilities acdfim
  63. [ 0.000000] percpu: Embedded 18 pages/cpu s34040 r8192 d31496 u73728
  64. [ 0.000000] Built 1 zonelists, mobility grouping on. Total pages: 64135
  65. [ 0.000000] Kernel command line: root=/dev/vda rw console=ttyS0
  66. [ 0.000000] Dentry cache hash table entries: 32768 (order: 6, 262144 bytes, linear)
  67. [ 0.000000] Inode-cache hash table entries: 16384 (order: 5, 131072 bytes, linear)
  68. [ 0.000000] mem auto-init: stack:off, heap alloc:off, heap free:off
  69. [ 0.000000] Virtual kernel memory layout:
  70. [ 0.000000] fixmap : 0xff1bfffffee00000 - 0xff1bffffff000000 (2048 kB)
  71. [ 0.000000] pci io : 0xff1bffffff000000 - 0xff1c000000000000 ( 16 MB)
  72. [ 0.000000] vmemmap : 0xff1c000000000000 - 0xff20000000000000 (1073741824 MB)
  73. [ 0.000000] vmalloc : 0xff20000000000000 - 0xff60000000000000 (17179869184 MB)
  74. [ 0.000000] lowmem : 0xff60000000000000 - 0xff6000000fe00000 ( 254 MB)
  75. [ 0.000000] kernel : 0xffffffff80000000 - 0xffffffffffffffff (2047 MB)
  76. [ 0.000000] Memory: 237564K/260096K available (6460K kernel code, 4865K rwdata, 2048K rodata, 2165K init, 334K bss, 22532K reserved, 0K cma-reserved)
  77. [ 0.000000] SLUB: HWalign=64, Order=0-3, MinObjects=0, CPUs=1, Nodes=1
  78. [ 0.000000] rcu: Hierarchical RCU implementation.
  79. [ 0.000000] rcu: RCU restricting CPUs from NR_CPUS=8 to nr_cpu_ids=1.
  80. [ 0.000000] rcu: RCU debug extended QS entry/exit.
  81. [ 0.000000] Tracing variant of Tasks RCU enabled.
  82. [ 0.000000] rcu: RCU calculated value of scheduler-enlistment delay is 25 jiffies.
  83. [ 0.000000] rcu: Adjusting geometry for rcu_fanout_leaf=16, nr_cpu_ids=1
  84. [ 0.000000] NR_IRQS: 64, nr_irqs: 64, preallocated irqs: 0
  85. [ 0.000000] riscv-intc: 64 local interrupts mapped
  86. [ 0.000000] plic: plic@c000000: mapped 53 interrupts with 1 handlers for 2 contexts.
  87. [ 0.000000] random: get_random_bytes called from start_kernel+0x4be/0x71a with crng_init=0
  88. [ 0.000000] riscv_timer_init_dt: Registering clocksource cpuid [0] hartid [0]
  89. [ 0.000000] clocksource: riscv_clocksource: mask: 0xffffffffffffffff max_cycles: 0x24e6a1710, max_idle_ns: 440795202120 ns
  90. [ 0.000111] sched_clock: 64 bits at 10MHz, resolution 100ns, wraps every 4398046511100ns
  91. [ 0.005518] Console: colour dummy device 80x25
  92. [ 0.010392] Calibrating delay loop (skipped), value calculated using timer frequency.. 20.00 BogoMIPS (lpj=40000)
  93. [ 0.010596] pid_max: default: 32768 minimum: 301
  94. [ 0.013666] Mount-cache hash table entries: 512 (order: 0, 4096 bytes, linear)
  95. [ 0.013719] Mountpoint-cache hash table entries: 512 (order: 0, 4096 bytes, linear)
  96. [ 0.045715] cblist_init_generic: Setting adjustable number of callback queues.
  97. [ 0.045930] cblist_init_generic: Setting shift to 0 and lim to 1.
  98. [ 0.046678] ASID allocator using 16 bits (65536 entries)
  99. [ 0.047947] rcu: Hierarchical SRCU implementation.
  100. [ 0.050035] EFI services will not be available.
  101. [ 0.052640] smp: Bringing up secondary CPUs ...
  102. [ 0.052761] smp: Brought up 1 node, 1 CPU
  103. [ 0.064569] devtmpfs: initialized
  104. [ 0.072062] clocksource: jiffies: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 7645041785100000 ns
  105. [ 0.072424] futex hash table entries: 256 (order: 2, 16384 bytes, linear)
  106. [ 0.078307] NET: Registered PF_NETLINK/PF_ROUTE protocol family
  107. [ 0.084426] cpuidle: using governor menu
  108. [ 0.114553] HugeTLB registered 2.00 MiB page size, pre-allocated 0 pages
  109. [ 0.120275] iommu: Default domain type: Translated
  110. [ 0.120336] iommu: DMA domain TLB invalidation policy: strict mode
  111. [ 0.121627] SCSI subsystem initialized
  112. [ 0.123678] usbcore: registered new interface driver usbfs
  113. [ 0.124019] usbcore: registered new interface driver hub
  114. [ 0.124451] usbcore: registered new device driver usb
  115. [ 0.138626] vgaarb: loaded
  116. [ 0.140390] clocksource: Switched to clocksource riscv_clocksource
  117. [ 0.159138] NET: Registered PF_INET protocol family
  118. [ 0.160529] IP idents hash table entries: 4096 (order: 3, 32768 bytes, linear)
  119. [ 0.164755] tcp_listen_portaddr_hash hash table entries: 128 (order: 0, 5120 bytes, linear)
  120. [ 0.165042] TCP established hash table entries: 2048 (order: 2, 16384 bytes, linear)
  121. [ 0.165279] TCP bind hash table entries: 2048 (order: 4, 65536 bytes, linear)
  122. [ 0.165513] TCP: Hash tables configured (established 2048 bind 2048)
  123. [ 0.167469] UDP hash table entries: 256 (order: 2, 24576 bytes, linear)
  124. [ 0.167823] UDP-Lite hash table entries: 256 (order: 2, 24576 bytes, linear)
  125. [ 0.169282] NET: Registered PF_UNIX/PF_LOCAL protocol family
  126. [ 0.172534] RPC: Registered named UNIX socket transport module.
  127. [ 0.172606] RPC: Registered udp transport module.
  128. [ 0.172627] RPC: Registered tcp transport module.
  129. [ 0.172642] RPC: Registered tcp NFSv4.1 backchannel transport module.
  130. [ 0.172794] PCI: CLS 0 bytes, default 64
  131. [ 0.180445] workingset: timestamp_bits=62 max_order=16 bucket_order=0
  132. [ 0.194614] NFS: Registering the id_resolver key type
  133. [ 0.195717] Key type id_resolver registered
  134. [ 0.195772] Key type id_legacy registered
  135. [ 0.196382] nfs4filelayout_init: NFSv4 File Layout Driver Registering...
  136. [ 0.196504] nfs4flexfilelayout_init: NFSv4 Flexfile Layout Driver Registering...
  137. [ 0.197282] 9p: Installing v9fs 9p2000 file system support
  138. [ 0.198830] NET: Registered PF_ALG protocol family
  139. [ 0.199384] Block layer SCSI generic (bsg) driver version 0.4 loaded (major 250)
  140. [ 0.199551] io scheduler mq-deadline registered
  141. [ 0.199638] io scheduler kyber registered
  142. [ 0.211458] pci-host-generic 30000000.pci: host bridge /soc/pci@30000000 ranges:
  143. [ 0.212538] pci-host-generic 30000000.pci: IO 0x0003000000..0x000300ffff -> 0x0000000000
  144. [ 0.213088] pci-host-generic 30000000.pci: MEM 0x0040000000..0x007fffffff -> 0x0040000000
  145. [ 0.213169] pci-host-generic 30000000.pci: MEM 0x0400000000..0x07ffffffff -> 0x0400000000
  146. [ 0.213761] pci-host-generic 30000000.pci: Memory resource size exceeds max for 32 bits
  147. [ 0.214890] pci-host-generic 30000000.pci: ECAM at [mem 0x30000000-0x3fffffff] for [bus 00-ff]
  148. [ 0.216401] pci-host-generic 30000000.pci: PCI host bridge to bus 0000:00
  149. [ 0.216695] pci_bus 0000:00: root bus resource [bus 00-ff]
  150. [ 0.216802] pci_bus 0000:00: root bus resource [io 0x0000-0xffff]
  151. [ 0.216882] pci_bus 0000:00: root bus resource [mem 0x40000000-0x7fffffff]
  152. [ 0.216900] pci_bus 0000:00: root bus resource [mem 0x400000000-0x7ffffffff]
  153. [ 0.218331] pci 0000:00:00.0: [1b36:0008] type 00 class 0x060000
  154. [ 0.294377] Serial: 8250/16550 driver, 4 ports, IRQ sharing disabled
  155. [ 0.303136] printk: console [ttyS0] disabled
  156. [ 0.305194] 10000000.uart: ttyS0 at MMIO 0x10000000 (irq = 2, base_baud = 230400) is a 16550A
  157. [ 0.331363] printk: console [ttyS0] enabled
  158. [ 0.348432] loop: module loaded
  159. [ 0.352537] virtio_blk virtio0: [vda] 2097152 512-byte logical blocks (1.07 GB/1.00 GiB)
  160. [ 0.376684] e1000e: Intel(R) PRO/1000 Network Driver
  161. [ 0.376828] e1000e: Copyright(c) 1999 - 2015 Intel Corporation.
  162. [ 0.377400] ehci_hcd: USB 2.0 'Enhanced' Host Controller (EHCI) Driver
  163. [ 0.377758] ehci-pci: EHCI PCI platform driver
  164. [ 0.378200] ehci-platform: EHCI generic platform driver
  165. [ 0.378530] ohci_hcd: USB 1.1 'Open' Host Controller (OHCI) Driver
  166. [ 0.378801] ohci-pci: OHCI PCI platform driver
  167. [ 0.379167] ohci-platform: OHCI generic platform driver
  168. [ 0.380468] usbcore: registered new interface driver uas
  169. [ 0.380919] usbcore: registered new interface driver usb-storage
  170. [ 0.382100] mousedev: PS/2 mouse device common for all mice
  171. [ 0.385879] goldfish_rtc 101000.rtc: registered as rtc0
  172. [ 0.386647] goldfish_rtc 101000.rtc: setting system clock to 2022-08-19T12:20:44 UTC (1660911644)
  173. [ 0.389614] syscon-poweroff soc:poweroff: pm_power_off already claimed for sbi_srst_power_off
  174. [ 0.389962] syscon-poweroff: probe of soc:poweroff failed with error -16
  175. [ 0.391492] sdhci: Secure Digital Host Controller Interface driver
  176. [ 0.391720] sdhci: Copyright(c) Pierre Ossman
  177. [ 0.392087] sdhci-pltfm: SDHCI platform and OF driver helper
  178. [ 0.393373] usbcore: registered new interface driver usbhid
  179. [ 0.393604] usbhid: USB HID core driver
  180. [ 0.394074] riscv-pmu-sbi: SBI PMU extension is available
  181. [ 0.394764] riscv-pmu-sbi: 16 firmware and 2 hardware counters
  182. [ 0.395033] riscv-pmu-sbi: Perf sampling/filtering is not supported as sscof extension is not available
  183. [ 0.399865] NET: Registered PF_INET6 protocol family
  184. [ 0.407267] Segment Routing with IPv6
  185. [ 0.407649] In-situ OAM (IOAM) with IPv6
  186. [ 0.408329] sit: IPv6, IPv4 and MPLS over IPv4 tunneling driver
  187. [ 0.411565] NET: Registered PF_PACKET protocol family
  188. [ 0.413200] 9pnet: Installing 9P2000 support
  189. [ 0.413775] Key type dns_resolver registered
  190. [ 0.415916] debug_vm_pgtable: [debug_vm_pgtable ]: Validating architecture page table helpers
  191. [ 0.504662] EXT4-fs (vda): mounted filesystem with ordered data mode. Quota mode: disabled.
  192. [ 0.505310] VFS: Mounted root (ext4 filesystem) on device 254:0.
  193. [ 0.529887] devtmpfs: mounted
  194. [ 0.559745] Freeing unused kernel image (initmem) memory: 2164K
  195. [ 0.560852] Run /sbin/init as init process
  196. Please press Enter to activate this console.

可以看见打印出的启动信息中 OpenSBI 版本是 v1.1,这是我们自行编译的 OpenSBI 版本。

3 总结

本文简要介绍了 RISC-V 的启动流程,QEMU ‘virt’ 平台下 OpenSBI 和 U-Boot 的简单使用,根文件系统的制作和 Linux 内核的引导,并分析了 QEMU 启动参数有无 -bios 时的不同行为。接下来的文章我们将探索如何通过 U-Boot 来引导和加载 Linux 内核,并结合 QEMU ‘virt’ 分析 ZSBL 阶段的行为。

4 参考资料

  1. Linux Lab 官方手册
  2. RISC-V UEFI 架构支持详解,第 1 部分 - OpenSBI/U-Boot/UEFI 简介
  3. RISC-V OpenSBI 快速上手
  4. QEMU 官方文档
  5. 在泰晓 Linux 实验盘中构建 QEMU 并引导 openEuler for RISC-V
  6. 在 QEMU 上运行 RISC-V 64 位版本的 Linux
  7. RISC-V 启动流程
  8. RISC-V SBI 官方文档
  9. OpenSBI Gitee 镜像
  10. 用 U-boot 来引导 riscv-linux kernel
  11. QEMU 6.1.0 运行 RISCV64 OpenSBI + U-Boot + Linux
  12. Booting RISC-V on QEMU
  13. 构建 RISC-V 上运行的 Linux 系统


Read Album:

Read Related:

Read Latest: