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 <tiejun.c...@intel.com>
Acked-by: Stefano Stabellini <stefano.stabell...@eu.citrix.com> > 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 > >