Teach you step by step: how to use Qemu to simulate an ARM system


This is Brother Dao's 011 original

Preface

Some time ago, because of work needs, I did some research on the ARM simulator. The purpose of the investigation is: because there are many people involved in the project, if the manpower is an ARM development board, the resources are relatively tight, and it is hoped that the simulator can be used instead.

During the investigation, I spent a lot of time to check information, test and verify. During the actual verification, a phenomenon was discovered: Although many articles give simple or detailed operation steps, most of them do not clearly write the background of the operation and the version of each software, which leads to the need to read the entire article. , After doing all the operation steps, you can understand what the author wants to express and what the purpose of the operation is .

In my opinion, for any article, we must first let readers know why they want to read this article, or what gains can be gained from reading this article .

If it is a highly operable article, then it is necessary to explain clearly what is the background of the work platform, what is the goal to be achieved, and what is the overall procedure . Only in this way, people who read the article first establish a macro framework in their minds, and then go to the actual operation on the basis of understanding the framework, so that it will be easier to understand.

Of course, everyone's learning and reading habits are different. The above are just my personal feelings, or I like such a more organized article, so that I will not be confused.

Back to the topic of Qemu, this article is mainly to sort out and summarize the results of the survey, including the following:

Why do we need an ARM simulation system?
What is
Qemu? What can Qemu do? Or what is it suitable for?
In Ubuntu 16.04 system, what are the steps to build an ARM virtual machine with Qemu?
Write a HelloWorld program and put it in a virtual machine for execution.

Why do you need an ARM analog system

Software development work on the ARM platform can be divided into two categories:

Application development
system development (kernel, file system, driver)

Application development

When we develop embedded projects, we generally develop most of the functions on the x86 platform first, and then cross-compile them to obtain executable programs or library files on the ARM platform. Then copy these files to the ARM board and execute them by means of scp command or NFS remote mounting .

Generally speaking, application programs use various resources and peripherals of hardware products to complete specific functions, such as data collection, control of external devices, network transmission, and so on. The main feature is to interact with various external devices.

System Development (BSP)

The ultimate goal of system development is to prepare a basic execution environment for the execution of applications, including: system bootloader bootloader, kernel kernel, file system rootfs, and drivers for all devices in the system . In the actual project development, the system development is more difficult. Once the development is completed, it is basically not easy to change for a board, and the life cycle of the code is longer.

The above two classifications are mainly divided from the perspective of the content of the development work. As can be seen:

Application development: greater flexibility, more changes in requirements (product managers or project managers often change your requirements).
System software development: The demand is more stable, many codes are officially provided or open source, and the work content is customization and tailoring.

For system software development, if a bootloader or kernel is compiled every time, it is verified on an ARM development board, which is really troublesome. If you can have an ARM simulation system and simulate directly on x86, the work efficiency will be much improved .

What is Qemu?

Qemu is an open source hosted virtual machine, which implements a virtual simulator through pure software, which can simulate almost any hardware device . For example: Qemu can simulate an ARM system: CPU, memory, IO devices, etc., and then on this simulation layer, you can run an ARM virtual machine, this ARM virtual machine thinks that it is dealing with the hardware, but actually The above hardware is simulated by Qemu .

Just because Qemu is implemented in pure software, all instructions have to go through its conversion, so the performance is very low. Therefore, in the production environment, most of the practices are to cooperate with KVM to complete the virtualization work, because KVM is a hardware-assisted virtualization technology, which is mainly responsible for the more cumbersome CPU and memory virtualization, while Qemu is responsible for I/O virtualization. , The two cooperate with each other to play their own advantages and complement each other. This part is not the focus, so I won't introduce it in detail.

Two modes of Qemu

Qemu has two execution modes :

  1. User mode: Use the dynamic code translation mechanism to execute codes of different host architectures, for example: Simulate the execution of ARM code on the x86 platform, that is to say: We write an ARM instruction and pass it to the entire simulator. The entire instruction will be translated into the instructions of the x86 platform, and then executed on the x86 CPU.

  1. System mode: Simulate the entire computer system and use other VMM (Xen, KVM) to use the virtualization support provided by the hardware to create a full-featured virtual machine close to the performance of the host.

