qemu-devel
[Top][All Lists]
Advanced

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

Re: [Qemu-devel] [v8][RESEND][PATCH 06/10] xen, gfx passthrough: retriev


From: Stefano Stabellini
Subject: Re: [Qemu-devel] [v8][RESEND][PATCH 06/10] xen, gfx passthrough: retrieve VGA BIOS to work
Date: Wed, 1 Jul 2015 16:51:12 +0100
User-agent: Alpine 2.02 (DEB 1266 2009-07-14)

On Fri, 5 Jun 2015, Tiejun Chen wrote:
> Now we retrieve VGA bios like kvm stuff in qemu but we need to
> fix Device Identification in case if its not matched with the
> real IGD device since Seabios is always trying to compare this
> ID to work out VGA BIOS.
> 
> Signed-off-by: Tiejun Chen <address@hidden>

Acked-by: Stefano Stabellini <address@hidden>


>  hw/xen/xen_pt.c          | 10 ++++++
>  hw/xen/xen_pt.h          |  5 +++
>  hw/xen/xen_pt_graphics.c | 79 
> ++++++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 94 insertions(+)
> 
> diff --git a/hw/xen/xen_pt.c b/hw/xen/xen_pt.c
> index 50bdf6f..3bf2233 100644
> --- a/hw/xen/xen_pt.c
> +++ b/hw/xen/xen_pt.c
> @@ -717,6 +717,16 @@ static int xen_pt_initfn(PCIDevice *d)
>      s->memory_listener = xen_pt_memory_listener;
>      s->io_listener = xen_pt_io_listener;
>  
> +    /* Setup VGA bios for passthrough GFX */
> +    if ((s->real_device.domain == 0) && (s->real_device.bus == 0) &&
> +        (s->real_device.dev == 2) && (s->real_device.func == 0)) {
> +        if (xen_pt_setup_vga(s, &s->real_device) < 0) {
> +            XEN_PT_ERR(d, "Setup VGA BIOS of passthrough GFX failed!\n");
> +            xen_host_pci_device_put(&s->real_device);
> +            return -1;
> +        }
> +    }
> +
>      /* Handle real device's MMIO/PIO BARs */
>      xen_pt_register_regions(s, &cmd);
>  
> diff --git a/hw/xen/xen_pt.h b/hw/xen/xen_pt.h
> index dfa6171..6c42754 100644
> --- a/hw/xen/xen_pt.h
> +++ b/hw/xen/xen_pt.h
> @@ -301,6 +301,11 @@ static inline bool 
> xen_pt_has_msix_mapping(XenPCIPassthroughState *s, int bar)
>      return s->msix && s->msix->bar_index == bar;
>  }
>  
> +extern void *pci_assign_dev_load_option_rom(PCIDevice *dev,
> +                                            struct Object *owner, int *size,
> +                                            unsigned int domain,
> +                                            unsigned int bus, unsigned int 
> slot,
> +                                            unsigned int function);
>  extern bool has_igd_gfx_passthru;
>  static inline bool is_igd_vga_passthrough(XenHostPCIDevice *dev)
>  {
> diff --git a/hw/xen/xen_pt_graphics.c b/hw/xen/xen_pt_graphics.c
> index 9b3df81..3232296 100644
> --- a/hw/xen/xen_pt_graphics.c
> +++ b/hw/xen/xen_pt_graphics.c
> @@ -109,3 +109,82 @@ int xen_pt_unregister_vga_regions(XenHostPCIDevice *dev)
>  
>      return 0;
>  }
> +
> +static void *get_vgabios(XenPCIPassthroughState *s, int *size,
> +                       XenHostPCIDevice *dev)
> +{
> +    return pci_assign_dev_load_option_rom(&s->dev, OBJECT(&s->dev), size,
> +                                          dev->domain, dev->bus,
> +                                          dev->dev, dev->func);
> +}
> +
> +/* Refer to Seabios. */
> +struct rom_header {
> +    uint16_t signature;
> +    uint8_t size;
> +    uint8_t initVector[4];
> +    uint8_t reserved[17];
> +    uint16_t pcioffset;
> +    uint16_t pnpoffset;
> +} __attribute__((packed));
> +
> +struct pci_data {
> +    uint32_t signature;
> +    uint16_t vendor;
> +    uint16_t device;
> +    uint16_t vitaldata;
> +    uint16_t dlen;
> +    uint8_t drevision;
> +    uint8_t class_lo;
> +    uint16_t class_hi;
> +    uint16_t ilen;
> +    uint16_t irevision;
> +    uint8_t type;
> +    uint8_t indicator;
> +    uint16_t reserved;
> +} __attribute__((packed));
> +
> +int xen_pt_setup_vga(XenPCIPassthroughState *s, XenHostPCIDevice *dev)
> +{
> +    unsigned char *bios = NULL;
> +    struct rom_header *rom;
> +    int bios_size;
> +    char *c = NULL;
> +    char checksum = 0;
> +    uint32_t len = 0;
> +    struct pci_data *pd = NULL;
> +
> +    if (!is_igd_vga_passthrough(dev)) {
> +        return -1;
> +    }
> +
> +    bios = get_vgabios(s, &bios_size, dev);
> +    if (!bios) {
> +        XEN_PT_ERR(&s->dev, "VGA: Can't getting VBIOS!\n");
> +        return -1;
> +    }
> +
> +    /* Currently we fixed this address as a primary. */
> +    rom = (struct rom_header *)bios;
> +    pd = (void *)(bios + (unsigned char)rom->pcioffset);
> +
> +    /* We may need to fixup Device Identification. */
> +    if (pd->device != s->real_device.device_id) {
> +        pd->device = s->real_device.device_id;
> +
> +        len = rom->size * 512;
> +        /* Then adjust the bios checksum */
> +        for (c = (char *)bios; c < ((char *)bios + len); c++) {
> +            checksum += *c;
> +        }
> +        if (checksum) {
> +            bios[len - 1] -= checksum;
> +            XEN_PT_LOG(&s->dev, "vga bios checksum is adjusted %x!\n",
> +                       checksum);
> +        }
> +    }
> +
> +    /* Currently we fixed this address as a primary for legacy BIOS. */
> +    cpu_physical_memory_rw(0xc0000, bios, bios_size, 1);
> +    return 0;
> +}
> -- 
> 1.9.1
> 
> 



reply via email to

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