基于QEMU搭建RISC-V的Linux环境

背景

和之前搭建x86的类似(基于QEMU的内核调试环境搭建),只是需要交叉编译即可,重点其实是在交叉编译工具链。

前提:QEMU已安装好!

准备工具链

RISC-V支持GNU工具链和LLVM工具链,目前主流Linux发行版好像都没有预编译的二进制包可以下载安装,只能自己通过源码编译安装。

获取工具链源码

$ git clone https://gitee.com/mirrors/riscv-gnu-toolchain
$ cd riscv-gnu-toolchain

注意上面 clone 的主仓库并不包含子仓库的内容,所以需要继续更新子仓库。注意这里首先排除了 qemu 这个子仓库,一来因为 qemu 完整下载太大;二来 qemu 对 toolchain 的编译本身来说其实并不需要。

$ git rm qemu
$ git submodule update --init --recursive

上面的过程可能要点时间,需要耐心等待。。。

编译安装工具链

riscv-gnu-toolchain工具链分 elf-gcc、linux-gnu-gcc 两个版本,以及对应的32位和64位版本。两个版本的主要区别是:

  • riscv32-unknown-elf-gccriscv64-unknown-elf-gcc使用的是riscv-newlib库(面向嵌入式的C库),只支持静态链接,不支持动态链接。
  • riscv32-unknown-linux-gnu-gccriscv64-unknown-linux-gnu-gcc使用的是glibc标准库,支持动态链接。

这里默认编译64位的linux-gnu-gcc版本。

安装相应依赖包

$ sudo apt-get install autoconf automake autotools-dev curl python3 python3-pip libmpc-dev libmpfr-dev libgmp-dev gawk build-essential bison flex texinfo gperf libtool patchutils bc zlib1g-dev libexpat-dev ninja-build git cmake libglib2.0-dev

配置编译

#配置,这里默认构建64位的交叉编译器,安装到/opt/riscv,
#若构建32位,添加--with-arch=rv32gc --with-abi=ilp32d
#若构建同时支持32位和64位,添加--enable-multilib
$ ./configure --prefix=/opt/riscv
#编译linux-gnu-gcc版本
$ sudo make linux -j $(nproc)

导出 toolchain 的安装路径

$ export PATH="$PATH:/opt/riscv/bin"

也可以写入 .bashrc 文件

测试 toolchain 是否安装成功

$ riscv64-unknown-linux-gnu-gcc -v

准备riscv内核

进入内核源码,使用riscv编译链重新配置并交叉编译内核

$ make ARCH=riscv CROSS_COMPILE=riscv64-unknown-linux-gnu- defconfig
$ make ARCH=riscv CROSS_COMPILE=riscv64-unknown-linux-gnu- -j $(nproc)

准备riscv文件系统

这里简单编译个busybox。

#配置
$ CROSS_COMPILE=riscv64-unknown-linux-gnu- make menuconfig
#select `Settings -> Build Options -> Build static binary (no shared libs)`

#编译安装
$ CROSS_COMPILE=riscv64-unknown-linux-gnu- make -j $(nproc)
$ CROSS_COMPILE=riscv64-unknown-linux-gnu- make install

后面的步骤与之前的一样,这里不在赘述。最终生成img文件:riscv-rootfs.img

运行qemu

与之前类似,换成riscv64的qemu,使能虚拟化,换内核和文件系统即可。

$ qemu-system-riscv64 -M virt -m 256M \
    -kernel ./RISC-V-Image \
    -drive file=riscv-rootfs.img,format=raw,id=hd0 \
    -device virtio-blk-device,drive=hd0 \
    -append "root=/dev/vda rw console=ttyS0" \
    -nographic

启动log如下:

OpenSBI v0.9
   ____                    _____ ____ _____
  / __ \                  / ____|  _ \_   _|
 | |  | |_ __   ___ _ __ | (___ | |_) || |
 | |  | | '_ \ / _ \ '_ \ \___ \|  _ < | |
 | |__| | |_) |  __/ | | |____) | |_) || |_
  \____/| .__/ \___|_| |_|_____/|____/_____|
        | |
        |_|

Platform Name             : riscv-virtio,qemu
Platform Features         : timer,mfdeleg
Platform HART Count       : 1
Firmware Base             : 0x80000000
Firmware Size             : 100 KB
Runtime SBI Version       : 0.2

Domain0 Name              : root
Domain0 Boot HART         : 0
Domain0 HARTs             : 0*
Domain0 Region00          : 0x0000000080000000-0x000000008001ffff ()
Domain0 Region01          : 0x0000000000000000-0xffffffffffffffff (R,W,X)
Domain0 Next Address      : 0x0000000080200000
Domain0 Next Arg1         : 0x000000008f000000
Domain0 Next Mode         : S-mode
Domain0 SysReset          : yes

