深入分析Linux虚拟化KVM-Qemu之ARMv8虚拟化

news2024/9/24 15:25:26

说明:

  1. KVM版本:5.9.1

  2. QEMU版本:5.0.0

  3. 工具:Source Insight 3.5, Visio

1. 概述

 

  • KVM虚拟化离不开底层硬件的支持,本文将介绍ARMv8架构处理器对虚拟化的支持,包括内存虚拟化、中断虚拟化、I/O虚拟化等内容;

  • ARM处理器主要用于移动终端领域,近年也逐渐往服务器领域靠拢,对虚拟化也有了较为完善的支持;

  • Hypervisor软件,涵盖的功能包括:内存管理、设备模拟、设备分配、异常处理、指令捕获、虚拟异常管理、中断控制器管理、调度、上下文切换、内存转换、多个虚拟地址空间管理等;

  • 本文描述的ARMv8虚拟化支持,对于理解arch/arm64/kvm下的代码很重要,脱离硬件去看Architecture-Specific代码,那是耍流氓;

开始旅程!

2. ARMv8虚拟化

2.1 Exception Level

  • ARMv7之前的架构,定义了一个处理器的异常处理模式,比如USR, FIQ, IRQ, SVC, ABT, UND, SYS, HYP, MON等,各个异常模式所处的特权级不一样,比如USR模式的特权级就为PL0,对应为用户态程序运行;

  • 处理器的异常模式可以在特权级软件控制下进行主动切换,比如修改CPSR寄存器,也可以被动进行异常模式切换,典型的比如中断来临时切换到IRQ模式

ARMv7处理器的异常模式如下表所示:

 

然鹅,到了ARMv8,Exception Level(EL)取代了特权级,其中处理器的异常模式与Exception Level的映射关系如下图:

 

  • 当异常发生时,处理器将改变Exception Level(相当于ARMv7中的处理器模式切换),来处理异常类型;

  • 图中可以看出Hypervisor运行在EL2,而Guest OS运行在EL1,可以通过HVC (Hypervisor Call)指令向Hypervisor请求服务,响应虚拟化请求时就涉及到了Exception Level的切换;

  资料直通车:Linux内核源码技术学习路线+视频教程内核源码

学习直通车:Linux内核源码内存调优文件系统进程管理设备驱动/网络协议栈

2.2 Stage 2 translation

Stage 2转换与内存虚拟化息息相关,这部分内容不仅包括常规的内存映射访问,还包含了基于内存映射的I/O(MMIO)访问,以及系统内存管理单元(SMMUs)控制下的内存访问。

2.2.1 内存映射

OS在访问物理内存前,需要先建立页表来维护虚拟地址到物理地址的映射关系,看过之前内存管理分析的同学应该熟悉下边这张图,这个可以认为是Stage 1转换

 

  • 当有了虚拟机时,情况就不太一样了,比如Qemu运行在Linux系统之上时,它只是Linux系统的一个用户进程,Guest OS所认为自己访问的物理地址,其实是Linux的用户进程虚拟地址,到最终的物理地址还需要进一步的映射;

  • Hypervisor可以通过Stage 2转换来控制虚拟机的内存视图,控制虚拟机是否可以访问某块物理内存,进而达到隔离的目的;

 

  • 整个地址的映射分成了两个阶段:

    1. Stage 1: VA(Virutal Address) -> IPA(Intermediate Physical Address),操作系统控制Stage 1转换;

    2. Stage 2: IPA(Intermediate Physical Address) -> PA(Physical Address)Hypervisor控制Stage 2转换;

  • Stage 2转换Stage 1转换机制很类似,不同点在于Stage 2转换时判断内存类型是normal还是device时,是存放进页表信息里了,而不是通过MAIR_ELx寄存器来判断;

  • 每个虚拟机(VM,Virtual Machine)都会分配一个VMID,用于标识TLB entry所属的VM,允许在TLB中同时存在多个不同VM的转换;

  • 操作系统会给应用程序分配一个ASID(Address Space Identifier),也可以用于标识TLB entry,属于同一个应用程序的TLB entry都有相同的ASID,不同的应用程序可以共享同一块TLB缓存。每个VM都有自己的ASID空间,通常会结合VMIDASID来同时使用;

  • Stage 1Stage 2的转换页表中,都包含了属性的相关设备,比如访问权限,存储类型等,在两级转换的过程中,MMU会整合成一个最终的也有效值,选择限制更严格的属性,如下图:

 

  • 图中的Device属性限制更严格,则选择Device类型;

  • Hypervisor如果想要改变默认整合行为,可以通过寄存器HCR_EL2(Hypervisor Configuration Register)来配置,比如设置Non-cacheable, Write-Back Cacheable等特性;

