WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-devel

RE: [Xen-devel] [PATCH][VTD] enable integrated graphics passthrough for

To: Stefano Stabellini <stefano.stabellini@xxxxxxxxxxxxx>
Subject: RE: [Xen-devel] [PATCH][VTD] enable integrated graphics passthrough for Calpella and Sandybridge
From: "Kay, Allen M" <allen.m.kay@xxxxxxxxx>
Date: Tue, 8 Jun 2010 14:46:48 -0700
Accept-language: en-US
Acceptlanguage: en-US
Cc: "xen-devel@xxxxxxxxxxxxxxxxxxx" <xen-devel@xxxxxxxxxxxxxxxxxxx>, "Han, Weidong" <weidong.han@xxxxxxxxx>, Jean Guyader <Jean.Guyader@xxxxxxxxxx>, Ian Pratt <Ian.Pratt@xxxxxxxxxxxxx>, Philipson <Ross.Philipson@xxxxxxxxxx>, Ross
Delivery-date: Tue, 08 Jun 2010 14:47:02 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
In-reply-to: <alpine.DEB.2.00.1006041616070.3401@kaball-desktop>
List-help: <mailto:xen-devel-request@lists.xensource.com?subject=help>
List-id: Xen developer discussion <xen-devel.lists.xensource.com>
List-post: <mailto:xen-devel@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=unsubscribe>
References: <987664A83D2D224EAE907B061CE93D530114C3D62D@xxxxxxxxxxxxxxxxxxxxxxxxxxxx> <alpine.DEB.2.00.1006041616070.3401@kaball-desktop>
Sender: xen-devel-bounces@xxxxxxxxxxxxxxxxxxx
Thread-index: AcsD+tpOd8gkGvKFT2Cr6oafWcBcoQDWHA9g
Thread-topic: [Xen-devel] [PATCH][VTD] enable integrated graphics passthrough for Calpella and Sandybridge
Stephano,

Thanks for your feedback.  I add "#ifdef CONFIG_PASSTHROUGH" in the next 
version of the patch.

I have tested the patch on a Intel Montevina software development platform and 
found it has the same behavior as current xen qemu upstream.

Can others who have been playing with IGD passthrough give the patch a try on 
older platforms?

Allen

-----Original Message-----
From: Stefano Stabellini [mailto:stefano.stabellini@xxxxxxxxxxxxx]
Sent: Friday, June 04, 2010 8:29 AM
To: Kay, Allen M
Cc: xen-devel@xxxxxxxxxxxxxxxxxxx; Ian Pratt; Han, Weidong; Ross Philipson; 
Jean Guyader
Subject: Re: [Xen-devel] [PATCH][VTD] enable integrated graphics passthrough 
for Calpella and Sandybridge

On Fri, 4 Jun 2010, Kay, Allen M wrote:
>
> Added Calpella and Sandybridge integrated graphics pass-through support, 
> consolidated graphics pass-through code into
> pt-graphics.c.
>
> Signed-off-by: Allen Kay <allen.m.kay@xxxxxxxxx>
>

some comments follow

