basic gfx passthrough support: - add a vga type for gfx passthrough - register/unregister legacy VGA I/O ports and MMIOs for passthrough GFX Signed-off-by: Tiejun Chen <tiejun.chen@intel.com> Signed-off-by: Yang Zhang <yang.z.zhang@Intel.com> Acked-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com> Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
112 lines
3.1 KiB
C
112 lines
3.1 KiB
C
/*
|
|
* graphics passthrough
|
|
*/
|
|
#include "xen_pt.h"
|
|
#include "xen-host-pci-device.h"
|
|
#include "hw/xen/xen_backend.h"
|
|
|
|
typedef struct VGARegion {
|
|
int type; /* Memory or port I/O */
|
|
uint64_t guest_base_addr;
|
|
uint64_t machine_base_addr;
|
|
uint64_t size; /* size of the region */
|
|
int rc;
|
|
} VGARegion;
|
|
|
|
#define IORESOURCE_IO 0x00000100
|
|
#define IORESOURCE_MEM 0x00000200
|
|
|
|
static struct VGARegion vga_args[] = {
|
|
{
|
|
.type = IORESOURCE_IO,
|
|
.guest_base_addr = 0x3B0,
|
|
.machine_base_addr = 0x3B0,
|
|
.size = 0xC,
|
|
.rc = -1,
|
|
},
|
|
{
|
|
.type = IORESOURCE_IO,
|
|
.guest_base_addr = 0x3C0,
|
|
.machine_base_addr = 0x3C0,
|
|
.size = 0x20,
|
|
.rc = -1,
|
|
},
|
|
{
|
|
.type = IORESOURCE_MEM,
|
|
.guest_base_addr = 0xa0000 >> XC_PAGE_SHIFT,
|
|
.machine_base_addr = 0xa0000 >> XC_PAGE_SHIFT,
|
|
.size = 0x20,
|
|
.rc = -1,
|
|
},
|
|
};
|
|
|
|
/*
|
|
* register VGA resources for the domain with assigned gfx
|
|
*/
|
|
int xen_pt_register_vga_regions(XenHostPCIDevice *dev)
|
|
{
|
|
int i = 0;
|
|
|
|
if (!is_igd_vga_passthrough(dev)) {
|
|
return 0;
|
|
}
|
|
|
|
for (i = 0 ; i < ARRAY_SIZE(vga_args); i++) {
|
|
if (vga_args[i].type == IORESOURCE_IO) {
|
|
vga_args[i].rc = xc_domain_ioport_mapping(xen_xc, xen_domid,
|
|
vga_args[i].guest_base_addr,
|
|
vga_args[i].machine_base_addr,
|
|
vga_args[i].size, DPCI_ADD_MAPPING);
|
|
} else {
|
|
vga_args[i].rc = xc_domain_memory_mapping(xen_xc, xen_domid,
|
|
vga_args[i].guest_base_addr,
|
|
vga_args[i].machine_base_addr,
|
|
vga_args[i].size, DPCI_ADD_MAPPING);
|
|
}
|
|
|
|
if (vga_args[i].rc) {
|
|
XEN_PT_ERR(NULL, "VGA %s mapping failed! (rc: %i)\n",
|
|
vga_args[i].type == IORESOURCE_IO ? "ioport" : "memory",
|
|
vga_args[i].rc);
|
|
return vga_args[i].rc;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* unregister VGA resources for the domain with assigned gfx
|
|
*/
|
|
int xen_pt_unregister_vga_regions(XenHostPCIDevice *dev)
|
|
{
|
|
int i = 0;
|
|
|
|
if (!is_igd_vga_passthrough(dev)) {
|
|
return 0;
|
|
}
|
|
|
|
for (i = 0 ; i < ARRAY_SIZE(vga_args); i++) {
|
|
if (vga_args[i].type == IORESOURCE_IO) {
|
|
vga_args[i].rc = xc_domain_ioport_mapping(xen_xc, xen_domid,
|
|
vga_args[i].guest_base_addr,
|
|
vga_args[i].machine_base_addr,
|
|
vga_args[i].size, DPCI_REMOVE_MAPPING);
|
|
} else {
|
|
vga_args[i].rc = xc_domain_memory_mapping(xen_xc, xen_domid,
|
|
vga_args[i].guest_base_addr,
|
|
vga_args[i].machine_base_addr,
|
|
vga_args[i].size, DPCI_REMOVE_MAPPING);
|
|
}
|
|
|
|
if (vga_args[i].rc) {
|
|
XEN_PT_ERR(NULL, "VGA %s unmapping failed! (rc: %i)\n",
|
|
vga_args[i].type == IORESOURCE_IO ? "ioport" : "memory",
|
|
vga_args[i].rc);
|
|
return vga_args[i].rc;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|