2.2.2 MMIO(Memory-Mapped Input/Output)

Guest OS认为的物理地址空间,实际是IPA地址空间,就像真实物理机中一样,IPA的地址空间,也分成内存地址空间和I/O地址空间:

 

 

  • 访问外设有两种情况:1)直通访问真实的外设;2)触发faultHypervisor通过软件来模拟;

  • VTTBR_EL2Virtualization Translation Table Base Register,虚拟转换表基地址寄存器,存放Stage 2转换的页表;

  • 为了模拟外设,Hypervisor需要知道访问的是哪个外设以及访问的寄存器,读访问还是写访问,访问长度是多少,使用哪些寄存器来传送数据等。Stage 2转换有一个专门的Hypervisor IPA Fault Address Register, EL2(HPFAR_EL2)寄存器,用于捕获Stage 2转换过程中的fault;

软件模拟外设的示例流程如下:

 

  • 1)虚拟机VM中的软件尝试访问串口设备;

  • 2)访问时Stage 2转换被block住,并触发abort异常路由到EL2。异常处理程序查询ESR_EL2(Exception Syndrome Register)寄存器关于异常的信息,如访问长度、目标寄存器,Load/Store操作等,异常处理程序还会查询HPFAR_EL2寄存器,获取abort的IPA地址;

  • 3)Hypervisor通过ESR_EL2HPFAR_EL2里的相关信息对相关虚拟外围设备进行模拟,完成后通过ERET指令返回给vCPU,从发生异常的下一条指令继续运行;

2.2.3 SMMUs(System Memory Management Units)

访问内存的另外一种case就是DMA控制器。

非虚拟化下DMA控制器的工作情况如下:

  • DMA控制器由内核的驱动程序来控制,能确保操作系统层面的内存的保护不会被破坏,用户程序无法通过DMA去访问被限制的区域;

虚拟化下DMA控制器,VM中的驱动直接与DMA控制器交互会出现什么问题呢?如下图:

  • DMA控制器不受Stage 2转换的约束,会破坏VM的隔离性;

  • Guest OS以为的物理地址是IPA地址,而DMA看到的地址是真实的物理地址,两者的视角不一致,为了解决这个问题,需要捕获每次VM与DMA控制器的交互,并提供转换,当内存出现碎片化时,这个处理低效且容易引入问题;

SMMUs可以用于解决这个问题:

  • SMMU也叫IOMMU,对IO部件提供MMU功能,虚拟化只是SMMU的一个应用;

  • Hypervisor可以负责对SMMU进行编程,以便让上层的控制器和虚拟机VM以同一个视角对待内存,同时也保持了隔离性;

2.3 Trapping and emulation of Instructions

Hypervisor也需要具备捕获(trap)和模拟指令的能力,比如当VM中的软件需要配置底层处理器来进行功耗管理或者缓存一致性操作时,为了不破坏隔离性,Hypervisor就需要捕获操作并进行模拟,以便不影响其他的VM。如果设置了捕获某个操作时,当该操作被执行时会向更高一级的Exception Level触发异常(比如Hypervisor为EL2),从而在相应的异常处理中完成模拟。

例子来了:

 

  • 在ARM处理器中执行WFI(wait for interrupt)命令,可以让CPU处于一个低功耗的状态;

  • HCR_EL2(Hypervisor Control Register),当该寄存器的TWI==1时,vCPU执行WFI指令会触发EL2异常,从而Hypervisor可以对其进行模拟,将任务调度到另外一个vCPU即可;

捕获(traps)的另一个作用是可以用于向Guest OS呈现寄存器的虚拟值,如下:

 

  • ID_AA64MMFR0_EL1寄存器用于查询处理器对内存系统相关特性的支持,系统可能在启动阶段会读取该寄存器,Hypervisor可以向Guest OS呈现一个不同的虚拟值;

  • 当vCPU读取该寄存器时,触发异常,Hypervisortrap_handler中进行处理,设置一个虚拟值,并最终返回给vCPU;

  • 通过trap来虚拟化一个操作需要大量的计算,包括触发异常、捕获,模拟、返回等一系列操作,像ID_AA64MMFR0_EL1寄存器访问并不频繁,这种方式问题不大。但是当需要频繁访问的寄存器,比如MIDR_EL1MPIDR_EL1等,出于性能的考虑,应该避免陷入到Hypervisor中进行模拟处理,可以通过其他机制,比如提供VPIDR_EL2VMIDR_EL2寄存器,在进入VM前就设置好该值,当读取MIDR_EL1MPIDR_EL1时,硬件就返回VPIDR_EL2VMIDR_EL2的值,避免了陷入处理;