What can Qemu do? Or what is suitable for?

Because Qemu uses pure software simulation, its strength is to simulate scenarios that do not involve external specific hardware devices , such as:

I want to learn how to customize the bootloader;
I want to cut the file system in the Arm system, and learn
how to mount the file system; I want to experience how to configure and tailor the linux kernel;
I want to learn the device tree in the Linux system;

In these scenarios, it is very suitable to use Qemu to simulate the ARM system.

In Ubuntu 16.04 system, use Qemu to build an ARM virtual machine

Several options for using Qemu virtual machine

Using Qemu to run the ARM virtual machine, you have 2 options :

  1. Simple way: directly download the image file compiled by others (including the kernel and root file system) and execute it directly.


    The disadvantage is: someone compiled it may not suit your needs and cannot be customized.
  2. Complex way: Download the kernel code and root file system code (for example: busybox) by yourself, and then compile it.


    The advantage is: you can tailor the kernel and root file system models according to your actual needs.

In the second complex mode, there are two options :

2-1. The kernel code and root file system code are all manually compiled by themselves, and finally these compiled results are manually organized in a folder to form their own root directory;
2-2. Using the entire framework of buildroot, you only need to manually configure ( For example: the location of the cross-compiler on the machine, the output path, the cutting of the system), and then you can compile a complete system with one click, which can be directly burned to the machine!

The choice of the above several operation modes can be selected according to your actual needs. If you are already very familiar with the entire process of building a system, use the buildroot tool; if you want to learn to build a system more thoroughly , then manually compile and operate step by step, and practice a few times, and you will become a big It's a cow.

Below, we will perform the actual operation in the 2-2 way. For all the instruction parts, I directly paste the code without taking screenshots, which is convenient for copying.

testing platform

My working computer is Win10, and I installed Ubuntu 16.04 virtual machine through VirtualBox , 64-bit system .

The following operations can be successfully compiled in the Ubuntu 16.04 virtual machine. Of course, some basic tools (for example: build-essential, make and other basic tools are not detailed here).

Install cross compiler

The role of the cross-compiler does not need to be explained in detail, because we are compiling on the x86 platform, and the running platform is the ARM system. The instruction sets of these two platforms are different, so cross-compilation is needed to get the execution on the ARM system. program of.

sudo apt-get install gcc-arm-linux-gnueabi 

Verify the installation result

dpkg -l gcc-arm-linux-gnueabi 

The display is as follows:

Some articles recommend downloading the cross-compiler yourself, and then manually setting the environment variables. I actually did it. The manually downloaded cross-compilation toolchain reported an error when compiling the kernel, so it is recommended to install it directly with apt-get .

Compile the kernel kernel

The role of the kernel kernel is also self-evident, it is equivalent to our Windows operating system, without this operating system, the hardware is a pile of scrap iron. When the system starts, the kernel will be loaded into the memory, and then executed from the entry address of the kernel.

  1. Download the kernel
    version: linux-4.14.212.tar.
    At the end of the article, I will list all the software package download addresses.

  2. Use the ready-made vexpress development board config file

make CROSS_COMPILE=arm-linux-gnueabi- ARCH=arm vexpress_defconfig 

This operation will save vexpress_defconfig as a configuration file as .config . When compiling the kernel, compile it according to the configuration in this config.

If you need to tailor the kernel, execute:

make menuconfig

Customize the kernel according to your actual needs. For example: you can configure the network and NFS, and automatically mount a directory in the host when the system starts.

  1. Compile the kernel
make CROSS_COMPILE=arm-linux-gnueabi- ARCH=arm

The kernel file arch/arm/boot/zImage is compiled , and this image file needs to be specified when Qemu starts.

Make the root file system

After the kernel is started and when it reaches the final step, it needs to mount the root file system , and then execute the execution program specified in the file system, for example: /etc/rc.local.

If there is no file system, the kernel will prompt: panic... at the end of execution .

  1. Download busybox

    Version: busybox-1.20.2.tar.bz2.

  2. Create rootfs root directory

