static int vfio_setup_pcie_cap(VFIOPCIDevice *vdev, int pos, uint8_t size,
                               Error **errp)
{
    uint16_t flags;
    uint8_t type;
    flags = pci_get_word(vdev->pdev.config + pos + PCI_CAP_FLAGS);
    type = (flags & PCI_EXP_FLAGS_TYPE) >> 4;
    if (type != PCI_EXP_TYPE_ENDPOINT &&
        type != PCI_EXP_TYPE_LEG_END &&
        type != PCI_EXP_TYPE_RC_END) {
        error_setg(errp, "assignment of PCIe type 0x%x "
                   "devices is not currently supported", type);
        return -EINVAL;
    if (!pci_bus_is_express(vdev->pdev.bus)) {
        PCIBus *bus = vdev->pdev.bus;
        PCIDevice *bridge;
         * Traditionally PCI device assignment exposes the PCIe capability
         * as-is on non-express buses.  The reason being that some drivers
         * simply assume that it's there, for example tg3.  However when
         * we're running on a native PCIe machine type, like Q35, we need
         * to hide the PCIe capability.  The reason for this is twofold;
         * first Windows guests get a Code 10 error when the PCIe capability
         * is exposed in this configuration.  Therefore express devices won't
         * work at all unless they're attached to express buses in the VM.
         * Second, a native PCIe machine introduces the possibility of fine
         * granularity IOMMUs supporting both translation and isolation.
         * Guest code to discover the IOMMU visibility of a device, such as
         * IOMMU grouping code on Linux, is very aware of device types and
         * valid transitions between bus types.  An express device on a non-
         * express bus is not a valid combination on bare metal systems.
         *
         * Drivers that require a PCIe capability to make the device
         * functional are simply going to need to have their devices placed
         * on a PCIe bus in the VM.
        while (!pci_bus_is_root(bus)) {
            bridge = pci_bridge_get_device(bus);
            bus = bridge->bus;
        if (pci_bus_is_express(bus)) {
            return 0;
    } else if (pci_bus_is_root(vdev->pdev.bus)) {
         * On a Root Complex bus Endpoints become Root Complex Integrated
         * Endpoints, which changes the type and clears the LNK & LNK2 fields.
        if (type == PCI_EXP_TYPE_ENDPOINT) {
                                   PCI_EXP_TYPE_RC_END << 4,
                                   PCI_EXP_FLAGS_TYPE);
            /* Link Capabilities, Status, and Control goes away */
            if (size > PCI_EXP_LNKCTL) {
                vfio_add_emulated_long(vdev, pos + PCI_EXP_LNKCAP, 0, ~0);
                vfio_add_emulated_word(vdev, pos + PCI_EXP_LNKCTL, 0, ~0);
                vfio_add_emulated_word(vdev, pos + PCI_EXP_LNKSTA, 0, ~0);
#ifndef PCI_EXP_LNKCAP2
#define PCI_EXP_LNKCAP2 44
#endif
#ifndef PCI_EXP_LNKSTA2
#define PCI_EXP_LNKSTA2 50
#endif
                /* Link 2 Capabilities, Status, and Control goes away */
                if (size > PCI_EXP_LNKCAP2) {
                    vfio_add_emulated_long(vdev, pos + PCI_EXP_LNKCAP2, 0, ~0);
                    vfio_add_emulated_word(vdev, pos + PCI_EXP_LNKCTL2, 0, ~0);
                    vfio_add_emulated_word(vdev, pos + PCI_EXP_LNKSTA2, 0, ~0);
        } else if (type == PCI_EXP_TYPE_LEG_END) {
             * Legacy endpoints don't belong on the root complex.  Windows
             * seems to be happier with devices if we skip the capability.
            return 0;
    } else {
         * Convert Root Complex Integrated Endpoints to regular endpoints.
         * These devices don't support LNK/LNK2 capabilities, so make them up.
        if (type == PCI_EXP_TYPE_RC_END) {
                                   PCI_EXP_TYPE_ENDPOINT << 4,
                                   PCI_EXP_FLAGS_TYPE);
            vfio_add_emulated_long(vdev, pos + PCI_EXP_LNKCAP,
                                   PCI_EXP_LNK_MLW_1 | PCI_EXP_LNK_LS_25, ~0);
            vfio_add_emulated_word(vdev, pos + PCI_EXP_LNKCTL, 0, ~0);
        /* Mark the Link Status bits as emulated to allow virtual negotiation */
        vfio_add_emulated_word(vdev, pos + PCI_EXP_LNKSTA,
                               pci_get_word(vdev->pdev.config + pos +
                                            PCI_EXP_LNKSTA),
                               PCI_EXP_LNKCAP_MLW | PCI_EXP_LNKCAP_SLS);
    pos = pci_add_capability(&vdev->pdev, PCI_CAP_ID_EXP, pos, size,
                             errp);
    if (pos < 0) {
        return pos;
    vdev->pdev.exp.exp_cap = pos;
    return pos;
static int vfio_setup_pcie_cap(VFIOPCIDevice *vdev, int pos, uint8_t size,
                               Error **errp)
{
    uint16_t flags;
    uint8_t type;
    flags = pci_get_word(vdev->pdev.config + pos + PCI_CAP_FLAGS);
    type = (flags & PCI_EXP_FLAGS_TYPE) >> 4;
    if (type != PCI_EXP_TYPE_ENDPOINT &&
        type != PCI_EXP_TYPE_LEG_END &&
        type != PCI_EXP_TYPE_RC_END) {
        error_setg(errp, "assignment of PCIe type 0x%x "
                   "devices is not currently supported", type);
        return -EINVAL;
    if (!pci_bus_is_express(vdev->pdev.bus)) {
        PCIBus *bus = vdev->pdev.bus;
        PCIDevice *bridge;
         * Traditionally PCI device assignment exposes the PCIe capability
         * as-is on non-express buses.  The reason being that some drivers
         * simply assume that it's there, for example tg3.  However when
         * we're running on a native PCIe machine type, like Q35, we need
         * to hide the PCIe capability.  The reason for this is twofold;
         * first Windows guests get a Code 10 error when the PCIe capability
         * is exposed in this configuration.  Therefore express devices won't
         * work at all unless they're attached to express buses in the VM.
         * Second, a native PCIe machine introduces the possibility of fine
         * granularity IOMMUs supporting both translation and isolation.
         * Guest code to discover the IOMMU visibility of a device, such as
         * IOMMU grouping code on Linux, is very aware of device types and
         * valid transitions between bus types.  An express device on a non-
         * express bus is not a valid combination on bare metal systems.
         *
         * Drivers that require a PCIe capability to make the device
         * functional are simply going to need to have their devices placed
         * on a PCIe bus in the VM.
        while (!pci_bus_is_root(bus)) {
            bridge = pci_bridge_get_device(bus);
            bus = bridge->bus;
        if (pci_bus_is_express(bus)) {
            return 0;
    } else if (pci_bus_is_root(vdev->pdev.bus)) {
         * On a Root Complex bus Endpoints become Root Complex Integrated
         * Endpoints, which changes the type and clears the LNK & LNK2 fields.
        if (type == PCI_EXP_TYPE_ENDPOINT) {
                                   PCI_EXP_TYPE_RC_END << 4,
                                   PCI_EXP_FLAGS_TYPE);
            
            if (size > PCI_EXP_LNKCTL) {
                vfio_add_emulated_long(vdev, pos + PCI_EXP_LNKCAP, 0, ~0);
                vfio_add_emulated_word(vdev, pos + PCI_EXP_LNKCTL, 0, ~0);
                vfio_add_emulated_word(vdev, pos + PCI_EXP_LNKSTA, 0, ~0);
#ifndef PCI_EXP_LNKCAP2
#define PCI_EXP_LNKCAP2 44
#endif
#ifndef PCI_EXP_LNKSTA2
#define PCI_EXP_LNKSTA2 50
#endif
                
                if (size > PCI_EXP_LNKCAP2) {
                    vfio_add_emulated_long(vdev, pos + PCI_EXP_LNKCAP2, 0, ~0);
                    vfio_add_emulated_word(vdev, pos + PCI_EXP_LNKCTL2, 0, ~0);
                    vfio_add_emulated_word(vdev, pos + PCI_EXP_LNKSTA2, 0, ~0);
        } else if (type == PCI_EXP_TYPE_LEG_END) {
             * Legacy endpoints don't belong on the root complex.  Windows
             * seems to be happier with devices if we skip the capability.
            return 0;
    } else {
         * Convert Root Complex Integrated Endpoints to regular endpoints.
         * These devices don't support LNK/LNK2 capabilities, so make them up.
        if (type == PCI_EXP_TYPE_RC_END) {
                                   PCI_EXP_TYPE_ENDPOINT << 4,
                                   PCI_EXP_FLAGS_TYPE);
            vfio_add_emulated_long(vdev, pos + PCI_EXP_LNKCAP,
                                   PCI_EXP_LNK_MLW_1 | PCI_EXP_LNK_LS_25, ~0);
            vfio_add_emulated_word(vdev, pos + PCI_EXP_LNKCTL, 0, ~0);
        
        vfio_add_emulated_word(vdev, pos + PCI_EXP_LNKSTA,
                               pci_get_word(vdev->pdev.config + pos +
                                            PCI_EXP_LNKSTA),
                               PCI_EXP_LNKCAP_MLW | PCI_EXP_LNKCAP_SLS);
    pos = pci_add_capability(&vdev->pdev, PCI_CAP_ID_EXP, pos, size,
                             errp);
    if (pos < 0) {
        return pos;
    vdev->pdev.exp.exp_cap = pos;
    return pos;
static int FUNC_0(VFIOPCIDevice *VAR_0, int VAR_1, uint8_t VAR_2,
                               Error **VAR_3)
{
    uint16_t flags;
    uint8_t type;
    flags = pci_get_word(VAR_0->pdev.config + VAR_1 + PCI_CAP_FLAGS);
    type = (flags & PCI_EXP_FLAGS_TYPE) >> 4;
    if (type != PCI_EXP_TYPE_ENDPOINT &&
        type != PCI_EXP_TYPE_LEG_END &&
        type != PCI_EXP_TYPE_RC_END) {
        error_setg(VAR_3, "assignment of PCIe type 0x%x "
                   "devices is not currently supported", type);
        return -EINVAL;
    if (!pci_bus_is_express(VAR_0->pdev.bus)) {
        PCIBus *bus = VAR_0->pdev.bus;
        PCIDevice *bridge;
         * Traditionally PCI device assignment exposes the PCIe capability
         * as-is on non-express buses.  The reason being that some drivers
         * simply assume that it's there, for example tg3.  However when
         * we're running on a native PCIe machine type, like Q35, we need
         * to hide the PCIe capability.  The reason for this is twofold;
         * first Windows guests get a Code 10 error when the PCIe capability
         * is exposed in this configuration.  Therefore express devices won't
         * work at all unless they're attached to express buses in the VM.
         * Second, a native PCIe machine introduces the possibility of fine
         * granularity IOMMUs supporting both translation and isolation.
         * Guest code to discover the IOMMU visibility of a device, such as
         * IOMMU grouping code on Linux, is very aware of device types and
         * valid transitions between bus types.  An express device on a non-
         * express bus is not a valid combination on bare metal systems.
         *
         * Drivers that require a PCIe capability to make the device
         * functional are simply going to need to have their devices placed
         * on a PCIe bus in the VM.
        while (!pci_bus_is_root(bus)) {
            bridge = pci_bridge_get_device(bus);
            bus = bridge->bus;
        if (pci_bus_is_express(bus)) {
            return 0;
    } else if (pci_bus_is_root(VAR_0->pdev.bus)) {
         * On a Root Complex bus Endpoints become Root Complex Integrated
         * Endpoints, which changes the type and clears the LNK & LNK2 fields.
        if (type == PCI_EXP_TYPE_ENDPOINT) {
                                   PCI_EXP_TYPE_RC_END << 4,
                                   PCI_EXP_FLAGS_TYPE);
            
            if (VAR_2 > PCI_EXP_LNKCTL) {
                vfio_add_emulated_long(VAR_0, VAR_1 + PCI_EXP_LNKCAP, 0, ~0);
                vfio_add_emulated_word(VAR_0, VAR_1 + PCI_EXP_LNKCTL, 0, ~0);
                vfio_add_emulated_word(VAR_0, VAR_1 + PCI_EXP_LNKSTA, 0, ~0);
#ifndef PCI_EXP_LNKCAP2
#define PCI_EXP_LNKCAP2 44
#endif
#ifndef PCI_EXP_LNKSTA2
#define PCI_EXP_LNKSTA2 50
#endif
                
                if (VAR_2 > PCI_EXP_LNKCAP2) {
                    vfio_add_emulated_long(VAR_0, VAR_1 + PCI_EXP_LNKCAP2, 0, ~0);
                    vfio_add_emulated_word(VAR_0, VAR_1 + PCI_EXP_LNKCTL2, 0, ~0);
                    vfio_add_emulated_word(VAR_0, VAR_1 + PCI_EXP_LNKSTA2, 0, ~0);
        } else if (type == PCI_EXP_TYPE_LEG_END) {
             * Legacy endpoints don't belong on the root complex.  Windows
             * seems to be happier with devices if we skip the capability.
            return 0;
    } else {
         * Convert Root Complex Integrated Endpoints to regular endpoints.
         * These devices don't support LNK/LNK2 capabilities, so make them up.
        if (type == PCI_EXP_TYPE_RC_END) {
                                   PCI_EXP_TYPE_ENDPOINT << 4,
                                   PCI_EXP_FLAGS_TYPE);
            vfio_add_emulated_long(VAR_0, VAR_1 + PCI_EXP_LNKCAP,
                                   PCI_EXP_LNK_MLW_1 | PCI_EXP_LNK_LS_25, ~0);
            vfio_add_emulated_word(VAR_0, VAR_1 + PCI_EXP_LNKCTL, 0, ~0);
        
        vfio_add_emulated_word(VAR_0, VAR_1 + PCI_EXP_LNKSTA,
                               pci_get_word(VAR_0->pdev.config + VAR_1 +
                                            PCI_EXP_LNKSTA),
                               PCI_EXP_LNKCAP_MLW | PCI_EXP_LNKCAP_SLS);
    VAR_1 = pci_add_capability(&VAR_0->pdev, PCI_CAP_ID_EXP, VAR_1, VAR_2,
                             VAR_3);
    if (VAR_1 < 0) {
        return VAR_1;
    VAR_0->pdev.exp.exp_cap = VAR_1;
    return VAR_1;
static int FUNC_0(VFIOPCIDevice *VAR_0, int VAR_1, uint8_t VAR_2,
Error **VAR_3)
{ uint16_t flags; uint8_t type; flags = pci_get_word(VAR_0->pdev.config + VAR_1 + PCI_CAP_FLAGS); type = (flags & PCI_EXP_FLAGS_TYPE) >> 4; if (type != PCI_EXP_TYPE_ENDPOINT &&
type != PCI_EXP_TYPE_LEG_END &&
type != PCI_EXP_TYPE_RC_END) { error_setg(VAR_3, "assignment of PCIe type 0x%x "
"devices is not currently supported", type); return -EINVAL; if (!pci_bus_is_express(VAR_0->pdev.bus)) { PCIBus *bus = VAR_0->pdev.bus; PCIDevice *bridge; * Traditionally PCI device assignment exposes the PCIe capability
* as-is on non-express buses.  The reason being that some drivers
* simply assume that it's there, for example tg3.  However when
* we're running on a native PCIe machine type, like Q35, we need
* to hide the PCIe capability.  The reason for this is twofold; * first Windows guests get a Code 10 error when the PCIe capability
* is exposed in this configuration.  Therefore express devices won't
* work at all unless they're attached to express buses in the VM.
* Second, a native PCIe machine introduces the possibility of fine
* granularity IOMMUs supporting both translation and isolation.
* Guest code to discover the IOMMU visibility of a device, such as
* IOMMU grouping code on Linux, is very aware of device types and
* valid transitions between bus types.  An express device on a non-
* express bus is not a valid combination on bare metal systems.
*
* Drivers that require a PCIe capability to make the device
* functional are simply going to need to have their devices placed
* on a PCIe bus in the VM.
while (!pci_bus_is_root(bus)) { bridge = pci_bridge_get_device(bus); bus = bridge->bus; if (pci_bus_is_express(bus)) { return 0; } else if (pci_bus_is_root(VAR_0->pdev.bus)) { * On a Root Complex bus Endpoints become Root Complex Integrated
* Endpoints, which changes the type and clears the LNK & LNK2 fields.
if (type == PCI_EXP_TYPE_ENDPOINT) { PCI_EXP_TYPE_RC_END << 4,
PCI_EXP_FLAGS_TYPE); if (VAR_2 > PCI_EXP_LNKCTL) { vfio_add_emulated_long(VAR_0, VAR_1 + PCI_EXP_LNKCAP, 0, ~0); vfio_add_emulated_word(VAR_0, VAR_1 + PCI_EXP_LNKCTL, 0, ~0); vfio_add_emulated_word(VAR_0, VAR_1 + PCI_EXP_LNKSTA, 0, ~0); #ifndef PCI_EXP_LNKCAP2
#define PCI_EXP_LNKCAP2 44
#endif
#ifndef PCI_EXP_LNKSTA2
#define PCI_EXP_LNKSTA2 50
#endif
if (VAR_2 > PCI_EXP_LNKCAP2) { vfio_add_emulated_long(VAR_0, VAR_1 + PCI_EXP_LNKCAP2, 0, ~0); vfio_add_emulated_word(VAR_0, VAR_1 + PCI_EXP_LNKCTL2, 0, ~0); vfio_add_emulated_word(VAR_0, VAR_1 + PCI_EXP_LNKSTA2, 0, ~0); } else if (type == PCI_EXP_TYPE_LEG_END) { * Legacy endpoints don't belong on the root complex.  Windows
* seems to be happier with devices if we skip the capability.
return 0; } else { * Convert Root Complex Integrated Endpoints to regular endpoints.
* These devices don't support LNK/LNK2 capabilities, so make them up.
if (type == PCI_EXP_TYPE_RC_END) { PCI_EXP_TYPE_ENDPOINT << 4,
PCI_EXP_FLAGS_TYPE); vfio_add_emulated_long(VAR_0, VAR_1 + PCI_EXP_LNKCAP,
PCI_EXP_LNK_MLW_1 | PCI_EXP_LNK_LS_25, ~0); vfio_add_emulated_word(VAR_0, VAR_1 + PCI_EXP_LNKCTL, 0, ~0); vfio_add_emulated_word(VAR_0, VAR_1 + PCI_EXP_LNKSTA,
pci_get_word(VAR_0->pdev.config + VAR_1 +
PCI_EXP_LNKSTA),
PCI_EXP_LNKCAP_MLW | PCI_EXP_LNKCAP_SLS); VAR_1 = pci_add_capability(&VAR_0->pdev, PCI_CAP_ID_EXP, VAR_1, VAR_2,
VAR_3); if (VAR_1 < 0) { return VAR_1; VAR_0->pdev.exp.exp_cap = VAR_1; return VAR_1;