zoukankan      html  css  js  c++  java
  • 基于 QEMU进行 arm 仿真开发 (以 vexpress-a9 为例)

    背景

    基于 QEMU 的仿真可以节省 硬件成本。

    参考:《qemu-system-arm仿真vexpress-a9踩坑记》《在Ubuntu下使用QEMU搭建arm开发环境(一)搭建基本开发环境》

    我们在这一讲主要以搭建仿真环境为主。

    host平台   :Ubuntu 16.04
    qemu 3.0.0
    arm-linux-gcc : v7.4.1 20181213 [linaro-7.4-2019.02 revision 56ec6f6b99cc167ff0c2f8e1a2eed33b1edc85d4]

    QEMU 介绍

    Qemu 是纯软件实现的虚拟化模拟器,几乎可以模拟任何硬件设备,我们最熟悉的就是能够模拟一台能够独立运行操作系统的虚拟机,虚拟机认为自己和硬件打交道,但其实是和 Qemu 模拟出来的硬件打交道,Qemu 将这些指令转译给真正的硬件。

    正因为 Qemu 是纯软件实现的,所有的指令都要经 Qemu 过一手,性能非常低,所以,在生产环境中,大多数的做法都是配合 KVM 来完成虚拟化工作,因为 KVM 是硬件辅助的虚拟化技术,主要负责 比较繁琐的 CPU 和内存虚拟化,而 Qemu 则负责 I/O 虚拟化,两者合作各自发挥自身的优势,相得益彰。

    QEMU 同时也是一个非常简单的虚拟机,给它一个硬盘镜像就可以启动一个虚拟机,如果想定制这个虚拟机的配置,比如用什么样的 CPU 啊、什么样的显卡啊、什么样的网络配置啊,指定相应的命令行参数就可以了。它支持许多格式的磁盘镜像,包括 VirtualBox 创建的磁盘镜像文件。它同时也提供一个创建和管理磁盘镜像的工具 qemu-img。QEMU 及其工具所使用的命令行参数,直接查看其文档即可。

    QEMU 安装

    由于包管理器中的qemu太老了,所以我们采取基于源码的安装。

    在此之前,需要先准备好有关的环境

    sudo apt-get install build-essential pkg-config zlib1g-dev libglib2.0-0 libglib2.0-dev  libsdl1.2-dev libpixman-1-dev libfdt-dev autoconf automake libtool librbd-dev libaio-dev flex bison -y
    

    下载有关的源码

    wget https://download.qemu.org/qemu-3.0.0.tar.bz2
    

    编译有关的源码

    tar xf qemu-3.0.0.tar.xz
    cd qemu-3.0.0
    ./configure --prefix=/usr/local/qemu --target-list=arm-softmmu --audio-drv-list=
    sudo make && sudo make install
    sudo ln -s /usr/local/qemu/bin/* /usr/local/bin/
    
    # --target-list:选择目标机器的架构。默认是将所有的架构都编译,但为了更快的完成编译,指定需要的架构即可。
    

    测试

    qemu-img -V
    qemu-img version 3.0.0
    Copyright (c) 2003-2017 Fabrice Bellard and the QEMU Project developers
    

    查看 QEMU 支持的板子

    $ qemu-system-arm -M help
    Supported machines are:
    akita                Sharp SL-C1000 (Akita) PDA (PXA270)
    ast2500-evb          Aspeed AST2500 EVB (ARM1176)
    borzoi               Sharp SL-C3100 (Borzoi) PDA (PXA270)
    canon-a1100          Canon PowerShot A1100 IS
    cheetah              Palm Tungsten|E aka. Cheetah PDA (OMAP310)
    collie               Sharp SL-5500 (Collie) PDA (SA-1110)
    connex               Gumstix Connex (PXA255)
    cubieboard           cubietech cubieboard
    emcraft-sf2          SmartFusion2 SOM kit from Emcraft (M2S010)
    highbank             Calxeda Highbank (ECX-1000)
    imx25-pdk            ARM i.MX25 PDK board (ARM926)
    integratorcp         ARM Integrator/CP (ARM926EJ-S)
    kzm                  ARM KZM Emulation Baseboard (ARM1136)
    lm3s6965evb          Stellaris LM3S6965EVB
    lm3s811evb           Stellaris LM3S811EVB
    mainstone            Mainstone II (PXA27x)
    mcimx7d-sabre        Freescale i.MX7 DUAL SABRE (Cortex A7)
    midway               Calxeda Midway (ECX-2000)
    mps2-an385           ARM MPS2 with AN385 FPGA image for Cortex-M3
    mps2-an505           ARM MPS2 with AN505 FPGA image for Cortex-M33
    mps2-an511           ARM MPS2 with AN511 DesignStart FPGA image for Cortex-M3
    musicpal             Marvell 88w8618 / MusicPal (ARM926EJ-S)
    n800                 Nokia N800 tablet aka. RX-34 (OMAP2420)
    n810                 Nokia N810 tablet aka. RX-44 (OMAP2420)
    netduino2            Netduino 2 Machine
    none                 empty machine
    nuri                 Samsung NURI board (Exynos4210)
    palmetto-bmc         OpenPOWER Palmetto BMC (ARM926EJ-S)
    raspi2               Raspberry Pi 2
    realview-eb          ARM RealView Emulation Baseboard (ARM926EJ-S)
    realview-eb-mpcore   ARM RealView Emulation Baseboard (ARM11MPCore)
    realview-pb-a8       ARM RealView Platform Baseboard for Cortex-A8
    realview-pbx-a9      ARM RealView Platform Baseboard Explore for Cortex-A9
    romulus-bmc          OpenPOWER Romulus BMC (ARM1176)
    sabrelite            Freescale i.MX6 Quad SABRE Lite Board (Cortex A9)
    smdkc210             Samsung SMDKC210 board (Exynos4210)
    spitz                Sharp SL-C3000 (Spitz) PDA (PXA270)
    sx1                  Siemens SX1 (OMAP310) V2
    sx1-v1               Siemens SX1 (OMAP310) V1
    terrier              Sharp SL-C3200 (Terrier) PDA (PXA270)
    tosa                 Sharp SL-6000 (Tosa) PDA (PXA255)
    verdex               Gumstix Verdex (PXA270)
    versatileab          ARM Versatile/AB (ARM926EJ-S)
    versatilepb          ARM Versatile/PB (ARM926EJ-S)
    vexpress-a15         ARM Versatile Express for Cortex-A15
    vexpress-a9          ARM Versatile Express for Cortex-A9
    virt-2.10            QEMU 2.10 ARM Virtual Machine
    virt-2.11            QEMU 2.11 ARM Virtual Machine
    virt-2.12            QEMU 2.12 ARM Virtual Machine
    virt-2.6             QEMU 2.6 ARM Virtual Machine
    virt-2.7             QEMU 2.7 ARM Virtual Machine
    virt-2.8             QEMU 2.8 ARM Virtual Machine
    virt-2.9             QEMU 2.9 ARM Virtual Machine
    virt                 QEMU 3.0 ARM Virtual Machine (alias of virt-3.0)
    virt-3.0             QEMU 3.0 ARM Virtual Machine
    witherspoon-bmc      OpenPOWER Witherspoon BMC (ARM1176)
    xilinx-zynq-a9       Xilinx Zynq Platform Baseboard for Cortex-A9
    z2                   Zipit Z2 (PXA27x)
    
    

    仿真文件的准备

    仿真很简单,只需要类似这样的:

    qemu-system-arm -M vexpress-a9 
    -m 512M 
    -kernel ./uImage 
    -dtb ./vexpress-v2p-ca9.dtb 
    -nographic 
    -append "console=ttyAMA0"
    

    或者是这样的

    qemu-system-arm -M vexpress-a9 -m 512M -kernel arch/arm/boot/zImage -dtb arch/arm/boot/dts/vexpress-v2p-ca9.dtb -nographic -append "console=ttyAMA0"
    

    其中,有关参数的解释如下:

    -M vexpress-a9 模拟vexpress-a9单板,你能够使用-M ?參数来获取该qemu版本号支持的全部单板
    -m 512M 单板执行物理内存512M
    -kernel arch/arm/boot/zImage   告诉qemu单板执行内核镜像路径
    -dtb arch/arm/boot/dts/vexpress-v2p-ca9.dtb  告诉qemu单板的设备树(必须加入)
    -nographic 不使用图形化界面,仅仅使用串口
    -append "console=ttyAMA0" 内核启动參数。这里告诉内核vexpress单板执行。串口设备是哪个tty。
    

    我们唯一缺少的就是有关的启动文件,查阅有关资料才发现,QEMU的仿真需要有 编译好以后的文件,因为根据QEMU的原理来看,需要二进制文件。

    QEMU是一个主机上的VMM(virtual machine monitor),通过动态二进制转换来模拟CPU,并提供一系列的硬件模型,使guest os认为自己和硬件直接打交道,其实是同QEMU模拟出来的硬件打交道,QEMU再将这些指令翻译给真正硬件进行操作。通过这种模式,guest os可以和主机上的硬盘,网卡,CPU,CD-ROM,音频设备和USB设备进行交互。

    编译有关的 Uboot、kernel、文件系统

    安装有关环境:sudo apt-get install flex bison flex -y

    编译 uboot 并仿真

    编译

    git clone git://git.denx.de/u-boot.git
    
    cd u-boot
    export ARCH=arm 
    export CROSS_COMPILE=arm-linux-gnueabihf-
    make clean && make vexpress_ca9x4_defconfig
    make -j4
    
    

    仿真

    qemu-system-arm -M vexpress-a9 -m 256 -kernel u-boot -nographic
    

    结果

    因为下载实在是太慢了,我使用了一个之前下载好的早期uboot版本。

    U-Boot 2018.01 (Feb 22 2020 - 17:34:52 +0800)
    
    DRAM:  256 MiB
    WARNING: Caches not enabled
    Flash: 128 MiB
    MMC:   MMC: 0
    *** Warning - bad CRC, using default environment
    
    In:    serial
    Out:   serial
    Err:   serial
    Net:   smc911x-0
    Hit any key to stop autoboot:  0
    MMC Device 1 not found
    no mmc device at slot 1
    Card did not respond to voltage select!
    mmc_init: -95, time 23
    smc911x: MAC 52:54:00:12:34:56
    smc911x: detected LAN9118 controller
    smc911x: phy initialized
    smc911x: MAC 52:54:00:12:34:56
    BOOTP broadcast 1
    DHCP client bound to address 10.0.2.15 (3 ms)
    *** Warning: no boot file name; using '0A00020F.img'
    Using smc911x-0 device
    TFTP from server 10.0.2.2; our IP address is 10.0.2.15
    ...
    

    输入ctrl + A 后按 X退出 QEMU

    编译 kernel 并仿真

    编译

    # git clone git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git kernel && cd kernel 
    wget https://mirrors.aliyun.com/linux-kernel/v4.x/linux-4.14.14.tar.xz && tar -xf linux-4.14.14.tar.xz && cd linux-4.14.14
    
    
    export ARCH=arm
    export CROSS_COMPILE=arm-linux-gnueabi-
    make clean
    make vexpress_defconfig
    make menuconfig 
    # 在配置中找到并去掉 Enable the L2x0 outer cache controller 取消,会导致仿真失败起不来
    #    System Type-> Enable the L2x0 outer cache controller ,或搜索 CACHE_L2X0
    
    make -j8
    
    # schips @ ubuntu in ~/arm/sc/linux-4.1.11 [18:19:19]
    $ make -j4
      HOSTCC  scripts/kallsyms
    In file included from include/linux/compiler.h:54:0,
                     from include/uapi/linux/stddef.h:1,
                     from include/linux/stddef.h:4,
                     from ./include/uapi/linux/posix_types.h:4,
                     from include/uapi/linux/types.h:13,
                     from include/linux/types.h:5,
                     from include/linux/mod_devicetable.h:11,
                     from scripts/mod/devicetable-offsets.c:2:
    include/linux/compiler-gcc.h:121:1: fatal error: linux/compiler-gcc7.h: No such file or directory
     #include gcc_header(__GNUC__)
    
    

    如果遇到上面的情况,就说明是工具链太新了,要么换旧的工具链来匹配这个低版本的内核;要么就再找一个高版本的内核

    仿真

    qemu-system-arm -M vexpress-a9 -m 512M -kernel arch/arm/boot/zImage -dtb arch/arm/boot/dts/vexpress-v2p-ca9.dtb -nographic -append "console=ttyAMA0"
    # 指定设备树,否则会失败
    

    结果
    不出意外的话会在 文件系统那里停下来。

    Booting Linux on physical CPU 0x0
    Linux version 4.14.14 (schips@ubuntu) (gcc version 7.4.1 20181213 [linaro-7.4-2019.02 revision 56ec6f6b99cc167ff0c2f8e1a2eed33b1edc85d4] (Linaro GCC 7.4-2019.02)) #1 SMP Sat Feb 22 21:14:14 CST 2020
    CPU: ARMv7 Processor [410fc090] revision 0 (ARMv7), cr=10c5387d
    CPU: PIPT / VIPT nonaliasing data cache, VIPT nonaliasing instruction cache
    OF: fdt: Machine model: V2P-CA9
    Memory policy: Data cache writeback
    CPU: All CPU(s) started in SVC mode.
    percpu: Embedded 16 pages/cpu @9fbae000 s36428 r8192 d20916 u65536
    Built 1 zonelists, mobility grouping on.  Total pages: 130048
    Kernel command line: console=ttyAMA0
    log_buf_len individual max cpu contribution: 4096 bytes
    log_buf_len total cpu_extra contributions: 12288 bytes
    log_buf_len min size: 16384 bytes
    log_buf_len: 32768 bytes
    early log buf free: 14964(91%)
    PID hash table entries: 2048 (order: 1, 8192 bytes)
    Dentry cache hash table entries: 65536 (order: 6, 262144 bytes)
    Inode-cache hash table entries: 32768 (order: 5, 131072 bytes)
    Memory: 509556K/524288K available (6144K kernel code, 402K rwdata, 1364K rodata, 1024K init, 169K bss, 14732K reserved, 0K cma-reserved)
    Virtual kernel memory layout:
        vector  : 0xffff0000 - 0xffff1000   (   4 kB)
        fixmap  : 0xffc00000 - 0xfff00000   (3072 kB)
        vmalloc : 0xa0800000 - 0xff800000   (1520 MB)
        lowmem  : 0x80000000 - 0xa0000000   ( 512 MB)
        modules : 0x7f000000 - 0x80000000   (  16 MB)
          .text : 0x80008000 - 0x80700000   (7136 kB)
          .init : 0x80900000 - 0x80a00000   (1024 kB)
          .data : 0x80a00000 - 0x80a649b8   ( 403 kB)
           .bss : 0x80a6bd30 - 0x80a964b4   ( 170 kB)
    SLUB: HWalign=64, Order=0-3, MinObjects=0, CPUs=4, Nodes=1
    Hierarchical RCU implementation.
            RCU event tracing is enabled.
            RCU restricting CPUs from NR_CPUS=8 to nr_cpu_ids=4.
    RCU: Adjusting geometry for rcu_fanout_leaf=16, nr_cpu_ids=4
    NR_IRQS: 16, nr_irqs: 16, preallocated irqs: 16
    GIC CPU mask not found - kernel will fail to boot.
    
    ... (省略很多行)
    
    input: ImExPS/2 Generic Explorer Mouse as /devices/platform/smb@4000000/smb@4000000:motherboard/smb@4000000:motherboard:iofpga@7,00000000/10007000.kmi/serio1/input/input2
    VFS: Cannot open root device "(null)" or unknown-block(0,0): error -6
    Please append a correct "root=" boot option; here are the available partitions:
    1f00          131072 mtdblock0
     (driver?)
    1f01           32768 mtdblock1
     (driver?)
    Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(0,0)
    CPU: 0 PID: 1 Comm: swapper/0 Not tainted 4.14.14 #1
    Hardware name: ARM-Versatile Express
    [<8010faac>] (unwind_backtrace) from [<8010bdd4>] (show_stack+0x10/0x14)
    [<8010bdd4>] (show_stack) from [<8065a728>] (dump_stack+0x88/0x9c)
    [<8065a728>] (dump_stack) from [<8011db88>] (panic+0xdc/0x248)
    [<8011db88>] (panic) from [<809012b0>] (mount_block_root+0x1d4/0x2a8)
    [<809012b0>] (mount_block_root) from [<809014a4>] (mount_root+0x120/0x128)
    [<809014a4>] (mount_root) from [<809015fc>] (prepare_namespace+0x150/0x194)
    [<809015fc>] (prepare_namespace) from [<80900eb4>] (kernel_init_freeable+0x248/0x258)
    [<80900eb4>] (kernel_init_freeable) from [<8066d548>] (kernel_init+0x8/0x108)
    [<8066d548>] (kernel_init) from [<80107968>] (ret_from_fork+0x14/0x2c)
    ---[ end Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(0,0)
    
    

    基于 busybox 制作rootfs,并让 kernel 带有 rootfs 仿真

    编译以及制作

    git clone git://busybox.net/busybox.git && cd busybox
    
    export ARCH=arm
    export CROSS_COMPILE=arm-linux-gnueabi-
    
    make defconfig
    make menuconfig
    #   勾选 Busybox Setting-> Build Options-> [*] Build static binary (no shared libs)    或者 搜索 CONFIG_STATIC
    
    make -j4
    make install
    
    

    制作

    ##
    #    Copyright By Schips, All Rights Reserved
    #    https://gitee.com/schips/
    
    #    File Name:  make_rootfs.sh
    #    Created  :  Sat 22 Feb 2020 09:39:26 PM CST
    
    ##
    #!/bin/sh
    base=`pwd`
    tmpfs=/_tmpfs
    
    sudo rm -rf rootfs
    sudo rm -rf ${tmpfs}
    sudo rm -f a9rootfs.ext3
    sudo mkdir rootfs
    sudo cp _install/*  rootfs/ -raf
    
    #sudo mkdir -p rootfs/{lib,proc,sys,tmp,root,var,mnt}
    cd rootfs && sudo mkdir -p lib proc sys tmp root var mnt && cd ${base}
    
    # 根据自己的实际情况, 找到并 拷贝 arm-gcc 中的 libc中的所有.so 库
    sudo cp -arf /usr/cross/gcc-linaro-7.4.1-2019.02-i686_arm-linux-gnueabi/arm-linux-gnueabi/libc/lib/*so*  rootfs/lib
    
    sudo cp app rootfs
    sudo cp examples/bootfloppy/etc rootfs/ -arf
    sudo sed -r  "/askfirst/ s/.*/::respawn:-/bin/sh/" rootfs/etc/inittab -i
    sudo mkdir -p rootfs/dev/
    sudo mknod rootfs/dev/tty1 c 4 1
    sudo mknod rootfs/dev/tty2 c 4 2pro
    sudo mknod rootfs/dev/tty3 c 4 3
    sudo mknod rootfs/dev/tty4 c 4 4
    sudo mknod rootfs/dev/console c 5 1
    sudo mknod rootfs/dev/null c 1 3
    sudo dd if=/dev/zero of=a9rootfs.ext3 bs=1M count=64
    # 如果提示 "No space left on device" 证明 dd 命令中 count 的大小不够
    
    sudo mkfs.ext3 a9rootfs.ext3
    sudo mkdir -p ${tmpfs}
    sudo chmod 777 ${tmpfs}
    sudo mount -t ext3 a9rootfs.ext3 ${tmpfs}/ -o loop
    sudo cp -r rootfs/*  ${tmpfs}/
    sudo umount ${tmpfs}
    

    仿真

    qemu-system-arm -M vexpress-a9 -m 512M -kernel arch/arm/boot/zImage -dtb arch/arm/boot/dts/vexpress-v2p-ca9.dtb -nographic -append "root=/dev/mmcblk0 rw console=ttyAMA0" -sd a9rootfs.ext3
    # 同样地,只要是 仿真kernle 就需要 指定设备树
    
    

    结果(节选)

    usbhid: USB HID core driver
    mmcblk0: mmc0:4567 QEMU! 32.0 MiB
    aaci-pl041 10004000.aaci: ARM AC'97 Interface PL041 rev0 at 0x10004000, irq 33
    aaci-pl041 10004000.aaci: FIFO 512 entries
    oprofile: using arm/armv7-ca9
    NET: Registered protocol family 17
    9pnet: Installing 9P2000 support
    Registering SWP/SWPB emulation handler
    rtc-pl031 10017000.rtc: setting system clock to 2020-02-22 14:26:16 UTC (1582381576)
    ALSA device list:
      #0: ARM AC'97 Interface PL041 rev0 at 0x10004000, irq 33
    input: ImExPS/2 Generic Explorer Mouse as /devices/platform/smb@4000000/smb@4000000:motherboard/smb@4000000:motherboard:iofpga@7,00000000/10007000.kmi/serio1/input/input2
    EXT4-fs (mmcblk0): mounting ext3 file system using the ext4 subsystem
    EXT4-fs (mmcblk0): mounted filesystem with ordered data mode. Opts: (null)
    VFS: Mounted root (ext3 filesystem) on device 179:0.
    Freeing unused kernel memory: 1024K
    random: crng init done
    
    Processing /etc/profile... Done
    
    / # ls
    bin         lib         mnt         sbin        usr
    dev         linuxrc     proc        sys         var
    etc         lost+found  root        tmp
    
    

    由于篇幅有限,我们在下一讲介绍更加高级的:《qemu运行uboot,在仿真中动态加载内核与文件系统》

  • 相关阅读:
    网络协议-网络编程学习方法介绍
    socket函数集-----网络编程必备值得拥有
    QT 等待对话框/进度--
    qt部分类释义
    Unicode 10.0版本出现了,可以表达13万个字符, 99年定制的3.0版本不超过6万个字符
    hadoop+spark+mongodb+mysql+c#
    mysql 主从复制
    Docker for Windows
    项目设计&重构&性能优化
    发布项目到 Linux 上运行 Core 项目
  • 原文地址:https://www.cnblogs.com/schips/p/12345431.html
Copyright © 2011-2022 走看看