From mboxrd@z Thu Jan 1 00:00:00 1970 From: Wei Huang Subject: Re: RE: [RFC][QEMU] ATI graphics VBIOS passthru support Date: Fri, 10 Dec 2010 17:40:19 -0600 Message-ID: <4D02BA63.5050806@amd.com> References: <20101207100052.GN2754@reaktio.net> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="------------010909060803090809050505" Return-path: In-Reply-To: <20101207100052.GN2754@reaktio.net> List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Sender: xen-devel-bounces@lists.xensource.com Errors-To: xen-devel-bounces@lists.xensource.com To: =?ISO-8859-1?Q?Pasi_K=E4rkk=E4inen?= Cc: "Wang2, Wei" , "Kay, Allen M" , Xen-devel , "djmagee@mageenet.net" , Ian Jackson List-Id: xen-devel@lists.xenproject.org --------------010909060803090809050505 Content-Type: text/plain; charset="ISO-8859-1"; format=flowed Content-Transfer-Encoding: quoted-printable Hi, The attached patch supports dynamic detection of BARs (both MMIO and=20 PIO). Hopefully it can alleviate some of the issues you saw with ATI gfx=20 passthru. Please let me know whether it works better for you. Thanks, -Wei On 12/07/2010 04:00 AM, Pasi K=E4rkk=E4inen wrote: > On Wed, Oct 13, 2010 at 04:37:10PM -0500, Huang2, Wei wrote: >> Sorry, hold on a second. This fix seems corrupt my pci config spac= e after >> several runs. >> > Hello, > > Any updates to these patches? Many users have been asking about amd/ati= vga passthru stuff.. > > -- Pasi > >> >> -Wei >> >> >> >> From: xen-devel-bounces@lists.xensource.com >> [mailto:xen-devel-bounces@lists.xensource.com] On Behalf Of Huang2= , Wei >> Sent: Wednesday, October 13, 2010 3:47 PM >> To: djmagee@mageenet.net; Kay, Allen M; Ian Jackson >> Cc: Wang2, Wei; Xen-devel >> Subject: RE: [Xen-devel] RE: [RFC][QEMU] ATI graphics VBIOS passth= ru >> support >> >> >> >> Hi Allen and Doug, >> >> >> >> Could you fix the following line in save_pci_conf_space() of >> tools/python/xen/util/pci.py? >> >> >> >> "for i in range(0, 256, 4):" to "for i in range(0, 512, 4)= :" >> >> >> >> This solves my black screen issue. Please let me know the results. >> >> >> >> >> >> Thanks, >> >> -Wei >> >> >> >> From: djmagee@mageenet.net [mailto:djmagee@mageenet.net] >> Sent: Friday, October 08, 2010 10:53 AM >> To: Huang2, Wei; Kay, Allen M; Ian Jackson >> Cc: Xen-devel; Wang2, Wei >> Subject: RE: [Xen-devel] RE: [RFC][QEMU] ATI graphics VBIOS passth= ru >> support >> >> >> >> Wei, >> >> These were guests that had never seen the catalyst= driver >> before. I booted each three with the graphics device and usb devi= ces >> assigned, they worked fine using the basic VGA driver, then instal= led >> fresh Catalyst 10.9, rebooted, and each one crashed. >> >> >> >> Let me know if there's any other info I can provid= e that >> will help you debug. The motherboard is a DQ45CB, running xen-uns= table >> c/s 22155 using `dom0_mem=3D768M iommu=3D1' on the grub line, and = using pvops >> Dom0 from stable-2.6.32.x commit 179eca50. >> >> >> >> Doug Magee >> >> >> >> From: Huang2, Wei [mailto:Wei.Huang2@amd.com] >> Sent: Friday, October 08, 2010 11:41 AM >> To: djmagee@mageenet.net; Kay, Allen M; Ian Jackson >> Cc: Xen-devel; Wang2, Wei >> Subject: RE: [Xen-devel] RE: [RFC][QEMU] ATI graphics VBIOS passth= ru >> support >> >> >> >> Hi Doug, >> >> >> >> Regarding Catalyst driver, we never saw guest crashing. Was it a f= resh >> Catalyst installation or an existing guest image? We felt this VBI= OS patch >> might not provide all necessary resources to driver, which got ups= et. >> Currently we are debugging it with our driver team and will let yo= u know >> the update. >> >> >> >> Thanks, >> >> -Wei >> >> >> >> From: djmagee@mageenet.net [mailto:djmagee@mageenet.net] >> Sent: Friday, October 08, 2010 9:41 AM >> To: Huang2, Wei; Kay, Allen M; Ian Jackson >> Cc: Xen-devel >> Subject: RE: [Xen-devel] RE: [RFC][QEMU] ATI graphics VBIOS passth= ru >> support >> >> >> >> Wei, >> >> I've tested with a Radeon 4770 and it the VBIOS wo= rks >> without a problem, through many guest (re)boots, so it seems prett= y >> solid. I tested a linux guest (fairly standard Fedora 12), Window= s XP, >> and Windows 7 (without accelerated drivers). The open radeon linu= x driver >> works fine. >> >> >> >> The Catalyst driver fails in Windows XP (STOP 0x000000EA, thread s= tuck in >> device driver), windows 7 (STOP 0x00000116, driver fails to proper= ly >> reset?), and linux (total system freeze). This seems to be differ= ent than >> the `Blank Screen' problem you report, as the driver is clearly no= t >> functioning properly. >> >> >> >> Doug Magee >> >> >> >> From: xen-devel-bounces@lists.xensource.com >> [mailto:xen-devel-bounces@lists.xensource.com] On Behalf Of Huang2= , Wei >> Sent: Friday, October 08, 2010 9:57 AM >> To: Kay, Allen M; Ian Jackson >> Cc: Xen-devel >> Subject: [Xen-devel] RE: [RFC][QEMU] ATI graphics VBIOS passthru s= upport >> >> >> >> Hi Allen, >> >> >> >> Yes, Catalyst driver is the one from public website. The driver st= ill has >> a minor issue with this VBIOS patch. The purpose of submitting VB= IOS >> patch is to get community feedbacks. After we figure out the root = cause of >> black screen, I will formally submit a patch for inclusion. >> >> >> >> Thanks, >> >> -Wei >> >> >> >> From: Kay, Allen M [mailto:allen.m.kay@intel.com] >> Sent: Friday, October 08, 2010 2:21 AM >> To: Huang2, Wei; Ian Jackson >> Cc: Xen-devel >> Subject: RE: [RFC][QEMU] ATI graphics VBIOS passthru support >> >> >> >> Hi Wei, >> >> >> >> Is Catalyst driver the one on AMD website? I think that's what I = have in >> my win7 guest and it matches the symptom you are describing. "lsp= ci" >> reports my ATI card is a V5700 - although it says v3750 on the box= . Where >> can I get a working driver? >> >> >> >> The patch looks reasonable to me in general. >> >> >> >> Allen >> >> >> >> From: Huang2, Wei [mailto:Wei.Huang2@amd.com] >> Sent: Thursday, October 07, 2010 9:06 PM >> To: Kay, Allen M; Ian Jackson >> Cc: Xen-devel >> Subject: RE: [RFC][QEMU] ATI graphics VBIOS passthru support >> >> >> >> Hi Allen, >> >> >> >> Thanks for testing it out. We have tested this patch with Radeon 4= 850, >> 4870, FirePro V5700 and FirePro M5800. Unfortunately we don't have= V3750 >> at hand. It is very possible this patch isn't compatible with V375= 0. We >> will try to get hold of one for debugging. For graphics which work= with >> this path, users should be able to get rid of emulated gfx (such a= s >> Cirrus). I have successfully installed a Windows guest VM using th= is >> patch. >> >> >> >> I also want to point out that there is still an issue. Users will = see a >> black screen after installing Catalyst driver. Even though the scr= een >> appears to be black, the driver is actually functioning correctly = (3DMark >> can be run with external monitor). Our driver team is currently de= bugging >> it and they believe this is easy to fix. >> >> >> >> What is your opinion on this patch (and the solution) in general? >> >> >> >> -Wei >> >> >> >> From: Kay, Allen M [mailto:allen.m.kay@intel.com] >> Sent: Thursday, October 07, 2010 6:58 PM >> To: Huang2, Wei; Ian Jackson >> Cc: Xen-devel >> Subject: RE: [RFC][QEMU] ATI graphics VBIOS passthru support >> >> >> >> Hi Wei, >> >> >> >> This patch did not cause any problems with Intel IGD passthrough f= or me. >> However, the monitor remained blank if I pass through ATI Firepro = V3750 >> either as the primary display device or the secondary device >> (gfx_passthru=3D1/0). Passing it through as the secondary device = used to >> work. >> >> >> >> Have you tested the patch with this graphics card? >> >> >> >> Allen >> >> >> >> From: Huang2, Wei [mailto:Wei.Huang2@amd.com] >> Sent: Thursday, October 07, 2010 9:57 AM >> To: Ian Jackson >> Cc: Xen-devel; Kay, Allen M >> Subject: [RFC][QEMU] ATI graphics VBIOS passthru support >> >> >> >> Hi Ian, >> >> >> >> There have been a lot of interest on gfx passthru recently. This p= atch >> enables ATI VBIOS in passthru mode. The guest VM system BIOS (incl= uding >> Windows boot logo) can now show in passthru screen. We have tested= with >> various Windows and Linux guest VMs. Please help review it. We are= also >> looking forward to comments and suggestions from Xen community use= rs. >> >> >> >> Signed-off-by: Wei Huang >> >> Signed-off-by: Wei Wang >> >> >> >> >> _______________________________________________ >> Xen-devel mailing list >> Xen-devel@lists.xensource.com >> http://lists.xensource.com/xen-devel > --------------010909060803090809050505 Content-Type: text/plain; name="ati_vbios_patch_with_bar_detection.txt" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="ati_vbios_patch_with_bar_detection.txt" Content-Description: ati_vbios_patch_with_bar_detection.txt diff --git a/hw/pass-through.c b/hw/pass-through.c index 9c5620d..71d4792 100644 --- a/hw/pass-through.c +++ b/hw/pass-through.c @@ -1379,9 +1379,17 @@ static void pt_ioport_map(PCIDevice *d, int i, if (e_phys != -1) { /* Create new mapping */ - ret = xc_domain_ioport_mapping(xc_handle, domid, e_phys, - assigned_device->bases[i].access.pio_base, e_size, - DPCI_ADD_MAPPING); + if ( vga_skip_ioport_map(d) ) + { + assigned_device->bases[i].e_physbase = -1; + } + else + { + ret = xc_domain_ioport_mapping(xc_handle, domid, e_phys, + assigned_device->bases[i].access.pio_base, e_size, + DPCI_ADD_MAPPING); + } + if ( ret != 0 ) { PT_LOG("Error: create new mapping failed!\n"); diff --git a/hw/pass-through.h b/hw/pass-through.h index dd218f7..4ef84c4 100644 --- a/hw/pass-through.h +++ b/hw/pass-through.h @@ -411,6 +411,11 @@ int pt_pci_host_write(int bus, int dev, int fn, u32 addr, u32 val, int len); void intel_pch_init(PCIBus *bus); int register_vga_regions(struct pt_dev *real_device); int unregister_vga_regions(struct pt_dev *real_device); +int vga_skip_ioport_map(PCIDevice *d); +int igd_register_vga_regions(struct pt_dev *real_device); +int igd_unregister_vga_regions(struct pt_dev *real_device); +int ati_register_vga_regions(struct pt_dev *real_device); +int ati_unregister_vga_regions(struct pt_dev *real_device); int setup_vga_pt(struct pt_dev *real_device); PCIBus *intel_pci_bridge_init(PCIBus *bus, int devfn, uint16_t vid, uint16_t did, const char *name, uint16_t revision); diff --git a/hw/pci.h b/hw/pci.h index e4cc79a..4aa0373 100644 --- a/hw/pci.h +++ b/hw/pci.h @@ -54,6 +54,8 @@ extern target_phys_addr_t pci_mem_base; #define PCI_VENDOR_ID_CIRRUS 0x1013 +#define PCI_VENDOR_ID_ATI 0x1002 + #define PCI_VENDOR_ID_IBM 0x1014 #define PCI_DEVICE_ID_IBM_OPENPIC2 0xffff diff --git a/hw/pt-graphics.c b/hw/pt-graphics.c index e3fdf8e..8379a9d 100644 --- a/hw/pt-graphics.c +++ b/hw/pt-graphics.c @@ -8,11 +8,248 @@ #include #include +#include #include extern int gfx_passthru; extern int igd_passthru; +/*********************************/ +/* Code for ATI GFX Passthru */ +/*********************************/ +/* ATI VBIOS Working Mechanism + * + * Generally there are three memory resources (two MMIO and one PIO) + * associated with modern ATI gfx. VBIOS uses special tricks to figure out + * BARs, instead of using regular PCI config space read. + * + * (1) VBIOS relies on I/O port 0x3C3 to retrieve PIO BAR + * (2) VBIOS maintains a shadow copy of PCI configure space. It retries the + * MMIO BARs from this shadow copy via sending I/O requests to first two + * registers of PIO (MMINDEX and MMDATA). The workflow is like this: + * MMINDEX (register 0) is written with an index value, specifying the + * register VBIOS wanting to access. Then the shadowed data can be + * read/written from MMDATA (register 1). For two MMIO BARs, the index + * values are 0x4010 + 4 * bar_index. For instance the index value for + * BAR 2 is 0x4018 (0x4010 + 4*2). + * + */ + +#define ATI_BAR_MMINDEX_BASE 0x4010 //data written to MMINDEX for MMIO BAR1 + +struct ati_gfx_info { + int initialized; /* initialized already? */ + + /* PIO */ + uint32_t host_pio_base; /* host base addr of PIO */ + uint32_t guest_pio_base; /* guest base addr of PIO */ + uint32_t pio_bar_index; /* PIO BAR index can vary */ + uint32_t pio_size; /* PIO size */ + + /* MMIO */ + uint32_t guest_mmio_base1; /* guest base addr of MMIO 1 */ + uint32_t mmio_bar1_index; /* guest MMIO BAR1 index */ + uint32_t guest_mmio_base2; /* guest base addr of MMIO 2 */ + uint32_t mmio_bar2_index; /* guest MMIO BAR2 index */ + + /* PIO MMINDEX access recording */ + uint32_t pre_mmindex_data; /* previous data written to MMINDEX */ +}; + +static struct ati_gfx_info gfx_info; + +/* Convert guest PIO port to host PIO port */ +static uint16_t gport_to_hport(uint16_t gport) +{ + return (gport - gfx_info.guest_pio_base) + gfx_info.host_pio_base; +} + +/* Read host PIO port */ +static uint32_t ati_hw_in(uint16_t hport) +{ + unsigned val; + + ioperm(gfx_info.host_pio_base, gfx_info.pio_size, 1); + asm volatile ("in %1,%0":"=a"(val):"Nd"(hport)); + ioperm(gfx_info.host_pio_base, gfx_info.pio_size, 0); + + return val; +} + +/* Write data to host PIO */ +static void ati_hw_out(uint16_t hport, uint32_t data) +{ + ioperm(gfx_info.host_pio_base, gfx_info.pio_size, 1); + asm volatile ("out %1, %0"::"Nd"(hport),"a"(data)); + ioperm(gfx_info.host_pio_base, gfx_info.pio_size, 0); +} + +static uint32_t ati_io_regs_read(void *opaque, uint32_t addr) +{ + uint32_t val, index; + + val = ati_hw_in(gport_to_hport(addr)); + + /* tweak the value if VBIOS is reading MMIO BAR1 and BAR2 */ + if ( addr == (gfx_info.guest_pio_base + 4) ) + { + index = (gfx_info.pre_mmindex_data - ATI_BAR_MMINDEX_BASE) / 4; + + if ( index == gfx_info.mmio_bar1_index ) + val = gfx_info.guest_mmio_base1 | (val & 0x0000000f); + else if ( index == gfx_info.mmio_bar2_index ) + val = gfx_info.guest_mmio_base2 | (val & 0x0000000f); + } + + return val; +} + +static void ati_io_regs_write(void *opaque, uint32_t addr, uint32_t val) +{ + ati_hw_out(gport_to_hport(addr), val); + + /* book keeping */ + if ( addr == gfx_info.guest_pio_base ) + gfx_info.pre_mmindex_data = val; +} + +#define PCI_NUM_BARS 6 +static void ati_gfx_init(struct pt_dev *assigned) +{ + PCIDevice *dev = (PCIDevice *)&assigned->dev; + int i, mmio_bar1_index, mmio_bar2_index, pio_index; + PCIIORegion *r; + + pio_index = mmio_bar1_index = mmio_bar2_index = -1; + + /* PCI configure space only contains 6 BARs. Don't use PCI_NUM_REGIONS. */ + for ( i = 0; i < PCI_NUM_BARS; i++ ) + { + r = &dev->io_regions[i]; + + if ( r->size && (r->addr > 0) && + (r->type == PCI_ADDRESS_SPACE_MEM || + r->type == PCI_ADDRESS_SPACE_MEM_PREFETCH) ) + { + if ( mmio_bar1_index < 0 ) + mmio_bar1_index = i; + else + mmio_bar2_index = i; + } + + if ( r->size && (r->addr > 0) && (r->type == PCI_ADDRESS_SPACE_IO) ) + { + pio_index = i; + + } + } + + if ( pio_index < 0 || mmio_bar1_index < 0 || mmio_bar2_index < 0 ) + { + PT_LOG("Error: can't find correct gfx memory resource BARs\n"); + return; + } + + register_ioport_read(dev->io_regions[pio_index].addr, + dev->io_regions[pio_index].size, 4, ati_io_regs_read, assigned); + + register_ioport_write(dev->io_regions[pio_index].addr, + dev->io_regions[pio_index].size, 4, ati_io_regs_write, assigned); + + /* initialize PIO fields */ + gfx_info.guest_pio_base = dev->io_regions[pio_index].addr; + gfx_info.pio_size = dev->io_regions[pio_index].size; + gfx_info.pio_bar_index = pio_index; + gfx_info.host_pio_base = assigned->bases[pio_index].access.pio_base; + + /* initialize MMIO fields */ + gfx_info.guest_mmio_base1 = dev->io_regions[mmio_bar1_index].addr; + gfx_info.mmio_bar1_index = mmio_bar1_index; + gfx_info.guest_mmio_base2 = dev->io_regions[mmio_bar2_index].addr; + gfx_info.mmio_bar2_index = mmio_bar2_index; + + gfx_info.initialized = 1; + + PT_LOG("ATI GFX Guest Info:\n" + " pio_index=0x%08x, guest_pio_bar=0x%08x\n" + " mmio_bar1_index=0x%08x, guest_mmio_bar1=0x%08x\n" + " mmio_bar2_index=0x%08x, guest_mmio_bar2=0x%08x\n", + gfx_info.pio_bar_index, gfx_info.guest_pio_base, + gfx_info.mmio_bar1_index, gfx_info.guest_mmio_base1, + gfx_info.mmio_bar2_index, gfx_info.guest_mmio_base2); +} + +static uint32_t ati_legacy_io_read(void *opaque, uint32_t addr) +{ + struct pt_dev *assigned_device = opaque; + PCIDevice *dev = (PCIDevice *)&assigned_device->dev; + uint32_t val = 0xFF; + + switch( addr ) + { + case 0x3c3: + val = dev->io_regions[gfx_info.pio_bar_index].addr >> 8; + /* Intercept GFX IO registers. This supposes to happen in + * ati_register_vga_regions(). But we cannot get guest phys IO BAR + * over there. */ + if ( !gfx_info.initialized ) + ati_gfx_init(assigned_device); + break; + default: + PT_LOG("ERROR: port 0x%x I/O read not handled\n", addr); + break; + } + + return val; +} + +static void ati_legacy_io_write(void *opaque, uint32_t addr, uint32_t val) +{ + PT_LOG("ERROR: port 0x%x I/O write not handled\n", addr); +} + +int ati_register_vga_regions(struct pt_dev *real_device) +{ + PCIDevice *dev = (PCIDevice *)&real_device->dev; + int ret = 0; + + /* We need to intercept VBIOS accesses to port 0x3C3, which returns + * device port I/O BAR. For the rest of legacy I/O ports, we allow direct + * accesses. + */ + ret |= xc_domain_ioport_mapping(xc_handle, domid, 0x3C0, + 0x3C0, 0x3, DPCI_ADD_MAPPING); + + ret |= xc_domain_ioport_mapping(xc_handle, domid, 0x3C4, + 0x3C4, 0x1C, DPCI_ADD_MAPPING); + + register_ioport_read(0x3c3, 1, 1, ati_legacy_io_read, real_device); + register_ioport_write(0x3c3, 1, 1, ati_legacy_io_write, real_device); + + /* initialized on the first port 0x3C3 access in ati_gfx_init */ + gfx_info.initialized = 0; + + return ret; +} + +int ati_unregister_vga_regions(struct pt_dev *real_device) +{ + int ret = 0; + + ret |= xc_domain_ioport_mapping(xc_handle, domid, 0x3C0, + 0x3C0, 0x3, DPCI_REMOVE_MAPPING); + + ret |= xc_domain_ioport_mapping(xc_handle, domid, 0x3C4, + 0x3C4, 0x1C, DPCI_REMOVE_MAPPING); + + gfx_info.initialized = 0; + + return ret; +} + +/*********************************/ +/* Code for Intel IGD Passthru */ +/*********************************/ static int pch_map_irq(PCIDevice *pci_dev, int irq_num) { PT_LOG("pch_map_irq called\n"); @@ -88,6 +325,77 @@ uint32_t igd_pci_read(PCIDevice *pci_dev, uint32_t config_addr, int len) return val; } +int igd_register_vga_regions(struct pt_dev *real_device) +{ + u32 vendor_id, igd_opregion; + int ret = 0; + + /* legacy I/O ports 0x3C0 -- 0x3E0 */ + ret |= xc_domain_ioport_mapping(xc_handle, domid, 0x3C0, + 0x3C0, 0x20, DPCI_ADD_MAPPING); + + /* 1:1 map ASL Storage register value */ + vendor_id = pt_pci_host_read(0, 2, 0, 0, 2); + igd_opregion = pt_pci_host_read(0, 2, 0, 0xfc, 4); + if ( (vendor_id == 0x8086) && igd_opregion ) + { + ret |= xc_domain_memory_mapping(xc_handle, domid, + igd_opregion >> XC_PAGE_SHIFT, + igd_opregion >> XC_PAGE_SHIFT, + 2, + DPCI_ADD_MAPPING); + PT_LOG("register_vga: igd_opregion = %x\n", igd_opregion); + } + + return ret; +} + +int igd_unregister_vga_regions(struct pt_dev *real_device) +{ + u32 vendor_id, igd_opregion; + int ret = 0; + + ret |= xc_domain_ioport_mapping(xc_handle, domid, 0x3C0, + 0x3C0, 0x20, DPCI_REMOVE_MAPPING); + + vendor_id = pt_pci_host_read(0, 2, 0, 0, 2); + igd_opregion = pt_pci_host_read(0, 2, 0, 0xfc, 4); + if ( (vendor_id == 0x8086) && igd_opregion ) + { + ret |= xc_domain_memory_mapping(xc_handle, domid, + igd_opregion >> XC_PAGE_SHIFT, + igd_opregion >> XC_PAGE_SHIFT, + 2, + DPCI_REMOVE_MAPPING); + } + + return ret; +} +/*********************************/ +/* Generic Code for GFX Passthru */ +/*********************************/ +/* This function decides whether I/O port map should be skipped */ +int vga_skip_ioport_map(PCIDevice *d) +{ + struct pt_dev *dev = (struct pt_dev *)d; + int skip = 0; + + if ( !gfx_passthru || dev->pci_dev->device_class != 0x0300 ) + return 0; + + switch( dev->pci_dev->vendor_id ) + { + case PCI_VENDOR_ID_ATI: + case PCI_VENDOR_ID_AMD: + skip = 1; + break; + default: + skip = 0; + break; + } + + return skip; +} /* * register VGA resources for the domain with assigned gfx */ @@ -99,29 +407,31 @@ int register_vga_regions(struct pt_dev *real_device) if ( !gfx_passthru || real_device->pci_dev->device_class != 0x0300 ) return ret; + /* legacy I/O ports 0x3B0 - 0x3BC */ ret |= xc_domain_ioport_mapping(xc_handle, domid, 0x3B0, 0x3B0, 0xC, DPCI_ADD_MAPPING); - - ret |= xc_domain_ioport_mapping(xc_handle, domid, 0x3C0, - 0x3C0, 0x20, DPCI_ADD_MAPPING); - + + /* legacy video MMIO range 0xA0000 - 0xBFFFF */ ret |= xc_domain_memory_mapping(xc_handle, domid, 0xa0000 >> XC_PAGE_SHIFT, 0xa0000 >> XC_PAGE_SHIFT, 0x20, DPCI_ADD_MAPPING); - /* 1:1 map ASL Storage register value */ - vendor_id = pt_pci_host_read(0, 2, 0, 0, 2); - igd_opregion = pt_pci_host_read(0, 2, 0, 0xfc, 4); - if ( (vendor_id == 0x8086) && igd_opregion ) + /* Other VGA regions are vendor specific */ + switch( real_device->pci_dev->vendor_id ) { - ret |= xc_domain_memory_mapping(xc_handle, domid, - igd_opregion >> XC_PAGE_SHIFT, - igd_opregion >> XC_PAGE_SHIFT, - 2, - DPCI_ADD_MAPPING); - PT_LOG("register_vga: igd_opregion = %x\n", igd_opregion); + case PCI_VENDOR_ID_INTEL: + ret = igd_register_vga_regions(real_device); + break; + case PCI_VENDOR_ID_ATI: + case PCI_VENDOR_ID_AMD: + ret = ati_register_vga_regions(real_device); + break; + default: + PT_LOG("gfx card wasn't supported by Xen passthru!\n"); + ret = 1; + break; } if ( ret != 0 ) @@ -135,33 +445,36 @@ int register_vga_regions(struct pt_dev *real_device) */ int unregister_vga_regions(struct pt_dev *real_device) { - u32 vendor_id, igd_opregion; int ret = 0; if ( !gfx_passthru || real_device->pci_dev->device_class != 0x0300 ) return ret; + /* legacy I/O ports 0x3B0 - 0x3BC */ ret |= xc_domain_ioport_mapping(xc_handle, domid, 0x3B0, 0x3B0, 0xC, DPCI_REMOVE_MAPPING); - ret |= xc_domain_ioport_mapping(xc_handle, domid, 0x3C0, - 0x3C0, 0x20, DPCI_REMOVE_MAPPING); - + /* legacy video MMIO range 0xA0000 - 0xBFFFF */ ret |= xc_domain_memory_mapping(xc_handle, domid, 0xa0000 >> XC_PAGE_SHIFT, 0xa0000 >> XC_PAGE_SHIFT, 20, DPCI_REMOVE_MAPPING); - vendor_id = pt_pci_host_read(0, 2, 0, 0, 2); - igd_opregion = pt_pci_host_read(0, 2, 0, 0xfc, 4); - if ( (vendor_id == 0x8086) && igd_opregion ) + /* Other VGA regions are vendor specific */ + switch( real_device->pci_dev->vendor_id ) { - ret |= xc_domain_memory_mapping(xc_handle, domid, - igd_opregion >> XC_PAGE_SHIFT, - igd_opregion >> XC_PAGE_SHIFT, - 2, - DPCI_REMOVE_MAPPING); + case PCI_VENDOR_ID_INTEL: + ret = igd_unregister_vga_regions(real_device); + break; + case PCI_VENDOR_ID_ATI: + case PCI_VENDOR_ID_AMD: + ret = ati_unregister_vga_regions(real_device); + break; + default: + PT_LOG("gfx card wasn't supported by Xen passthru!\n"); + ret = 1; + break; } if ( ret != 0 ) @@ -231,12 +544,12 @@ int setup_vga_pt(struct pt_dev *real_device) if ( !gfx_passthru || real_device->pci_dev->device_class != 0x0300 ) return rc; - /* Allocated 64K for the vga bios */ - if ( !(bios = malloc(64 * 1024)) ) + /* Allocated 128K for the vga bios */ + if ( !(bios = malloc(128 * 1024)) ) return -1; bios_size = get_vgabios(bios); - if ( bios_size == 0 || bios_size > 64 * 1024) + if ( bios_size == 0 || bios_size > 128 * 1024) { PT_LOG("vga bios size (0x%x) is invalid!\n", bios_size); rc = -1; --------------010909060803090809050505 Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Disposition: inline _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel --------------010909060803090809050505--