美文网首页
在服务器上进行海思开发板的仿真

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

作者: 叶迎宪 | 来源:发表于2020-06-23 21:18 被阅读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

    相关文章

      网友评论

          本文标题:在服务器上进行海思开发板的仿真

          本文链接:https://www.haomeiwen.com/subject/xzdkfktx.html