static int pt_exp_rom_bar_reg_restore(struct pt_dev *ptdev,
struct pt_reg_tbl *cfg_entry,
uint32_t real_offset, uint32_t dev_value, uint32_t *value);
+static int pt_intel_opregion_read(struct pt_dev *ptdev,
+ struct pt_reg_tbl *cfg_entry,
+ uint32_t *value, uint32_t valid_mask);
+static int pt_intel_opregion_write(struct pt_dev *ptdev,
+ struct pt_reg_tbl *cfg_entry,
+ uint32_t *value, uint32_t dev_value, uint32_t valid_mask);
+static uint8_t pt_reg_grp_header0_size_init(struct pt_dev *ptdev,
+ struct pt_reg_grp_info_tbl *grp_reg, uint32_t base_offset);
/* pt_reg_info_tbl declaration
* - only for emulated register (either a part or whole bit).
.u.dw.write = pt_exp_rom_bar_reg_write,
.u.dw.restore = pt_exp_rom_bar_reg_restore,
},
+ /* Intel IGFX OpRegion reg */
+ {
+ .offset = PCI_INTEL_OPREGION,
+ .size = 4,
+ .init_val = 0,
+ .no_wb = 1,
+ .u.dw.read = pt_intel_opregion_read,
+ .u.dw.write = pt_intel_opregion_write,
+ .u.dw.restore = NULL,
+ },
{
.size = 0,
},
.grp_id = 0xFF,
.grp_type = GRP_TYPE_EMU,
.grp_size = 0x40,
- .size_init = pt_reg_grp_size_init,
+ .size_init = pt_reg_grp_header0_size_init,
.emu_reg_tbl= pt_emu_reg_header0_tbl,
},
/* PCI PowerManagement Capability reg group */
return reg->init_val;
}
+static uint8_t pt_reg_grp_header0_size_init(struct pt_dev *ptdev,
+ struct pt_reg_grp_info_tbl *grp_reg, uint32_t base_offset)
+{
+ /*
+ ** By default we will trap up to 0x40 in the cfg space.
+ ** If an intel device is pass through we need to trap 0xfc,
+ ** therefore the size should be 0xff.
+ */
+ if (igd_passthru)
+ return 0xFF;
+ return grp_reg->grp_size;
+}
+
/* get register group size */
static uint8_t pt_reg_grp_size_init(struct pt_dev *ptdev,
struct pt_reg_grp_info_tbl *grp_reg, uint32_t base_offset)
return 0;
}
+static int pt_intel_opregion_read(struct pt_dev *ptdev,
+ struct pt_reg_tbl *cfg_entry,
+ uint32_t *value, uint32_t valid_mask)
+{
+ *value = igd_read_opregion(ptdev);
+ return 0;
+}
+
+static int pt_intel_opregion_write(struct pt_dev *ptdev,
+ struct pt_reg_tbl *cfg_entry,
+ uint32_t *value, uint32_t dev_value, uint32_t valid_mask)
+{
+ igd_write_opregion(ptdev, *value);
+ return 0;
+}
+
static struct pt_dev * register_real_device(PCIBus *e_bus,
const char *e_dev_name, int e_devfn, uint8_t r_bus, uint8_t r_dev,
uint8_t r_func, uint32_t machine_irq, struct pci_access *pci_access,
uint16_t did, const char *name, uint16_t revision);
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(struct pt_dev *pci_dev);
+void igd_write_opregion(struct pt_dev *real_dev, uint32_t val);
#endif /* __PASSTHROUGH_H__ */
extern int gfx_passthru;
extern int igd_passthru;
+static uint32_t igd_guest_opregion = 0;
+
static int pch_map_irq(PCIDevice *pci_dev, int irq_num)
{
PT_LOG("pch_map_irq called\n");
pch_map_irq, "intel_bridge_1f");
}
+uint32_t igd_read_opregion(struct pt_dev *pci_dev)
+{
+ uint32_t val = -1;
+
+ if ( igd_guest_opregion == 0 )
+ return -1;
+
+ val = igd_guest_opregion;
+#ifdef PT_DEBUG_PCI_CONFIG_ACCESS
+ PT_LOG_DEV((PCIDevice*)pci_dev, "addr=%x len=%x val=%x\n",
+ PCI_INTEL_OPREGION, 4, val);
+#endif
+ return val;
+}
+
+void igd_write_opregion(struct pt_dev *real_dev, uint32_t val)
+{
+ uint32_t host_opregion = 0;
+ int ret;
+
+ if ( igd_guest_opregion )
+ {
+ PT_LOG("opregion register already been set, ignoring %x\n", val);
+ return;
+ }
+
+ host_opregion = pt_pci_host_read(real_dev->pci_dev, PCI_INTEL_OPREGION, 4);
+ igd_guest_opregion = (val & ~0xfff) | (host_opregion & 0xfff);
+ PT_LOG("Map OpRegion: %x -> %x\n", host_opregion, igd_guest_opregion);
+
+ ret = xc_domain_memory_mapping(xc_handle, domid,
+ igd_guest_opregion >> XC_PAGE_SHIFT,
+ host_opregion >> XC_PAGE_SHIFT,
+ 2,
+ DPCI_ADD_MAPPING);
+
+ if ( ret != 0 )
+ {
+ PT_LOG("Error: Can't map opregion\n");
+ igd_guest_opregion = 0;
+ }
+#ifdef PT_DEBUG_PCI_CONFIG_ACCESS
+ PT_LOG_DEV((PCIDevice*)real_dev, "addr=%x len=%lx val=%x\n",
+ PCI_INTEL_OPREGION, len, val);
+#endif
+
+}
+
void igd_pci_write(PCIDevice *pci_dev, uint32_t config_addr, uint32_t val, int len)
{
struct pci_dev *pci_dev_host_bridge;
int register_vga_regions(struct pt_dev *real_device)
{
u16 vendor_id;
- int igd_opregion;
int ret = 0;
if ( !gfx_passthru || real_device->pci_dev->device_class != 0x0300 )
0x20,
DPCI_ADD_MAPPING);
- /* 1:1 map ASL Storage register value */
- vendor_id = pt_pci_host_read(real_device->pci_dev, 0, 2);
- igd_opregion = pt_pci_host_read(real_device->pci_dev, PCI_INTEL_OPREGION, 4);
- if ( (vendor_id == PCI_VENDOR_ID_INTEL ) && igd_opregion )
- {
- ret |= xc_domain_memory_mapping(xc_handle, domid,
- igd_opregion >> XC_PAGE_SHIFT,
- igd_opregion >> XC_PAGE_SHIFT,
- 2,
- DPCI_ADD_MAPPING);
- PT_LOG("register_vga: igd_opregion = %x\n", igd_opregion);
- }
-
if ( ret != 0 )
PT_LOG("VGA region mapping failed\n");
*/
int unregister_vga_regions(struct pt_dev *real_device)
{
- u32 vendor_id, igd_opregion;
+ u32 vendor_id;
int ret = 0;
if ( !gfx_passthru || real_device->pci_dev->device_class != 0x0300 )
DPCI_REMOVE_MAPPING);
vendor_id = pt_pci_host_read(real_device->pci_dev, PCI_VENDOR_ID, 2);
- igd_opregion = pt_pci_host_read(real_device->pci_dev, PCI_INTEL_OPREGION, 4);
- if ( (vendor_id == PCI_VENDOR_ID_INTEL) && igd_opregion )
+ if ( (vendor_id == PCI_VENDOR_ID_INTEL) && igd_guest_opregion )
{
ret |= xc_domain_memory_mapping(xc_handle, domid,
- igd_opregion >> XC_PAGE_SHIFT,
- igd_opregion >> XC_PAGE_SHIFT,
+ igd_guest_opregion >> XC_PAGE_SHIFT,
+ igd_guest_opregion >> XC_PAGE_SHIFT,
2,
DPCI_REMOVE_MAPPING);
}