2.4 Virtualizing exceptions

  • Hypervisor对虚拟中断的处理比较复杂,Hypervisor本身需要机制来在EL2处理中断,还需要机制来将外设的中断信号发送到目标虚拟机VM(或vCPU)上,为了使能这些机制,ARM体系架构包含了对虚拟中断的支持(vIRQs,vFIQs,vSErrors);

  • 处理器只有在EL0/EL1执行状态下,才能收到虚拟中断,在EL2/EL3状态下不能收到虚拟中断;

  • Hypervisor通过设置HCR_EL2寄存器来控制向EL0/EL1发送虚拟中断,比如为了使能vIRQ,需要设置HCR_EL2.IMO,设置后便会将物理中断发送至EL2,然后使能将虚拟中断发送至EL1;

有两种方式可以产生虚拟中断:1)在处理器内部控制HCR_EL2寄存器;2)通过GIC中断控制器(v2版本以上);其中方式一使用比较简单,但是它只提供了产生中断的方式,需要Hypervisor来模拟VM中的中断控制器,通过捕获然后模拟的方式,会带来overhead,当然不是一个最优解。

让我们来看看GIC吧,看过之前中断子系统系列文章的同学,应该见过下图:

 

  • Hypervisor可以将GIC中的Virtual CPU Interface映射到VM中,从而允许VM中的软件直接与GIC进行通信,Hypervisor只需要进行配置即可,这样可以减少虚拟中断的overhead;

来个虚拟中断的例子吧:

 

  1. 外设触发中断信号到GIC;

  2. GIC产生物理中断IRQ或者FIQ信号,如果设置了HCR_EL2.IMO/FMO,中断信号将被路由到HypervisorHypervisor会检查中断信号转发给哪个vCPU

  3. Hypervisor设置GIC,将该物理中断信号以虚拟中断的形式发送给某个vCPU,如果此时处理器运行在EL2,中断信号会被忽略;

  4. Hypervisor将控制权返回给vCPU;

  5. 处理器运行在EL0/EL1时,虚拟中断会被接受和处理

  • ARMv8处理器中断屏蔽由PSTATE中的比特位来控制(比如PSTATE.I),虚拟化时比特位的作用有些不一样,比如设置HCR_EL2.IMO时,表明物理IRQ路由到EL2,并且对EL0/EL1开启vIRQs,因此,当运行在EL0/EL1时,PSTATE.I比特位针对的是虚拟vIRQs而不是物理的pIRQs

2.5 Virtualizing the Generic Timers

先来看一下SoC的内部:

 

简化之后是这样的:

 

  • ARM体系架构每个处理器都包含了一组通用定时器,从图中可以看到两个模块:ComparatorsCounter Module,当Comparators的值小于等于系统的count值时便会产生中断,我们都知道在操作系统中timer的中断就是系统的脉搏了;

下图展示虚拟化系统中运行的vCPU的时序:

 

  • 物理时间4ms,每个vCPU运行2ms,如果设置vCPU0T=0之后的3ms后产生中断,那希望是物理时间的3ms后(也就是vCPU0的虚拟时间2ms)产生中断,还是虚拟时间3ms后产生中断?ARM体系结构支持这两种设置;

  • 运行在vCPU上的软件可以同时访问两种时钟:EL1物理时钟EL1虚拟时钟

EL1物理时钟EL1虚拟时钟

 

  • EL1物理时钟与系统计数器模块直接比较,使用的是wall-clock时间;

  • EL1虚拟时钟与虚拟计数器比较,而虚拟计数器是在物理计数器上减去一个偏移;

  • Hypervisor负责为当前调度运行的vCPU指定对应的偏移,这种方式使得虚拟时间只会覆盖vCPU实际运行的那部分时间;

来一张示例图:

 

  • 6ms的时间段里,每个vCPU运行3ms,Hypervisor可以使用偏移寄存器来将vCPU的时间调整为其实际的运行时间;

2.6 Virtualization Host Extensions(VHE)

  • 先抛出一个问题:通常Host OS的内核都运行在EL1,而控制虚拟化的代码运行在EL2,这就意味着传统的上下文切换,这个显然是比较低效的;

  • VHE用于支持type-2Hypervisor,这种扩展可以让内核直接跑在EL2,减少host和guest之间共享的系统寄存器数量,同时也减少虚拟化的overhead;

VHE由系统寄存器HCR_EL2E2HTGE两个比特位来控制,如下图:

 

