前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >[kvm][virt]MMIO技术分析

[kvm][virt]MMIO技术分析

作者头像
皮振伟
发布2018-04-09 11:22:31
5.8K0
发布2018-04-09 11:22:31
举报
文章被收录于专栏:皮振伟的专栏皮振伟的专栏

前言: 简单回顾一下前文,《内存映射技术分析》描述了虚拟内存的管理、内存映射;《物理内存管理》介绍了物理内存管理。《内存回收》介绍了一下PFRA内存回收。 上述三篇,简单建立Linux的内存管理模型,下面开始分析MMIO技术。 分析: 1,MMIO MMIO,即Memory mapping I/O;在x86上,CPU如果想要和外部交互数据,一种是使用in、out类型的端口访问的指令;一种是mov类型的读写内存的指令。对于前者来讲,就是PortIO(PIO);对于后者,就是MMIO。(这里说明一下,ARM上只有MMIO,简单了一些~) 所以,如果CPU和外部的设备交互,也逃不开这两种方式。对于PIO,如前文《PIO技术分析》中所说,CPU只要截获VM(Virtual Machine)的in、out指令,就可以知道CPU想要访问设备,那么用软件来模拟硬件的行为,就可以让VM觉得自己有设备。 对于MMIO,则相对复杂一点。首先来看一下VM中的iomem的layout,在VM中敲cat /proc/iomem:

2,System RAM 说明一下,作者给VM配置了6G的RAM。如上图中的System RAM: 00001000-0009fbff : System RAM 00100000-bffd7fff : System RAM -->这段大小约3G,地址范围在约低0G~3G的范围内。 100000000-1bfffffff : System RAM -->这段大小约3G,在4G~7G的范围内。 原因就是中间有1G的地址空间给了PCI、IOAPIC、LAPIC等使用。 在qemu-2.8.0-rc4/hw/i386/pc_piix.c中:

可见,在qemu中,就已经提前把内存分块,并留下了3G~4G的1G的物理地址空间。

那么问题来了,为什么不让内存连续在一起呢?内存连在一起的好处在于memory block之间没有hole,可以节省一些page struct(spare memory的情况下,节省一点计算量)。因为qemu并不知道将来要运行的VM的操作系统是否支持64bit,在32bit下,地址空间只有0~4G,那么可以减少一些内存,但是不能没有PCI,APIC等。

3,PCI Address 在VM中敲lspci:

以00:03.0 Ethernet controller: Intel Corporation 82540EM Gigabit Ethernet Controller (rev 03)为例,对应的是iomem中: febc0000-febdffff : 0000:00:03.0 febc0000-febdffff : e1000 00:03.0表示PCI地址:bus 0x00,device 0x03, function 0x00。 febc0000-febdffff表示网卡的MMIO的地址。 e1000是常用的虚拟网卡。 此时,CPU可以通过访问febc0000-febdffff之间的地址和e1000网卡交互。需要注意的是,这里是VM的物理地址,操作系统加载之后,跑在protected mode下,是访问虚拟地址的。所以还需要做一次mapping。 4,misconfig 继续上文3步,如果CPU访问了febc0000-febdffff,就说明在访问网卡设备了。所以,CPU需要截获虚拟机访问的具体地址,并发生了异常,从VM-mode下退出来,让qemu继续处理,模拟硬件的行为即可。这就是MMIO下的设备模拟过程,CPU截获MMIO的是misconfig异常。 在intel的官方文档中:EPT misconfiguration. An attempt to access memory with a guest-physical address encountered a misconfigured EPT paging-structure entry. 结合上面的地址信息,PCI的地址空间确实也不在内存的地址空间范围内。 5,KVM_EXIT_MMIO 如果发生了misconfig,KVM会返回KVM_EXIT_MMIO的exit reason。 6,handle mmio qemu-2.8.0-rc4/kvm-all.c中kvm_cpu_exec函数处理KVM_EXIT_MMIO:

根据地址,找到对应的设备。再继续模拟设备的行为。 后记: 设备的模拟,无论是PIO,还是MMIO,思路都差不多:CPU能够感知到访问了设备,并根据访问的具体的地址,找到对应的设备,最后模拟出来硬件的行为。 区别在于,两种方式下的处理不同,明显MMIO的路径要长一些,而且更加复杂一些。 Virtio设备本质上也是一个PCI设备(例如例子中的fe000000-fe003fff : virtio-pci-modern,就是作者挂载的Virtio-Blk),在Guest中需要kick Host,默认会使用PIO,而非MMIO。原因就是PIO的性能略好于MMIO。作者也实验过,在PIO VS MMIO的对比中,MMIO和PIO的性能都是ns级别的,二者相差不是很多,总体来说,PIO的数据略好于MMIO。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2017-03-05,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 AlwaysGeek 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档