Skip to content

Commit

Permalink
virtio-pci: compat page aligned ATS
Browse files Browse the repository at this point in the history
Commit 4c70875 ("pci: advertise a page aligned ATS") advertises
the page aligned via ATS capability (RO) to unbrek recent Linux IOMMU
drivers since 5.2. But it forgot the compat the capability which
breaks the migration from old machine type:

(qemu) qemu-kvm: get_pci_config_device: Bad config data: i=0x104 read:
0 device: 20 cmask: ff wmask: 0 w1cmask:0

This patch introduces a new parameter "x-ats-page-aligned" for
virtio-pci device and turns it on for machine type which is newer than
5.1.

Cc: Michael S. Tsirkin <mst@redhat.com>
Cc: Peter Xu <peterx@redhat.com>
Cc: Dr. David Alan Gilbert <dgilbert@redhat.com>
Cc: qemu-stable@nongnu.org
Fixes: 4c70875 ("pci: advertise a page aligned ATS")
Signed-off-by: Jason Wang <jasowang@redhat.com>
Message-Id: <20210406040330.11306-1-jasowang@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
  • Loading branch information
jasowang authored and mstsirkin committed Apr 6, 2021
1 parent 90a66f4 commit d83f46d
Show file tree
Hide file tree
Showing 5 changed files with 17 additions and 6 deletions.
1 change: 1 addition & 0 deletions hw/core/machine.c
Expand Up @@ -53,6 +53,7 @@ GlobalProperty hw_compat_5_1[] = {
{ "nvme", "use-intel-id", "on"},
{ "pvpanic", "events", "1"}, /* PVPANIC_PANICKED */
{ "pl011", "migrate-clk", "off" },
{ "virtio-pci", "x-ats-page-aligned", "off"},
};
const size_t hw_compat_5_1_len = G_N_ELEMENTS(hw_compat_5_1);

Expand Down
10 changes: 6 additions & 4 deletions hw/pci/pcie.c
Expand Up @@ -963,16 +963,18 @@ void pcie_dev_ser_num_init(PCIDevice *dev, uint16_t offset, uint64_t ser_num)
pci_set_quad(dev->config + offset + pci_dsn_cap, ser_num);
}

void pcie_ats_init(PCIDevice *dev, uint16_t offset)
void pcie_ats_init(PCIDevice *dev, uint16_t offset, bool aligned)
{
pcie_add_capability(dev, PCI_EXT_CAP_ID_ATS, 0x1,
offset, PCI_EXT_CAP_ATS_SIZEOF);

dev->exp.ats_cap = offset;

/* Invalidate Queue Depth 0, Page Aligned Request 1 */
pci_set_word(dev->config + offset + PCI_ATS_CAP,
PCI_ATS_CAP_PAGE_ALIGNED);
/* Invalidate Queue Depth 0 */
if (aligned) {
pci_set_word(dev->config + offset + PCI_ATS_CAP,
PCI_ATS_CAP_PAGE_ALIGNED);
}
/* STU 0, Disabled by default */
pci_set_word(dev->config + offset + PCI_ATS_CTRL, 0);

Expand Down
5 changes: 4 additions & 1 deletion hw/virtio/virtio-pci.c
Expand Up @@ -1856,7 +1856,8 @@ static void virtio_pci_realize(PCIDevice *pci_dev, Error **errp)
}

if (proxy->flags & VIRTIO_PCI_FLAG_ATS) {
pcie_ats_init(pci_dev, last_pcie_cap_offset);
pcie_ats_init(pci_dev, last_pcie_cap_offset,
proxy->flags & VIRTIO_PCI_FLAG_ATS_PAGE_ALIGNED);
last_pcie_cap_offset += PCI_EXT_CAP_ATS_SIZEOF;
}

Expand Down Expand Up @@ -1933,6 +1934,8 @@ static Property virtio_pci_properties[] = {
ignore_backend_features, false),
DEFINE_PROP_BIT("ats", VirtIOPCIProxy, flags,
VIRTIO_PCI_FLAG_ATS_BIT, false),
DEFINE_PROP_BIT("x-ats-page-aligned", VirtIOPCIProxy, flags,
VIRTIO_PCI_FLAG_ATS_PAGE_ALIGNED_BIT, true),
DEFINE_PROP_BIT("x-pcie-deverr-init", VirtIOPCIProxy, flags,
VIRTIO_PCI_FLAG_INIT_DEVERR_BIT, true),
DEFINE_PROP_BIT("x-pcie-lnkctl-init", VirtIOPCIProxy, flags,
Expand Down
5 changes: 5 additions & 0 deletions hw/virtio/virtio-pci.h
Expand Up @@ -42,6 +42,7 @@ enum {
VIRTIO_PCI_FLAG_INIT_PM_BIT,
VIRTIO_PCI_FLAG_INIT_FLR_BIT,
VIRTIO_PCI_FLAG_AER_BIT,
VIRTIO_PCI_FLAG_ATS_PAGE_ALIGNED_BIT,
};

/* Need to activate work-arounds for buggy guests at vmstate load. */
Expand Down Expand Up @@ -84,6 +85,10 @@ enum {
/* Advanced Error Reporting capability */
#define VIRTIO_PCI_FLAG_AER (1 << VIRTIO_PCI_FLAG_AER_BIT)

/* Page Aligned Address space Translation Service */
#define VIRTIO_PCI_FLAG_ATS_PAGE_ALIGNED \
(1 << VIRTIO_PCI_FLAG_ATS_PAGE_ALIGNED_BIT)

typedef struct {
MSIMessage msg;
int virq;
Expand Down
2 changes: 1 addition & 1 deletion include/hw/pci/pcie.h
Expand Up @@ -137,7 +137,7 @@ void pcie_acs_reset(PCIDevice *dev);

void pcie_ari_init(PCIDevice *dev, uint16_t offset, uint16_t nextfn);
void pcie_dev_ser_num_init(PCIDevice *dev, uint16_t offset, uint64_t ser_num);
void pcie_ats_init(PCIDevice *dev, uint16_t offset);
void pcie_ats_init(PCIDevice *dev, uint16_t offset, bool aligned);

void pcie_cap_slot_pre_plug_cb(HotplugHandler *hotplug_dev, DeviceState *dev,
Error **errp);
Expand Down

0 comments on commit d83f46d

Please sign in to comment.