VHE的引入,需要考虑虚拟地址空间的问题,如下图:

 

  • 我们在内存子系统分析时提到过虚拟地址空间的问题,分为用户地址空间(EL0)和内核地址空间(EL1),两者的区域不一致,而在EL2只有一个虚拟地址空间区域,这是因为Hypervisor不支持应用程序,因此也就不需要分成内核空间和用户空间了;

  • EL0/EL1虚拟地址空间也同时支持ASID(Address Space Identifiers),而EL2不支持,原因也是Hypervisor不需要支持应用程序;

从上两点可以看出,为了支持Host OS能运行在EL2,需要添加一个地址空间区域,以及支持ASID,设置HCR_EL2.E2H的寄存器位可以解决这个问题,如下图:

 

Host OS运行在EL2需要解决的另一个问题就是寄存器访问重定向,在内核中需要访问EL1的寄存器,比如TTBR0_EL1,而当内核运行在EL2时,不需要修改内核代码,可以通过寄存器的设置来控制访问流,如下图:

 

  • 重定向访问寄存器引入一个新的问题,Hypervisor在某些情况下需要访问真正的EL1寄存器,ARM架构引入了一套新的别名机制,以_EL12/_EL02结尾,如下图,可以在ECH==1EL2访问TTBR0_EL1

 

Host OS运行在EL2还需要考虑异常处理的问题,前边提到过HCR_EL2.IMO/FMO/AMO的比特位可以用来控制物理异常路由到EL1/EL2。当运行在EL0TGE==1时,所有物理异常都会被路由到EL2(除了SCR_EL3控制的),这是因为Host Apps运行在EL0,而Host OS运行在EL2

2.7 总结

  • 本文涉及到内存虚拟化(stage 2转换),I/O虚拟化(包含了SMMU,中断等),中断虚拟化,以及指令trap and emulation等内容;

  • 基本的套路就是请求虚拟化服务时,路由到EL2去处理,如果有硬件支持的则硬件负责处理,否则可以通过软件进行模拟;

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/130358.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

BM33 二叉树的镜像

题目 操作给定的二叉树,将其变换为源二叉树的镜像。 数据范围:二叉树的节点数 0≤n≤1000, 二叉树每个节点的值 0≤val≤1000。 要求: 空间复杂度 O(n)。本题也有原地操作,即空间复杂度 O(1)的解法,时间…

windows系统中安装maven用来编译项目

1为什么要安装maven 作为一个编程小白,我们先看一下以前学java的时候,下载一个项目源码,是不是需要把所依赖的第三方jar包一起跟着源码打包放一起,这样别人的代码才能运行起来。这种方式不利于对jar包的管理,后来就出现…

力扣sql入门篇(三)

力扣sql入门篇(三) 1 修复表中的名字 1.1 题目内容 1.1.1 基本题目信息 1.1.2 示例输入输出 1.2 示例sql语句 SELECT user_id,CONCAT(upper(substring(name,1,1)),lower(substring(name,2,length(name)-1))) name FROM Users ORDER BY user_id;1.3 运行截图 2 按日期分组销…

计算机网络学习笔记(谢希仁版本)

计算机网络学习笔记 1. 概述 1.1 计算机网络在信息时代的作用 互联网基本特点: 连通性:互联网上用户不管距离多远,都能通信,就像这些用户终端都彼此连通 共享性:指资源共享,包含信息、软件、硬件等共享…

WebRTC的拥塞控制技术(Congestion Control)

\1. 概述 对于共享网络资源的各类应用来说,拥塞控制技术的使用有利于提高带宽利用率,同时也使得终端用户在使用网络时能够获得更好的体验。在协议层面上拥塞控制是TCP的一个总要的组成部分;但是对于非面向链接的传输层协议,如UDP&…

智慧城管违规摆摊沿街晾晒识别检测 python

智慧城管违规摆摊沿街晾晒识别检测通过opencvpython对现场画面中进行7*24小时不间断实时监测,当opencvpython城管违规摆摊沿街晾晒识别检测监测到沿街晾晒违规摆摊占道经营时,立即抓拍告警。OpenCV的全称是Open Source Computer Vision Library&#xff…

小侃设计模式(十九)-解释器模式

