Qemu-kvm的memory hotplug特性

声明:

本博客欢迎转发,但请保留原作者信息!

博客地址:http://blog.csdn.net/halcyonbaby

内容系本人学习、研究和总结,如有雷同,实属荣幸!


支持piix4,ich9两种芯片模拟下的内存热插拔。

编译,运行

  • qemu-kvm的patch

    http://github.com/vliaskov/qemu-kvm/commits/memhp-v4

  • seabios的patch

    http://github.com/vliaskov/seabios/commits/memhp-v4

使用方法

  • 确认guest支持memory hot plug
    进入boot目录,通过命令

    grep hotplug -i config-********
  • 使用命令卸载内存

    "echo 1 > /sys/bus/acpi/devices/PNP0C80\:00/eject"
  • 添加dimm设备

    (qemu) device_add dimm,id=ram0,bus=membus.0
  • 查询添加dimm设备命令执行结果

    (qemu) info memory-hotplug  
    dimm: ram0 hot-add success  
    or  
    dimm: ram0 hot-add failure  
  • 删除dimm设备 (还需要在guest内部使用命令卸载内存)

    (qemu) device_del ram3  
  • 查询删除dimm设备命令执行结果

    (qemu) info memory-hotplug  
    dimm: ram3 hot-remove success  
    or  
    dimm: ram3 hot-remove failure    
  • 查询dimm设备情况

    (qemu) info dimm  
    dimm0: on
    dimm1: off
    dimm2: off
    dimm3: on   
  • 可以正确显示guest使用的内存

    info balloon
  • 查询guest总可用内存情况

    info memory-total  
  • 启动虚拟机时指定dimm设备

    "-device dimm,id=name,size=sz,node=pxm,populated=on|off,bus=membus.0"

代码原理、解读

  • 几个重要的结构

    DimmBus

    提供hotplug能力的bus.独立于main system bus.

    挂载在北桥芯片上,如i440FX.

    主要记录关联的dimm device,以及DimmBus的相关操作。

    
    74 typedef struct DimmBus {
    75     BusState qbus;
    76     DeviceState *dimm_hotplug_qdev;
    77     dimm_hotplug_fn dimm_hotplug;
    78     DimmConfiglist dimmconfig_list;
    79     dimm_hotplug_fn dimm_revert;
    80     QTAILQ_HEAD(Dimmlist, DimmDevice) dimmlist;
    81     QTAILQ_HEAD(dimm_hp_result_head, dimm_hp_result)  dimm_hp_result_queue;
    82     QLIST_ENTRY(DimmBus) next;
    83 } DimmBus;
    

    DimmDevice

    Dimm设备内部信息(HotPlug enable Slot)。挂设备载在DimmBus上。

    
    45 struct DimmDevice {
    46     DeviceState qdev;
    47     uint32_t idx; /* index in memory hotplug register/bitmap */
    48     ram_addr_t start; /* starting physical address */
    49     ram_addr_t size;
    50     uint32_t node; /* numa node proximity */
    51     uint32_t populated; /* 1 means device has been hotplugged. Default is 0. */
    52     MemoryRegion *mr; /* MemoryRegion for this slot. !NULL only if populated */
    53     dimm_hp_pending_code pending; /* pending hot operation for this dimm */
    54     QTAILQ_ENTRY(DimmDevice) nextdimm;
    55 };
    

    DimmConfig
    主要记录dimm slot信息。初始由用户输入。
    用于dimm设备创建和查询dimm设备poplulate状态(qmp_query_dimm_info)。

    
    57 typedef struct DimmConfig {
    58     const char *name;
    59     uint32_t idx; /* index in linear memory hotplug bitmap */
    60     const char *bus_name;
    61     ram_addr_t start; /* starting physical address */
    62     ram_addr_t size;
    63     uint32_t node; /* numa node proximity */
    64     uint32_t populated; /* 1 means device has been hotplugged. Default is 0. */
    65     QTAILQ_ENTRY(DimmConfig) nextdimmcfg;
    66 } DimmConfig;
    

    dimm_hp_result 记录上次dimm hotplug操作的结果。只能查询 一次,查询后删除。
    关联函数主要有qmp_query_memory_hotplug。用于用户查询hotplug命令执行情况。

    
    85 struct dimm_hp_result {
    86     const char *dimmname;
    87     dimm_hp_result_code ret;
    88     QTAILQ_ENTRY(dimm_hp_result) next;
    89 };
    
  • qemu做了什么?

    对于查询系的命令来说,很简单。只是向用户返回当前的信息。

    对于设定系的命令:

    1. 初始创建虚拟机指定dimm设备
      系统初始化主板设备时,会创建membus.0/1和membus.pv两个内存热插拔的bus。这些bus挂载在北桥 芯片下。详细可见i440fx_initfn函数。 然后根据用户指定,初始化dimm设备并根据populated进行plug。详细可见dimm_init函数。
      plug过程:
      a. memory region初始化并修改虚拟机内存配置
      b. 修改dimm device信息(主要是populate状态)
      c. 调用bus的hot plug处理,详细见ich9_dimm_hotplug或piix4_dimm_hotplug,主要是设置acpi寄存器并通过中断注入给虚拟机。
    2. hot add dimm设备
      do_device_add->qdev_device_add->qdev_init->dimm_init
      过程描述:
      a.do_device_add为device add操作的入口,函数获取了输入的device参数,然后调用qdev_device_add进行添加操作。
      b.qdev_device_add函数获取设备driver,bus,然后调用qdev_init进行初始化。
      c.后续调用dimm_init进行初始化,过程同上。
    3. hot remove dimm设备
      qmp_device_del ->qdev_unplug ->device unplug implement(dimm_unplug_device)->dimmbus's unplug(ich9_dimm_hotplug、piix4_dimm_hotplug) 过程描述:
      a. qmp_device_del根据id查询到dev,然后调用qdev_unplug函数进行卸载。
      b. qdev_unplug中确认设备是否支持hotplug,然后调用设备类的unplug函数。
      c. dimm_unplug_device的实现实际上是直接调用dimm bus的unplug函数。
      d. ich9_dimm_hotplug为例,调用disable_mem_device(实际上是进行了acpi寄存器的读写)进行卸载。

限制

规格 最多256个dimm hotplug设备

  • i440fx
    membus.0 只能挂8个dimm设备
    membus.pv 无限制
  • q35
    membus.0/memebus.1 只能挂4个dimm设备
    membus.pv 无限制  

你可能感兴趣的:(技术笔记,Qemu,那些事)