在服务器上进行海思开发板的仿真

2020-06-23  本文已影响0人  叶迎宪

参考文章
https://www.cnblogs.com/pengdonglin137/p/5023342.html
https://blog.csdn.net/sxw1002/article/details/52841671
https://wiki.ubuntu.com/Kernel/Dev/QemuARMVexpress
https://translatedcode.wordpress.com/2016/11/03/installing-debian-on-qemus-32-bit-arm-virt-board/
https://gmplib.org/~tege/qemu.html

1、编译linux内核

https://mirrors.edge.kernel.org/pub/linux/kernel/v3.x/ 下载合适的内核源码。我用的是linux-3.18.24

除了arm-hisiv400-linux的工具链,编译内核还需要安装bc、ncurses-devel(在make menuconfig时用到)
yum install bc ncurses-devel

然后就可以开始编译了
make CROSS_COMPILE=arm-hisiv400-linux- ARCH=arm O=./_out vexpress_defconfig
make CROSS_COMPILE=arm-hisiv400-linux- ARCH=arm O=./_out menuconfig

可以选上,否则对ext4不能支持
[*] Enable the block layer --->
 [*] Support for large (2TB+) block devices and files

make CROSS_COMPILE=arm-hisiv400-linux- ARCH=arm O=./_out zImage -j4

2、安装qemu

偷个懒,直接用yum装。CentOS7在epel里面有
yum install qemu-system-arm

列出qemu-system-arm可以支持的机型
qemu-system-arm -machine help

3、试运行内核

cd _out/arch/arm/boot
qemu-system-arm -M virt -m 512M -kernel zImage -nographic