Boot HART ID              : 0
Boot HART Domain          : root
Boot HART ISA             : rv64imafdcsu
Boot HART Features        : scounteren,mcounteren,time
Boot HART PMP Count       : 16
Boot HART PMP Granularity : 4
Boot HART PMP Address Bits: 54
Boot HART MHPM Count      : 0
Boot HART MHPM Count      : 0
Boot HART MIDELEG         : 0x0000000000000222
Boot HART MEDELEG         : 0x000000000000b109
[    0.000000] Linux version 6.8.0-rc7 (zdd@zhaodongdong) (riscv64-unknown-linux-gnu-gcc (GCC) 13.2.0, GNU ld (GNU Binutils) 2.42) #1 SMP Tue Mar 12 10:24:27 CST 2024
[    0.000000] Machine model: riscv-virtio,qemu
[    0.000000] SBI specification v0.2 detected
[    0.000000] SBI implementation ID=0x1 Version=0x9
[    0.000000] SBI TIME extension detected
[    0.000000] SBI IPI extension detected
[    0.000000] SBI RFENCE extension detected
[    0.000000] efi: UEFI not found.
[    0.000000] OF: reserved mem: 0x0000000080000000..0x000000008001ffff (128 KiB) map non-reusable mmode_resv0@80000000
[    0.000000] Zone ranges:
[    0.000000]   DMA32    [mem 0x0000000080000000-0x000000008fffffff]
[    0.000000]   Normal   empty
[    0.000000] Movable zone start for each node
[    0.000000] Early memory node ranges
[    0.000000]   node   0: [mem 0x0000000080000000-0x000000008fffffff]
[    0.000000] Initmem setup node 0 [mem 0x0000000080000000-0x000000008fffffff]
[    0.000000] SBI HSM extension detected
[    0.000000] Falling back to deprecated "riscv,isa"
[    0.000000] riscv: base ISA extensions acdfim
[    0.000000] riscv: ELF capabilities acdfim
[    0.000000] percpu: Embedded 20 pages/cpu s41464 r8192 d32264 u81920
[    0.000000] Kernel command line: root=/dev/vda rw console=ttyS0
[    0.000000] Dentry cache hash table entries: 32768 (order: 6, 262144 bytes, linear)
[    0.000000] Inode-cache hash table entries: 16384 (order: 5, 131072 bytes, linear)
[    0.000000] Built 1 zonelists, mobility grouping on.  Total pages: 64512
[    0.000000] mem auto-init: stack:all(zero), heap alloc:off, heap free:off
[    0.000000] Virtual kernel memory layout:
[    0.000000]       fixmap : 0xff1bfffffea00000 - 0xff1bffffff000000   (6144 kB)
[    0.000000]       pci io : 0xff1bffffff000000 - 0xff1c000000000000   (  16 MB)
[    0.000000]      vmemmap : 0xff1c000000000000 - 0xff20000000000000   (1024 TB)
[    0.000000]      vmalloc : 0xff20000000000000 - 0xff60000000000000   (16384 TB)
[    0.000000]      modules : 0xffffffff01583000 - 0xffffffff80000000   (2026 MB)
[    0.000000]       lowmem : 0xff60000000000000 - 0xff60000010000000   ( 256 MB)
[    0.000000]       kernel : 0xffffffff80000000 - 0xffffffffffffffff   (2047 MB)
[    0.000000] Memory: 218468K/262144K available (9666K kernel code, 4955K rwdata, 4096K rodata, 2241K init, 491K bss, 43676K reserved, 0K cma-reserved)
[    0.000000] SLUB: HWalign=64, Order=0-3, MinObjects=0, CPUs=1, Nodes=1
[    0.000000] rcu: Hierarchical RCU implementation.
[    0.000000] rcu: 	RCU restricting CPUs from NR_CPUS=64 to nr_cpu_ids=1.
[    0.000000] rcu: 	RCU debug extended QS entry/exit.
[    0.000000] 	Tracing variant of Tasks RCU enabled.
[    0.000000] rcu: RCU calculated value of scheduler-enlistment delay is 25 jiffies.
[    0.000000] rcu: Adjusting geometry for rcu_fanout_leaf=16, nr_cpu_ids=1
[    0.000000] NR_IRQS: 64, nr_irqs: 64, preallocated irqs: 0
[    0.000000] riscv-intc: 64 local interrupts mapped
[    0.000000] plic: plic@c000000: mapped 53 interrupts with 1 handlers for 2 contexts.
[    0.000000] riscv: providing IPIs using SBI IPI extension
[    0.000000] rcu: srcu_init: Setting srcu_struct sizes based on contention.
[    0.000000] clocksource: riscv_clocksource: mask: 0xffffffffffffffff max_cycles: 0x24e6a1710, max_idle_ns: 440795202120 ns
[    0.000074] sched_clock: 64 bits at 10MHz, resolution 100ns, wraps every 4398046511100ns
[    0.004121] Console: colour dummy device 80x25
[    0.008016] Calibrating delay loop (skipped), value calculated using timer frequency.. 20.00 BogoMIPS (lpj=40000)
[    0.008151] pid_max: default: 32768 minimum: 301
[    0.009251] LSM: initializing lsm=capability,integrity
[    0.011286] Mount-cache hash table entries: 512 (order: 0, 4096 bytes, linear)
[    0.011322] Mountpoint-cache hash table entries: 512 (order: 0, 4096 bytes, linear)
[    0.039513] RCU Tasks Trace: Setting shift to 0 and lim to 1 rcu_task_cb_adjust=1.
[    0.039978] riscv: ELF compat mode unsupported
[    0.040427] ASID allocator using 16 bits (65536 entries)
[    0.041448] rcu: Hierarchical SRCU implementation.
[    0.041482] rcu: 	Max phase no-delay instances is 1000.
[    0.044669] EFI services will not be available.
[    0.046414] smp: Bringing up secondary CPUs ...
[    0.047003] smp: Brought up 1 node, 1 CPU
[    0.057361] devtmpfs: initialized
[    0.065618] clocksource: jiffies: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 7645041785100000 ns
[    0.065860] futex hash table entries: 256 (order: 2, 16384 bytes, linear)
[    0.067674] pinctrl core: initialized pinctrl subsystem
[    0.073393] NET: Registered PF_NETLINK/PF_ROUTE protocol family
[    0.081280] DMA: preallocated 128 KiB GFP_KERNEL pool for atomic allocations
[    0.081527] DMA: preallocated 128 KiB GFP_KERNEL|GFP_DMA32 pool for atomic allocations
[    0.081789] audit: initializing netlink subsys (disabled)
[    0.085115] thermal_sys: Registered thermal governor 'step_wise'
[    0.085772] audit: type=2000 audit(0.076:1): state=initialized audit_enabled=0 res=1
[    0.086264] cpuidle: using governor menu
[    0.109076] cpu0: Ratio of byte access time to unaligned word access is 7.31, unaligned accesses are fast
[    0.121282] HugeTLB: registered 2.00 MiB page size, pre-allocated 0 pages
[    0.121311] HugeTLB: 28 KiB vmemmap can be freed for a 2.00 MiB page
[    0.125746] ACPI: Interpreter disabled.
[    0.126171] iommu: Default domain type: Translated
[    0.126203] iommu: DMA domain TLB invalidation policy: strict mode
[    0.128178] SCSI subsystem initialized
[    0.130077] usbcore: registered new interface driver usbfs
[    0.130297] usbcore: registered new interface driver hub
[    0.130437] usbcore: registered new device driver usb
[    0.132032] Advanced Linux Sound Architecture Driver Initialized.
[    0.142630] vgaarb: loaded
[    0.145363] clocksource: Switched to clocksource riscv_clocksource
[    0.147855] pnp: PnP ACPI: disabled
[    0.165540] NET: Registered PF_INET protocol family
[    0.166439] IP idents hash table entries: 4096 (order: 3, 32768 bytes, linear)
[    0.170945] tcp_listen_portaddr_hash hash table entries: 128 (order: 0, 4096 bytes, linear)
[    0.171040] Table-perturb hash table entries: 65536 (order: 6, 262144 bytes, linear)
[    0.171092] TCP established hash table entries: 2048 (order: 2, 16384 bytes, linear)
[    0.171256] TCP bind hash table entries: 2048 (order: 5, 131072 bytes, linear)
[    0.171485] TCP: Hash tables configured (established 2048 bind 2048)
[    0.172496] UDP hash table entries: 256 (order: 2, 24576 bytes, linear)
[    0.172805] UDP-Lite hash table entries: 256 (order: 2, 24576 bytes, linear)
[    0.173823] NET: Registered PF_UNIX/PF_LOCAL protocol family
[    0.176679] RPC: Registered named UNIX socket transport module.
[    0.176737] RPC: Registered udp transport module.
[    0.176749] RPC: Registered tcp transport module.
[    0.176759] RPC: Registered tcp-with-tls transport module.
[    0.176767] RPC: Registered tcp NFSv4.1 backchannel transport module.
[    0.176895] PCI: CLS 0 bytes, default 64
[    0.183249] workingset: timestamp_bits=46 max_order=16 bucket_order=0
[    0.186700] NFS: Registering the id_resolver key type
[    0.187526] Key type id_resolver registered
[    0.187558] Key type id_legacy registered
[    0.187813] nfs4filelayout_init: NFSv4 File Layout Driver Registering...
[    0.187891] nfs4flexfilelayout_init: NFSv4 Flexfile Layout Driver Registering...
[    0.188447] 9p: Installing v9fs 9p2000 file system support
[    0.189930] NET: Registered PF_ALG protocol family
[    0.190189] Block layer SCSI generic (bsg) driver version 0.4 loaded (major 245)
[    0.190317] io scheduler mq-deadline registered
[    0.190379] io scheduler kyber registered
[    0.190470] io scheduler bfq registered
[    0.193851] pci-host-generic 30000000.pci: host bridge /soc/pci@30000000 ranges:
[    0.194486] pci-host-generic 30000000.pci:       IO 0x0003000000..0x000300ffff -> 0x0000000000
[    0.194858] pci-host-generic 30000000.pci:      MEM 0x0040000000..0x007fffffff -> 0x0040000000
[    0.194921] pci-host-generic 30000000.pci:      MEM 0x0400000000..0x07ffffffff -> 0x0400000000
[    0.195345] pci-host-generic 30000000.pci: Memory resource size exceeds max for 32 bits
[    0.195721] pci-host-generic 30000000.pci: ECAM at [mem 0x30000000-0x3fffffff] for [bus 00-ff]
[    0.197020] pci-host-generic 30000000.pci: PCI host bridge to bus 0000:00
[    0.197229] pci_bus 0000:00: root bus resource [bus 00-ff]
[    0.197300] pci_bus 0000:00: root bus resource [io  0x0000-0xffff]
[    0.197337] pci_bus 0000:00: root bus resource [mem 0x40000000-0x7fffffff]
[    0.197347] pci_bus 0000:00: root bus resource [mem 0x400000000-0x7ffffffff]
[    0.198475] pci 0000:00:00.0: [1b36:0008] type 00 class 0x060000 conventional PCI endpoint
[    0.295449] Serial: 8250/16550 driver, 4 ports, IRQ sharing disabled
[    0.305384] printk: legacy console [ttyS0] disabled
[    0.308167] 10000000.uart: ttyS0 at MMIO 0x10000000 (irq = 12, base_baud = 230400) is a 16550A
[    0.309475] printk: legacy console [ttyS0] enabled
[    0.330541] SuperH (H)SCI(F) driver initialized
[    0.344441] loop: module loaded
[    0.345367] virtio_blk virtio0: 1/0/0 default/read/poll queues
[    0.348187] virtio_blk virtio0: [vda] 2097152 512-byte logical blocks (1.07 GB/1.00 GiB)
[    0.369465] e1000e: Intel(R) PRO/1000 Network Driver
[    0.369629] e1000e: Copyright(c) 1999 - 2015 Intel Corporation.
[    0.371734] usbcore: registered new interface driver uas
[    0.372093] usbcore: registered new interface driver usb-storage
[    0.373211] mousedev: PS/2 mouse device common for all mice
[    0.376029] goldfish_rtc 101000.rtc: registered as rtc0
[    0.376796] goldfish_rtc 101000.rtc: setting system clock to 2024-03-13T01:49:05 UTC (1710294545)
[    0.380080] cpuidle-riscv-sbi: HSM suspend not available
[    0.380747] sdhci: Secure Digital Host Controller Interface driver
[    0.380923] sdhci: Copyright(c) Pierre Ossman
[    0.381272] Synopsys Designware Multimedia Card Interface Driver
[    0.381777] sdhci-pltfm: SDHCI platform and OF driver helper
[    0.382516] usbcore: registered new interface driver usbhid
[    0.382679] usbhid: USB HID core driver
[    0.386321] NET: Registered PF_INET6 protocol family
[    0.392319] Segment Routing with IPv6
[    0.392739] In-situ OAM (IOAM) with IPv6
[    0.393206] sit: IPv6, IPv4 and MPLS over IPv4 tunneling driver
[    0.395810] NET: Registered PF_PACKET protocol family
[    0.397131] 9pnet: Installing 9P2000 support
[    0.397612] Key type dns_resolver registered
[    0.426860] debug_vm_pgtable: [debug_vm_pgtable         ]: Validating architecture page table helpers
[    0.433147] Legacy PMU implementation is available
[    0.434355] clk: Disabling unused clocks
[    0.434665] ALSA device list:
[    0.434783]   No soundcards found.
[    0.482664] EXT4-fs (vda): mounted filesystem 0032faeb-2db8-4c5f-9b58-f4a4889124fe r/w with ordered data mode. Quota mode: disabled.
[    0.487994] VFS: Mounted root (ext4 filesystem) on device 254:0.
[    0.490614] devtmpfs: mounted
[    0.518466] Freeing unused kernel image (initmem) memory: 2240K
[    0.519154] Run /sbin/init as init process

Please press Enter to activate this console. 
~ #

参考