X86_64平台上利用qemu安装aarch64架构的虚拟机

以下在x86平台上安装arm架构的虚拟机(包括aarch64),希望能帮到大家。
Qemu架构
Qemu 是纯软件实现的虚拟化模拟器,几乎可以模拟任何硬件设备,我们最熟悉的就是能够模拟一台能够独立运行操作系统的虚拟机,虚拟机认为自己和硬件打交道,但其实是和 Qemu 模拟出来的硬件打交道,Qemu 将这些指令转译给真正的硬件。
正因为 Qemu 是纯软件实现的,所有的指令都要经 Qemu 过一手,性能非常低,所以,在生产环境中,大多数的做法都是配合 KVM 来完成虚拟化工作,因为 KVM 是硬件辅助的虚拟化技术,主要负责 比较繁琐的 CPU 和内存虚拟化,而 Qemu 则负责 I/O 虚拟化,两者合作各自发挥自身的优势,相得益彰。
KVM
KVM(名称来自英语:Kernel-basedVirtual Machine的缩写,即基于内核的虚拟机),是一种用于Linux内核中的虚拟化基础设施,可以将Linux内核转化为一个hypervisor(管理程序)。KVM在2007年2月被导入Linux 2.6.20核心中,以可加载核心模块的方式被移植到FreeBSD(完整)。
关于kvm,kvm 是linux内核包含的东西,使用qemu作为上层管理(命令行),kvm面向的对象主要是服务器。

1).KVM是开源软件,全称是kernel-based virtual machine(基于内核的虚拟机)。
2).是x86架构且硬件支持虚拟化技术(如 intel VT 或 AMD-V)的Linux全虚拟化解决方案。
3).它包含一个为处理器提供底层虚拟化 可加载的核心模块kvm.ko(kvm-intel.ko或kvm-AMD.ko)。
4).KVM还需要一个经过修改的QEMU软件(qemu-kvm),作为虚拟机上层控制和界面。
5).KVM能在不改变linux或windows镜像的情况下同时运行多个虚拟机,(它的意思是多个虚拟机使用同一镜像)并为每一个虚拟机配置个性化硬件环境(网卡、磁盘、图形适配器……)。
6).在主流的Linux内核,如2.6.20以上的内核均已包含了KVM核心。

qemu 全称Quick Emulator。是独立虚拟软件,能独立运行虚拟机(根本不需要kvm)。kqemu是该软件的加速软件。kvm并不需要qemu进行虚拟处理,只是需要它的上层管理界面进行虚拟机控制。虚拟机依旧是由kvm驱动。

KVM内存管理
KVM继承了Linux系统管理内存的诸多特性,比如,分配给虚拟使用的内存可以被交换至交换空间、能够使用大内存页以实现更好的性能,以及对NUMA的支持能够让虚拟机高效访问更大的内存空间等。
KVM基于Intel的EPT(ExtendedPage Table)或AMD的RVI(Rapid Virtualization Indexing)技术可以支持更新的内存虚拟功能,这可以降低CPU的占用率,并提供较好的吞吐量。
此外,KVM还借助于KSM(Kernel Same-pageMerging)这个内核特性实现了内存页面共享。KSM通过扫描每个虚拟机的内存查找各虚拟机间相同的内存页,并将这些内存页合并为一个被各相关虚拟机共享的单独页面。在某虚拟机试图修改此页面中的数据时,KSM会重新为其提供一个新的页面副本。实践中,运行于同一台物理主机上的具有相同GuestOS的虚拟机之间出现相同内存页面的概率是很的,比如共享库、内核或其它内存对象等都有可能表现为相同的内存页,因此,KSM技术可以降低内存占用进而提高整体性能。
X86_64平台上利用qemu安装aarch64架构的虚拟机_第1张图片
从本质上看,虚拟出的每个虚拟机对应 host 上的一个 Qemu 进程,而虚拟机的执行线程(如 CPU 线程、I/O 线程等)对应 Qemu 进程的一个线程。下面通过一个虚拟机启动过程看看 Qemu 是如何与 KVM 交互的。

