From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:53225) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1WGjvE-0000vf-Eh for qemu-devel@nongnu.org; Fri, 21 Feb 2014 01:49:24 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1WGjvA-0007gA-0F for qemu-devel@nongnu.org; Fri, 21 Feb 2014 01:49:20 -0500 Received: from mga02.intel.com ([134.134.136.20]:48867) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1WGjv9-0007cJ-GN for qemu-devel@nongnu.org; Fri, 21 Feb 2014 01:49:15 -0500 From: Yang Zhang Date: Fri, 21 Feb 2014 14:44:13 +0800 Message-Id: <1392965053-1069-6-git-send-email-yang.z.zhang@intel.com> In-Reply-To: <1392965053-1069-1-git-send-email-yang.z.zhang@intel.com> References: <1392965053-1069-1-git-send-email-yang.z.zhang@intel.com> Subject: [Qemu-devel] [PATCH 5/5] xen, gfx passthrough: add opregion mapping List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: peter.maydell@linaro.org, xen-devel@lists.xensource.com, stefano.stabellini@eu.citrix.com, allen.m.kay@intel.com, weidong.han@intel.com, jean.guyader@eu.citrix.com, Yang Zhang , anthony@codemonkey.ws, anthony.perard@citrix.com From: Yang Zhang The OpRegion shouldn't be mapped 1:1 because the address in the host can't be used in the guest directly. This patch traps read and write access to the opregion of the Intel GPU config space (offset 0xfc). The original patch is from Jean Guyader Signed-off-by: Yang Zhang Cc: Jean Guyader --- hw/xen/xen_pt.h | 4 ++- hw/xen/xen_pt_config_init.c | 45 ++++++++++++++++++++++++++++++++++++++++++- hw/xen/xen_pt_graphics.c | 45 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 92 insertions(+), 2 deletions(-) diff --git a/hw/xen/xen_pt.h b/hw/xen/xen_pt.h index 92e4d51..9f7fd4e 100644 --- a/hw/xen/xen_pt.h +++ b/hw/xen/xen_pt.h @@ -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 */ diff --git a/hw/xen/xen_pt_config_init.c b/hw/xen/xen_pt_config_init.c index 8ccc2e4..30135c1 100644 --- a/hw/xen/xen_pt_config_init.c +++ b/hw/xen/xen_pt_config_init.c @@ -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); diff --git a/hw/xen/xen_pt_graphics.c b/hw/xen/xen_pt_graphics.c index 2a01406..bebfcfd 100644 --- a/hw/xen/xen_pt_graphics.c +++ b/hw/xen/xen_pt_graphics.c @@ -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); +} -- 1.7.1 From mboxrd@z Thu Jan 1 00:00:00 1970 From: Yang Zhang Subject: [PATCH 5/5] xen, gfx passthrough: add opregion mapping Date: Fri, 21 Feb 2014 14:44:13 +0800 Message-ID: <1392965053-1069-6-git-send-email-yang.z.zhang@intel.com> References: <1392965053-1069-1-git-send-email-yang.z.zhang@intel.com> Mime-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Return-path: In-Reply-To: <1392965053-1069-1-git-send-email-yang.z.zhang@intel.com> List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Sender: xen-devel-bounces@lists.xen.org Errors-To: xen-devel-bounces@lists.xen.org To: qemu-devel@nongnu.org Cc: peter.maydell@linaro.org, xen-devel@lists.xensource.com, stefano.stabellini@eu.citrix.com, allen.m.kay@intel.com, weidong.han@intel.com, jean.guyader@eu.citrix.com, Yang Zhang , anthony@codemonkey.ws, anthony.perard@citrix.com List-Id: xen-devel@lists.xenproject.org From: Yang Zhang The OpRegion shouldn't be mapped 1:1 because the address in the host can't be used in the guest directly. This patch traps read and write access to the opregion of the Intel GPU config space (offset 0xfc). The original patch is from Jean Guyader Signed-off-by: Yang Zhang Cc: Jean Guyader --- hw/xen/xen_pt.h | 4 ++- hw/xen/xen_pt_config_init.c | 45 ++++++++++++++++++++++++++++++++++++++++++- hw/xen/xen_pt_graphics.c | 45 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 92 insertions(+), 2 deletions(-) diff --git a/hw/xen/xen_pt.h b/hw/xen/xen_pt.h index 92e4d51..9f7fd4e 100644 --- a/hw/xen/xen_pt.h +++ b/hw/xen/xen_pt.h @@ -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 */ diff --git a/hw/xen/xen_pt_config_init.c b/hw/xen/xen_pt_config_init.c index 8ccc2e4..30135c1 100644 --- a/hw/xen/xen_pt_config_init.c +++ b/hw/xen/xen_pt_config_init.c @@ -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); diff --git a/hw/xen/xen_pt_graphics.c b/hw/xen/xen_pt_graphics.c index 2a01406..bebfcfd 100644 --- a/hw/xen/xen_pt_graphics.c +++ b/hw/xen/xen_pt_graphics.c @@ -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); +} -- 1.7.1