1.概述 解释器模式(Interpreter Pattern)是一种使用相对较少的模式,主要使用在编译解释等场景,例如:编译器、规则引擎解释、正则表达式解析等,这些语言又被称为领域特定语言(Domain Specific L…

【数据结构与算法】数据结构介绍与稀疏数组相关操作

文章目录一 数据结构介绍1 数据结构和算法的重要性2 数据结构和算法的关系3 线性结构和非线性结构(1)线性结构(2)非线性结构二 稀疏数组1 应用场景2 基本概念(1)基本介绍(2)压缩策略…

并发编程——1.进程与线程

目录1.进程与线程1.1.概述1.2.并行与并发本文笔记整理来自黑马视频https://www.bilibili.com/video/BV16J411h7Rd/?p1,相关资料可在视频评论区进行获取。 1.进程与线程 1.1.概述 (1)进程 程序由指令和数据组成,但这些指令要运…

2022 年度作品优秀大赏 | 开发者说·DTalk

岁聿云暮之际,回首 2022,开发者们一直在迈着坚定的步伐向顶峰攀登,我们也竭尽所能不断为大家提供帮助——操作系统 Android 13 完成 Beta 版到正式版的蜕变,开发工具 Flutter 3.3 全力支持您的跨平台之旅,应用平台 Goo…

并行、并发、同步、异步、阻塞、非阻塞

并行 是指两个或者多个事件在同一时刻发生。并行是在不同实体上的多个事件。 并行针对多核 CPU 而言,它指的是多个核心同时执行多个任务的能力 单核 CPU 无法并行,并行只可能发生在多核 CPU 中。 并发 是指两个或多个事件在同一时间间隔发生。并发是…

【观察】让行业AI“触手可及”,NVIDIA创新与实践“从未止步”

毫无疑问,今天AI正与产业结合得越来越紧密,从自动驾驶,到智慧医疗,智慧金融、智慧城市等,AI已经开始渗透到我们生活的方方面面。事实上,即便目前来自传统行业用户的AI转型需求尚未完全激活爆发,…

第一篇 AlexNet——论文翻译

文章目录摘要1 简介2 数据集3 架构 3.1 ReLU非线性3.2 多GPU训练3.3 局部响应归一化3.4 重叠池化3.5 整体架构4 减少过拟合4.1 数据增强4.2 失活(Dropout)5 学习细节6 结果6.1 定性评估7 探讨摘要 论文链接:http://www.cs.toronto.edu/~fritz/absps/imagenet.pdf …

VTK--交互方式vtkInteractorStyleTrackballCamera

前言:本博文主要介绍vtk中基于Camera的交互方式vtkInteractorStyleTrackballCamera 及其子类,小伙伴可以根据需求自定义交互方式。 目录 vtkInteractorStyleTrackballCamera vtkGeoInteractorStyle vtkInteractorStyleImage vtkInteractorStyleMult…

LeetCode刷题复盘笔记—一文搞懂动态规划之152. 乘积最大子数组问题(动态规划系列第三十六篇)

今日主要总结一下动态规划的一道题目,152. 乘积最大子数组 题目:152. 乘积最大子数组 Leetcode题目地址 题目描述: 给你一个整数数组 nums ,请你找出数组中乘积最大的非空连续子数组(该子数组中至少包含一个数字&…

怎样学习线性代数?

最近在看《线性代数的几何意义》这本书,刚好也借用书里的总结,分享一下。 (注:本文是一篇我国代数名家丘维声教授在电大讲授线性代数课程时关于如何学好线性代数的综合论述,超牛!) 初学线性代数…

社区10款年度优秀插件框架盘点!

Cocos 社区年度插件框架 TOP 10以下游戏资源排名不分先后,Cocos Store & Cocos微店 年终元旦限时优惠进行中......作者:Chuan——张川介绍:一款节点树实时预览插件,支持 Cocos Creator 2.x\3.x 引擎版本,除节点预览…

云信小课堂 | 如何管理音视频的通话状态?

2022.12业务背景 用户在实际使用云信音视频通话 2.0 服务中,常常会遇到弱网,掉线等情况,对于这类情况,云信 SDK 提供了自动重连的相关策略,业务层不需要单独处理重连,只需要监听并做好相应的 UI 逻辑。所以…

【OpenCV】使用 Python 的铅笔素描图像

目录:使用 Python 的铅笔素描图像一、前言二、代码实战2.1 导包2.2 读取照片2.3 使用 OpenCV 显示图像2.4 灰度图像2.5 反转图像2.6 模糊图像2.7 减淡和融合三、结果展示五、源代码一、前言 图片在 Python 中表示为一组数字。所以我们可以进行各种矩阵操作来得到令…

跨域问题(三种解决方法)

跨域就是一个域名的网页去请求另一个域名的资源,比如你刚刚在A网站输入了自己的账号密码,然后访问B网站,B网站无法获取账号密码 两个请求的协议(比如http),域名(比如说localhost或者192.168.0.…