Virtio 设备迁移
Copyright 2015 IBM Corp.
This work is licensed under the terms of the GNU GPL, version 2 or later. See the COPYING file in the top-level directory.
保存和恢复 virtio 设备状态较为复杂,原因有几方面:
状态分散在多个部分:
virtio 核心:功能、队列数等通用字段。
virtio 传输(pci、ccw 等):各代理设备及传输专用状态, 例如 MSI-X 向量、指示器。
virtio 设备(net、blk 等):各设备类型及其状态,例如 MAC 地址、请求队列。
大多数字段通过流接口保存,后来又增加子节以支持跨版本迁移。
本文记录当前流程,并说明需要注意的问题。
保存状态流程
virtio core virtio transport virtio device
----------- ---------------- -------------
save() function registered
via VMState wrapper on
device class
virtio_save() <----------
------> save_config()
- save proxy device
- save transport-specific
device fields
- save common device
fields
- save common virtqueue
fields
------> save_queue()
- save transport-specific
virtqueue fields
------> save_device()
- save device-specific
fields
- save subsections
- device endianness,
if changed from
default endianness
- 64 bit features, if
any high feature bit
is set
- virtio-1 virtqueue
fields, if VERSION_1
is set
加载状态流程
virtio core virtio transport virtio device
----------- ---------------- -------------
load() function registered
via VMState wrapper on
device class
virtio_load() <----------
------> load_config()
- load proxy device
- load transport-specific
device fields
- load common device
fields
- load common virtqueue
fields
------> load_queue()
- load transport-specific
virtqueue fields
- notify guest
------> load_device()
- load device-specific
fields
- load subsections
- device endianness
- 64 bit features
- virtio-1 virtqueue
fields
- sanitize endianness
- sanitize features
- virtqueue index sanity
check
- feature-dependent setup
这种设计的影响
加载状态时必须谨慎:核心在子节加载之前调用 load_device()。 因此,依赖子节传输信息的代码,例如依赖功能位的代码, 必须在设备 load() 中、virtio_load() 返回之后调用。
为保持兼容,迁移状态的扩展应通过向核心添加子节完成。 如果扩展传输或设备专用状态,核心需从新子节调用对应回调。