// 第一步,获取到 KVM 句柄
kvmfd = open("/dev/kvm", O_RDWR);
// 第二步,创建虚拟机,获取到虚拟机句柄。
vmfd = ioctl(kvmfd, KVM_CREATE_VM, 0);
// 第三步,为虚拟机映射内存,还有其他的 PCI,信号处理的初始化。ioctl(kvmfd, KVM_SET_USER_MEMORY_REGION, &mem);
// 第四步,将虚拟机镜像映射到内存,相当于物理机的 boot 过程,把镜像映射到内存。
// 第五步,创建 vCPU,并为 vCPU 分配内存空间。
ioctl(kvmfd, KVM_CREATE_VCPU, vcpuid);
vcpu->kvm_run_mmap_size = ioctl(kvm->dev_fd, KVM_GET_VCPU_MMAP_SIZE, 0);
// 第五步,创建 vCPU 个数的线程并运行虚拟机。ioctl(kvm->vcpus->vcpu_fd, KVM_RUN, 0);
// 第六步,线程进入循环,并捕获虚拟机退出原因,做相应的处理。
for (;;) {  
  ioctl(KVM_RUN)  
  switch (exit_reason) {      
    case KVM_EXIT_IO:  /* ... */      
    case KVM_EXIT_HLT: /* ... */  
  }
}
// 这里的退出并不一定是虚拟机关机,
// 虚拟机如果遇到 I/O 操作,访问硬件设备,缺页中断等都会退出执行,
// 退出执行可以理解为将 CPU 执行上下文返回到 Qemu。

Qemu 源码结构
Qemu 软件虚拟化实现的思路是采用二进制指令翻译技术,主要是提取 guest 代码,然后将其翻译成 TCG 中间代码,最后再将中间代码翻译成 host 指定架构的代码,如 x86 体系就翻译成其支持的代码形式,ARM 架构同理。
X86_64平台上利用qemu安装aarch64架构的虚拟机_第2张图片
所以,从宏观上看,源码结构主要包含以下几个部分:

  1. /vl.c:最主要的模拟循环,虚拟机环境初始化,和 CPU 的执行。
  2. /target-arch/translate.c:将 guest代码翻译成不同架构的 TCG 操作码。
  3. /tcg/tcg.c:主要的 TCG 代码。
  4. /tcg/arch/tcg-target.c:将TCG 代码转化生成 主机代码。
  5. /cpu-exec.c:主要寻找下一个二进制翻译代码块,如果没有找到就请求得到下一个代码块,并且操作生成的代码块。

其中,涉及的主要几个函数如下:
X86_64平台上利用qemu安装aarch64架构的虚拟机_第3张图片
知道了这个总体的代码结构,再去具体了解每一个模块可能会相对容易一点。
qemu-kvm虚拟化平台构建
准备工作
首先需要检查一下CPU是否支持虚拟化,执行一下命令来检查/proc/cpuinfo文件中是否有vmx或svm虚拟化相关的字,如果有的话表明CPU支持虚拟化技术。

egrep “(svm|vmx)” /proc/cpuinfo

有结果输出,如下图:
X86_64平台上利用qemu安装aarch64架构的虚拟机_第4张图片
上面命令执行结果如果返回0,表示CPU不支持虚拟化技术。当然主板BIOS中的虚拟化技术也可能不是默认开启的,如果没有开启需要手动开启一下。
安装KVM及相关依赖包

sudo apt-get install qemu-kvm
sudo apt-get install qemu
sudo apt-get install virt-manager
sudo apt-get install virt-viewer 
sudo apt-get install libvirt-bin 
sudo apt-get install bridge-utils

其中:virt-manager为GUI管理窗口,bridge-utils:用于网络桥接
命令行输入kvm --version kvm-ok lsmod | grep kvm来验证安装是否成功
上面的方式为联网安装,也可以下载源码编译安装,具体如下:
源码下载

centos:sudo apt-get install qemu
ubuntu:sudo yum install qemu -y
安装包:
$wget http://wiki.qemu-project.org/download/qemu-2.0.0.tar.bz2
$tar xjvf qemu-2.0.0.tar.bz2
Git:
$git clone git://git.qemu-project.org/qemu.git

编译及安装

$cd qemu-2.0.0 //如果使用的是git下载的源码,执行cd qemu
$./configure --enable-kvm --enable-debug --enable-vnc --enable-werror  --target-list="x86_64-softmmu"
$make -j8
$sudo make install

configure 脚本用于生成 Makefile,其选项可以用 ./configure --help 查看。

这里使用到的选项含义如下:

  1. --enable-kvm:编译 KVM 模块,使 Qemu 可以利用 KVM 来访问硬件提供的虚拟化服务。
  2. --enable-vnc:启用 VNC。
  3. --enalbe-werror:编译时,将所有的警告当作错误处理。
  4. --target-list:选择目标机器的架构。默认是将所有的架构都编译,但为了更快的完成编译,指定需要的架构即可。
    安装好之后,会生成如下应用程序:
    在这里插入图片描述
  5. ivshmem-client/server:这是一个 guest 和 host 共享内存的应用程序,遵循 C/S 的架构。
  6. qemu-ga:这是一个不利用网络实现 guest 和 host 之间交互的应用程序(使用 virtio-serial),运行在guest 中。
  7. qemu-io:这是一个执行 Qemu I/O 操作的命令行工具。
  8. qemu-system-x86_64:Qemu 的核心应用程序,虚拟机就由它创建的。
  9. qemu-img:创建虚拟机镜像文件的工具,下面有例子说明。
  10. qemu-nbd:磁盘挂载工具。
    安装KVM所需组件
    安装kvm所需的组件,也就是之前安装的qemu-kvm libvirt-bin virt-manager,安装完成后启动libvirtd服务
    此处省略。。
    使用网桥管理命令查看:
    在这里插入图片描述
    像VMware Workstation中我们需要创建物理桥接设备,可以使用virsh创建桥设备关联网卡到桥接设备上:
    需要将NetworkManager服务关闭,开机启动也关闭
    systemctl stop NetworkManager关闭nm服务 == service NetworkManager stop
    systemctl disabled NetworkManager关闭开机启动
    systemctl status NetworkManager.server用于查看状态 ==service NetworkManager status

