qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] [v8][RESEND][PATCH 05/10] xen, gfx passthrough: basic g


From: Stefano Stabellini
Subject: Re: [Qemu-devel] [v8][RESEND][PATCH 05/10] xen, gfx passthrough: basic graphics passthrough support
Date: Wed, 1 Jul 2015 16:45:37 +0100
User-agent: Alpine 2.02 (DEB 1266 2009-07-14)

On Fri, 5 Jun 2015, Tiejun Chen wrote:
> 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 <address@hidden>
> Signed-off-by: Yang Zhang <address@hidden>

Acked-by: Stefano Stabellini <address@hidden>


>  hw/core/machine.c            |  20 ++++++++
>  hw/xen/Makefile.objs         |   1 +
>  hw/xen/xen-host-pci-device.c |   5 ++
>  hw/xen/xen-host-pci-device.h |   1 +
>  hw/xen/xen_pt.c              |   4 ++
>  hw/xen/xen_pt.h              |  10 +++-
>  hw/xen/xen_pt_graphics.c     | 111 
> +++++++++++++++++++++++++++++++++++++++++++
>  include/hw/boards.h          |   1 +
>  qemu-options.hx              |   3 ++
>  vl.c                         |  10 ++++
>  10 files changed, 165 insertions(+), 1 deletion(-)
>  create mode 100644 hw/xen/xen_pt_graphics.c
> 
> diff --git a/hw/core/machine.c b/hw/core/machine.c
> index 25c45e6..0655665 100644
> --- a/hw/core/machine.c
> +++ b/hw/core/machine.c
> @@ -226,6 +226,20 @@ static void machine_set_usb(Object *obj, bool value, 
> Error **errp)
>      ms->usb_disabled = !value;
>  }
>  
> +static bool machine_get_igd_gfx_passthru(Object *obj, Error **errp)
> +{
> +    MachineState *ms = MACHINE(obj);
> +
> +    return ms->igd_gfx_passthru;
> +}
> +
> +static void machine_set_igd_gfx_passthru(Object *obj, bool value, Error 
> **errp)
> +{
> +    MachineState *ms = MACHINE(obj);
> +
> +    ms->igd_gfx_passthru = value;
> +}
> +
>  static char *machine_get_firmware(Object *obj, Error **errp)
>  {
>      MachineState *ms = MACHINE(obj);
> @@ -380,6 +394,12 @@ static void machine_initfn(Object *obj)
>      object_property_set_description(obj, "usb",
>                                      "Set on/off to enable/disable usb",
>                                      NULL);
> +    object_property_add_bool(obj, "igd-passthru",
> +                             machine_get_igd_gfx_passthru,
> +                             machine_set_igd_gfx_passthru, NULL);
> +    object_property_set_description(obj, "igd-passthru",
> +                                    "Set on/off to enable/disable igd 
> passthrou",
> +                                    NULL);
>      object_property_add_str(obj, "firmware",
>                              machine_get_firmware,
>                              machine_set_firmware, NULL);
> diff --git a/hw/xen/Makefile.objs b/hw/xen/Makefile.objs
> index a0ca0aa..a9ad7e7 100644
> --- a/hw/xen/Makefile.objs
> +++ b/hw/xen/Makefile.objs
> @@ -3,3 +3,4 @@ common-obj-$(CONFIG_XEN_BACKEND) += xen_backend.o 
> xen_devconfig.o
>  
>  obj-$(CONFIG_XEN_PCI_PASSTHROUGH) += xen-host-pci-device.o
>  obj-$(CONFIG_XEN_PCI_PASSTHROUGH) += xen_pt.o xen_pt_config_init.o 
> xen_pt_msi.o
> +obj-$(CONFIG_XEN_PCI_PASSTHROUGH) += xen_pt.o xen_pt_config_init.o 
> xen_pt_msi.o xen_pt_graphics.o
> diff --git a/hw/xen/xen-host-pci-device.c b/hw/xen/xen-host-pci-device.c
> index 743b37b..a54b7de 100644
> --- a/hw/xen/xen-host-pci-device.c
> +++ b/hw/xen/xen-host-pci-device.c
> @@ -376,6 +376,11 @@ int xen_host_pci_device_get(XenHostPCIDevice *d, 
> uint16_t domain,
>          goto error;
>      }
>      d->irq = v;
> +    rc = xen_host_pci_get_hex_value(d, "class", &v);
> +    if (rc) {
> +        goto error;
> +    }
> +    d->class_code = v;
>      d->is_virtfn = xen_host_pci_dev_is_virtfn(d);
>  
>      return 0;
> diff --git a/hw/xen/xen-host-pci-device.h b/hw/xen/xen-host-pci-device.h
> index c2486f0..f1e1c30 100644
> --- a/hw/xen/xen-host-pci-device.h
> +++ b/hw/xen/xen-host-pci-device.h
> @@ -25,6 +25,7 @@ typedef struct XenHostPCIDevice {
>  
>      uint16_t vendor_id;
>      uint16_t device_id;
> +    uint32_t class_code;
>      int irq;
>  
>      XenHostPCIIORegion io_regions[PCI_NUM_REGIONS - 1];
> diff --git a/hw/xen/xen_pt.c b/hw/xen/xen_pt.c
> index 9afcda8..50bdf6f 100644
> --- a/hw/xen/xen_pt.c
> +++ b/hw/xen/xen_pt.c
> @@ -494,6 +494,7 @@ static int xen_pt_register_regions(XenPCIPassthroughState 
> *s, uint16_t *cmd)
>                     d->rom.size, d->rom.base_addr);
>      }
>  
> +    xen_pt_register_vga_regions(d);
>      return 0;
>  }
>  
> @@ -798,6 +799,7 @@ out:
>  static void xen_pt_unregister_device(PCIDevice *d)
>  {
>      XenPCIPassthroughState *s = DO_UPCAST(XenPCIPassthroughState, dev, d);
> +    XenHostPCIDevice *host_dev = &s->real_device;
>      uint8_t machine_irq = s->machine_irq;
>      uint8_t intx = xen_pt_pci_intx(s);
>      int rc;
> @@ -841,6 +843,8 @@ static void xen_pt_unregister_device(PCIDevice *d)
>      /* delete all emulated config registers */
>      xen_pt_config_delete(s);
>  
> +    xen_pt_unregister_vga_regions(host_dev);
> +
>      memory_listener_unregister(&s->memory_listener);
>      memory_listener_unregister(&s->io_listener);
>  
> diff --git a/hw/xen/xen_pt.h b/hw/xen/xen_pt.h
> index 4bba559..dfa6171 100644
> --- a/hw/xen/xen_pt.h
> +++ b/hw/xen/xen_pt.h
> @@ -301,5 +301,13 @@ static inline bool 
> xen_pt_has_msix_mapping(XenPCIPassthroughState *s, int bar)
>      return s->msix && s->msix->bar_index == bar;
>  }
>  
> -
> +extern bool has_igd_gfx_passthru;
> +static inline bool is_igd_vga_passthrough(XenHostPCIDevice *dev)
> +{
> +    return (has_igd_gfx_passthru
> +            && ((dev->class_code >> 0x8) == PCI_CLASS_DISPLAY_VGA));
> +}
> +int xen_pt_register_vga_regions(XenHostPCIDevice *dev);
> +int xen_pt_unregister_vga_regions(XenHostPCIDevice *dev);
> +int xen_pt_setup_vga(XenPCIPassthroughState *s, XenHostPCIDevice *dev);
>  #endif /* !XEN_PT_H */
> diff --git a/hw/xen/xen_pt_graphics.c b/hw/xen/xen_pt_graphics.c
> new file mode 100644
> index 0000000..9b3df81
> --- /dev/null
> +++ b/hw/xen/xen_pt_graphics.c
> @@ -0,0 +1,111 @@
> +/*
> + * 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;
> +}
> diff --git a/include/hw/boards.h b/include/hw/boards.h
> index ff79797..a7b75ac 100644
> --- a/include/hw/boards.h
> +++ b/include/hw/boards.h
> @@ -134,6 +134,7 @@ struct MachineState {
>      bool mem_merge;
>      bool usb;
>      bool usb_disabled;
> +    bool igd_gfx_passthru;
>      char *firmware;
>      bool iommu;
>      bool suppress_vmdesc;
> diff --git a/qemu-options.hx b/qemu-options.hx
> index 7edd1f1..964ba0d 100644
> --- a/qemu-options.hx
> +++ b/qemu-options.hx
> @@ -38,6 +38,7 @@ DEF("machine", HAS_ARG, QEMU_OPTION_machine, \
>      "                dump-guest-core=on|off include guest memory in a core 
> dump (default=on)\n"
>      "                mem-merge=on|off controls memory merge support 
> (default: on)\n"
>      "                iommu=on|off controls emulated Intel IOMMU (VT-d) 
> support (default=off)\n"
> +    "                igd-passthru=on|off controls IGD GFX passthrough 
> support (default=off)\n"
>      "                aes-key-wrap=on|off controls support for AES key 
> wrapping (default=on)\n"
>      "                dea-key-wrap=on|off controls support for DEA key 
> wrapping (default=on)\n"
>      "                suppress-vmdesc=on|off disables self-describing 
> migration (default=off)\n",
> @@ -55,6 +56,8 @@ than one accelerator specified, the next one is used if the 
> previous one fails
>  to initialize.
>  @item kernel_irqchip=on|off
>  Enables in-kernel irqchip support for the chosen accelerator when available.
> address@hidden gfx_passthru=on|off
> +Enables IGD GFX passthrough support for the chosen machine when available.
>  @item vmport=on|off|auto
>  Enables emulation of VMWare IO port, for vmmouse etc. auto says to select the
>  value based on accel. For accel=xen the default is off otherwise the default
> diff --git a/vl.c b/vl.c
> index 1d4c089..34c1d55 100644
> --- a/vl.c
> +++ b/vl.c
> @@ -1224,6 +1224,13 @@ static void configure_msg(QemuOpts *opts)
>      enable_timestamp_msg = qemu_opt_get_bool(opts, "timestamp", true);
>  }
>  
> +/* Now we still need this for compatibility with XEN. */
> +bool has_igd_gfx_passthru;
> +static void igd_gfx_passthru(void)
> +{
> +    has_igd_gfx_passthru = current_machine->igd_gfx_passthru;
> +}
> +
>  /***********************************************************/
>  /* USB devices */
>  
> @@ -4256,6 +4263,9 @@ int main(int argc, char **argv, char **envp)
>              exit(1);
>      }
>  
> +    /* Check if IGD GFX passthrough. */
> +    igd_gfx_passthru();
> +
>      /* init generic devices */
>      if (qemu_opts_foreach(qemu_find_opts("device"), device_init_func, NULL, 
> 1) != 0)
>          exit(1);
> -- 
> 1.9.1
> 
> 



reply via email to

[Prev in Thread] Current Thread [Next in Thread]