mkdir -p rootfs/{dev,etc/init.d,lib} 
  1. Copy the files in busybox-1.20.2 to the root directory of rootfs, mainly some basic commands
cp busybox-1.20.2/_install/* -r rootfs/ 
  1. Copy the library files in the cross-compilation tool chain to the lib folder in the root directory of rootfs
sudo cp -P /usr/arm-linux-gnueabi/lib/* rootfs/lib/ 
  1. Making a root file system image The
    root file system image is equivalent to a hard disk , that is, all files in the root directory of the above rootfs are copied to this hard disk.

(1) Generate 512M disk image

qemu-img create -f raw disk.img 512M 

(2) Format the disk image into ext4 file system

mkfs -t ext4 ./disk.img 

(3) Copy all files in the root directory of rootfs to the disk image. The
operation steps are: create a mount point-mount-copy files-unmount.

mkdir tmpfs 
sudo mount -o loop ./disk.img tmpfs/  
sudo cp -r rootfs/* tmpfs/
sudo umount tmpfs 

(4) Use the file command to check

file disk.img

Use Qemu to start the ARM virtual machine

1. Start the virtual machine

This command is a bit long, it is recommended to copy and paste directly when testing.

qemu-system-arm -M vexpress-a9 -m 512M -kernel ./linux-4.14.212/arch/arm/boot/zImage -dtb  ./linux-4.14.212/arch/arm/boot/dts/vexpress-v2p-ca9.dtb -nographic -append "root=/dev/mmcblk0 rw console=ttyAMA0" -sd disk.img

2. Stop the virtual machine
In another terminal window of Ubuntu, use the killall command to stop it.

killall qemu-system-arm

Of course, you can also use the ps command to find the process number of qemu-system-arm, and then use kill -9 to stop the virtual machine.

Test the HelloWorld application

  1. In any directory of Ubuntu, write the HelloWorld executable program hello.c:
#include <stdio.h> 
int main() 
{     
    printf("HelloWorld! \n");
    return 0; 
} 
  1. Cross compile hello.c to get the executable program hello:
arm-linux-gnueabi-gcc hello.c -o hello 

Check the hello program through the file command:

file hello

  1. Stop the virtual machine through the kill command.

  2. Copy the hello executable program to the disk image disk.img. The
    operation steps are: mount-copy files-uninstall.

sudo mount -o loop ./disk.img tmpfs/  
cp hello tmpfs/ 
sudo umount tmpfs 
  1. Execute the hello program
    and start the virtual machine again. At this time, you can see the hello file under the root directory, and execute it directly to see the output result.

to sum up

In the above operation steps, we manually compile and operate all the programs needed by an ARM system before starting the application . It's easy to understand after reading it, and the impression will be even more impressive if you operate it with your own hands.

Some of the operations here need to be further deepened. For example, after the system is started, a folder in the host machine (Ubuntu system) is automatically mounted , so that executable programs such as hello can be copied to the mount directory, and then It is executed directly in the ARM system, and there is no need to perform the following series of operations (stop the virtual machine-mount the disk image-copy the file-uninstall-start the virtual machine).

Finally, I hope this summary can bring you little gains and improvements!

Software download address

  1. linux-4.14.212.tar.xz
    link: https://pan.baidu.com/s/1d8RxjMkYQhPtbZgiybD8Gw
    extraction code: b6ft

  2. busybox-1.20.2.tar.bz2
    link: https://pan.baidu.com/s/1oPeH7juEWuFR6y1Qpna_BA
    extraction code: 9kh6


[Original Statement]

If you think the article is good, please forward it and share it with your friends.

I will summarize and share the actual combat experience of projects in embedded development for more than ten years , I believe you will not be disappointed!

Press and hold the picture to follow, each article has dry goods.

Reprint: Welcome to reprint, but without the consent of the author, this statement must be retained, and the original link must be given in the article.




Recommended reading

[1] The underlying debugging principle of the original gdb is so simple
[2] Double buffering technology in the producer and consumer mode
[3] In- depth LUA scripting language, let you thoroughly understand the principle of debugging
[4] Step by step analysis-how to implement it in C Object-Oriented Programming

Guess you like

Origin blog.csdn.net/u012296253/article/details/111908443