还是首先看一下其配置:
X86_64平台上利用qemu安装aarch64架构的虚拟机_第5张图片
其中interface与NetworkManager(nm)之间具有某种关系,感兴趣的朋友可以自行百度,nm会与右上角的图标有关。

常用命令

  • 重新加载service文件: systemctl daemon-reload
  • 启动一个服务: systemctl start nginx-1.13.0.service
  • 关闭一个服务: systemctl stop nginx-1.13.0.service
  • 重启一个服务: systemctl restart nginx-1.13.0.service
  • 显示一个服务的状态: systemctl status nginx-1.13.0.service
  • 在开机时启用一个服务: systemctl enable nginx-1.13.0.service
  • 在开机时禁用一个服务: systemctl disable nginx-1.13.0.service
  • 查看服务是否开机启动: systemctl is-enabled nginx-1.13.0.service
  • 查看已启动的服务列表: systemctl list-unit-files|grep enabled
  • 查看启动失败的服务列表:systemctl --failed
    然后再创建桥接设备及关联网卡到桥接设备上,这样做是为了后面可以使host与虚拟机之间进行通信,也可以使用nat的方式,这里不做讲解。

virsh iface-bridge ens33 br0
提示找不到网卡为啥呢????
如果出现问题,也没关系

原先的配置
X86_64平台上利用qemu安装aarch64架构的虚拟机_第6张图片
如果virsh iface-bridge ens33 br0出现问题,用下面的方法
brctl addbr br0 创建br0网桥
编辑/etc/network/interfaces,增加如下内容

auto br0
iface br0 inet dhcp  # 网桥使用DHCP模式,从DHCP服务器获取IP
bridge_ports enp3s0  # 网卡名称,网桥创建前连接外部的网卡,可通过ifconfig命令查看,有IP地址的就是
bridge_stp on  # 避免数据链路出现死循环
bridge_fd 0  # 将转发延迟设置为0

systemctl restart networking.service //重启网络

桥接之后的配置
在这里插入图片描述
如果宿主机ip已经成功变到网桥上,并且宿主机能正常上网而虚拟机获取不到ip,可能是ufw没有允许ip转发导致的,编辑/etc/default/ufw允许ip转发。

DEFAULT_FORWARD_POLICY="ACCEPT"

重启ufw服务让设置生效

systemctl restart ufw.service

创建虚拟机

  • 使用qemu-img创建虚拟机镜像
    虚拟机镜像用来模拟虚拟机的硬盘,在启动虚拟机之前需要创建镜像文件,用来存储虚拟机硬盘中的数据。
qemu-img create ubuntu16.04-arm64.img 16G

镜像文件创建完成后,可使用 qemu-system-x86_64 来启动aarch64 (x86_64)架构的虚拟机:

  • 启动 VM 安装操作系统镜像
qemu-system-aarch64 -m 2048 -cpu cortex-a57 -smp 2 -M virt -bios QEMU_EFI.fd -nographic -drive if=none,file=ubuntu-16.04.3-server-arm64.iso,id=cdrom,media=cdrom -device virtio-scsi-device -device scsi-cd,drive=cdrom -drive if=none,file=ubuntu16.04-arm64.img,id=hd0 -device virtio-blk-device,drive=hd0

