建立个人网站,如何快速进行网站开发,关键词生成器在线,可信赖的响应式网站1. 简介
QEMU#xff08;Quick EMUlator#xff09;是一个开源的虚拟化软件#xff0c;它能够模拟多种硬件平台#xff0c;并在这些平台上运行各种操作系统。QEMU可以在不同的主机架构之间进行虚拟化#xff0c;例如x86、ARM、PowerPC、Risc-V等。QEMU是一个功能强大且灵…1. 简介
QEMUQuick EMUlator是一个开源的虚拟化软件它能够模拟多种硬件平台并在这些平台上运行各种操作系统。QEMU可以在不同的主机架构之间进行虚拟化例如x86、ARM、PowerPC、Risc-V等。QEMU是一个功能强大且灵活的虚拟化软件可用于多种应用场景包括系统仿真、硬件虚拟化、交叉编译以及设备模拟等。它广泛应用于开发、测试和部署各种软件和操作系统。 以下是QEMU的一些重要特点和用途
系统仿真QEMU可以模拟整个计算机系统包括处理器、内存、硬盘、网络接口等。这使得用户可以在自己的计算机上运行不同体系结构的操作系统如在x86主机上运行ARM操作系统。虚拟化支持QEMU提供了硬件虚拟化功能允许在宿主机上创建和管理虚拟机。这样可以在一台物理机上同时运行多个操作系统实例每个实例都像独立的计算机一样运行。交叉编译支持QEMU可以为不同的目标平台提供交叉编译环境以便在一种体系结构上编译代码并在另一种体系结构上执行。快速启动时间QEMU通过使用动态二进制翻译技术Dynamic Binary Translation来提高性能。它将客户机指令动态转换为主机指令从而提供接近原生速度的执行效率。虚拟设备模拟QEMU提供了许多虚拟设备模拟如磁盘驱动器、网络接口卡、显卡等。这些设备可以用于测试和开发目的或者在虚拟机中运行嵌入式操作系统。
2. 安装
QEMU适用于Windows、Linux和Mac因为Linux开源的原因QEMU在Linux上能够更好地利用虚拟化等技术使得虚拟的性能相较其他平台会更好一些。通用情况下可以直接使用预编译后的二进制版本如果需要进行额外地扩展可以自行编译版本。
2.1. Windows
2.1.1. 二进制版本
● 可以从https://qemu.weilnetz.de/下载相应的版本。 ● 可以在MSYS32中通过命令 pacman -S qemu 来安装。
2.1.2. 编译版本
Windows版本的QEMU需要使用mingw来编译可以在Linux下编译也可以在Windows下编译。Windows下推荐使用MSYS2进行编译。
从MSYS2官网下载安装最新版本。启用MSYS2更新最新源。 pacman -Syu 重启MSYS2更新最新软件包。 pacman -Su 安装基本开发工具包 pacman -S base-devel mingw-w64-x86_64-toolchain git python ninja 安装QEMU相关依赖包 pacman -S mingw-w64-x86_64-glib2 mingw-w64-x86_64-pixman python-setuptools 添加扩展特性依赖包 pacman -S mingw-w64-x86_64-gtk3 mingw-w64-x86_64-SDL2 mingw-w64-x86_64-libslirp 关闭MSYS2控制台。启动msys目录下的mingw64.exe。下载最新的QEMU源代码 git clone https://gitlab.com/qemu-project/qemu.git // gitlab较慢时可以使用国内镜像 git clone https://gitee.com/mirrors/qemu.git 编译 cd qemu ./configure make 更多编译方法参见QEMU Build for Windows
2.2. Linux
此处主要以ubuntu 22.04版本为例。
2.2.1. 二进制版本
Linux下的qemu各版本需要分别安装如 sudo apt install qemu-system-arm sudo apt install qemu-system-aarch64 sudo apt install qemu-system-riscv32 sudo apt install qemu-system-riscv64 2.2.2. 编译安装
推荐从源码编译安装更方便调试添加打印信息。推荐以tag版本安装更可靠。以下测试是基于从gitee上克隆的版本进行测试。安装可以配置–enable-debug启用调试。 git clone https://gitee.com/mirrors/qemu.git cd qemu mkdir build cd build …/configure make -j8 sudo make install 2.2.3. 测试
输入qemu-system-aarch64 -version显示以下信息表示安装成功。 QEMU emulator version 8.1.93 (v8.2.0-rc3) Copyright © 2003-2023 Fabrice Bellard and the QEMU Project developers 3. 使用
3.1. 嵌入式裸机
此处以最小系统嵌入式固件来演示使用过程并且分别演示Windows和Linux下的交叉编译以及基于Cortext-M和risc-v两个当下流行的单片机为例。代码只执行一个Uart打印信息。
int main (void)
{InitUart();UartWrite(Hello World!\n, 13);while (1){/* code */}return 0;
}3.1.1. Cortex-M7
下载交叉编译工具https://developer.arm.com/downloads/-/gnu-rm将工具目录(如D:/toolchains/arm/arm-eabi-v103/bin)添加进环境目录。进入代码目录以make编译生成elf文件。运行elf qemu-system-arm.exe -machine mps2-an385 -monitor null -semihosting --semihosting-config enableon,targetnative -kernel $(APP) -serial stdio -nographic 调试运行elf a. -S表示暂停在固件的起始指令。 b. -s是-gdb tcp::1234的简写表示启动tcp远程调试。 qemu-system-arm.exe -machine mps2-an385 -monitor null -semihosting --semihosting-config enableon,targetnative -kernel $(APP) -serial stdio -nographic -S -s gdb调试 结果
3.1.2. RISC-V
riscv-v使用Linux进行测试。 安装交叉编译工具链 在https://www.sifive.com/software上下载工具链并将路径添加进环境路径。 编译并运行 调试 方法同cortext-m7。
3.1.3. VSCode调试
gdb调试不太方便利用VSCode可以更方便地查看变量单步调试代码。添加lanch.json文件将以下内容覆盖。按F5启动调试代码即停止在main函数处。 {// Use IntelliSense to learn about possible attributes.// Hover to view descriptions of existing attributes.// For more information, visit: https://go.microsoft.com/fwlink/?linkid830387version: 0.2.0,configurations: [{name: Launch QEMU to debug HelloWorld.elf,type: cppdbg,request: launch,program: ${workspaceFolder}/HelloWorld.elf,cwd: ${workspaceFolder},miDebuggerPath: arm-none-eabi-gdb,miDebuggerServerAddress: localhost:1234,stopAtEntry: true,preLaunchTask: Run QEMU}]
}3.1.4. 代码
代码包括完整的固件只需要安装交叉编译工具和qemu即可以测试。
make 编译。make qemu 仿真运行。make qemu-remotegdb -x gdbinit启用调试。 代码路径https://github.com/feihe027/qemu_mcu
3.2. 嵌入式Linux
3.2.1. ubuntu
3.2.1.1. 安装运行
下面是Cortex-A57 CPU来安装Linux。
下载Linux镜像从官方网站下载ubuntu-20.04-live-server-arm64.iso。(服务器版本无UI)下载EFI启动文件 wget http://releases.linaro.org/components/kernel/uefi-linaro/16.02/release/qemu64/QEMU_EFI.fd -O /data/kvm/QEMU_EFI.fd 创建启动盘镜像 qemu-img create ubuntu20.04-arm64.img 32G 创建nvme SSD镜像 qemu-img create -f qcow2 nvme.qcow2 10G 安装系统 注意上面4个文件统一放到新建的虚拟机目录进入目录执行下列命令 qemu-system-aarch64 -machine virt -cpu cortex-a57 -smp 2 -m 4G -bios QEMU_EFI.fd -device virtio-scsi-device -device scsi-cd,drivecdrom -drive ifnone,fileubuntu-20.04-live-server-arm64.iso,idcdrom,mediacdrom -device virtio-blk-device,drivevd0 -drive ifnone,fileubuntu20.04-arm64.img,idvd0 -drive filenvme.qcow2,ifnone,idnvme0 -device nvme,drivenvme0,serialfoo -net nic -net tap,ifnametap0,scriptno,downscriptno -nographic 几分钟后安装界面默认往下执行即可设置用户名密码等最终进入安装流程安装会比较慢。安装完成之后直接关闭当前控制台窗口不要选Restart会重新进行安装。 6. 启动虚拟机 启动虚拟机和安装差不多只是不用cdrom系统文件直接从镜像启动即可。 qemu-system-aarch64 -machine virt -cpu cortex-a57 -smp 2 -m 4G -bios QEMU_EFI.fd -device virtio-blk-device,drivevd0 -drive ifnone,fileubuntu20.04-arm64.img,idvd0 -drive filenvme.qcow2,ifnone,idnvme0 -device nvme,drivenvme0,serialfoo -net nic -net tap,ifnametap0,scriptno,downscriptno -nographic 启动之后等一两分钟就会进入系统输入用户名密码登录。
3.2.2. 调试内核
3.2.2.1. 编译内核
下载Kernel代码测试使用6.8-rc5 git clone https://gitee.com/mirrors/linux_old1.git 安装工具链 sudo apt-getinstall gcc-aarch64-linux-gnu 配置内核选项 cd linux_old1 // arch/arm64/configs/defconfig 中将CONFIG_RANDOMIZE_BASEy修改成CONFIG_RANDOMIZE_BASEn // 检查CONFIG_DEBUG_KERNELy // 检查CONFIG_DEBUG_INFO_REDUCEDy make ARCHarm64 CROSS_COMPILEaarch64-linux-gnu- defconfig 编译内核 make ARCHarm64 CROSS_COMPILEaarch64-linux-gnu- Image -j8 根文件系统制作 根文件系统制作下载最新busybox配置busybox make menuconfig Settings — [] Build static binary (no shared libs) //静态编译 [] Build with debug information //可选带调试信息方便后续调试编译 make make install
3.2.2.2. 制作根文件 qemu-img create rootfs.img 512m mkfs.ext4 rootfs.img mkdir rootfs sudo mount rootfs.img rootfs sudo cp -rf _install/* rootfs cd rootfs sudo mkdir proc sys dev etc etc/init.d sudo vim etc/init.d/rcS sudo chmod x etc/init.d/rcS cd … sudo umount rootfs //# etc/init.d/rcS文件内容如下 #!/bin/sh mount -t proc none /proc mount -t sysfs none /sys mount -t debugfs none /sys/kernel/debug 3.2.2.3. 运行
将arch/arm64/boot/Image 和rootfs.img 文件拷贝到任意目录。执行下面命令 qemu-system-aarch64 -machine virt,virtualizationtrue,gic-version3 -nographic -m size1024M -cpu cortex-a72 -smp 2 -kernel Image -drive formatraw,filerootfs.img -append “root/dev/vda rw” 系统开始启动
3.2.2.4. 调试
远程启动 qemu-system-aarch64 -machine virt,virtualizationtrue,gic-version3 -nographic -m size1024M -cpu cortex-a72 -smp 2 -kernel Image -drive formatraw,filerootfs.img -append “root/dev/vda rw nokaslr” -S -s 调整GDB权限问题 创建/root/.gdbinit文件并写入以下信息 set auto-load safe-path / 启动GDB 进入Kernel源代码目录执行gdb-multiarch vmlinux。vmlinux是原始的内核elf文件Image文件则是压缩之后的elf文件。 连接远程调试添加断点函数 VSCode调试 gdb调试不太方便用VSCode更方便。用VSCode打开Kernel源代码在.vscode目录添加launch.josn文件内容如下然后找到init/main.c的的start_kernel函数下断点然后按F5启动调试。
{// Use IntelliSense to learn about possible attributes.// Hover to view descriptions of existing attributes.// For more information, visit: https://go.microsoft.com/fwlink/?linkid830387version: 0.2.0,configurations: [{name: Launch QEMU to debug HelloWorld.elf,type: cppdbg,request: launch,program: ${workspaceFolder}/vmlinux,cwd: ${workspaceFolder},miDebuggerPath: gdb-multiarch,miDebuggerServerAddress: localhost:1234,stopAtConnect: true,stopAtEntry: true,}]
}4. 扩展QEMU
4.1. 下载代码
开发代码基于qemu 8.2.1版本。 git clone https://gitee.com/mirrors/qemu.git 4.2. 编译
要扩展QEMU的功能肯定需要用到调试所以编译时需要打开debug选项并且可以指定编译的工具来减少编译时间。详细编译配置参见./configure -help。如下只编译riscv版本。 ./configure --target-listriscv32-softmmu --enable-debug --disable-werror make -j8 4.3. 添加uart
qemu是默认一块完整的开发板其模拟的硬件不仅有cpu还有各种外设。相关代码放在hw目录uart外设则放 在char目录中。
添加uart代码。 cmsdk-apb-uart是mps2主板(支持Cortext-M7)配套的uart我们将其移植到riscv中来。将cmsdk-apb-uart改为ys_uart。并将函数中的cmsdk-apb-uart也相应修改为ys_uart。添加打印函数 uart中用到的一些函数是编译时python调用trace-event文件中的相关描述生成的。所以在trace-event中添加 ys_uart.c ys_uart_read(uint64_t offset, uint64_t data, unsigned size) “CMSDK APB UART read: offset 0x%” PRIx64 data 0x% PRIx64 size %u ys_uart_write(uint64_t offset, uint64_t data, unsigned size) “CMSDK APB UART write: offset 0x%” PRIx64 data 0x% PRIx64 size %u ys_uart_reset(void) “CMSDK APB UART: reset” ys_uart_receive(uint8_t c) “CMSDK APB UART: got character 0x%x from backend” ys_uart_tx_pending(void) “CMSDK APB UART: character send to backend pending” ys_uart_tx(uint8_t c) “CMSDK APB UART: character 0x%x sent to backend” ys_uart_set_params(int speed) “CMSDK APB UART: params set to %d 8N1” 编译配置 qemu是采用kconfig配置和meson来编译的所以需要配置char目录的Kconfig文件添加 system_ss.add(when: ‘CONFIG_YS_UART’, if_true: files(‘ys_uart.c’)) Kconfig文件添加 config YS_UART bool 给hw/riscv/virt.c添加自定义的uart
#include hw/char/ys_uart.h // 添加头文件// 在函数virt_machine_inti中添加如下代码
DeviceState *dev qdev_new(TYPE_YS_UART);
SysBusDevice *sbd SYS_BUS_DEVICE(dev);
qdev_prop_set_chr(dev, chardev, serial_hd(0));
qdev_prop_set_uint32(dev, pclk-frq, 25000000);
sysbus_realize_and_unref(sbd, error_fatal);
sysbus_mmio_map(sbd, 0, 0x40004000);
// 上面的代码为新添加
serial_mm_init(system_memory, memmap[VIRT_UART0].base,0, qdev_get_gpio_in(mmio_irqchip, UART0_IRQ), 399193,serial_hd(1), DEVICE_LITTLE_ENDIAN);修改machine名 将hw/riscv/virt.c、virt.h中的 MACHINE_TYPE_NAME(“virt”), // 修改为 MACHINE_TYPE_NAME(“ys_virt”),代码 相关代码见https://gitee.com/michael_duan/qemu_riscv.git
4.4. 测试
4.4.1. 固件 #define UART0_ADDRESS (0x40004000UL)
#define UART0_DATA (*(((volatile uint32_t *)(UART0_ADDRESS 0UL))))
#define UART0_STATE (*(((volatile uint32_t *)(UART0_ADDRESS 4UL))))
#define UART0_CTRL (*(((volatile uint32_t *)(UART0_ADDRESS 8UL))))
#define UART0_BAUDDIV (*(((volatile uint32_t *)(UART0_ADDRESS 16UL))))
#define TX_BUFFER_MASK (1UL)static void InitUart(void)
{UART0_BAUDDIV 16;UART0_CTRL 1;
}
/*-----------------------------------------------------------*/static int UartWrite(char *pcString, int iStringLength)
{int iNextChar;/* Output the formatted string to the UART. */for (iNextChar 0; iNextChar iStringLength; iNextChar){while ((UART0_STATE TX_BUFFER_MASK) ! 0){}UART0_DATA *pcString;pcString;}return iStringLength;
}int main(void)
{InitUart();UartWrite(Hello World!\n, 13);while (1){/* code */}
}
4.4.2. 调试
调试qemu利用VSCode更在.vscode目录中添加launch.json文件添加如下内容
{version: 0.2.0,configurations: [{name: Debug,type: cppdbg,request: launch,args: [-machine, ys_virt, -serial, stdio, -nodefaults, -bios, none, -smp, 1, -nographic, -kernel, e:\\HelloWorld_riscv.elf],cwd: ${workspaceFolder},environment: [],externalConsole: false,stopAtEntry: false,windows: {MIMode: gdb,miDebuggerPath: C:\\msys64\\mingw64\\bin\\gdb.exe,program: ${workspaceFolder}\\build\\qemu-system-riscv32.exe,},}]
}
在\system\main.c的int main(int argc, char **argv)处添加断点按F5调试显示如下
4.4.3. 验证 ./build/qemu-system-riscv32.exe -machine ys_virt -serial stdio -nodefaults -bios none -kernel /e/HelloWorld_riscv.elf -nographic