| ======================= |
| Virtio device migration |
| ======================= |
| |
| 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. |
| |
| Saving and restoring the state of virtio devices is a bit of a twisty maze, |
| for several reasons: |
| |
| - state is distributed between several parts: |
| |
| - virtio core, for common fields like features, number of queues, ... |
| |
| - virtio transport (pci, ccw, ...), for the different proxy devices and |
| transport specific state (msix vectors, indicators, ...) |
| |
| - virtio device (net, blk, ...), for the different device types and their |
| state (mac address, request queue, ...) |
| |
| - most fields are saved via the stream interface; subsequently, subsections |
| have been added to make cross-version migration possible |
| |
| This file attempts to document the current procedure and point out some |
| caveats. |
| |
| Save state procedure |
| ==================== |
| |
| :: |
| |
| 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 |
| |
| Load state procedure |
| ==================== |
| |
| :: |
| |
| 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 |
| |
| Implications of this setup |
| ========================== |
| |
| Devices need to be careful in their state processing during load: The |
| load_device() procedure is invoked by the core before subsections have |
| been loaded. Any code that depends on information transmitted in subsections |
| therefore has to be invoked in the device's load() function _after_ |
| virtio_load() returned (like e.g. code depending on features). |
| |
| Any extension of the state being migrated should be done in subsections |
| added to the core for compatibility reasons. If transport or device specific |
| state is added, core needs to invoke a callback from the new subsection. |