[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Qemu-devel] [PATCH v7 04/13] vfio: Add save and load functions for
From: |
Alex Williamson |
Subject: |
Re: [Qemu-devel] [PATCH v7 04/13] vfio: Add save and load functions for VFIO PCI devices |
Date: |
Tue, 16 Jul 2019 15:14:01 -0600 |
On Tue, 9 Jul 2019 15:19:11 +0530
Kirti Wankhede <address@hidden> wrote:
> These functions save and restore PCI device specific data - config
> space of PCI device.
> Tested save and restore with MSI and MSIX type.
>
> Signed-off-by: Kirti Wankhede <address@hidden>
> Reviewed-by: Neo Jia <address@hidden>
> ---
> hw/vfio/pci.c | 114
> ++++++++++++++++++++++++++++++++++++++++++
> include/hw/vfio/vfio-common.h | 2 +
> 2 files changed, 116 insertions(+)
>
> diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c
> index de0d286fc9dd..5fe4f8076cac 100644
> --- a/hw/vfio/pci.c
> +++ b/hw/vfio/pci.c
> @@ -2395,11 +2395,125 @@ static Object *vfio_pci_get_object(VFIODevice
> *vbasedev)
> return OBJECT(vdev);
> }
>
> +static void vfio_pci_save_config(VFIODevice *vbasedev, QEMUFile *f)
> +{
> + VFIOPCIDevice *vdev = container_of(vbasedev, VFIOPCIDevice, vbasedev);
> + PCIDevice *pdev = &vdev->pdev;
> + uint16_t pci_cmd;
> + int i;
> +
> + for (i = 0; i < PCI_ROM_SLOT; i++) {
> + uint32_t bar;
> +
> + bar = pci_default_read_config(pdev, PCI_BASE_ADDRESS_0 + i * 4, 4);
> + qemu_put_be32(f, bar);
> + }
> +
> + qemu_put_be32(f, vdev->interrupt);
> + if (vdev->interrupt == VFIO_INT_MSI) {
> + uint32_t msi_flags, msi_addr_lo, msi_addr_hi = 0, msi_data;
> + bool msi_64bit;
> +
> + msi_flags = pci_default_read_config(pdev, pdev->msi_cap +
> PCI_MSI_FLAGS,
> + 2);
> + msi_64bit = (msi_flags & PCI_MSI_FLAGS_64BIT);
> +
> + msi_addr_lo = pci_default_read_config(pdev,
> + pdev->msi_cap + PCI_MSI_ADDRESS_LO,
> 4);
> + qemu_put_be32(f, msi_addr_lo);
> +
> + if (msi_64bit) {
> + msi_addr_hi = pci_default_read_config(pdev,
> + pdev->msi_cap +
> PCI_MSI_ADDRESS_HI,
> + 4);
> + }
> + qemu_put_be32(f, msi_addr_hi);
> +
> + msi_data = pci_default_read_config(pdev,
> + pdev->msi_cap + (msi_64bit ? PCI_MSI_DATA_64 :
> PCI_MSI_DATA_32),
> + 2);
> + qemu_put_be32(f, msi_data);
> + } else if (vdev->interrupt == VFIO_INT_MSIX) {
> + uint16_t offset;
> +
> + /* save enable bit and maskall bit */
> + offset = pci_default_read_config(pdev,
> + pdev->msix_cap + PCI_MSIX_FLAGS + 1,
> 2);
> + qemu_put_be16(f, offset);
> + msix_save(pdev, f);
> + }
> + pci_cmd = pci_default_read_config(pdev, PCI_COMMAND, 2);
> + qemu_put_be16(f, pci_cmd);
> +}
> +
> +static void vfio_pci_load_config(VFIODevice *vbasedev, QEMUFile *f)
> +{
> + VFIOPCIDevice *vdev = container_of(vbasedev, VFIOPCIDevice, vbasedev);
> + PCIDevice *pdev = &vdev->pdev;
> + uint32_t interrupt_type;
> + uint32_t msi_flags, msi_addr_lo, msi_addr_hi = 0, msi_data;
> + uint16_t pci_cmd;
> + bool msi_64bit;
> + int i;
> +
> + /* retore pci bar configuration */
> + pci_cmd = pci_default_read_config(pdev, PCI_COMMAND, 2);
> + vfio_pci_write_config(pdev, PCI_COMMAND,
> + pci_cmd & (!(PCI_COMMAND_IO | PCI_COMMAND_MEMORY)),
> 2);
> + for (i = 0; i < PCI_ROM_SLOT; i++) {
> + uint32_t bar = qemu_get_be32(f);
> +
> + vfio_pci_write_config(pdev, PCI_BASE_ADDRESS_0 + i * 4, bar, 4);
> + }
> + vfio_pci_write_config(pdev, PCI_COMMAND,
> + pci_cmd | PCI_COMMAND_IO | PCI_COMMAND_MEMORY, 2);
> +
> + interrupt_type = qemu_get_be32(f);
> +
> + if (interrupt_type == VFIO_INT_MSI) {
> + /* restore msi configuration */
> + msi_flags = pci_default_read_config(pdev,
> + pdev->msi_cap + PCI_MSI_FLAGS,
> 2);
> + msi_64bit = (msi_flags & PCI_MSI_FLAGS_64BIT);
> +
> + vfio_pci_write_config(pdev, pdev->msi_cap + PCI_MSI_FLAGS,
> + msi_flags & (!PCI_MSI_FLAGS_ENABLE), 2);
> +
> + msi_addr_lo = qemu_get_be32(f);
> + vfio_pci_write_config(pdev, pdev->msi_cap + PCI_MSI_ADDRESS_LO,
> + msi_addr_lo, 4);
> +
> + msi_addr_hi = qemu_get_be32(f);
> + if (msi_64bit) {
> + vfio_pci_write_config(pdev, pdev->msi_cap + PCI_MSI_ADDRESS_HI,
> + msi_addr_hi, 4);
> + }
> + msi_data = qemu_get_be32(f);
> + vfio_pci_write_config(pdev,
> + pdev->msi_cap + (msi_64bit ? PCI_MSI_DATA_64 :
> PCI_MSI_DATA_32),
> + msi_data, 2);
> +
> + vfio_pci_write_config(pdev, pdev->msi_cap + PCI_MSI_FLAGS,
> + msi_flags | PCI_MSI_FLAGS_ENABLE, 2);
> + } else if (interrupt_type == VFIO_INT_MSIX) {
> + uint16_t offset = qemu_get_be16(f);
> +
> + /* load enable bit and maskall bit */
> + vfio_pci_write_config(pdev, pdev->msix_cap + PCI_MSIX_FLAGS + 1,
> + offset, 2);
> + msix_load(pdev, f);
> + }
> + pci_cmd = qemu_get_be16(f);
> + vfio_pci_write_config(pdev, PCI_COMMAND, pci_cmd, 2);
> +}
Pardon my migration ignorance, but there are bound to be more fields
and capabilities that get migrated over time. How does this get
extended to support that and maintain backwards compatibility? Thanks,
Alex
> +
> static VFIODeviceOps vfio_pci_ops = {
> .vfio_compute_needs_reset = vfio_pci_compute_needs_reset,
> .vfio_hot_reset_multi = vfio_pci_hot_reset_multi,
> .vfio_eoi = vfio_intx_eoi,
> .vfio_get_object = vfio_pci_get_object,
> + .vfio_save_config = vfio_pci_save_config,
> + .vfio_load_config = vfio_pci_load_config,
> };
>
> int vfio_populate_vga(VFIOPCIDevice *vdev, Error **errp)
> diff --git a/include/hw/vfio/vfio-common.h b/include/hw/vfio/vfio-common.h
> index 771b6d59a3db..ee72bd984a36 100644
> --- a/include/hw/vfio/vfio-common.h
> +++ b/include/hw/vfio/vfio-common.h
> @@ -120,6 +120,8 @@ struct VFIODeviceOps {
> int (*vfio_hot_reset_multi)(VFIODevice *vdev);
> void (*vfio_eoi)(VFIODevice *vdev);
> Object *(*vfio_get_object)(VFIODevice *vdev);
> + void (*vfio_save_config)(VFIODevice *vdev, QEMUFile *f);
> + void (*vfio_load_config)(VFIODevice *vdev, QEMUFile *f);
> };
>
> typedef struct VFIOGroup {
- Re: [Qemu-devel] [PATCH v7 01/13] vfio: KABI for migration interface, (continued)
- [Qemu-devel] [PATCH v7 02/13] vfio: Add function to unmap VFIO region, Kirti Wankhede, 2019/07/09
- [Qemu-devel] [PATCH v7 03/13] vfio: Add vfio_get_object callback to VFIODeviceOps, Kirti Wankhede, 2019/07/09
- [Qemu-devel] [PATCH v7 04/13] vfio: Add save and load functions for VFIO PCI devices, Kirti Wankhede, 2019/07/09
- [Qemu-devel] [PATCH v7 05/13] vfio: Add migration region initialization and finalize function, Kirti Wankhede, 2019/07/09
- [Qemu-devel] [PATCH v7 06/13] vfio: Add VM state change handler to know state of VM, Kirti Wankhede, 2019/07/09
- Re: [Qemu-devel] [PATCH v7 06/13] vfio: Add VM state change handler to know state of VM, Alex Williamson, 2019/07/16