-m 指定虚拟机内存大小,默认单位是 MB。可在弹出的窗口中操作虚拟机,安装操作系统,安装完成后重起虚拟机便会从硬盘 (ubuntu16.04-arm64.img ) 启动
各个选项的含义如下:

  • -m megs:设定虚拟机的RAM大小;
  • -cpu model:设定CPU模型,如coreduo、qemu64等,可以使用“qemu-kvm -cpu ?”获取所支持的所有模型;
  • -smp n[,cores=cores][,threads=threads][,sockets=sockets][,maxcpus=maxcpus]:设定模拟的SMP架构中CPU的个数等、每个CPU的核心数及CPU的socket数目等;PC机上最多可以模拟255颗CPU;maxcpus用于指定热插入的CPU个数上限;
  • -M machine:指定要模拟的主机类型,如Standard PC、ISA-only PC或Intel-Mac等,可以使用“qemu-kvm -M ?”获取所支持的所有类型;
  • -nographic:默认情况下,qemu使用SDL来显示VGA输出;而此选项用于禁止图形接口,此时,qemu类似一个简单的命令行程序,其仿真串口设备将被重定向到控制台;
  • -drive option[,option[,option[,…]]]:定义一个硬盘设备;可用子选项有很多。
    file=/path/to/somefile:硬件映像文件路径;
    if=interface:指定硬盘设备所连接的接口类型,即控制器类型,如ide、scsi、sd、mtd、floppy、pflash及virtio等;
    index=index:设定同一种控制器类型中不同设备的索引号,即标识号;
    media=media:定义介质类型为硬盘(disk)还是光盘(cdrom);
    snapshot=snapshot:指定当前硬盘设备是否支持快照功能:on或off;
    cache=cache:定义如何使用物理机缓存来访问块数据,其可用值有none、writeback、unsafe和writethrough四个;
    format=format:指定映像文件的格式,具体格式可参见qemu-img命令;
    id=name # 定义硬盘设备名称
    执行上述命令时确保QEMU_EFI.fd、ubuntu-16.04.3-server-arm64.iso、ubuntu16.04-arm64.img文件在当前目前下,否则需要修改成对应的文件路径。在上述参数中,指定安装光盘这里-drive if=none,file=ubuntu-16.04.3-server-arm64.iso,id=cdrom,media=cdrom -device virtio-scsi-device -device scsi-cd,drive=cdrom我在有些网站上找到了不同的方式并尝试,但进入到光盘的安装界面后会报如下图所示错误,最后发现上述指定能正确的完成安装。
    虚拟机的启动
    安装完成之后,下面就是启动虚拟机。正常情况下,安装完成后会自动重新启动,安装过程中的部分截图。
    X86_64平台上利用qemu安装aarch64架构的虚拟机_第7张图片
    下面是我的进入操作系统界面的截图
    X86_64平台上利用qemu安装aarch64架构的虚拟机_第8张图片
    X86_64平台上利用qemu安装aarch64架构的虚拟机_第9张图片
    下次启动时可以输入命令直接启动虚拟机
qemu-system-aarch64 -m 2048 -cpu cortex-a57 -smp 2 -M virt -bios QEMU_EFI.fd -nographic -drive if=none,file=ubuntu16.04-arm64.img,id=hd0 -device virtio-blk-device,drive=hd0

如果出现下面的界面,不要慌。。。
X86_64平台上利用qemu安装aarch64架构的虚拟机_第10张图片
上面是进入到了UEFI的交互shell里面,为什么没有执行grub并引导进入ubuntu系统?说明UEFI固件没有找到ESP分区(EFI system partition,安装过程中就会看见创建了一个ESP分区)或者没有找到ESP分区中的EFI文件,因为系统需要该EFI文件来引导。在该shell下执行exit进入到UEFI的管理界面,并手动选择EFI文件启动系统,如下图所示。
X86_64平台上利用qemu安装aarch64架构的虚拟机_第11张图片
X86_64平台上利用qemu安装aarch64架构的虚拟机_第12张图片
X86_64平台上利用qemu安装aarch64架构的虚拟机_第13张图片
这样就可以进入到系统中。
利用virt-manager启动虚拟机
下面介绍用带界面的virt-manager工具去直观地管理虚拟机(开关虚拟机、添加删除网络接口也很方便),于是进行了一番尝试,找到了一个可行的方法。启动virt-manager,这种情况下需要提供系统镜像外,还要提供vmlinuz内核文件和initrd文件。
安装完成后启动virt-manager,如下图。在选择Architecture为aarch64后,出现了图中所示的warning,表示找不到aarch64架构的UEFI固件,并且在安装方式上自动选择了Import existing disk image(导入已存在的磁盘映像)。一想也是,系统最开始执行的就是UEFI固件,而我们并没有指定UEFI固件的路径。
X86_64平台上利用qemu安装aarch64架构的虚拟机_第14张图片
在ubantu系统下安装uefi固件,可以直接用以下命令:

sudo apt-get install qemu-efi

固件就会下载到/usr/share/qemu-efi/中,接着就可以用图行界面来安装,具体步骤省略。

参考链接
https://blog.csdn.net/chenxiangneu/article/details/78955462#6%E5%88%A9%E7%94%A8virt-manager%E5%90%AF%E5%8A%A8%E8%99%9A%E6%8B%9F%E6%9C%BA
http://makaidong.com/pengdonglin137/86753_291419.html
https://blog.csdn.net/wujianyongw4/article/details/80353892
https://www.cnblogs.com/wangaohui/p/5184476.html

你可能感兴趣的:(aarch64,qemu)