@@ -63,7 +63,7 @@ typedef int (*xen_pt_conf_byte_read)
#define XEN_PT_BAR_UNMAPPED (-1)
#define PCI_CAP_MAX 48
-
+#define PCI_INTEL_OPREGION 0xfc
typedef enum {
XEN_PT_GRP_TYPE_HARDWIRED = 0, /* 0 Hardwired reg group */
@@ -307,5 +307,7 @@ int intel_pch_init(PCIBus *bus);
void igd_pci_write(PCIDevice *pci_dev, uint32_t config_addr,
uint32_t val, int len);
uint32_t igd_pci_read(PCIDevice *pci_dev, uint32_t config_addr, int len);
+uint32_t igd_read_opregion(XenPCIPassthroughState *s);
+void igd_write_opregion(XenPCIPassthroughState *s, uint32_t val);
#endif /* !XEN_PT_H */
@@ -575,6 +575,22 @@ static int xen_pt_exp_rom_bar_reg_write(XenPCIPassthroughState *s,
return 0;
}
+static int xen_pt_intel_opregion_read(XenPCIPassthroughState *s,
+ XenPTReg *cfg_entry,
+ uint32_t *value, uint32_t valid_mask)
+{
+ *value = igd_read_opregion(s);
+ return 0;
+}
+
+static int xen_pt_intel_opregion_write(XenPCIPassthroughState *s,
+ XenPTReg *cfg_entry, uint32_t *value,
+ uint32_t dev_value, uint32_t valid_mask)
+{
+ igd_write_opregion(s, *value);
+ return 0;
+}
+
/* Header Type0 reg static information table */
static XenPTRegInfo xen_pt_emu_reg_header0[] = {
/* Vendor ID reg */
@@ -1438,6 +1454,20 @@ static XenPTRegInfo xen_pt_emu_reg_msix[] = {
},
};
+static XenPTRegInfo xen_pt_emu_reg_igd_opregion[] = {
+ /* Intel IGFX OpRegion reg */
+ {
+ .offset = 0x0,
+ .size = 4,
+ .init_val = 0,
+ .no_wb = 1,
+ .u.dw.read = xen_pt_intel_opregion_read,
+ .u.dw.write = xen_pt_intel_opregion_write,
+ },
+ {
+ .size = 0,
+ },
+};
/****************************
* Capabilities
@@ -1675,6 +1705,14 @@ static const XenPTRegGroupInfo xen_pt_emu_reg_grps[] = {
.size_init = xen_pt_msix_size_init,
.emu_regs = xen_pt_emu_reg_msix,
},
+ /* Intel IGD Opregion group */
+ {
+ .grp_id = PCI_INTEL_OPREGION,
+ .grp_type = XEN_PT_GRP_TYPE_EMU,
+ .grp_size = 0x4,
+ .size_init = xen_pt_reg_grp_size_init,
+ .emu_regs = xen_pt_emu_reg_igd_opregion,
+ },
{
.grp_size = 0,
},
@@ -1804,7 +1842,8 @@ int xen_pt_config_init(XenPCIPassthroughState *s)
uint32_t reg_grp_offset = 0;
XenPTRegGroup *reg_grp_entry = NULL;
- if (xen_pt_emu_reg_grps[i].grp_id != 0xFF) {
+ if (xen_pt_emu_reg_grps[i].grp_id != 0xFF
+ && xen_pt_emu_reg_grps[i].grp_id != PCI_INTEL_OPREGION) {
if (xen_pt_hide_dev_cap(&s->real_device,
xen_pt_emu_reg_grps[i].grp_id)) {
continue;
@@ -1817,6 +1856,10 @@ int xen_pt_config_init(XenPCIPassthroughState *s)
}
}
+ if (xen_pt_emu_reg_grps[i].grp_id == PCI_INTEL_OPREGION) {
+ reg_grp_offset = PCI_INTEL_OPREGION;
+ }
+
reg_grp_entry = g_new0(XenPTRegGroup, 1);
QLIST_INIT(®_grp_entry->reg_tbl_list);
QLIST_INSERT_HEAD(&s->reg_grps, reg_grp_entry, entries);
@@ -6,6 +6,7 @@
#include "hw/xen/xen_backend.h"
int igd_passthru;
+static int igd_guest_opregion;
/*
* register VGA resources for the domain with assigned gfx
@@ -360,3 +361,47 @@ err_out:
return -1;
}
+uint32_t igd_read_opregion(XenPCIPassthroughState *s)
+{
+ uint32_t val = -1;
+
+ if (igd_guest_opregion == 0) {
+ return val;
+ }
+
+ val = igd_guest_opregion;
+
+ XEN_PT_LOG(&s->dev, "Read opregion val=%x\n", val);
+ return val;
+}
+
+void igd_write_opregion(XenPCIPassthroughState *s, uint32_t val)
+{
+ uint32_t host_opregion = 0;
+ int ret;
+
+ if (igd_guest_opregion) {
+ XEN_PT_LOG(&s->dev, "opregion register already been set, ignoring %x\n",
+ val);
+ return;
+ }
+
+ xen_host_pci_get_block(&s->real_device, PCI_INTEL_OPREGION,
+ (uint8_t *)&host_opregion, 4);
+ igd_guest_opregion = (val & ~0xfff) | (host_opregion & 0xfff);
+
+ ret = xc_domain_memory_mapping(xen_xc, xen_domid,
+ igd_guest_opregion >> XC_PAGE_SHIFT,
+ host_opregion >> XC_PAGE_SHIFT,
+ 2,
+ DPCI_ADD_MAPPING);
+
+ if (ret != 0) {
+ XEN_PT_ERR(&s->dev, "Error: Can't map opregion\n");
+ igd_guest_opregion = 0;
+ return;
+ }
+
+ XEN_PT_LOG(&s->dev, "Map OpRegion: %x -> %x\n", host_opregion,
+ igd_guest_opregion);
+}