设为首页 收藏本站
查看: 1411|回复: 0

[经验分享] Qemu创建KVM虚拟机内存初始化流程

[复制链接]

尚未签到

发表于 2015-4-10 13:41:19 | 显示全部楼层 |阅读模式
  转载请注明:【转载自博客xelatex KVM】,并附本文链接。谢谢。
  【注】文章中采用的版本:

  • Linux-3.11,https://www.kernel.org/pub/linux/kernel/v3.x/linux-3.11.tar.gz
  • qemu-kvm,git clone http://git.kernel.org/pub/scm/virt/kvm/qemu-kvm.git,
          git checkout 4d9367b76f71c6d938cf8201392abe4bfb1136cb
  一、Qemu的内存模型
  Qemu中的内存模型,简单来说就是Qemu申请用户态内存并进行管理,并将该部分申请的内存注册到对应的加速器(如KVM)中。这样的模型有如下好处:

  • 策略与机制分离。加速的机制由KVM负责,而如何调用加速的机制由Qemu负责
  • 可以由Qemu设置多种内存模型,如UMA、NUMA等等
  • 方便Qemu对特殊内存的管理(如MMIO)
  • 内存的分配、回收、换出等都可以采用Linux原有的机制,不需要为KVM单独开发。
  • 兼容其他加速器模型(或者无加速器,单纯使用Qemu做模拟)
  所以在初始化阶段,Qemu需要做的有两方面工作:向KVM注册用户态内存空间,申请用户态内存空间。
  Qemu主要通过如下结构来维护内存:
  /* A system address space - I/O, memory, etc. */     
struct AddressSpace {      
    MemoryRegion *root;      
    FlatView current_map;      
    int ioeventfd_nb;      
    MemoryRegionIoeventfd *ioeventfds;      
};
  AddressSpace设置了一段内存,其主要信息存储在root成员中,root成员是个MemoryRegion结构,主要存储内存区的结构。在Qemu中最主要的两个AddressSpace是address_space_memory和address_space_io,分别对应的MemoryRegion变量是system_memory和system_io。
  二、Qemu初始化KVM内存流程
  Qemu的主函数是vl.c中的main函数,其中调用了configure_accelerator(),是KVM初始化的配置部分。
  configure_accelerator中首先根据命令行输入的参数找到对应的accelerator,这里是KVM。之后调用accel_list.init(),即kvm_init()。
  在kvm_init()函数中主要做如下几件事情:

  • s->fd = qemu_open("/dev/kvm", O_RDWR),打开kvm控制的总设备文件/dev/kvm
  • s->vmfd = kvm_ioctl(s, KVM_CREATE_VM, 0),调用创建虚拟机的API,对应Linux kernel中的创建流程,请全文搜索kernel,关键词“KVM_CREATE_VM”
  • kvm_check_extension,检查各种extension,并设置对应的features
  • ret = kvm_arch_init(s),做一些体系结构相关的初始化,如msr、identity map、mmu pages number等等
  • kvm_irqchip_create,调用kvm_vm_ioctl(s, KVM_CREATE_IRQCHIP)在KVM中虚拟IRQ芯片,详细流程请全文搜索
  • memory_listener_register,该函数是初始化内存的主要函数,下面详细分析
  memory_listener_register调用了两次,分别注册了kvm_memory_listener和kvm_io_listener,即通用的内存和MMIO是分开管理的。以通用的内存注册为例,函数首先在全局的memory_listener链表中添加了kvm_memory_listener,之后调用listener_add_address_space分别将该listener添加到address_space_memory和address_space_io中。
  然后调用listener的region_add(即kvm_region_add()),该函数最终调用了kvm_set_user_memory_region(),其中调用kvm_vm_ioctl(s, KVM_SET_USER_MEMORY_REGION, &mem),该调用是最终将内存区域注册到kvm中的函数。
  之后在vl.c的main函数中调用了cpu_exec_init_all() => memory_map_init(),设置system_memory和system_io。
  至此初始化好了所有Qemu中需要维护的相关的内存结构,并完成了在KVM中的注册。下面需要初始化KVM中的MMU支持。
  ram_size内存大小从内存被读取到ram_size中,在vl.c的main中调用machine->init()来初始化,machine是命令行指定的机器类型,默认的init是pc_init_pci

  • 调用pc_init1,参数分别是system_memory,system_io,ram_size,boot_device,kernel_filename,kernel_cmdline,initrd_filename,cpu_model,pci_enabled,kvmclock_enabled

    • 设置above_4g_mem_size和below_4g_mem_size
    • 调用pc_memory_init设置ram,第5、6个参数分别是below_4g_mem_size和above_4g_mem_size,MemoryRegion是system_memory

      • 调用memory_region_init_ram初始化ram

        • 调用memory_region_init()初始化MemoryRegion ram
        • 设置destructor memory_region_destructor_ram
        • 调用qemu_ram_alloc()初始化ram空间,内部调用qemu_ram_alloc_from_ptr()

          • 如果没有设置-mem-path参数,则进入到第二个else(if (xen_enabled()) {)
          • if (kvm_enabled()),调用kvm_vmalloc

            • 如果是TARGET_S390X,调用kvm_arch_vmalloc
            • 否则调用qemu_vmalloc(此处走posix流程)

              • 调用qemu_memalign->posix_memalign(),此处真正alloc memory并且aligned
                                     
            • 或者直接调用malloc(在qemu_memalign中,没有_POSIX_C_SOURCE和CONFIG_BSD
                              
                         
                   
      • 调用memory_region_init_alias初始化ram_below_4g,设置MemoryRegion的一个alias
      • if (above_4g_mem_size > 0),调用memory_region_init_alias初始化ram_above_4g,设置alias
      • memory_region_init_ram初始化pc.rom
      • 调用bochs_bios_init初始化bios
            
       
  这样就建立好了Qemu-KVM的内存结构。在KVM创建Qemu内存映射的入口在kernel中kvm_vm_ioctl的case KVM_SET_USER_MEMORY_REGION,调用kvm_vm_ioctl_set_memory_region。kvm中用kvm_memory_slot结构来维护队用户空间地址的映射。该部分会在其他文章中详细介绍。

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-55694-1-1.html 上篇帖子: QEMU KVM Libvirt手册(10):Managing Virtual Machines with libvirt 下篇帖子: Set up KVM/QEMU/SPICE on Ubuntu 11.04
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表