使用qemu运行riscv64 linux

本文使用qemu运行riscv64 linux旨在与真实硬件板保持一致,因此不使用qemu提供的任何直接加载elf文件的方式启动,而是从头到尾均加载原始的bin文件程序给qemu,使其完整的执行opensbi、u-boot、kernel。如读者想利用qemu加载elf文件直接启动内核,是更为容易的,也不必再阅读本文。

本文Ver1.0编写于2021.6.6,经笔者测试所述编译配置流程均正确,如若出现错误,请检查各组件版本是否和笔者使用的一致。附:各组件版本号为linux-5.10.42,busybox-1.33.1,U-Boot 2021.04,OpenSBI v0.9,qemu-5.2.0,riscv64–glibc–bleeding-edge-2020.08-1
本文Ver1.1更新于2021.6.13,改动如下:1.修改smp参数由4改为8;2.rootfs映像修改为两个分区,并将内核image和fdt单独存放在第一个fat分区内;3.增加对U-Boot的Distro Boot Script支持,现在可以在启动u-boot后自动boot内核,不需要每次手动输入命令;4.增加备注说明提供了使用qemu 9p的虚拟共享目录的方式方便在后续内核开发中交换host和qemu target系统中的文件。
本文Ver1.2更新于2021.6.20,增加如下:1.busybox改为动态链接;2.启动脚本的完善以及多用户管理等

1.编译u-boot,生成u-boot.bin文件

make CROSS_COMPILE=/opt/riscv64--glibc--bleeding-edge-2020.08-1/bin/riscv64-linux- qemu-riscv64_smode_defconfig
make CROSS_COMPILE=/opt/riscv64--glibc--bleeding-edge-2020.08-1/bin/riscv64-linux- -j16

2.编译opensbi,生成fw_jump.bin文件

make CROSS_COMPILE=/opt/riscv64--glibc--bleeding-edge-2020.08-1/bin/riscv64-linux- PLATFORM=generic FW_PAYLOAD_PATH=../u-boot-2021.04/u-boot.bin

3.编译linux内核,生成Image文件

make ARCH=riscv CROSS_COMPILE=/opt/riscv64--glibc--bleeding-edge-2020.08-1/bin/riscv64-linux- defconfig
make ARCH=riscv CROSS_COMPILE=/opt/riscv64--glibc--bleeding-edge-2020.08-1/bin/riscv64-linux- -j16

4.编译busybox,生成最小文件系统所需的应用程序文件

make ARCH=riscv CROSS_COMPILE=/opt/riscv64--glibc--bleeding-edge-2020.08-1/bin/riscv64-linux- menuconfig
make ARCH=riscv CROSS_COMPILE=/opt/riscv64--glibc--bleeding-edge-2020.08-1/bin/riscv64-linux- -j16
make ARCH=riscv CROSS_COMPILE=/opt/riscv64--glibc--bleeding-edge-2020.08-1/bin/riscv64-linux- install

这里我们在menuconfig时候配置下静态编译,这样生成的文件系统内的程序是静态编译的不需要添加动态链接库和动态解释器就可以执行。后文我将给出使用动态可执行程序所需要拷贝的库文件到文件系统的方法。

5.从qemu读出设备树文件qemu-virt.dtb,并转化为源文件qemu-virt.dts

/usr/local/bin/qemu-system-riscv64 \
-M virt,dumpdtb=qemu-virt.dtb \
-m 1G \
-smp 8 \
-kernel u-boot-2021.04/u-boot.bin  \
-append "root=/dev/vda2 rw console=ttyS0"# dtc可以使用内核编译生成的,也可以使用包管理器安装sudo apt-get install device-tree-compiler
dtc -I dtb -O dts -o qemu-virt.dts qemu-virt.dtb

这里写/dev/vda2是因为我们后续制作根文件系统时打算制作两个分区,其中第一个分区存放boot需要的image和fdt,第二个分区为运行时的根文件系统,如果你只打算制作一个分区,请使用/dev/vda

