@@ -402,6 +402,9 @@ static void pc_xen_hvm_init(MachineState *machine)
}
pc_xen_hvm_init_pci(machine);
+ if (xen_igd_gfx_pt_enabled()) {
+ xen_igd_reserve_slot(pcms->bus);
+ }
pci_create_simple(pcms->bus, -1, "xen-platform");
}
#endif
@@ -950,11 +950,35 @@ static void xen_pci_passthrough_instance_init(Object *obj)
PCI_DEVICE(obj)->cap_present |= QEMU_PCI_CAP_EXPRESS;
}
+void xen_igd_reserve_slot(PCIBus *pci_bus)
+{
+ XEN_PT_LOG(0, "Reserving PCI slot 2 for IGD\n");
+ pci_bus->slot_reserved_mask |= XEN_PCI_IGD_SLOT_MASK;
+}
+
+static void xen_igd_clear_slot(DeviceState *qdev, Error **errp)
+{
+ PCIDevice *pci_dev = (PCIDevice *)qdev;
+ XenPCIPassthroughState *s = XEN_PT_DEVICE(pci_dev);
+ XenPTDeviceClass *xptc = XEN_PT_DEVICE_GET_CLASS(s);
+ PCIBus *pci_bus = pci_get_bus(pci_dev);
+
+ if (is_igd_vga_passthrough(&s->real_device) &&
+ (s->real_device.vendor_id == PCI_VENDOR_ID_INTEL)) {
+ pci_bus->slot_reserved_mask &= ~XEN_PCI_IGD_SLOT_MASK;
+ XEN_PT_LOG(pci_dev, "Intel IGD found, using slot 2\n");
+ }
+ xptc->pci_qdev_realize(qdev, errp);
+}
+
static void xen_pci_passthrough_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+ XenPTDeviceClass *xptc = XEN_PT_DEVICE_CLASS(klass);
+ xptc->pci_qdev_realize = dc->realize;
+ dc->realize = xen_igd_clear_slot;
k->realize = xen_pt_realize;
k->exit = xen_pt_unregister_device;
k->config_read = xen_pt_pci_read_config;
@@ -977,6 +1001,7 @@ static const TypeInfo xen_pci_passthrough_info = {
.instance_size = sizeof(XenPCIPassthroughState),
.instance_finalize = xen_pci_passthrough_finalize,
.class_init = xen_pci_passthrough_class_init,
+ .class_size = sizeof(XenPTDeviceClass),
.instance_init = xen_pci_passthrough_instance_init,
.interfaces = (InterfaceInfo[]) {
{ INTERFACE_CONVENTIONAL_PCI_DEVICE },
@@ -3,6 +3,7 @@
#include "hw/xen/xen_common.h"
#include "hw/pci/pci.h"
+#include "hw/pci/pci_bus.h"
#include "xen-host-pci-device.h"
#include "qom/object.h"
@@ -41,7 +42,20 @@ typedef struct XenPTReg XenPTReg;
#define TYPE_XEN_PT_DEVICE "xen-pci-passthrough"
OBJECT_DECLARE_SIMPLE_TYPE(XenPCIPassthroughState, XEN_PT_DEVICE)
+#define XEN_PT_DEVICE_CLASS(klass) \
+ OBJECT_CLASS_CHECK(XenPTDeviceClass, klass, TYPE_XEN_PT_DEVICE)
+#define XEN_PT_DEVICE_GET_CLASS(obj) \
+ OBJECT_GET_CLASS(XenPTDeviceClass, obj, TYPE_XEN_PT_DEVICE)
+
+typedef void (*XenPTQdevRealize)(DeviceState *qdev, Error **errp);
+
+typedef struct XenPTDeviceClass {
+ PCIDeviceClass parent_class;
+ XenPTQdevRealize pci_qdev_realize;
+} XenPTDeviceClass;
+
uint32_t igd_read_opregion(XenPCIPassthroughState *s);
+void xen_igd_reserve_slot(PCIBus *pci_bus);
void igd_write_opregion(XenPCIPassthroughState *s, uint32_t val);
void xen_igd_passthrough_isa_bridge_create(XenPCIPassthroughState *s,
XenHostPCIDevice *dev);
@@ -76,6 +90,8 @@ typedef int (*xen_pt_conf_byte_read)
#define XEN_PCI_INTEL_OPREGION 0xfc
+#define XEN_PCI_IGD_SLOT_MASK 0x4UL /* Intel IGD slot_reserved_mask */
+
typedef enum {
XEN_PT_GRP_TYPE_HARDWIRED = 0, /* 0 Hardwired reg group */
XEN_PT_GRP_TYPE_EMU, /* emul reg group */
@@ -20,3 +20,7 @@ void xen_igd_gfx_pt_set(bool value, Error **errp)
error_setg(errp, "Xen PCI passthrough support not built in");
}
}
+
+void xen_igd_reserve_slot(PCIBus *pci_bus)
+{
+}