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
|