6.制作根文件系统,将编译完成的内核image、设备树文件dtb、busybox文件、以及相关启动脚本文件打包生成rootfs.img文件

# 1.创建用于制作根文件系统的目录
mkdir rootfs
mkdir rootfs/rootfs
mkdir rootfs/bootfs
cd rootfs# 2.制作虚拟映像文件
dd if=/dev/zero of=rootfs.img bs=1M count=1024
sudo losetup -o 0 --sizelimit 1073741824 /dev/loop70 rootfs.img -P
# 使用fdisk创建两个分区一个fat文件系统,100M,一个ext4文件系统,剩余大小,ubuntu用户建议使用图形界面进行分区更加容易操作
sudo fdisk /dev/loop70 # 3.挂载两个分区
sudo mount /dev/loop70p1 ./bootfs
sudo mount /dev/loop70p2 ./rootfs# 4.uboot需要的相关文件存入bootfs
sudo cp ./linux-5.10.42/arch/riscv/boot/Image ./bootfs/
sudo cp ../qemu-virt.dtb ./bootfs/
# 创建启动相关的脚本文件,编辑其内容如本文第8节中的内容,如果你不知道为什么填入第8节内容,你可以先填入help命令到这个文件中
sudo touch ./bootfs/boot.cmd
# 执行uboot中的mkimage生成boot.scr
sudo ../u-boot-2021.04/tools/mkimage -A riscv -O linux -T script -C none -a 0 -e 0 -n "Distro Boot Script" -d ./bootfs/boot.cmd ./bootfs/boot.scr# 5.内核需要的相关文件存入rootfs
sudo cp -r ../busybox-1.33.1/_install/* ./rootfs/
sudo mkdir ./rootfs/boot ./rootfs/etc
sudo mkdir ./rootfs/boot ./rootfs/etc/init.d
# 创建四个启动相关的脚本文件,并增加执行权限,编辑其内容如下文
sudo touch ./rootfs/etc/fstab ./rootfs/etc/inittab ./rootfs/etc/profile ./rootfs/etc/init.d/rcS
sudo chmod +x ./rootfs/etc/fstab ./rootfs/etc/inittab ./rootfs/etc/profile ./rootfs/etc/init.d/rcS# 6.卸载分区
sudo umount ./rootfs
sudo umount ./bootfs
sudo losetup -d /dev/loop70
  • ./rootfs/etc/fstab
proc         /proc                               proc            defaults    0   0
none            /tmp                                ramfs       defaults    0   0
sysfs           /sys                                sysfs           defaults    0   0
mdev        /dev                                ramfs       defaults     0  0
debugfs /sys/kernel/debug   debugfs defaults    0 0
  • ./rootfs/etc/inittab
::sysinit:/etc/init.d/rcS
console::askfirst:-/bin/sh
  • ./rootfs/etc/profile
# /etc/profile: system-wide .profile file for the Bourne shellsecho
echo -n "Processing /etc/profile... "
# no-op
echo "Done"
echo
  • ./rootfs/etc/init.d/rcS
#! /bin/sh
PATH=/sbin:/bin:/usr/sbin:/usr/bin
LD_LIBRARY_PATH=/lib
export PATH LD_LIBRARY_PATHmount -a
/sbin/mdev -s
mount -aecho "--------------------------------------------"
echo " welcome debugging on qemu risc-v 64"
echo "--------------------------------------------"

7.启动qemu

/usr/local/bin/qemu-system-riscv64 \
-M virt \
-m 1G \
-smp 8 \
-nographic \
-bios ./opensbi/build/platform/generic/firmware/fw_jump.bin \
-kernel ./u-boot-2021.04/u-boot.bin \
-drive file=./rootfs/rootfs.img,format=raw,id=hd0 \
-device virtio-blk-device,drive=hd0

8.进入uboot后如果你在本文第6节中填入boot.cmd内容为help,则uboot自动boot将失败,你可以执行以下命令加载内核镜像和设备树文件,进入linux内核;如果你已经填入这三条命令到boot.cmd,则不需要任何操作,uboot将自动加载内核。

load virtio 0:1 0x80200000 /Image
load virtio 0:1 0x82000000 /qemu-virt.dtb
booti 0x80200000 - 0x82000000

备注:

1.qemu 编译 配置增加./configure --enable-gtk --enable-virtfs后,可以增加一以下host和target命令,用以共享目录交换数据,方便后续开发

/usr/local/bin/qemu-system-riscv64 \
-M virt \
-m 1G \
-smp 4 \
-nographic \
-bios ./opensbi/build/platform/generic/firmware/fw_jump.bin \
-kernel ./u-boot-2021.04/u-boot.bin \
-drive file=./rootfs/rootfs.img,format=raw,id=hd0 \
-device virtio-blk-device,drive=hd0 \
-fsdev local,security_model=passthrough,id=fsdev0,path=./ \
-device virtio-9p-pci,id=fs0,fsdev=fsdev0,mount_tag=hostshare
mount -t 9p -o trans=virtio,version=9p2000.L hostshare /mnt/

2.busybox使用动态链接的方法以及内核加载动态链接程序的原理

  • 之前我们使用静态链接的方法是为了快速跑起最小的文件系统,随着后续增加相关用户程序,静态编译的开销将不划算,因此我们这里要重新编译busybox,使用完全的默认的配置动态编译

  • 由于使用了动态编译,因此需要拷贝编译器中的.so库文件到文件系统的lib目录,具体为:编译器下/riscv64–glibc–bleeding-edge-2020.08-1/riscv64-buildroot-linux-gnu/sysroot/lib拷贝到/lib,/riscv64–glibc–bleeding-edge-2020.08-1/riscv64-buildroot-linux-gnu/sysroot/usr/lib拷贝到/usr/lib,创建软连接/lib64到/lib和/usr/lib64到/usr/lib。

  • 动态链接的细节:

    待笔者整理补充,后续更新

3.syslogd/klogd的使用

待笔者整理补充,后续更新

4.增加多用户管理以及登录密码等设置

  • 修改文件/etc/inittab内容如下,
::sysinit:/etc/init.d/rcS
console::respawn:/sbin/getty 38400 console
console::restart:/sbin/init
console::ctrlaltdel:/sbin/reboot
  • 创建配置文件/etc/group
root:x:0:
daemon:x:1:
bin:x:2:
sys:x:3:
sudo:x:27:xiaoming
users:x:100:
nogroup:x:65534:
xiaoming:x:1000:
  • 创建配置文件/etc/passwd
root:x:0:0:root:/home/root:/bin/sh
daemon:x:1:1:daemon:/usr/sbin:/bin/sh
bin:x:2:2:bin:/bin:/bin/sh
sys:x:3:3:sys:/dev:/bin/sh
nobody:x:65534:65534:nobody:/nonexistent:/bin/sh
xiaoming:x:1000:1000:Linux User,,,:/home/xiaoming:/bin/sh
  • 创建配置文件/etc/passwd
root:8f3SuzAlYA9zc:18802:0:99999:7:::
daemon:*:16092:0:99999:7:::
bin:*:16092:0:99999:7:::
sys:*:16092:0:99999:7:::
nobody:*:16092:0:99999:7:::
xiaoming:8KRJzPtwP/eRQ:18802:0:99999:7:::
  • 创建用户主目录,注意xiaoming目录以及内容的所属用户改为xiaoming
mkdir /home
mkdir /home/root
mkdir /home/xiaoming

这三个文件定义了一些用户组用户以及对应的登录密码,xiaoming这个用户是笔者自己加的,你可以改为使用你的用户名称,另外root密码是root,xiaoming的密码是xiaoming。完成以上文件的修改,reboot再次进入系统即可看到用户登录界面。

  • 创建配置文件/etc/busybox.conf,之所以创建这个文件是由于busybox带的部分命令如reboot非root用户无法运行,需要增加这个配置才能使用,内容如下:
[SUID]
su = ssx 0.0 # run with euid=0/egid=0
id = ssx 0.0 # run with euid=0/egid=0
halt = ssx 0.0 # run with euid=0/egid=0
reboot = ssx 0.0 # run with euid=0/egid=0
shutdown= ssx 0.0 # run with euid=0/egid=0
passwd = --- 0.0 # disabled for all user except for root
  • 创建/home/root/.bashrc和/home/xiaoming/.bashrc,内如如下,注意xiaoming目录以及内容的所属用户改为xiaoming
PATH=/sbin:/bin:/usr/sbin:/usr/bin
LD_LIBRARY_PATH=/lib
export PATH LD_LIBRARY_PATH
  • 修改/etc/profile
# /etc/profile: system-wide .profile file for the Bourne shellsecho -n "Processing /etc/profile... "source ~/.bashrc# no-op
echo "Done"
  • 修改/etc/init.d/rcS,这里完善一下我们的启动项目,方便使用
#! /bin/sh
PATH=/sbin:/bin:/usr/sbin:/usr/bin
LD_LIBRARY_PATH=/lib
export PATH LD_LIBRARY_PATHmount -a
/sbin/mdev -s
mount -amount -t 9p -o trans=virtio,version=9p2000.L hostshare /mnt/echo RISCV-QEMU-QQM > /proc/sys/kernel/hostname/etc/init.d/syslog  startecho "--------------------------------------------"
echo "         welcome to RISCV-QEMU-QQM !        "
echo "--------------------------------------------"

5.增加sudo并配置给xiaoming用户

  • 下载sudo源码,切换到最新版本的tag
git clone https://github.com/sudo-project/sudo.git
  • 交叉编译得到sudo程序拷贝到系统的/usr/bin/sudo
  • 创建/etc/sudoers文件
#
# This file MUST be edited with the 'visudo' command as root.
#
# See the sudoers man page for the details on how to write a sudoers file.
#                                                                         ##
# Override built-in defaults
##
Defaults                syslog=auth,runcwd=~
Defaults>root           !set_logname
Defaults:FULLTIMERS     !lecture,runchroot=*
Defaults:millert        !authenticate
Defaults@SERVERS        log_year, logfile=/var/log/sudo.log
Defaults!PAGERS         noexec                             # Host alias specification                                 # User alias specification                                 # Cmnd alias specification    # User privilege specification
root    ALL=(ALL:ALL) ALL                                                    # Members of the admin group may gain root privileges
%admin ALL=(ALL) ALL                                                         # Allow members of group sudo to execute any command
%sudo   ALL=(ALL:ALL) ALL
  • 执行以下命令,完成最终配置,然后reboot重启系统,使用xiaoming用户登录,尝试sudo确认工作正常
chown root:root /usr/bin/sudo && chmod 4755 /usr/bin/sudo
adduser xiaoming sudo
chmod 0440 /etc/sudoers

qemu运行riscv64 linux相关推荐

  1. qemu 运行arm linux,在ubuntu bionic下对基于qemu的arm64进行linux内核5.0.1版本的编译和运行...

    一.环境介绍 OS:ubuntu bionic 64bit 二.准备工作 2.1 安装必要的开发工具 sudo apt-get install git flex bison build-essenti ...

  2. QEMU 上运行 RISC-V Linux 内核

    QEMU 上运行 RISC-V Linux 内核 最近这段时间我在研究 RISC-V 内核.作为计划的开始,首先要将它运行起来.配置过程有点复杂,在此做详细介绍. 准备 操作系统 Ubuntu 18. ...

  3. linux运行在RISC上面,linux - 如何在riscv64 linux上运行SPEC CPU 2006? - 堆栈内存溢出...

    我有一个使用qemu模拟运行的riscv64 linux(fedora 28). [gqb@stage4 cpu2006]$ uname -a Linux stage4.fedoraproject.o ...

  4. armv8运行linux,ARMv8-A QEMU运行OP-TEE/ATF环境搭建

    关键词:OP-TEE.ATF.xtest.Linux等等. 下面记录通过ARMv8-A QEMU运行OP-TEE.ARM Trusted Firmware.Linux环境搭建过程. 1. 编译环境准备 ...

  5. linux下的arm仿真,使用QEMU仿真ARM Linux系统

    使用QEMU仿真ARM  Linux系统 使用方法,网上有很多文章可以参考: http://www.aurel32.net/info/debian_arm_qemu.php http://qemu-f ...

  6. 自动搭建openEuler虚拟机QEMU运行环境

    本文介绍了一个自动搭建openEuler虚拟机QEMU运行环境的脚本使用方法,本脚本能下载并安装各种依赖项,自动下载并编译安装QEMU 4.1.1和busybox 1.25.1,下载并安装对Linux ...

  7. 用QEMU构建嵌入式LINUX系统

    Table of Contents Qemu –从源头建造 ARM工具链 Linux内核 构建文件系统 通过NFS使用根文件系统 配置QEMU Tap网络 创建运行脚本 推荐阅读:<在CentO ...

  8. mono linux 运行机制,linux – Mono如何神奇?

    我正在学习C#,所以我制作了一个名为Hello,World!的C#程序,然后用mono-csc编译并用mono运行它: $mono-csc Hello.cs $mono Hello.exe Hello ...

  9. 0.使用Qemu运行OP-TEE

    历经一年多时间的系统整理合补充,<手机安全和可信应用开发指南:TrustZone与OP-TEE技术详解 >一书得以出版,书中详细介绍了TEE以及系统安全中的所有内容,全书按照从硬件到软件, ...

最新文章

  1. PHP 对象、数组间的转换
  2. 扒开系统调用的三层皮(下)
  3. 4982亿背后的前端技术—2020天猫双11前端体系大揭秘
  4. 腾讯的抖音官号被封杀了?抖音回应:谣言
  5. Android Studio 3.3功能
  6. 使用 data URI scheme 在网页中内嵌图片[转]
  7. ZeptoLab Code Rush 2015 B. Om Nom and Dark Park DFS
  8. Java设计模式实战 ~ 总目录
  9. Ubuntu configuration-1 安装常用软件
  10. hard link soft link
  11. 验证用户名和密码的C语言程序,客户端验证用户名和密码的方法详解
  12. 微微一笑很倾城(3)
  13. 【Android高级】Android系统以及Activity启动讲解
  14. 接口监控,系统监控,服务保证
  15. python实现繁体中文和简体中文的互相转化
  16. 【数电】常用组合逻辑电路模块总结
  17. 20170622《指导生活的算法》
  18. 无法打开“×××”,因为无法确认开发者的身份——解决办法
  19. 软件测试与正确性论证,OO学期总结
  20. kubernetes 禁用虚拟内存 swapoff -a ----- 顺便复习sed 命令

热门文章

  1. 关于mysql varchar类型的长度
  2. idea安装easy-api插件生成yapi文档
  3. strict_strtoul函数找不到定义问题
  4. angular2系统学习 - 路由与导航(4)
  5. 探索戴森在科技行业的统治地位:分析其后吹风机的成功
  6. 男人们必知的人生定律~(其实女人也得知道)
  7. 【动态规划】最长数对链
  8. cs架构和bs架构的区别
  9. ansi、unicode、UCS、UTF等概念(转)
  10. 必读 四六级考试报名|考试注意|分值比例|时间安排