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

RE: [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


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.