> diff --git a/hw/pass-through.c b/hw/pass-through.c
> index 5a76e8d..971c7f1 100644
> --- a/hw/pass-through.c
> +++ b/hw/pass-through.c
> @@ -1865,50 +1865,6 @@ static int pt_dev_is_virtfn(struct pci_dev *dev)
>      return rc;
>  }
>
> -/*
> - * register VGA resources for the domain with assigned gfx
> - */
> -static int register_vga_regions(struct pt_dev *real_device)
> -{
> -    int ret = 0;
> -
> -    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);
> -
> -    ret |= xc_domain_memory_mapping(xc_handle, domid,
> -            0xa0000 >> XC_PAGE_SHIFT,
> -            0xa0000 >> XC_PAGE_SHIFT,
> -            0x20,
> -            DPCI_ADD_MAPPING);
> -
> -    return ret;
> -}
> -
> -/*
> - * unregister VGA resources for the domain with assigned gfx
> - */
> -static int unregister_vga_regions(struct pt_dev *real_device)
> -{
> -    int ret = 0;
> -
> -    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);
> -
> -    ret |= xc_domain_memory_mapping(xc_handle, domid,
> -            0xa0000 >> XC_PAGE_SHIFT,
> -            0xa0000 >> XC_PAGE_SHIFT,
> -            0x20,
> -            DPCI_REMOVE_MAPPING);
> -
> -    return ret;
> -}
> -
>  static int pt_register_regions(struct pt_dev *assigned_device)
>  {
>      int i = 0;
> @@ -1970,17 +1926,7 @@ static int pt_register_regions(struct pt_dev 
> *assigned_device)
>          PT_LOG("Expansion ROM registered (size=0x%08x base_addr=0x%08x)\n",
>              (uint32_t)(pci_dev->rom_size), 
> (uint32_t)(pci_dev->rom_base_addr));
>      }
> -
> -    if ( gfx_passthru && (pci_dev->device_class == 0x0300) )
> -    {
> -        ret = register_vga_regions(assigned_device);
> -        if ( ret != 0 )
> -        {
> -            PT_LOG("VGA region mapping failed\n");
> -            return ret;
> -        }
> -    }
> -
> +    register_vga_regions(assigned_device);
>      return 0;
>  }
>
> @@ -2029,13 +1975,7 @@ static void pt_unregister_regions(struct pt_dev 
> *assigned_device)
>          }
>
>      }
> -
> -    if ( gfx_passthru && (assigned_device->pci_dev->device_class == 0x0300) )
> -    {
> -        ret = unregister_vga_regions(assigned_device);
> -        if ( ret != 0 )
> -            PT_LOG("VGA region unmapping failed\n");
> -    }
> +    unregister_vga_regions(assigned_device);
>  }
>
>  static uint8_t find_cap_offset(struct pci_dev *pci_dev, uint8_t cap)
> @@ -2097,46 +2037,66 @@ static uint32_t find_ext_cap_offset(struct pci_dev 
> *pci_dev, uint32_t cap)
>      return 0;
>  }
>
> -u8 pt_pci_host_read_byte(int bus, int dev, int fn, u32 addr)
> +static void pci_access_init(void)
>  {
> -    struct pci_dev *pci_dev;
> -    u8 val;
> +    struct pci_access *pci_access;
>
> -    pci_dev = pci_get_dev(dpci_infos.pci_access, 0, bus, dev, fn);
> -    if ( !pci_dev )
> -        return 0;
> +    if (dpci_infos.pci_access)
> +        return;
>
> -    val = pci_read_byte(pci_dev, addr);
> -    pci_free_dev(pci_dev);
> -    return val;
> +    /* Initialize libpci */
> +    pci_access = pci_alloc();
> +    if ( pci_access == NULL ) {
> +        PT_LOG("Error: pci_access is NULL\n");
> +        return -1;
> +    }
> +    pci_init(pci_access);
> +    pci_scan_bus(pci_access);
> +    dpci_infos.pci_access = pci_access;
>  }
>
> -u16 pt_pci_host_read_word(int bus, int dev, int fn, u32 addr)
> +u32 pt_pci_host_read(int bus, int dev, int fn, u32 addr, int len)
>  {
> +
>      struct pci_dev *pci_dev;
> -    u16 val;
> +    u32 val = -1;
>
> +    pci_access_init();
>      pci_dev = pci_get_dev(dpci_infos.pci_access, 0, bus, dev, fn);
>      if ( !pci_dev )
>          return 0;
>
> -    val = pci_read_word(pci_dev, addr);
> -    pci_free_dev(pci_dev);
> +    switch (len)
> +    {
> +        case 1: val = pci_read_byte(pci_dev, addr); break;
> +        case 2: val = pci_read_word(pci_dev, addr); break;
> +        case 4: val = pci_read_long(pci_dev, addr); break;
> +        default:
> +            fprintf(stderr, "error: pt_pci_host_read: invalid len = %d\n", 
> len);
> +    }
>      return val;
>  }
>
> -u32 pt_pci_host_read_long(int bus, int dev, int fn, u32 addr)
> +int pt_pci_host_write(int bus, int dev, int fn, u32 addr, u32 val, int len)
>  {
>      struct pci_dev *pci_dev;
> -    u32 val;
> +    int ret = 0;
>
> +    pci_access_init();
>      pci_dev = pci_get_dev(dpci_infos.pci_access, 0, bus, dev, fn);
>      if ( !pci_dev )
>          return 0;
>
> -    val = pci_read_long(pci_dev, addr);
> +    switch (len)
> +    {
> +        case 1: ret = pci_write_byte(pci_dev, addr, val); break;
> +        case 2: ret = pci_write_word(pci_dev, addr, val); break;
> +        case 4: ret = pci_write_long(pci_dev, addr, val); break;
> +        default:
> +            fprintf(stderr, "error: pt_pci_host_write: invalid len = %d\n", 
> len);
> +    }
>      pci_free_dev(pci_dev);
> -    return val;
> +    return ret;
>  }
>
>  /* parse BAR */
> @@ -4200,92 +4160,6 @@ static int pt_pmcsr_reg_restore(struct pt_dev *ptdev,
>      return 0;
>  }
>
> -static int get_vgabios(unsigned char *buf)
> -{
> -    int fd;
> -    uint32_t bios_size = 0;
> -    uint32_t start = 0xC0000;
> -    uint16_t magic = 0;
> -
> -    if ( (fd = open("/dev/mem", O_RDONLY)) < 0 )
> -    {
> -        PT_LOG("Error: Can't open /dev/mem: %s\n", strerror(errno));
> -        return 0;
> -    }
> -
> -    /*
> -     * Check if it a real bios extension.
> -     * The magic number is 0xAA55.
> -     */
> -    if ( start != lseek(fd, start, SEEK_SET) )
> -        goto out;
> -    if ( read(fd, &magic, 2) != 2 )
> -        goto out;
> -    if ( magic != 0xAA55 )
> -        goto out;
> -
> -    /* Find the size of the rom extension */
> -    if ( start != lseek(fd, start, SEEK_SET) )
> -        goto out;
> -    if ( lseek(fd, 2, SEEK_CUR) != (start + 2) )
> -        goto out;
> -    if ( read(fd, &bios_size, 1) != 1 )
> -        goto out;
> -
> -    /* This size is in 512 bytes */
> -    bios_size *= 512;
> -
> -    /*
> -     * Set the file to the begining of the rombios,
> -     * to start the copy.
> -     */
> -    if ( start != lseek(fd, start, SEEK_SET) )
> -        goto out;
> -
> -    if ( bios_size != read(fd, buf, bios_size))
> -        bios_size = 0;
> -
> -out:
> -    close(fd);
> -    return bios_size;
> -}
> -
> -static int setup_vga_pt(void)
> -{
> -    unsigned char *bios = NULL;
> -    int bios_size = 0;
> -    char *c = NULL;
> -    char checksum = 0;
> -    int rc = 0;
> -
> -    /* Allocated 64K for the vga bios */
> -    if ( !(bios = malloc(64 * 1024)) )
> -        return -1;
> -
> -    bios_size = get_vgabios(bios);
> -    if ( bios_size == 0 || bios_size > 64 * 1024)
> -    {
> -        PT_LOG("vga bios size (0x%x) is invalid!\n", bios_size);
> -        rc = -1;
> -        goto out;
> -    }
> -
> -    /* Adjust the bios checksum */
> -    for ( c = (char*)bios; c < ((char*)bios + bios_size); c++ )
> -        checksum += *c;
> -    if ( checksum )
> -    {
> -        bios[bios_size - 1] -= checksum;
> -        PT_LOG("vga bios checksum is adjusted!\n");
> -    }
> -
> -    cpu_physical_memory_rw(0xc0000, bios, bios_size, 1);
> -
> -out:
> -    free(bios);
> -    return rc;
> -}
> -
>  static struct pt_dev * register_real_device(PCIBus *e_bus,
>          const char *e_dev_name, int e_devfn, uint8_t r_bus, uint8_t r_dev,
>          uint8_t r_func, uint32_t machine_irq, struct pci_access *pci_access,
> @@ -4387,16 +4261,13 @@ static struct pt_dev * register_real_device(PCIBus 
> *e_bus,
>      pt_register_regions(assigned_device);
>
>      /* Setup VGA bios for passthroughed gfx */
> -    if ( gfx_passthru && (assigned_device->pci_dev->device_class == 0x0300) )
> +    if ( setup_vga_pt(assigned_device) < 0 )
>      {
> -        rc = setup_vga_pt();
> -        if ( rc < 0 )
> -        {
> -            PT_LOG("Setup VGA BIOS of passthroughed gfx failed!\n");
> -            return NULL;
> -        }
> +        PT_LOG("Setup VGA BIOS of passthroughed gfx failed!\n");
> +        return NULL;
>      }
>
> +
>      /* reinitialize each config register to be emulated */
>      rc = pt_config_init(assigned_device);
>      if ( rc < 0 ) {
> @@ -4548,19 +4419,8 @@ int power_on_php_devfn(int devfn)
>  {
>      struct php_dev *php_dev = &dpci_infos.php_devs[devfn];
>      struct pt_dev *pt_dev;
> -    struct pci_access *pci_access;
>
> -    if (!dpci_infos.pci_access) {
> -        /* Initialize libpci */
> -        pci_access = pci_alloc();
> -        if ( pci_access == NULL ) {
> -            PT_LOG("Error: pci_access is NULL\n");
> -            return -1;
> -        }
> -        pci_init(pci_access);
> -        pci_scan_bus(pci_access);
> -        dpci_infos.pci_access = pci_access;
> -    }
> +    pci_access_init();
>
>      pt_dev =
>          register_real_device(dpci_infos.e_bus,
> diff --git a/hw/pass-through.h b/hw/pass-through.h
> index f8a0c73..6c5e8ca 100644
> --- a/hw/pass-through.h
> +++ b/hw/pass-through.h
> @@ -406,10 +406,16 @@ static inline pciaddr_t pt_pci_base_addr(pciaddr_t base)
>  }
>
>  uint8_t pci_intx(struct pt_dev *ptdev);
> -
> -u8 pt_pci_host_read_byte(int bus, int dev, int fn, u32 addr);
> -u16 pt_pci_host_read_word(int bus, int dev, int fn, u32 addr);
> -u32 pt_pci_host_read_long(int bus, int dev, int fn, u32 addr);
> +u32 pt_pci_host_read(int bus, int dev, int fn, u32 addr, int len);
> +int pt_pci_host_write(int bus, int dev, int fn, u32 addr, u32 val, int len);
> +PCIBus *intel_pch_init(PCIBus *bus);
> +int igd_pci_write(PCIDevice *pci_dev, int config_addr, uint32_t val, int 
> len);
> +int igd_pci_read(PCIDevice *pci_dev, int config_addr, uint32_t *val, int 
> len);
> +int register_vga_regions(struct pt_dev *real_device);
> +int 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);
>
>  #endif /* __PASSTHROUGH_H__ */
>
> diff --git a/hw/pc.c b/hw/pc.c
> index 9375951..7364cb8 100644
> --- a/hw/pc.c
> +++ b/hw/pc.c
> @@ -42,6 +42,10 @@
>  #include "virtio-console.h"
>  #include "hpet_emul.h"
>
> +#ifdef CONFIG_PASSTHROUGH
> +#include "pass-through.h"
> +#endif
> +
>  /* output Bochs bios info messages */
>  //#define DEBUG_BIOS
>
> @@ -978,6 +982,8 @@ vga_bios_error:
>          pci_bus = NULL;
>      }
>
> +    intel_pch_init(pci_bus);
> +
>      /* init basic PC hardware */
>      register_ioport_write(0x80, 1, 1, ioport80_write, NULL);
>

You are missing a ifdef CONFIG_PASSTHROUGH here


> diff --git a/hw/pci.c b/hw/pci.c
> index b07e5ea..fa32ed9 100644
> --- a/hw/pci.c
> +++ b/hw/pci.c
> @@ -39,24 +39,6 @@ extern int igd_passthru;
>
>  //#define DEBUG_PCI
>
> -struct PCIBus {
> -    int bus_num;
> -    int devfn_min;
> -    pci_set_irq_fn set_irq;
> -    pci_map_irq_fn map_irq;
> -    uint32_t config_reg; /* XXX: suppress */
> -    /* low level pic */
> -    SetIRQFunc *low_set_irq;
> -    qemu_irq *irq_opaque;
> -    PCIDevice *devices[256];
> -    PCIDevice *parent_dev;
> -    PCIBus *next;
> -    /* The bus IRQ state is the logical OR of the connected devices.
> -       Keep a count of the number of devices with raised IRQs.  */
> -    int nirq;
> -    int irq_count[];
> -};
> -
>  static void pci_update_mappings(PCIDevice *d);
>  static void pci_set_irq(void *opaque, int irq_num, int level);
>
> @@ -96,7 +78,7 @@ PCIBus *pci_register_bus(pci_set_irq_fn set_irq, 
> pci_map_irq_fn map_irq,
>      return bus;
>  }
>
> -static PCIBus *pci_register_secondary_bus(PCIDevice *dev, pci_map_irq_fn 
> map_irq)
> +PCIBus *pci_register_secondary_bus(PCIDevice *dev, pci_map_irq_fn map_irq)
>  {
>      PCIBus *bus;
>      bus = qemu_mallocz(sizeof(PCIBus));
> @@ -590,6 +572,10 @@ void pci_data_write(void *opaque, uint32_t addr, 
> uint32_t val, int len)
>      printf("pci_config_write: %s: addr=%02x val=%08x len=%d\n",
>             pci_dev->name, config_addr, val, len);
>  #endif
> +
> +#ifdef CONFIG_PASSTHROUGH
> +    if (igd_pci_write(pci_dev, config_addr, val, len) == 0)
> +#endif
>      pci_dev->config_write(pci_dev, config_addr, val, len);
>  }
>
> @@ -598,7 +584,7 @@ uint32_t pci_data_read(void *opaque, uint32_t addr, int 
> len)
>      PCIBus *s = opaque;
>      PCIDevice *pci_dev;
>      int config_addr, bus_num;
> -    uint32_t val;
> +    uint32_t val = 0;
>
>      bus_num = (addr >> 16) & 0xff;
>      while (s && s->bus_num != bus_num)
> @@ -625,26 +611,8 @@ uint32_t pci_data_read(void *opaque, uint32_t addr, int 
> len)
>      config_addr = addr & 0xff;
>
>  #ifdef CONFIG_PASSTHROUGH
> -    /* host bridge reads for IGD passthrough */
> -    if ( igd_passthru && pci_dev->devfn == 0x00 ) {
> -        val = pci_dev->config_read(pci_dev, config_addr, len);
> -
> -        if ( config_addr == 0x00 && len == 4 )
> -            val = pt_pci_host_read_long(0, 0, 0, 0x00);
> -        else if ( config_addr == 0x02 ) // Device ID
> -            val = pt_pci_host_read_word(0, 0, 0, 0x02);
> -        else if ( config_addr == 0x52 ) // GMCH Graphics Control Register
> -            val = pt_pci_host_read_word(0, 0, 0, 0x52);
> -        else if ( config_addr == 0xa0 ) // GMCH Top of Memory Register
> -            val = pt_pci_host_read_word(0, 0, 0, 0xa0);
> -        goto done_config_read;
> -    } else if ( igd_passthru && pci_dev->devfn == 0x10 &&
> -              config_addr == 0xfc ) { // read on IGD device
> -        val = 0;  // use SMI to communicate with the system BIOS
> -        goto done_config_read;
> -    }
> +    if ( igd_pci_read(pci_dev, config_addr, &val, len) == 0)
>  #endif
> -
>      val = pci_dev->config_read(pci_dev, config_addr, len);
>
>   done_config_read:
> @@ -892,12 +860,7 @@ void pci_unplug_netifs(void)
>      }
>  }
>
> -typedef struct {
> -    PCIDevice dev;
> -    PCIBus *bus;
> -} PCIBridge;
> -
> -static void pci_bridge_write_config(PCIDevice *d,
> +void pci_bridge_write_config(PCIDevice *d,
>                               uint32_t address, uint32_t val, int len)
>  {
>      PCIBridge *s = (PCIBridge *)d;
> diff --git a/hw/pci.h b/hw/pci.h
> index de5a4e1..18e7b6f 100644
> --- a/hw/pci.h
> +++ b/hw/pci.h
> @@ -207,6 +207,32 @@ struct PCIDevice {
>      int irq_state[4];
>  };
>
> +typedef void (*pci_set_irq_fn)(qemu_irq *pic, int irq_num, int level);
> +typedef int (*pci_map_irq_fn)(PCIDevice *pci_dev, int irq_num);
> +
> +struct PCIBus {
> +    int bus_num;
> +    int devfn_min;
> +    pci_set_irq_fn set_irq;
> +    pci_map_irq_fn map_irq;
> +    uint32_t config_reg; /* XXX: suppress */
> +    /* low level pic */
> +    SetIRQFunc *low_set_irq;
> +    qemu_irq *irq_opaque;
> +    PCIDevice *devices[256];
> +    PCIDevice *parent_dev;
> +    PCIBus *next;
> +    /* The bus IRQ state is the logical OR of the connected devices.
> +       Keep a count of the number of devices with raised IRQs.  */
> +    int nirq;
> +    int irq_count[];
> +};
> +
> +typedef struct {
> +    PCIDevice dev;
> +    PCIBus *bus;
> +} PCIBridge;
> +
>  extern char direct_pci_str[];
>  extern int direct_pci_msitranslate;
>  extern int direct_pci_power_mgmt;
> @@ -235,8 +261,6 @@ void pci_default_write_config(PCIDevice *d,
>  void pci_device_save(PCIDevice *s, QEMUFile *f);
>  int pci_device_load(PCIDevice *s, QEMUFile *f);
>
> -typedef void (*pci_set_irq_fn)(qemu_irq *pic, int irq_num, int level);
> -typedef int (*pci_map_irq_fn)(PCIDevice *pci_dev, int irq_num);
>  PCIBus *pci_register_bus(pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
>                           qemu_irq *pic, int devfn_min, int nirq);
>
> @@ -341,5 +365,9 @@ PCIBus *sh_pci_register_bus(pci_set_irq_fn set_irq, 
> pci_map_irq_fn map_irq,
>
>  /* pass-through.c */
>  int pt_init(PCIBus *e_bus);
> +void pci_bridge_write_config(PCIDevice *d,
> +                             uint32_t address, uint32_t val, int len);
> +PCIBus *pci_register_secondary_bus(PCIDevice *dev, pci_map_irq_fn map_irq);
> +
>
>  #endif
> diff --git a/hw/pt-graphics.c b/hw/pt-graphics.c
> new file mode 100644
> index 0000000..3b9ce95
> --- /dev/null
> +++ b/hw/pt-graphics.c
> @@ -0,0 +1,266 @@
> +/*
> + * graphics passthrough
> + */
> +
> +#include "pass-through.h"
> +#include "pci/header.h"
> +#include "pci/pci.h"
> +#include "pt-msi.h"
> +#include "qemu-xen.h"
> +#include "iomulti.h"
> +
> +#include <unistd.h>
> +#include <sys/ioctl.h>
> +
> +extern int gfx_passthru;
> +extern int igd_passthru;
> +
> +static int pch_irq_function(PCIDevice *pci_dev, int irq_num)
> +{
> +    PT_LOG("pch_irq_function called\n");
> +    return irq_num;
> +}
> +
> +PCIBus *intel_pch_init(PCIBus *bus)
> +{
> +    PCIBridge *pch;
> +    u16 vendor_id, device_id;
> +    u8  rev_id;
> +
> +    if ( !gfx_passthru )
> +        return NULL;
> +
> +    vendor_id = pt_pci_host_read(0, 0x1f, 0, 0, 2);
> +    device_id = pt_pci_host_read(0, 0x1f, 0, 2, 2);
> +    rev_id    = pt_pci_host_read(0, 0x1f, 0, 8, 1);
> +
> +    pch = (PCIBridge *)
> +          pci_register_device(bus, "intel_bridge_1f", sizeof(PCIBridge),
> +                     PCI_DEVFN(0x1f, 0), NULL, pci_bridge_write_config);
> +
> +    pci_config_set_vendor_id(pch->dev.config, vendor_id);
> +    pci_config_set_device_id(pch->dev.config, device_id);
> +
> +    pch->dev.config[0x04] = 0x06; // command = bus master, pci mem
> +    pch->dev.config[0x05] = 0x00;
> +    pch->dev.config[0x06] = 0xa0; // status = fast back-to-back, 66MHz, no 
> error
> +    pch->dev.config[0x07] = 0x00; // status = fast devsel
> +    pch->dev.config[0x08] = rev_id;
> +    pch->dev.config[0x09] = 0x00; // programming i/f
> +    pci_config_set_class(pch->dev.config, PCI_CLASS_BRIDGE_ISA);
> +    pch->dev.config[0x0D] = 0x10; // latency_timer
> +    pch->dev.config[0x0E] = 0x81; // header_type
> +    pch->dev.config[0x1E] = 0xa0; // secondary status
> +
> +    pch->bus = pci_register_secondary_bus(&pch->dev, pch_irq_function);
> +    return pch->bus;
> +}
> +

What happens if the hardware is a pre-Calpella Intel graphic card? Is it
still going to work?


> +int igd_pci_write(PCIDevice *pci_dev, int config_addr, uint32_t val, int len)
> +{
> +    if ( !igd_passthru || (pci_dev->devfn != 0x00 ) )
> +        return 0;
> +
> +    switch (config_addr)
> +    {
> +        case 0x58:        // PAVPC Offset
> +            pt_pci_host_write(0, 0, 0, config_addr, val, len);
> +            PT_LOG("pci_config_write: %x:%x.%x: addr=%x len=%x val=%x\n",
> +                   pci_bus_num(pci_dev->bus), PCI_SLOT(pci_dev->devfn),
> +                   PCI_FUNC(pci_dev->devfn), config_addr, len, val);
> +            break;
> +        default:
> +            pci_dev->config_write(pci_dev, config_addr, val, len);
> +    }
> +    return 1;
> +}
> +
> +int igd_pci_read(PCIDevice *pci_dev, int config_addr, uint32_t *val, int len)
> +{
> +    if ( !igd_passthru || (pci_dev->devfn != 0) )
> +        return 0;
> +
> +    switch (config_addr)
> +    {
> +        case 0x00:        /* vendor id */
> +        case 0x02:        /* device id */
> +        case 0x52:        /* processor graphics control register */
> +        case 0xa0:        /* top of memory */
> +        case 0xb0:        /* ILK: BSM: should read from dev 2 offset 0x5c */
> +        case 0x58:        /* SNB: PAVPC Offset */
> +        case 0xa4:        /* SNB: graphics base of stolen memory */
> +        case 0xa8:        /* SNB: base of GTT stolen memory */
> +            *val = pt_pci_host_read(0, PCI_SLOT(pci_dev->devfn),
> +                                   0, config_addr, len);
> +            PT_LOG("pci_config_read: %x:%x.%x: addr=%x len=%x val=%x\n",
> +                   pci_bus_num(pci_dev->bus), PCI_SLOT(pci_dev->devfn),
> +                   PCI_FUNC(pci_dev->devfn), config_addr, len, *val);
> +
> +            break;
> +        default:
> +            *val = pci_dev->config_read(pci_dev, config_addr, len);
> +    }
> +    return 1;
> +}
> +
> +/*
> + * register VGA resources for the domain with assigned gfx
> + */
> +int register_vga_regions(struct pt_dev *real_device)
> +{
> +    u32 igd_opregion, igd_bsm;
> +    int ret = 0;
> +
> +    if ( !gfx_passthru || real_device->pci_dev->device_class != 0x0300 )
> +        return ret;
> +
> +    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);
> +
> +    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 */
> +    igd_opregion = pt_pci_host_read(0, 2, 0, 0xfc, 4);
> +    PT_LOG("register_vga: igd_opregion = %x\n", igd_opregion);
> +    ret |= xc_domain_memory_mapping(xc_handle, domid,
> +            igd_opregion >> XC_PAGE_SHIFT,
> +            igd_opregion >> XC_PAGE_SHIFT,
> +            2,
> +            DPCI_ADD_MAPPING);

Again, what happens if the hardware is older? Do all Intel graphic cards
have an opregion?

> +    igd_opregion = pt_pci_host_read(0, 2, 0, 0xfc, 4);
> +    ret |= xc_domain_memory_mapping(xc_handle, domid,
> +            igd_opregion >> XC_PAGE_SHIFT,
> +            igd_opregion >> XC_PAGE_SHIFT,
> +            2,
> +            DPCI_REMOVE_MAPPING);
> +

ditto



_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel

<Prev in Thread] Current Thread [Next in Thread>