@@ -46,6 +46,8 @@ struct kvm;
#define PCI_DEV_CFG_SIZE_EXTENDED 4096
#ifdef ARCH_HAS_PCI_EXP
+#define arch_has_pci_exp() (true)
+
#define PCI_CFG_SIZE PCI_CFG_SIZE_EXTENDED
#define PCI_DEV_CFG_SIZE PCI_DEV_CFG_SIZE_EXTENDED
@@ -73,6 +75,8 @@ union pci_config_address {
};
#else
+#define arch_has_pci_exp() (false)
+
#define PCI_CFG_SIZE PCI_CFG_SIZE_LEGACY
#define PCI_DEV_CFG_SIZE PCI_DEV_CFG_SIZE_LEGACY
@@ -143,6 +147,24 @@ struct pci_cap_hdr {
u8 next;
};
+struct pci_exp_cap {
+ u8 cap;
+ u8 next;
+ u16 cap_reg;
+ u32 dev_cap;
+ u16 dev_ctrl;
+ u16 dev_status;
+ u32 link_cap;
+ u16 link_ctrl;
+ u16 link_status;
+ u32 slot_cap;
+ u16 slot_ctrl;
+ u16 slot_status;
+ u16 root_ctrl;
+ u16 root_cap;
+ u32 root_status;
+};
+
struct pci_device_header;
typedef int (*bar_activate_fn_t)(struct kvm *kvm,
@@ -188,6 +210,8 @@ struct pci_device_header {
u8 min_gnt;
u8 max_lat;
struct msix_cap msix;
+ /* Used only by architectures which support PCIE */
+ struct pci_exp_cap pci_exp;
} __attribute__((packed));
/* Pad to PCI config space size */
u8 __pad[PCI_DEV_CFG_SIZE];
@@ -12,6 +12,11 @@
#include <assert.h>
+/* Some distros don't have the define. */
+#ifndef PCI_CAP_EXP_RC_ENDPOINT_SIZEOF_V1
+#define PCI_CAP_EXP_RC_ENDPOINT_SIZEOF_V1 12
+#endif
+
/* Wrapper around UAPI vfio_irq_set */
union vfio_irq_eventfd {
struct vfio_irq_set irq;
@@ -623,6 +628,12 @@ static ssize_t vfio_pci_cap_size(struct pci_cap_hdr *cap_hdr)
return PCI_CAP_MSIX_SIZEOF;
case PCI_CAP_ID_MSI:
return vfio_pci_msi_cap_size((void *)cap_hdr);
+ case PCI_CAP_ID_EXP:
+ /*
+ * We don't emulate any of the link, slot and root complex
+ * properties, so ignore them.
+ */
+ return PCI_CAP_EXP_RC_ENDPOINT_SIZEOF_V1;
default:
pr_err("unknown PCI capability 0x%x", cap_hdr->type);
return 0;
@@ -694,6 +705,13 @@ static int vfio_pci_parse_caps(struct vfio_device *vdev)
pdev->msi.pos = pos;
pdev->irq_modes |= VFIO_PCI_IRQ_MODE_MSI;
break;
+ case PCI_CAP_ID_EXP:
+ if (!arch_has_pci_exp())
+ continue;
+ ret = vfio_pci_add_cap(vdev, virt_hdr, cap, pos);
+ if (ret)
+ return ret;
+ break;
}
}