如果能走到
---[ end Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(0,0)

这一步,说明内核可以成功运行了

PS:其他参考文章,一般提到qemu-system-arm要模拟vexpress-a9这个型号。但是这个型号只有sd卡一个存储,不太方便进行定制。用virt虚拟型号可定制性更强。用virt型号的时候,不用指定tty

参考文章1提到的找console tty的方法有些不对及不完善。首先,生成的.config文件位于O=指定的输出_out目录下。其次.config文件中相关的配置项是
CONFIG_CMDLINE="console=ttyAMA0"
因此,应该以console=来查找,而不是按CONFIG_CONSOLE来查找。后来我曾经尝试编译内核的时候改成hisi_defconfig来取代vexpress,结果.config中CONFIG_CMDLINE是空的,qemu-system-arm启动后看不到输出了

4、编译busybox

wget http://www.busybox.net/downloads/busybox-1.25.1.tar.bz2
tar xjf busybox-1.25.1.tar.bz2
cd busybox-1.25.1
export ARCH=arm
export CROSS_COMPILE=arm-hisiv400-linux-
make menuconfig

在 Busybox Settings ---> Build Options 中注意选中
[*]Build BusyBox as a static binary (no shared libs)

make -j4
make install

编译后生成的文件在busybox的_install目录下

5、制作根文件系统

mkdir rootfs
cp -r busybox-1.25.1/_install/* rootfs/

busybox只是让这个根文件系统有了最基本的命令。linux中还需要添加一些必要的目录和文件

mkdir -p rootfs/dev/ rootfs/lib/ rootfs/proc/ rootfs/tmp/ rootfs/var/ rootfs/sys/
mknod rootfs/dev/tty1 c 4 1
mknod rootfs/dev/tty2 c 4 2
mknod rootfs/dev/tty3 c 4 3
mknod rootfs/dev/tty4 c 4 4
mknod rootfs/dev/urandom c 1 9
mknod rootfs/dev/null c 1 3
cd rootfs
wget http://files.cnblogs.com/files/pengdonglin137/etc.tar.gz
tar xzf etc.tar.gz
rm etc.tar.gz -rf

cp /opt/hisi-linux/x86-arm/arm-hisiv400-linux/target/lib/*.so* rootfs/lib/ -d

etc目录下需要放一些系统初始化的必要脚本,待会再细讲。这里先用别人现成的

将rootfs目录下的内容,制作成镜像。回退到rootfs的父级目录

yum install qemu-img
qemu-img create -f raw rootfs.img 1G
mkfs.ext3 -F rootfs.img
mkdir tmpfs
mount -t ext3 rootfs.img tmpfs/ 
cp -r rootfs/*  tmpfs/
umount tmpfs/

6、尝试启动

qemu-system-arm -M virt -m 512M -kernel linux-3.18.24/_out/arch/arm/boot/zImage -nographic -drive if=none,file=rootfs.img,format=raw,id=hd -device virtio-blk-device,drive=hd -append "root=/dev/vda rw console=ttyAMA0"

这组参数也是试了很久才试验出来的。加了硬盘之后,需要append console才能有启动日志输出。而且要指定root路径。由于还不能敲命令行,硬盘挂载在/dev/下面的什么也要靠猜。

想退出qemu,先按Ctrl+D退出console,然后再按Ctrl+a,松手再按x,结束qemu

参考网上其他文章,将设备型号模拟成vexpress-a9也是可以的,不过文件系统要挂载在sd卡上面,不是硬盘上面。模拟成vexpress-a15无法启动,不知道为什么。
qemu-system-arm -M vexpress-a9 -m 512M -kernel linux-3.18.24/_out/arch/arm/boot/zImage -nographic -append "root=/dev/mmcblk0 rw console=ttyAMA0" -sd rootfs.img

7、添加网络支持

网络的各种文章,都没有把qemu网络该怎么设置,说得很清楚。说得比较清楚的是
https://www.linux-kvm.org/page/Networking

qmeu的网络分为user-mode和tap两种。user-mode只能让虚拟机访问外网,但外网不能访问虚拟机。如果要让外面能访问虚拟机,就必须要使用tap。

要使用tap,必须要在宿主机上面创建一个bridge,这点和kvm使用网桥是一样的
https://www.jianshu.com/p/eb7d8bd7e477

然后添加一个/etc/qemu-ifup的文件

#!/bin/sh
set -x

switch=br0

if [ -n "$1" ];then
        #tunctl -u `whoami` -t $1
        ip tuntap add $1 mode tap user `whoami`
        ip link set $1 up
        sleep 0.5s
        #brctl addif $switch $1
        ip link set $1 master $switch
        exit 0
else
        echo "Error: no interface specified"
        exit 1
fi

qemu-ifup文件需要赋予执行权限。注意switch变量要设置为宿主机上面的网桥名字

然后可以往虚拟机中添加网卡了
qemu-system-arm -M virt -m 512M -kernel linux-3.18.24/_out/arch/arm/boot/zImage -nographic -drive if=none,file=rootfs.img,format=raw,id=hd -device virtio-blk-device,drive=hd -append "root=/dev/vda rw console=ttyAMA0" -device virtio-net-device,netdev=network0 -netdev tap,id=network0,ifname=tap0

或者用vexpress-a9也可以
qemu-system-arm -M vexpress-a9 -m 512M -kernel linux-3.18.24/_out/arch/arm/boot/zImage -nographic -append "root=/dev/mmcblk0 rw console=ttyAMA0" -sd rootfs.img -net nic,vlan=0 -net tap,vlan=0,ifname=tap0

在虚拟机中用ip link命令可以看到lo和eth0两个网卡了。不过要等网络通起来,还需要一些配置

ifconfig eth0 192.168.1.33 netmask 255.255.255.0 broadcast 192.168.1.255 up

这样,宿主机和虚拟机之间就可以通信起来了。我们可以把设置ip地址等初始化工作放到/etc/init.d/rcS脚本里面。不过现在的网络功能还是有缺陷的,域名解析的工作还不正常

参考
http://blog.sina.com.cn/s/blog_6de4c6c30100tiw7.html
https://blog.csdn.net/prog_6103/article/details/78569510

首先,即时busybox是静态链接编译的,系统中/lib目录下还是需要有libnss_dns.so.2、libresolv.so.2这些库,否则域名解析无法工作。这些库可以从海思的gcc里面找到、

其次,根文件系统中还没有/etc/resolv.conf,没有配置dns服务器

DNS配置好了之后,在虚拟机上面依然无法解析成功域名。在宿主机上面通过tcpdump抓包,发现dns请求是发出了,但是宿主机会回复一条ICMP命令,Destination Unreachable (Host administratively prohibited)。这里主要是宿主机启用了iptables,复杂的FORWARD规则拦截了。最简单的解决方法是在iptables插入一条
iptables -I FORWARD -i br0 -j ACCEPT
让所有br0进来的数据都允许转发

8、编译dropbear

为了方便往虚拟开发板上面传文件,远程控制,需要在虚拟开发板上面加上dropbear,方便用ssh远程登录及传输文件

mkdir dropbear
cd dropbear

wget http://zlib.net/zlib-1.2.11.tar.gz
tar xzf zlib-1.2.11.tar.gz
cd zlib-1.2.11
./configure --prefix=/home/kernel/dropbear/lib/zlib --static

修改Makefile
CC=gcc  改为  CC=arm-hisiv400-linux-gcc
LDSHARED=gcc  改为 LDSHARED=arm-hisiv400-linux-gcc
CPP=gcc -E  改为  CPP=arm-hisiv400-linux-cpp -E

make -j4
make install

wget https://matt.ucc.asn.au/dropbear/releases/dropbear-2017.75.tar.bz2
tar xjf dropbear-2017.75.tar.bz2
cd dropbear-2017.75
./configure --with-zlib=/home/kernel/dropbear/lib/zlib --host=arm-hisiv400-linux
make -j4

编译出dropbear后,把它拷贝到rootfs的/sbin目录下。然而,直接运行dropbear,会发现进程还是启动不起来。使用dropbear -E启动,可以看到报错信息是因为缺少了秘钥文件。回到宿主机上面,进入把dropbearkey也拷贝到rootfs/sbin目录下,另外根文件系统也要确保有/dev/urandom这个设备,否则dropbearkey无法运行。进入虚拟机

mkdir -p /etc/dropbear
cd /etc/dropbear/
dropbearkey -t rsa -s 4096 -f dropbear_rsa_host_key

记得从虚拟机中把/etc/dropbear/dropbear_rsa_host_key备份
这时候,使用dropbear -E是可以启动的,但是使用dropbear不带任何参数是启动失败的。把syslog打印出来,发现报错信息为Early exit: Failed to daemonize: No such file or directory。这是一个相当奇葩的问题,居然在调用daemon函数的时候出现了ENOENT的errno。谷歌找到的答案是
https://www.linuxquestions.org/questions/linux-networking-3/sshd-fatal-daemon-failed-no-such-device-279664/
mknod /dev/null c 1 3

9、其余优化

虚拟多核心的arm cpu,qemu-system-arm启动时加上-smp 4,虚拟四核。不过CentOS 7 epel带的qemu 2.0.0还不支持虚拟多核心,需要自己编译更新的qemu版本
上面创建的根文件系统镜像rootfs.img,采用的是raw格式,而且容量只有1G。如果希望虚拟更大的硬盘,则建议用qcow2格式
qemu-img create -f qcow2 rootfs.img 300G

附1:虚拟机根文件中的/etc/init.d/rcS文件参考

#!/bin/sh

# Mount fs accroding to /etc/fstab 
mount -a

# Network
ipaddr=192.168.1.33
netmask=255.255.255.0
gateway=192.168.1.1

ifconfig lo 127.0.0.1 up  
ifconfig eth0 $ipaddr \
  netmask $netmask up
route add default gw $gateway

dropbear 

/etc/fstab 文件参考

#device         mount-point     type    options         dump    fsck order
proc            /proc           proc    defaults        0       0
sysfs           /sys            sysfs   defaults        0       0
#/dev目录在qemu下不能设置为tmpfs,否则会覆盖了mknod已经创建好的tty1-tty4
#dev             /dev            tmpfs   defaults        0       0
var             /var            tmpfs   defaults        0       0
tmp             /tmp            tmpfs   defaults        0       0

附2:交叉编译strace

wget https://strace.io/files/5.7/strace-5.7.tar.xz
tar xJf strace-5.7.tar.xz
cd strace-5.7
./configure --host=arm-hisiv400-linux
make -j4
arm-hisiv400-linux-strip strace

附3:查看syslog的方法
首先要手动启动syslogd
其次要手动创建好/var/log/目录

附4:编译更新版本的qemu
wget https://download.qemu.org/qemu-4.0.1.tar.xz
tar xJf qemu-4.0.1.tar.xz
cd qemu-4.0.1
./configure --target-list=arm-softmmu,aarch64-softmmu --audio-drv-list=
make -j4
make install

上一篇下一篇

猜你喜欢

热点阅读