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

Re: [Xen-devel] Experimental results for VGA passthrough


  • To: "Beng Heng, Ng" <bengheng@xxxxxxxxxxxxxx>
  • From: Andrew Lyon <andrew.lyon@xxxxxxxxx>
  • Date: Mon, 8 Jun 2009 15:19:01 +0100
  • Cc: Xen-devel <xen-devel@xxxxxxxxxxxxxxxxxxx>
  • Delivery-date: Mon, 08 Jun 2009 07:19:54 -0700
  • Domainkey-signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=mime-version:in-reply-to:references:date:message-id:subject:from:to :cc:content-type:content-transfer-encoding; b=X1tDNYPXIBVQZM6Jcha+oXH+IZbWada6Q9C9xbKY+CxHs01rrWMZ+onz6AnqQsDtR1 UB+wXyedWH1rirNQIgjgSecphcBbju3d482iSKw838bOPmNq2AL9TTV5SrxcldcbAXsR Lvi31RYLBAOoaSg/qcprvjz5WZgMOA/N3XgVE=
  • List-id: Xen developer discussion <xen-devel.lists.xensource.com>

On Mon, Jun 8, 2009 at 2:51 PM, Beng Heng, Ng<bengheng@xxxxxxxxxxxxxx> wrote:
> The patch was mostly originally from XCI, and subsequently the Xen 3.4
> testing branch.
>
> Note that this does not include HID passthrough. It only demonstrates
> VGA passthrough.
>
> Also, you need to specify the following in your DomU configuration.
> vga_passthrough=1
> intel=1

What does intel=1 do?

> dom0_input="0" (can ignore for now, since I did not include dom0 driver)
>
> I've only tried it for HVM guests. But it should work for PV too. I've
> got good results on Windows DomU. On Linux, there was an error that says
> the guest is trying to access unintialised BAR.
>
> - Beng Heng
>
> Andrew Lyon wrote:
>> On Mon, Jun 8, 2009 at 6:36 AM, Beng Heng, Ng <bengheng@xxxxxxxxxxxxxx> 
>> wrote:
>>> Certainly. I tried this on Xen 3.4.1 rc1 pre, changeset 19645. Most of
>>> these stuff are from Jean and his team. Hopefully more people can update
>>> their results.
>>>
>>> - Beng Heng
>>>
>>> Jun Koi wrote:
>>>> Hi Beng,
>>>>
>>>> Would you please send the patch you applied on top of Xen to the list?
>>>> I think many people are interested in that.
>>>>
>>>> Thanks,
>>>> Jun
>>>>
>>>>
>>>>
>>>
>>> diff -rupN --ignore-blank-lines-X diffignore 
>>> a/linux-2.6.18-xen.hg/drivers/xen/pciback/controller.c 
>>> b/linux-2.6.18-xen.hg/drivers/xen/pciback/controller.c
>>> --- a/linux-2.6.18-xen.hg/drivers/xen/pciback/controller.c      2009-06-07 
>>> 20:48:21.000000000 -0400
>>> +++ b/linux-2.6.18-xen.hg/drivers/xen/pciback/controller.c      2009-06-07 
>>> 19:04:11.000000000 -0400
>>> @@ -208,7 +208,7 @@ void pciback_release_pci_dev(struct pcib
>>>        }
>>>
>>>        spin_unlock_irqrestore(&dev_data->lock, flags);
>>> -       pcistub_put_pci_dev(found_dev);
>>> +       pcistub_put_pci_dev(found_dev, 0);
>>>  }
>>>
>>>  int pciback_init_devices(struct pciback_device *pdev)
>>> @@ -396,7 +396,7 @@ void pciback_release_devices(struct pcib
>>>                list_for_each_entry_safe(dev_entry, d,
>>>                                         &cntrl_entry->dev_list, list) {
>>>                        list_del(&dev_entry->list);
>>> -                       pcistub_put_pci_dev(dev_entry->dev);
>>> +                       pcistub_put_pci_dev(dev_entry->dev, 0);
>>>                        kfree(dev_entry);
>>>                }
>>>                list_del(&cntrl_entry->list);
>>> diff -rupN --ignore-blank-lines-X diffignore 
>>> a/linux-2.6.18-xen.hg/drivers/xen/pciback/passthrough.c 
>>> b/linux-2.6.18-xen.hg/drivers/xen/pciback/passthrough.c
>>> --- a/linux-2.6.18-xen.hg/drivers/xen/pciback/passthrough.c     2009-06-07 
>>> 20:48:21.000000000 -0400
>>> +++ b/linux-2.6.18-xen.hg/drivers/xen/pciback/passthrough.c     2009-06-07 
>>> 19:04:11.000000000 -0400
>>> @@ -88,7 +88,7 @@ void pciback_release_pci_dev(struct pcib
>>>        spin_unlock_irqrestore(&dev_data->lock, flags);
>>>
>>>        if (found_dev)
>>> -               pcistub_put_pci_dev(found_dev);
>>> +               pcistub_put_pci_dev(found_dev, 1);
>>>  }
>>>
>>>  int pciback_init_devices(struct pciback_device *pdev)
>>> @@ -157,7 +157,7 @@ void pciback_release_devices(struct pcib
>>>
>>>        list_for_each_entry_safe(dev_entry, t, &dev_data->dev_list, list) {
>>>                list_del(&dev_entry->list);
>>> -               pcistub_put_pci_dev(dev_entry->dev);
>>> +               pcistub_put_pci_dev(dev_entry->dev, 1);
>>>                kfree(dev_entry);
>>>        }
>>>
>>> diff -rupN --ignore-blank-lines-X diffignore 
>>> a/linux-2.6.18-xen.hg/drivers/xen/pciback/pciback.h 
>>> b/linux-2.6.18-xen.hg/drivers/xen/pciback/pciback.h
>>> --- a/linux-2.6.18-xen.hg/drivers/xen/pciback/pciback.h 2009-06-07 
>>> 20:48:21.000000000 -0400
>>> +++ b/linux-2.6.18-xen.hg/drivers/xen/pciback/pciback.h 2009-06-07 
>>> 19:04:11.000000000 -0400
>>> @@ -25,6 +25,14 @@ struct pci_dev_entry {
>>>  #define _PCIB_op_pending       (1)
>>>  #define PCIB_op_pending                (1<<(_PCIB_op_pending))
>>>
>>> +#define PCIBACK_TYPE_UNKNOWN       0
>>> +#define PCIBACK_TYPE_PCIe_ENDPOINT 1
>>> +#define PCIBACK_TYPE_PCIe_BRIDGE   2
>>> +#define PCIBACK_TYPE_PCI_BRIDGE    3
>>> +#define PCIBACK_TYPE_PCI           4
>>> +
>>> +#define DEV_CLASS_PCI_PCI_BRIDGE 0x0604
>>> +
>>>  struct pciback_device {
>>>        void *pci_dev_data;
>>>        spinlock_t dev_lock;
>>> @@ -48,6 +56,13 @@ struct pciback_dev_data {
>>>        struct list_head config_fields;
>>>        int permissive;
>>>        int warned_on_write;
>>> +       u32 dev_type;
>>> +       int no_flr;
>>> +       int exp_flr_offset;
>>> +       int af_flr_offset;
>>> +       int use_sbr;
>>> +       int use_d3r;
>>> +       u8 *cfg_space; /* saved config space for device */
>>>  };
>>>
>>>  /* Get/Put PCI Devices that are hidden from the PCI Backend Domain */
>>> @@ -56,11 +71,25 @@ struct pci_dev *pcistub_get_pci_dev_by_s
>>>                                            int slot, int func);
>>>  struct pci_dev *pcistub_get_pci_dev(struct pciback_device *pdev,
>>>                                    struct pci_dev *dev);
>>> -void pcistub_put_pci_dev(struct pci_dev *dev);
>>> +void pcistub_put_pci_dev(struct pci_dev *dev, int do_flr);
>>> +
>>> +/* Reference/unreference PCI Devices and stubs without changing the state 
>>> */
>>> +struct pci_dev *pcistub_ref_pci_dev(struct pci_dev *dev);
>>> +void pcistub_unref_pci_dev(struct pci_dev *dev);
>>> +
>>> +/* Store/reload config space for devices */
>>> +void pciback_store_config_space(struct pci_dev *dev);
>>> +void pciback_reload_config_space(struct pci_dev *dev);
>>>
>>>  /* Ensure a device is turned off or reset */
>>>  void pciback_reset_device(struct pci_dev *pdev);
>>>
>>> +/* Do a function level reset (or approximage functionality) for device */
>>> +void pciback_flr_device(struct pci_dev *dev);
>>> +
>>> +/* Helper to classify the device type */
>>> +void pciback_classify_device(struct pci_dev *dev);
>>> +
>>>  /* Access a virtual configuration space for a PCI device */
>>>  int pciback_config_init(void);
>>>  int pciback_config_init_dev(struct pci_dev *dev);
>>> @@ -102,6 +131,10 @@ void pciback_release_devices(struct pcib
>>>  irqreturn_t pciback_handle_event(int irq, void *dev_id, struct pt_regs 
>>> *regs);
>>>  void pciback_do_op(void *data);
>>>
>>> +/* Parse and load device specific module parameters */
>>> +int pciback_parse_device_params(const char *device_args, int type,
>>> +                                       int (*add_func) (int domain, int 
>>> bus, int slot, int func, int type));
>>> +
>>>  int pciback_xenbus_register(void);
>>>  void pciback_xenbus_unregister(void);
>>>
>>> diff -rupN --ignore-blank-lines-X diffignore 
>>> a/linux-2.6.18-xen.hg/drivers/xen/pciback/pciback_ops.c 
>>> b/linux-2.6.18-xen.hg/drivers/xen/pciback/pciback_ops.c
>>> --- a/linux-2.6.18-xen.hg/drivers/xen/pciback/pciback_ops.c     2009-06-07 
>>> 20:48:21.000000000 -0400
>>> +++ b/linux-2.6.18-xen.hg/drivers/xen/pciback/pciback_ops.c     2009-06-07 
>>> 19:04:11.000000000 -0400
>>> @@ -5,20 +5,189 @@
>>>  */
>>>  #include <linux/module.h>
>>>  #include <linux/wait.h>
>>> +#include <linux/delay.h> /* For mdelay function */
>>>  #include <asm/bitops.h>
>>>  #include <xen/evtchn.h>
>>>  #include "pciback.h"
>>>
>>> +#define PCIBACK_VENDOR_INTEL     0x8086
>>> +#define PCIBACK_CLASS_ID_USB     0x0c03
>>> +#define PCIBACK_CLASS_ID_VGA     0x0300
>>> +#define PCIBACK_USB_FLRCTRL      0x4
>>> +
>>> +#define PCIBACK_IGFX_CAP09_OFFSET    0xa4
>>> +#define PCIBACK_IGFX_CAP13_OFFSET    0xa4
>>> +
>>> +#define PCIBACK_IGFX_MEDIARST        0x0d
>>> +#define PCIBACK_IGFX_MEDIARST_OFFSET 0xc0
>>> +
>>>  int verbose_request = 0;
>>>  module_param(verbose_request, int, 0644);
>>>
>>> +struct pcistub_sbr_entry {
>>> +       struct list_head dev_list;
>>> +       struct pci_dev *dev;
>>> +};
>>> +
>>> +struct pcistub_sbr_list {
>>> +       struct list_head dev_list;
>>> +       struct pci_dev *bridge;
>>> +       struct pci_dev *dev;
>>> +       int find_all;
>>> +       int err;
>>> +};
>>> +
>>> +/* Used to store the config state so it can be restored after
>>> + * resets.
>>> + */
>>> +void pciback_store_config_space(struct pci_dev *dev)
>>> +{
>>> +       struct pciback_dev_data *dev_data = pci_get_drvdata(dev);
>>> +       u32 *ptr = (u32*)dev_data->cfg_space;
>>> +       int i, count = dev->cfg_size/sizeof(u32);
>>> +
>>> +       for (i = 0; i < count; i += sizeof(u32), ptr++)
>>> +               pci_read_config_dword(dev, i, ptr);
>>> +}
>>> +
>>> +/* Used to reload the config state after resets.
>>> + */
>>> +void pciback_reload_config_space(struct pci_dev *dev)
>>> +{
>>> +       struct pciback_dev_data *dev_data = pci_get_drvdata(dev);
>>> +       u32 *ptr = (u32*)dev_data->cfg_space;
>>> +       int i, val, count = dev->cfg_size/sizeof(u32);
>>> +
>>> +       for (i = 0; i < count; i += sizeof(u32), ptr++) {
>>> +               pci_read_config_dword(dev, i, &val);
>>> +               if (val != *ptr)
>>> +                       pci_write_config_dword(dev, i, *ptr);
>>> +       }
>>> +}
>>> +
>>> +static void pciback_walk_bus_cb(struct pci_dev *dev, void *userdata)
>>> +{
>>> +       struct pcistub_sbr_list *list = (struct pcistub_sbr_list*)userdata;
>>> +       struct pcistub_sbr_entry *entry;
>>> +       struct pci_dev *dev_tmp;
>>> +
>>> +       if (list->err != 0)
>>> +               return;
>>> +
>>> +       /* For PCIe endpoints we are only looking for co-assigned functions 
>>> */
>>> +       if (!list->find_all &&
>>> +               (dev->bus->number != list->dev->bus->number ||
>>> +                PCI_SLOT(dev->devfn) != PCI_SLOT(list->dev->devfn)))
>>> +               return;
>>> +
>>> +       dev_tmp = pcistub_ref_pci_dev(dev);
>>> +       if (dev_tmp == NULL) {
>>> +               /* not controlled by pciback, fail */
>>> +               list->err = ENXIO;
>>> +               return;
>>> +       }
>>> +
>>> +       entry = kzalloc(sizeof(*entry), GFP_ATOMIC);
>>> +       if (entry == NULL) {
>>> +               pcistub_unref_pci_dev(dev_tmp);
>>> +               list->err = ENOMEM;
>>> +               return;
>>> +       }
>>> +
>>> +       entry->dev = dev_tmp;
>>> +       list_add_tail(&entry->dev_list, &list->dev_list);
>>> +}
>>> +
>>> +static void pciback_cleanup_sbr_list(struct pcistub_sbr_list *list)
>>> +{
>>> +       struct pcistub_sbr_entry *entry;
>>> +
>>> +       list_for_each_entry(entry, &list->dev_list, dev_list) {
>>> +               pcistub_unref_pci_dev(entry->dev);
>>> +               kfree(entry);
>>> +       }
>>> +}
>>> +
>>> +/* Routine to find all devices and bridges that need to be reset
>>> + * during a secondary bus reset. For PCIe this is simply all the
>>> + * functions on the particular device. For PCI this is all devices
>>> + * and bridges below the topmost PCI/PCI-X bridge. Note for PCI,
>>> + * there is at least one something->PCI/PCI-X bridge to find since
>>> + * the device is not on the host bus 0 and is on a PCI bus.
>>> + */
>>> +static int pciback_get_sbr_list(struct pci_dev *dev,
>>> +       struct pcistub_sbr_list *list, int pcie_endpoint)
>>> +{
>>> +       struct pci_dev *bridge = dev->bus->self;
>>> +       struct pci_dev *last = NULL;
>>> +       int exp_pos;
>>> +       u16 exp_caps = 0;
>>> +
>>> +       list->err = 0;
>>> +       list->dev = dev;
>>> +       INIT_LIST_HEAD(&list->dev_list);
>>> +
>>> +       if (!pcie_endpoint) {
>>> +               while (bridge) {
>>> +                       /* Looking for the uppermost PCI/PCI-X bridge. If 
>>> it is not PCIe then
>>> +                        * this is a PCI/PCI-X bridge. If it is PCIe then 
>>> except the PCIe to
>>> +                        * PCI/PCI-X type 7, the rest of the bridge types 
>>> are PCIe so the last
>>> +                        * bridge encountered was the topmost PCI/PCI-X 
>>> bridge.
>>> +                        */
>>> +                       exp_pos = pci_find_capability(bridge, 
>>> PCI_CAP_ID_EXP);
>>> +                       if (exp_pos != 0) {
>>> +                               pci_read_config_word(bridge, exp_pos + 
>>> PCI_EXP_FLAGS, &exp_caps);
>>> +                               if (((exp_caps & PCI_EXP_FLAGS_TYPE) >> 4) 
>>> != PCI_EXP_TYPE_PCI_BRIDGE)
>>> +                                       break; /* don't want it in the list 
>>> if it is a PCIe bridge */
>>> +                       }
>>> +                       last = bridge;
>>> +                       bridge = last->bus->self;
>>> +               }
>>> +               list->bridge = last;
>>> +               list->find_all = 1; /* find all devices/bridges below the 
>>> topmost */
>>> +       }
>>> +       else {
>>> +               if (bridge) {
>>> +                       /* For PCIe, SBR logic is limited to PCIe endpoints 
>>> behind a root/switch
>>> +                        * port.
>>> +                        */
>>> +                       exp_pos = pci_find_capability(bridge, 
>>> PCI_CAP_ID_EXP);
>>> +                       if (likely(exp_pos != 0)) {
>>> +                               pci_read_config_word(bridge, exp_pos + 
>>> PCI_EXP_FLAGS, &exp_caps);
>>> +                               exp_caps = ((exp_caps & PCI_EXP_FLAGS_TYPE) 
>>> >> 4);
>>> +                               if (exp_caps == PCI_EXP_TYPE_ROOT_PORT ||
>>> +                                       exp_caps == PCI_EXP_TYPE_UPSTREAM ||
>>> +                                       exp_caps == PCI_EXP_TYPE_DOWNSTREAM)
>>> +                                       last = bridge;
>>> +                       }
>>> +               }
>>> +               list->bridge = last;
>>> +               list->find_all = 0; /* find just functions on this slot */
>>> +       }
>>> +
>>> +       /* Sanity check, there may not be any appropriate bridge to reset */
>>> +       if (!list->bridge) {
>>> +               dev_dbg(&dev->dev, "No appropriate bridge to reset\n");
>>> +               return ENXIO;
>>> +       }
>>> +
>>> +       pci_walk_bus(list->bridge->subordinate, pciback_walk_bus_cb, list);
>>> +
>>> +       if (list->err) {
>>> +               pciback_cleanup_sbr_list(list);
>>> +               return list->err;
>>> +       }
>>> +
>>> +       return 0;
>>> +}
>>> +
>>>  /* Ensure a device is "turned off" and ready to be exported.
>>>  * (Also see pciback_config_reset to ensure virtual configuration space is
>>>  * ready to be re-exported)
>>>  */
>>>  void pciback_reset_device(struct pci_dev *dev)
>>>  {
>>> -       u16 cmd;
>>> +       u16 cmd = 0;
>>>
>>>        /* Disable devices (but not bridges) */
>>>        if (dev->hdr_type == PCI_HEADER_TYPE_NORMAL) {
>>> @@ -38,6 +207,425 @@ void pciback_reset_device(struct pci_dev
>>>                }
>>>        }
>>>  }
>>> +
>>> +/* Do a PCIe type function level reset for a single function on this
>>> + * device.
>>> + */
>>> +static void pciback_do_pcie_flr(struct pci_dev *dev, int exp_pos)
>>> +{
>>> +       u16 status = 0;
>>> +
>>> +       dev_dbg(&dev->dev, "doing PCIe FLR\n");
>>> +
>>> +       pci_block_user_cfg_access(dev);
>>> +
>>> +       /* Wait for Transaction Pending bit clean */
>>> +       msleep(100);
>>> +       pci_read_config_word(dev, exp_pos + PCI_EXP_DEVSTA, &status);
>>> +       if (status & PCI_EXP_DEVSTA_TRPND) {
>>> +               dev_dbg(&dev->dev, "Busy after 100ms while trying to reset; 
>>> sleeping for 1 second\n");
>>> +               ssleep(1);
>>> +               pci_read_config_word(dev, exp_pos + PCI_EXP_DEVSTA, 
>>> &status);
>>> +               if (status & PCI_EXP_DEVSTA_TRPND)
>>> +                       dev_warn(&dev->dev, "Still busy after 1s; 
>>> proceeding with reset anyway\n");
>>> +       }
>>> +
>>> +       pci_write_config_word(dev, exp_pos + PCI_EXP_DEVCTL, 
>>> PCI_EXP_DEVCTL_BCR_FLR);
>>> +       mdelay(200);
>>> +
>>> +       pciback_reload_config_space(dev);
>>> +
>>> +       pci_unblock_user_cfg_access(dev);
>>> +}
>>> +
>>> +/* Do a PCI type function level reset for a single function on this
>>> + * device. This uses the Advanced Features Capability extensions to
>>> + * the PCI spec.
>>> + */
>>> +static void pciback_do_pci_flr(struct pci_dev *dev, int af_pos, int 
>>> clear_cmd)
>>> +{
>>> +       u8 status = 0;
>>> +
>>> +       dev_dbg(&dev->dev, "doing PCI FLR\n");
>>> +
>>> +       pci_block_user_cfg_access(dev);
>>> +
>>> +       /* Clear the command register to prevent new transactions */
>>> +       if (clear_cmd)
>>> +               pci_write_config_word(dev, PCI_COMMAND, 0);
>>> +
>>> +       /* Wait for Transaction Pending bit clean */
>>> +       msleep(100);
>>> +       pci_read_config_byte(dev, af_pos + PCI_AF_STA, &status);
>>> +       if (status & PCI_AF_STA_TP) {
>>> +               dev_dbg(&dev->dev, "Busy after 100ms while trying to reset; 
>>> sleeping for 1 second\n");
>>> +               ssleep(1);
>>> +               pci_read_config_byte(dev, af_pos + PCI_AF_STA, &status);
>>> +               if (status & PCI_AF_STA_TP)
>>> +                       dev_warn(&dev->dev, "Still busy after 1s; 
>>> proceeding with reset anyway\n");
>>> +       }
>>> +
>>> +       pci_write_config_byte(dev, af_pos + PCI_AF_CTRL, PCI_AF_CTRL_FLR);
>>> +       mdelay(200);
>>> +
>>> +       pciback_reload_config_space(dev);
>>> +
>>> +       pci_unblock_user_cfg_access(dev);
>>> +}
>>> +
>>> +/* Vendor specific resets. These can be set in the vendor specific
>>> + * capabilities structures. Currently only the Intel USB and iGFX
>>> + * reset is supported.
>>> + */
>>> +static int pciback_do_vendor_specific_reset(struct pci_dev *dev)
>>> +{
>>> +       struct pci_dev *gmch;
>>> +       int vendor_pos, i;
>>> +       u32 reg32 = 0;
>>> +       u16 device_id, cmd;
>>> +       u8 reg8 = 0;
>>> +
>>> +       dev_dbg(&dev->dev, "doing vendor specific resets\n");
>>> +
>>> +       if (dev->vendor != PCIBACK_VENDOR_INTEL)
>>> +               return -ENXIO;
>>> +
>>> +       if ((dev->class >> 8) == PCIBACK_CLASS_ID_VGA) {
>>> +               if (dev->bus->number != 0 || dev->devfn != PCI_DEVFN(2,0))
>>> +                       return -ENXIO;
>>> +
>>> +               /* Locate the GMCH (north bridge) and test for specific 
>>> Intel devices */
>>> +               gmch = pci_get_bus_and_slot(0, PCI_DEVFN(0,0));
>>> +               if (!gmch)
>>> +                       return -ENXIO;
>>> +
>>> +               device_id = gmch->device;
>>> +               pci_dev_put(gmch);
>>> +
>>> +               if (device_id != PCI_DEVICE_ID_INTEL_GMCHGM45)
>>> +                       return -ENXIO;
>>> +
>>> +               /* Correct device and platform, assume vendor specific 
>>> offset */
>>> +               pci_read_config_dword(dev, PCIBACK_IGFX_CAP09_OFFSET, 
>>> &reg32);
>>> +               if ((reg32 & 0x000000FF) != PCI_CAP_ID_VNDR ||
>>> +                       ((reg32 >> 16) & 0x000000FF) != 0x06 ||
>>> +                       ((reg32 >> 24) & 0x000000F0) != 0x20)
>>> +                       return -ENXIO;
>>> +
>>> +               vendor_pos = PCIBACK_IGFX_CAP09_OFFSET;
>>> +       } else if ((dev->class >> 8) == PCIBACK_CLASS_ID_USB) {
>>> +               vendor_pos = pci_find_capability(dev, PCI_CAP_ID_VNDR);
>>> +               if (vendor_pos == 0)
>>> +                       return -ENXIO;
>>> +       }
>>> +       else
>>> +               return -ENXIO;
>>> +
>>> +       if ((dev->class >> 8) == PCIBACK_CLASS_ID_VGA) {
>>> +               pci_write_config_byte(dev, PCIBACK_IGFX_MEDIARST_OFFSET, 
>>> PCIBACK_IGFX_MEDIARST);
>>> +               for (i = 0; i <= 10; i++) {
>>> +                       msleep(100);
>>> +                       pci_read_config_byte(dev, 
>>> PCIBACK_IGFX_MEDIARST_OFFSET, &reg8);
>>> +                       if ((reg8 & 0x01) == 0)
>>> +                               break;
>>> +                       if (i == 10) {
>>> +                               dev_warn(&dev->dev, "media not reset after 
>>> 1s; skipping FLR\n");
>>> +                               goto out;
>>> +                       }
>>> +               }
>>> +
>>> +               /* This specific reset will hang if the command register 
>>> does not have
>>> +                * memory space access enabled */
>>> +               pci_read_config_word(dev, PCI_COMMAND, &cmd);
>>> +               pci_write_config_word(dev, PCI_COMMAND, (cmd | 
>>> PCI_COMMAND_MEMORY));
>>> +               /* The rest is the same as a PCI AF FLR - use the same 
>>> routine */
>>> +               pciback_do_pci_flr(dev, vendor_pos, 0);
>>> +               pci_write_config_word(dev, PCI_COMMAND, cmd);
>>> +       } else {
>>> +               pci_block_user_cfg_access(dev);
>>> +
>>> +               pci_write_config_byte(dev, vendor_pos + 
>>> PCIBACK_USB_FLRCTRL, 1);
>>> +               mdelay(200);
>>> +
>>> +               pciback_reload_config_space(dev);
>>> +
>>> +               pci_unblock_user_cfg_access(dev);
>>> +       }
>>> +
>>> +out:
>>> +       return 0;
>>> +}
>>> +
>>> +/* Use a D0-D3-D0 device state transition to reset the device. This
>>> + * is a good enough reset for some devices (like NICs).
>>> + */
>>> +static int pciback_do_dstate_transition_reset(struct pci_dev *dev)
>>> +{
>>> +       int pm_pos;
>>> +       u32 pm_ctl = 0;
>>> +
>>> +       pm_pos = pci_find_capability(dev, PCI_CAP_ID_PM);
>>> +       if (pm_pos == 0)
>>> +               return -ENXIO;
>>> +
>>> +       dev_dbg(&dev->dev, "doing Dstate transition reset\n");
>>> +
>>> +       /* No_Soft_Reset - When set 1, this bit indicates that devices
>>> +        * transitioning from D3hot to D0 because of PowerState commands
>>> +        * do not perform an internal reset.
>>> +        */
>>> +       pci_read_config_dword(dev, pm_pos + PCI_PM_CTRL, &pm_ctl);
>>> +       if (pm_ctl & PCI_PM_CTRL_NO_SOFT_RESET)
>>> +               return -ENXIO;
>>> +
>>> +       pci_block_user_cfg_access(dev);
>>> +
>>> +       pm_ctl &= ~PCI_PM_CTRL_STATE_MASK;
>>> +       pm_ctl |= PCI_PM_CTRL_D3HOT;
>>> +       pci_write_config_word(dev, pm_pos + PCI_PM_CTRL, pm_ctl);
>>> +       mdelay(10);
>>> +
>>> +       pm_ctl &= ~PCI_PM_CTRL_STATE_MASK;
>>> +       pm_ctl |= PCI_PM_CTRL_D0;
>>> +       pci_write_config_word(dev, pm_pos + PCI_PM_CTRL, pm_ctl);
>>> +       mdelay(10);
>>> +
>>> +       pciback_reload_config_space(dev);
>>> +
>>> +       pci_unblock_user_cfg_access(dev);
>>> +
>>> +       return 0;
>>> +}
>>> +
>>> +/* Do a secondary bus reset on a bridge. This is only done if all
>>> + * co-assignment rules are satisfied and if it was explicitly
>>> + * requested via pciback parameters.
>>> + */
>>> +static int pciback_do_secondary_bus_reset(struct pci_dev *dev, u32 
>>> dev_type)
>>> +{
>>> +       struct pcistub_sbr_list sbr_list;
>>> +       struct pcistub_sbr_entry *entry;
>>> +       u16 pci_bctl = 0;
>>> +       int err = 0;
>>> +
>>> +       /* Call helper to get the device list needed for the device type. */
>>> +       err = pciback_get_sbr_list(dev, &sbr_list,
>>> +                       (dev_type == PCIBACK_TYPE_PCIe_ENDPOINT ? 1 : 0));
>>> +       if (err) {
>>> +               dev_warn(&dev->dev,
>>> +                       "secondary bus reset failed for device - all 
>>> functions need to be co-assigned - err: %d\n", err);
>>> +               return err;
>>> +       }
>>> +
>>> +       pci_block_user_cfg_access(dev);
>>> +
>>> +       /* Reset the secondary bus and restore the PCI space for all the 
>>> devfn found above.
>>> +        */
>>> +       pci_read_config_word(sbr_list.bridge, PCI_BRIDGE_CONTROL, 
>>> &pci_bctl);
>>> +       pci_write_config_word(sbr_list.bridge, PCI_BRIDGE_CONTROL, pci_bctl 
>>> | PCI_BRIDGE_CTL_BUS_RESET);
>>> +       msleep(200);
>>> +       pci_write_config_word(sbr_list.bridge, PCI_BRIDGE_CONTROL, 
>>> pci_bctl);
>>> +       msleep(200);
>>> +
>>> +       list_for_each_entry(entry, &sbr_list.dev_list, dev_list) {
>>> +               pciback_reload_config_space(entry->dev);
>>> +       }
>>> +
>>> +       pci_unblock_user_cfg_access(dev);
>>> +
>>> +       pciback_cleanup_sbr_list(&sbr_list);
>>> +
>>> +       return 0;
>>> +}
>>> +
>>> +/* This function is used to do a function level reset on a singe
>>> + * device/function. FLRs must be done on devices before they are
>>> + * unassigned from one domain and passed through to another. The
>>> + * preferred method is to do an actual FLR on the device but the
>>> + * functionality may not be present or exposed. In the later case
>>> + * we attempt to locate the capability even though it is not
>>> + * chained into the capabilities list.
>>> + *
>>> + * In some cases, there is no way to perform the actual FLR so we
>>> + * fall back to some alternate methods (which are not as effective
>>> + * or useful).
>>> + */
>>> +void pciback_flr_device(struct pci_dev *dev)
>>> +{
>>> +       struct pciback_dev_data *dev_data = pci_get_drvdata(dev);
>>> +       int err = 0;
>>> +
>>> +       if (dev_data->no_flr) {
>>> +               dev_dbg(&dev->dev, "FLR disabled for device\n");
>>> +               return;
>>> +       }
>>> +       dev_dbg(&dev->dev, "FLR invoked for device\n");
>>> +
>>> +       do {
>>> +               /* First, always try to do an FLR */
>>> +               if (dev_data->dev_type == PCIBACK_TYPE_PCIe_ENDPOINT &&
>>> +                       dev_data->exp_flr_offset != 0) {
>>> +                       pciback_do_pcie_flr(dev, dev_data->exp_flr_offset);
>>> +                       break;
>>> +               }
>>> +               if (dev_data->dev_type == PCIBACK_TYPE_PCI &&
>>> +                       dev_data->af_flr_offset != 0) {
>>> +                       pciback_do_pci_flr(dev, dev_data->af_flr_offset, 1);
>>> +                       break;
>>> +               }
>>> +
>>> +               /* Next for integrated devices on the host bus 0, try some 
>>> other methods */
>>> +               if (dev->bus->number == 0) {
>>> +                       err = pciback_do_vendor_specific_reset(dev);
>>> +                       if (err && dev_data->use_d3r)
>>> +                               err = 
>>> pciback_do_dstate_transition_reset(dev);
>>> +                       if (err)
>>> +                               dev_warn(&dev->dev, "FLR functionality not 
>>> supported; "
>>> +                                               "attempts to use vendor FLR 
>>> or D-states unsuccessful\n");
>>> +                       break;
>>> +               }
>>> +
>>> +               /* Else attempt a secondary bus reset if all conditions are 
>>> met */
>>> +               if (dev_data->use_sbr) {
>>> +                       err = pciback_do_secondary_bus_reset(dev, 
>>> dev_data->dev_type);
>>> +                       if (err)
>>> +                               dev_warn(&dev->dev, "FLR functionality not 
>>> supported; "
>>> +                                               "attempts to use secondary 
>>> bus reset unsuccessful;\n");
>>> +                       break;
>>> +               }
>>> +
>>> +               err = -ENODEV;
>>> +       } while (0);
>>> +
>>> +       if (err)
>>> +               dev_warn(&dev->dev, "FLR not performed for device\n");
>>> +}
>>> +
>>> +/* Helper used to location the FLR capabilities for a PCIe device.
>>> + * When the capability cannot be found in the chain but is present,
>>> + * special logic is used to attempt to locate functionality.
>>> + *
>>> + * returns: the offset to the capability, zero if not found.
>>> + */
>>> +static int pciback_find_pcie_flr_caps(struct pci_dev *dev)
>>> +{
>>> +       int exp_pos;
>>> +       u32 cap = 0;
>>> +
>>> +       /* First look for the PCIe FLR capabilities using the capabilities 
>>> list */
>>> +       exp_pos = pci_find_capability(dev, PCI_CAP_ID_EXP);
>>> +       if (exp_pos) {
>>> +               pci_read_config_dword(dev, exp_pos + PCI_EXP_DEVCAP, &cap);
>>> +               if (cap & PCI_EXP_DEVCAP_FLR) {
>>> +                       return exp_pos;
>>> +               }
>>> +       }
>>> +
>>> +       return 0;
>>> +}
>>> +
>>> +/* Helper used to location the AF FLR capabilities for a PCI device.
>>> + * When the capability cannot be found in the chain but is present,
>>> + * special logic is used to attempt to locate functionality.
>>> + *
>>> + * returns: the offset to the capability, zero if not found.
>>> + */
>>> +static int pciback_find_pci_flr_caps(struct pci_dev *dev)
>>> +{
>>> +       struct pci_dev *gmch;
>>> +       int af_pos;
>>> +       u16 device_id;
>>> +       u8 cap = 0, reg8 = 0;
>>> +
>>> +       /* First look for the PCI AF capabilities for FLR using the 
>>> capabilities list. This
>>> +        * is only used on the devices on the root/host bus (integrated 
>>> devices).
>>> +        */
>>> +       if (dev->bus->number != 0)
>>> +               return 0;
>>> +
>>> +       af_pos = pci_find_capability(dev, PCI_CAP_ID_AF);
>>> +       if (af_pos) {
>>> +               pci_read_config_byte(dev, af_pos + PCI_AF_DEVCAP, &cap);
>>> +               if (cap & PCI_AF_CAP_FLR) {
>>> +                       return af_pos;
>>> +               }
>>> +       }
>>> +
>>> +       /* Next look for the unchained AF capabilities for FLR using 
>>> specific
>>> +        * logic. Currently only the graphics device on the Intel Q45 etc
>>> +        * systems has special logic for locating the hidden FLR caps.
>>> +     */
>>> +       do {
>>> +               if (dev->bus->number != 0 || dev->devfn != PCI_DEVFN(2,0) ||
>>> +                       dev->vendor != PCIBACK_VENDOR_INTEL || (dev->class 
>>> >> 8) != PCIBACK_CLASS_ID_VGA)
>>> +                       break;
>>> +
>>> +               /* Locate the GMCH (north bridge) and test for specific 
>>> Intel devices */
>>> +               gmch = pci_get_bus_and_slot(0, PCI_DEVFN(0,0));
>>> +               if (!gmch)
>>> +                       break;
>>> +
>>> +               device_id = gmch->device;
>>> +               pci_dev_put(gmch);
>>> +
>>> +               if (device_id != PCI_DEVICE_ID_INTEL_GMCHQ45 &&
>>> +                       device_id != PCI_DEVICE_ID_INTEL_GMCHG45 &&
>>> +                       device_id != PCI_DEVICE_ID_INTEL_GMCHG41)
>>> +                       break;
>>> +
>>> +               /* Correct device and platform, assume AF offset */
>>> +               af_pos = PCIBACK_IGFX_CAP13_OFFSET;
>>> +               pci_read_config_byte(dev, af_pos + PCI_AF_LENFLD, &reg8);
>>> +               if (reg8 == PCI_AF_LENGTH) {
>>> +                       pci_read_config_byte(dev, af_pos + PCI_AF_DEVCAP, 
>>> &cap);
>>> +                       if (cap & PCI_AF_CAP_FLR) {
>>> +                               return af_pos;
>>> +                       }
>>> +               }
>>> +       } while (0);
>>> +
>>> +       /* Else not found */
>>> +       return 0;
>>> +}
>>> +
>>> +/* Classify the device, specifically determine if it is PCIe/PCI
>>> + * and whether it is a PCIe endpoint, bridge, or other PCI device.
>>> + */
>>> +void pciback_classify_device(struct pci_dev *dev)
>>> +{
>>> +       struct pciback_dev_data *dev_data;
>>> +       int exp_pos;
>>> +       u16 exp_caps = 0;
>>> +
>>> +       dev_data = pci_get_drvdata(dev);
>>> +       dev_data->dev_type = PCIBACK_TYPE_UNKNOWN;
>>> +
>>> +       exp_pos = pci_find_capability(dev, PCI_CAP_ID_EXP);
>>> +
>>> +       if ((dev->class >> 8) != DEV_CLASS_PCI_PCI_BRIDGE) {
>>> +               if (exp_pos != 0) {
>>> +                       dev_data->dev_type = PCIBACK_TYPE_PCIe_ENDPOINT;
>>> +                       dev_data->exp_flr_offset = 
>>> pciback_find_pcie_flr_caps(dev);
>>> +               } else {
>>> +                       dev_data->dev_type = PCIBACK_TYPE_PCI;
>>> +                       dev_data->af_flr_offset = 
>>> pciback_find_pci_flr_caps(dev);
>>> +               }
>>> +               goto classify_done;
>>> +       }
>>> +
>>> +       if (exp_pos == 0) {
>>> +               dev_data->dev_type = PCIBACK_TYPE_PCI_BRIDGE;
>>> +               goto classify_done;
>>> +       }
>>> +
>>> +       pci_read_config_word(dev, exp_pos + PCI_EXP_FLAGS, &exp_caps);
>>> +       dev_data->dev_type = (((exp_caps & PCI_EXP_FLAGS_TYPE) >> 4) == 
>>> PCI_EXP_TYPE_PCI_BRIDGE) ? PCIBACK_TYPE_PCI_BRIDGE : 
>>> PCIBACK_TYPE_PCIe_BRIDGE;
>>> +
>>> +classify_done:
>>> +
>>> +       return;
>>> +}
>>> +
>>>  extern wait_queue_head_t aer_wait_queue;
>>>  extern struct workqueue_struct *pciback_wq;
>>>  /*
>>> @@ -132,3 +720,51 @@ irqreturn_t pciback_handle_event(int irq
>>>
>>>        return IRQ_HANDLED;
>>>  }
>>> +
>>> +/* Helper routine used to parse command line parameters passed to the
>>> + * pciback module from the boot loader. These params all have the form
>>> + * of a list of one or more devices, e.g.:
>>> + * (XXXX:XX:XX.X)(XXXX:XX:XX.X)
>>> + * Which is: (domain/segment:bus:dev.func)
>>> + */
>>> +int pciback_parse_device_params(const char *device_args, int type,
>>> +                       int (*add_func) (int domain, int bus, int slot, int 
>>> func, int type))
>>> +{
>>> +       int pos = 0;
>>> +       int err = 0;
>>> +       int domain, bus, slot, func;
>>> +       int parsed;
>>> +
>>> +       if (device_args && *device_args) {
>>> +               do {
>>> +                       parsed = 0;
>>> +
>>> +                       err = sscanf(device_args + pos,
>>> +                                    " (%x:%x:%x.%x) %n",
>>> +                                    &domain, &bus, &slot, &func, &parsed);
>>> +                       if (err != 4) {
>>> +                               domain = 0;
>>> +                               err = sscanf(device_args + pos,
>>> +                                            " (%x:%x.%x) %n",
>>> +                                            &bus, &slot, &func, &parsed);
>>> +                               if (err != 3)
>>> +                                       goto parse_error;
>>> +                       }
>>> +
>>> +                       err = add_func(domain, bus, slot, func, type);
>>> +                       if (err)
>>> +                               goto out;
>>> +
>>> +                       /* if parsed<=0, we've reached the end of the 
>>> string */
>>> +                       pos += parsed;
>>> +               } while (parsed > 0 && device_args[pos]);
>>> +       }
>>> +
>>> +out:
>>> +       return err;
>>> +
>>> +parse_error:
>>> +       printk(KERN_ERR "pciback: Error parsing device parameters \"%s\" at 
>>> \"%s\"\n",
>>> +              device_args, device_args + pos);
>>> +       return -EINVAL;
>>> +}
>>> diff -rupN --ignore-blank-lines-X diffignore 
>>> a/linux-2.6.18-xen.hg/drivers/xen/pciback/pci_stub.c 
>>> b/linux-2.6.18-xen.hg/drivers/xen/pciback/pci_stub.c
>>> --- a/linux-2.6.18-xen.hg/drivers/xen/pciback/pci_stub.c        2009-06-07 
>>> 20:48:21.000000000 -0400
>>> +++ b/linux-2.6.18-xen.hg/drivers/xen/pciback/pci_stub.c        2009-06-07 
>>> 19:04:11.000000000 -0400
>>> @@ -24,10 +24,28 @@ wait_queue_head_t aer_wait_queue;
>>>  * We want to avoid in middle of AER ops, pciback devices is being removed
>>>  */
>>>  static DECLARE_RWSEM(pcistub_sem);
>>> -module_param_named(hide, pci_devs_to_hide, charp, 0444);
>>> +module_param_named(hide, pci_devs_to_hide, charp, S_IRUGO);
>>> +
>>> +static char *pci_devs_use_sbr = NULL;
>>> +module_param_named(sbr, pci_devs_use_sbr, charp, S_IRUGO);
>>> +
>>> +static char *pci_devs_use_d3r = NULL;
>>> +module_param_named(d3r, pci_devs_use_d3r, charp, S_IRUGO);
>>> +
>>> +static char *pci_devs_no_flr = NULL;
>>> +module_param_named(noflr, pci_devs_no_flr, charp, S_IRUGO);
>>> +
>>> +/* Device id list holding different device type listings
>>> + * for hiding devices and reset logic.
>>> + */
>>> +#define PCIBACK_ID_TYPE_HIDE  1
>>> +#define PCIBACK_ID_TYPE_SBR   2
>>> +#define PCIBACK_ID_TYPE_D3R   3
>>> +#define PCIBACK_ID_TYPE_NOFLR 4
>>>
>>>  struct pcistub_device_id {
>>>        struct list_head slot_list;
>>> +       int type;
>>>        int domain;
>>>        unsigned char bus;
>>>        unsigned int devfn;
>>> @@ -56,6 +74,8 @@ static LIST_HEAD(pcistub_devices);
>>>  static int initialize_devices = 0;
>>>  static LIST_HEAD(seized_devices);
>>>
>>> +static int disable_all_flr = 0;
>>> +
>>>  static struct pcistub_device *pcistub_device_alloc(struct pci_dev *dev)
>>>  {
>>>        struct pcistub_device *psdev;
>>> @@ -78,6 +98,23 @@ static struct pcistub_device *pcistub_de
>>>        return psdev;
>>>  }
>>>
>>> +static struct pciback_dev_data *pcistub_dev_data_alloc(struct pci_dev *dev)
>>> +{
>>> +       struct pciback_dev_data *dev_data;
>>> +
>>> +       dev_dbg(&dev->dev, "pcistub_dev_data_alloc\n");
>>> +
>>> +       dev_data = kzalloc(sizeof(*dev_data) + dev->cfg_size, GFP_ATOMIC);
>>> +       if (!dev_data)
>>> +               return NULL;
>>> +
>>> +       pci_set_drvdata(dev, dev_data);
>>> +
>>> +       dev_data->cfg_space = (u8*)(dev_data) + sizeof(*dev_data);
>>> +
>>> +       return dev_data;
>>> +}
>>> +
>>>  /* Don't call this directly as it's called by pcistub_device_put */
>>>  static void pcistub_device_release(struct kref *kref)
>>>  {
>>> @@ -200,7 +237,7 @@ struct pci_dev *pcistub_get_pci_dev(stru
>>>        return found_dev;
>>>  }
>>>
>>> -void pcistub_put_pci_dev(struct pci_dev *dev)
>>> +void pcistub_put_pci_dev(struct pci_dev *dev, int do_flr)
>>>  {
>>>        struct pcistub_device *psdev, *found_psdev = NULL;
>>>        unsigned long flags;
>>> @@ -220,6 +257,13 @@ void pcistub_put_pci_dev(struct pci_dev
>>>        * pcistub and pciback when AER is in processing
>>>        */
>>>        down_write(&pcistub_sem);
>>> +
>>> +       /* For pass-through devices, do an FLR (or approximate) for the 
>>> device
>>> +        * before it is put back and ready for the next domain
>>> +        */
>>> +       if (!disable_all_flr && do_flr)
>>> +               pciback_flr_device(dev);
>>> +
>>>        /* Cleanup our device
>>>         * (so it's ready for the next domain)
>>>         */
>>> @@ -235,6 +279,43 @@ void pcistub_put_pci_dev(struct pci_dev
>>>        up_write(&pcistub_sem);
>>>  }
>>>
>>> +struct pci_dev *pcistub_ref_pci_dev(struct pci_dev *dev)
>>> +{
>>> +       struct pcistub_device *psdev;
>>> +       struct pci_dev *found_dev = NULL;
>>> +       unsigned long flags;
>>> +
>>> +       spin_lock_irqsave(&pcistub_devices_lock, flags);
>>> +
>>> +       list_for_each_entry(psdev, &pcistub_devices, dev_list) {
>>> +               if (psdev->dev == dev) {
>>> +                       pcistub_device_get(psdev); /* just a ref count */
>>> +                       found_dev = psdev->dev;
>>> +                       break;
>>> +               }
>>> +       }
>>> +
>>> +       spin_unlock_irqrestore(&pcistub_devices_lock, flags);
>>> +       return found_dev;
>>> +}
>>> +
>>> +void pcistub_unref_pci_dev(struct pci_dev *dev)
>>> +{
>>> +       struct pcistub_device *psdev;
>>> +       unsigned long flags;
>>> +
>>> +       spin_lock_irqsave(&pcistub_devices_lock, flags);
>>> +
>>> +       list_for_each_entry(psdev, &pcistub_devices, dev_list) {
>>> +               if (psdev->dev == dev) {
>>> +                       pcistub_device_get(psdev); /* just an unref count */
>>> +                       break;
>>> +               }
>>> +       }
>>> +
>>> +       spin_unlock_irqrestore(&pcistub_devices_lock, flags);
>>> +}
>>> +
>>>  static int __devinit pcistub_match_one(struct pci_dev *dev,
>>>                                       struct pcistub_device_id *pdev_id)
>>>  {
>>> @@ -255,7 +336,7 @@ static int __devinit pcistub_match_one(s
>>>        return 0;
>>>  }
>>>
>>> -static int __devinit pcistub_match(struct pci_dev *dev)
>>> +static int __devinit pcistub_match(struct pci_dev *dev, int type)
>>>  {
>>>        struct pcistub_device_id *pdev_id;
>>>        unsigned long flags;
>>> @@ -263,6 +344,8 @@ static int __devinit pcistub_match(struc
>>>
>>>        spin_lock_irqsave(&device_ids_lock, flags);
>>>        list_for_each_entry(pdev_id, &pcistub_device_ids, slot_list) {
>>> +               if (pdev_id->type != type)
>>> +                       continue;
>>>                if (pcistub_match_one(dev, pdev_id)) {
>>>                        found = 1;
>>>                        break;
>>> @@ -285,12 +368,11 @@ static int __devinit pcistub_init_device
>>>         * would need to be called somewhere to free the memory allocated
>>>         * here and then to call kfree(pci_get_drvdata(psdev->dev)).
>>>         */
>>> -       dev_data = kzalloc(sizeof(*dev_data), GFP_ATOMIC);
>>> +       dev_data = pcistub_dev_data_alloc(dev);
>>>        if (!dev_data) {
>>>                err = -ENOMEM;
>>>                goto out;
>>>        }
>>> -       pci_set_drvdata(dev, dev_data);
>>>
>>>        dev_dbg(&dev->dev, "initializing config\n");
>>>
>>> @@ -317,6 +399,22 @@ static int __devinit pcistub_init_device
>>>        dev_dbg(&dev->dev, "reset device\n");
>>>        pciback_reset_device(dev);
>>>
>>> +       /* Classify the device so we know if it is PCI/PCIe and if it is
>>> +        * a bridge - this information is used for FLR logic. Also store
>>> +        * values if SBR/D3R reset logic was requested.
>>> +        */
>>> +       pciback_classify_device(dev);
>>> +       dev_data->no_flr = pcistub_match(dev, PCIBACK_ID_TYPE_NOFLR);
>>> +       if (!dev_data->no_flr) {
>>> +               dev_data->use_sbr = pcistub_match(dev, PCIBACK_ID_TYPE_SBR);
>>> +               dev_data->use_d3r = pcistub_match(dev, PCIBACK_ID_TYPE_D3R);
>>> +       }
>>> +
>>> +       /* Store the config space here where the device is off and ready to 
>>> be
>>> +        * exported before any FLRs or other resets are done
>>> +        */
>>> +       pciback_store_config_space(dev);
>>> +
>>>        return 0;
>>>
>>>       config_release:
>>> @@ -414,7 +512,7 @@ static int __devinit pcistub_probe(struc
>>>
>>>        dev_dbg(&dev->dev, "probing...\n");
>>>
>>> -       if (pcistub_match(dev)) {
>>> +       if (pcistub_match(dev, PCIBACK_ID_TYPE_HIDE)) {
>>>
>>>                if (dev->hdr_type != PCI_HEADER_TYPE_NORMAL
>>>                    && dev->hdr_type != PCI_HEADER_TYPE_BRIDGE) {
>>> @@ -851,7 +949,7 @@ static inline int str_to_quirk(const cha
>>>        return -EINVAL;
>>>  }
>>>
>>> -static int pcistub_device_id_add(int domain, int bus, int slot, int func)
>>> +static int pcistub_device_id_add(int domain, int bus, int slot, int func, 
>>> int type)
>>>  {
>>>        struct pcistub_device_id *pci_dev_id;
>>>        unsigned long flags;
>>> @@ -860,12 +958,13 @@ static int pcistub_device_id_add(int dom
>>>        if (!pci_dev_id)
>>>                return -ENOMEM;
>>>
>>> +       pci_dev_id->type = type;
>>>        pci_dev_id->domain = domain;
>>>        pci_dev_id->bus = bus;
>>>        pci_dev_id->devfn = PCI_DEVFN(slot, func);
>>>
>>> -       pr_debug("pciback: wants to seize %04x:%02x:%02x.%01x\n",
>>> -                domain, bus, slot, func);
>>> +       pr_debug("pciback: adding device ID type: %d for 
>>> %04x:%02x:%02x.%01x\n",
>>> +                type, domain, bus, slot, func);
>>>
>>>        spin_lock_irqsave(&device_ids_lock, flags);
>>>        list_add_tail(&pci_dev_id->slot_list, &pcistub_device_ids);
>>> @@ -874,7 +973,7 @@ static int pcistub_device_id_add(int dom
>>>        return 0;
>>>  }
>>>
>>> -static int pcistub_device_id_remove(int domain, int bus, int slot, int 
>>> func)
>>> +static int pcistub_device_id_remove(int domain, int bus, int slot, int 
>>> func, int type)
>>>  {
>>>        struct pcistub_device_id *pci_dev_id, *t;
>>>        int devfn = PCI_DEVFN(slot, func);
>>> @@ -884,7 +983,7 @@ static int pcistub_device_id_remove(int
>>>        spin_lock_irqsave(&device_ids_lock, flags);
>>>        list_for_each_entry_safe(pci_dev_id, t, &pcistub_device_ids, 
>>> slot_list) {
>>>
>>> -               if (pci_dev_id->domain == domain
>>> +               if (pci_dev_id->type == type && pci_dev_id->domain == domain
>>>                    && pci_dev_id->bus == bus && pci_dev_id->devfn == devfn) 
>>> {
>>>                        /* Don't break; here because it's possible the same
>>>                         * slot could be in the list more than once
>>> @@ -939,6 +1038,32 @@ static int pcistub_reg_add(int domain, i
>>>        return err;
>>>  }
>>>
>>> +static int pcistub_device_do_flr(int domain, int bus, int slot, int func)
>>> +{
>>> +       int err = 0;
>>> +       struct pcistub_device *psdev;
>>> +       struct pci_dev *dev;
>>> +
>>> +       psdev = pcistub_device_find(domain, bus, slot, func);
>>> +       if (!psdev || !psdev->dev) {
>>> +               err = -ENODEV;
>>> +               goto out;
>>> +       }
>>> +       dev = psdev->dev;
>>> +
>>> +       /* Do an FLR (or approximate) for the device on demand and
>>> +        * reload config
>>> +        */
>>> +       if (!disable_all_flr) {
>>> +               pciback_flr_device(dev);
>>> +       }
>>> +       else
>>> +               dev_dbg(&dev->dev, "FLR disabled for all devices\n");
>>> +
>>> +out:
>>> +       return err;
>>> +}
>>> +
>>>  static ssize_t pcistub_slot_add(struct device_driver *drv, const char *buf,
>>>                                size_t count)
>>>  {
>>> @@ -949,7 +1074,7 @@ static ssize_t pcistub_slot_add(struct d
>>>        if (err)
>>>                goto out;
>>>
>>> -       err = pcistub_device_id_add(domain, bus, slot, func);
>>> +       err = pcistub_device_id_add(domain, bus, slot, func, 
>>> PCIBACK_ID_TYPE_HIDE);
>>>
>>>       out:
>>>        if (!err)
>>> @@ -969,7 +1094,7 @@ static ssize_t pcistub_slot_remove(struc
>>>        if (err)
>>>                goto out;
>>>
>>> -       err = pcistub_device_id_remove(domain, bus, slot, func);
>>> +       err = pcistub_device_id_remove(domain, bus, slot, func, 
>>> PCIBACK_ID_TYPE_HIDE);
>>>
>>>       out:
>>>        if (!err)
>>> @@ -987,6 +1112,10 @@ static ssize_t pcistub_slot_show(struct
>>>
>>>        spin_lock_irqsave(&device_ids_lock, flags);
>>>        list_for_each_entry(pci_dev_id, &pcistub_device_ids, slot_list) {
>>> +               /* only want devices set for hide, not reset entries */
>>> +               if (pci_dev_id->type != PCIBACK_ID_TYPE_HIDE)
>>> +                       continue;
>>> +
>>>                if (count >= PAGE_SIZE)
>>>                        break;
>>>
>>> @@ -1068,7 +1197,7 @@ static ssize_t pcistub_quirk_show(struct
>>>
>>>  DRIVER_ATTR(quirks, S_IRUSR | S_IWUSR, pcistub_quirk_show, 
>>> pcistub_quirk_add);
>>>
>>> -static ssize_t permissive_add(struct device_driver *drv, const char *buf,
>>> +static ssize_t pcistub_permissive_add(struct device_driver *drv, const 
>>> char *buf,
>>>                              size_t count)
>>>  {
>>>        int domain, bus, slot, func;
>>> @@ -1109,7 +1238,7 @@ static ssize_t permissive_add(struct dev
>>>        return err;
>>>  }
>>>
>>> -static ssize_t permissive_show(struct device_driver *drv, char *buf)
>>> +static ssize_t pcistub_permissive_show(struct device_driver *drv, char 
>>> *buf)
>>>  {
>>>        struct pcistub_device *psdev;
>>>        struct pciback_dev_data *dev_data;
>>> @@ -1132,7 +1261,68 @@ static ssize_t permissive_show(struct de
>>>        return count;
>>>  }
>>>
>>> -DRIVER_ATTR(permissive, S_IRUSR | S_IWUSR, permissive_show, 
>>> permissive_add);
>>> +DRIVER_ATTR(permissive, S_IRUSR | S_IWUSR, pcistub_permissive_show, 
>>> pcistub_permissive_add);
>>> +
>>> +static ssize_t pcistub_do_flr(struct device_driver *drv, const char *buf,
>>> +                                  size_t count)
>>> +{
>>> +       int domain, bus, slot, func;
>>> +       int err;
>>> +
>>> +       err = str_to_slot(buf, &domain, &bus, &slot, &func);
>>> +       if (err)
>>> +               goto out;
>>> +
>>> +       err = pcistub_device_do_flr(domain, bus, slot, func);
>>> +
>>> +out:
>>> +       if (!err)
>>> +               err = count;
>>> +       return err;
>>> +}
>>> +
>>> +DRIVER_ATTR(do_flr, S_IWUSR, NULL, pcistub_do_flr);
>>> +
>>> +static ssize_t pcistub_resets(struct device_driver *drv, const char *buf,
>>> +                                  size_t count)
>>> +{
>>> +       int domain, bus, slot, func;
>>> +       int type, err = 0;
>>> +
>>> +       /* string begins with reset type specifier sbr=|dr3=|noflr= */
>>> +       if (!strncmp(buf, "sbr=", 4)) {
>>> +               type = PCIBACK_ID_TYPE_SBR;
>>> +               buf += 4;
>>> +       } else if (!strncmp(buf, "d3r=", 4)) {
>>> +               type = PCIBACK_ID_TYPE_D3R;
>>> +               buf += 4;
>>> +       } else if (!strncmp(buf, "noflr=", 6)) {
>>> +               type = PCIBACK_ID_TYPE_NOFLR;
>>> +               buf += 6;
>>> +       } else {
>>> +               err = -EINVAL;
>>> +               goto out;
>>> +       }
>>> +
>>> +       /* check special wildcard noflr */
>>> +       if (type == PCIBACK_ID_TYPE_NOFLR && !strncmp(buf, "(*)", 3)) {
>>> +               disable_all_flr = 1;
>>> +               goto out;
>>> +       }
>>> +
>>> +       err = str_to_slot(buf, &domain, &bus, &slot, &func);
>>> +       if (err)
>>> +               goto out;
>>> +
>>> +       err = pcistub_device_id_add(domain, bus, slot, func, type);
>>> +
>>> +out:
>>> +       if (!err)
>>> +               err = count;
>>> +       return err;
>>> +}
>>> +
>>> +DRIVER_ATTR(resets, S_IWUSR, NULL, pcistub_resets);
>>>
>>>  #ifdef CONFIG_PCI_MSI
>>>
>>> @@ -1158,6 +1348,8 @@ static void pcistub_exit(void)
>>>        driver_remove_file(&pciback_pci_driver.driver, &driver_attr_slots);
>>>        driver_remove_file(&pciback_pci_driver.driver, &driver_attr_quirks);
>>>        driver_remove_file(&pciback_pci_driver.driver, 
>>> &driver_attr_permissive);
>>> +       driver_remove_file(&pciback_pci_driver.driver, &driver_attr_do_flr);
>>> +       driver_remove_file(&pciback_pci_driver.driver, &driver_attr_resets);
>>>
>>>        pci_unregister_driver(&pciback_pci_driver);
>>>        WARN_ON(unregister_msi_get_owner(pciback_get_owner));
>>> @@ -1165,35 +1357,27 @@ static void pcistub_exit(void)
>>>
>>>  static int __init pcistub_init(void)
>>>  {
>>> -       int pos = 0;
>>>        int err = 0;
>>> -       int domain, bus, slot, func;
>>> -       int parsed;
>>>
>>> -       if (pci_devs_to_hide && *pci_devs_to_hide) {
>>> -               do {
>>> -                       parsed = 0;
>>> -
>>> -                       err = sscanf(pci_devs_to_hide + pos,
>>> -                                    " (%x:%x:%x.%x) %n",
>>> -                                    &domain, &bus, &slot, &func, &parsed);
>>> -                       if (err != 4) {
>>> -                               domain = 0;
>>> -                               err = sscanf(pci_devs_to_hide + pos,
>>> -                                            " (%x:%x.%x) %n",
>>> -                                            &bus, &slot, &func, &parsed);
>>> -                               if (err != 3)
>>> -                                       goto parse_error;
>>> -                       }
>>> +       /* Parse device lists for hide, sbr, and d3r */
>>> +       err = pciback_parse_device_params(pci_devs_to_hide, 
>>> PCIBACK_ID_TYPE_HIDE, pcistub_device_id_add);
>>> +       if (err)
>>> +               goto out;
>>>
>>> -                       err = pcistub_device_id_add(domain, bus, slot, 
>>> func);
>>> -                       if (err)
>>> -                               goto out;
>>> +       err = pciback_parse_device_params(pci_devs_use_sbr, 
>>> PCIBACK_ID_TYPE_SBR, pcistub_device_id_add);
>>> +       if (err)
>>> +               goto out;
>>>
>>> -                       /* if parsed<=0, we've reached the end of the 
>>> string */
>>> -                       pos += parsed;
>>> -               } while (parsed > 0 && pci_devs_to_hide[pos]);
>>> -       }
>>> +       err = pciback_parse_device_params(pci_devs_use_d3r, 
>>> PCIBACK_ID_TYPE_D3R, pcistub_device_id_add);
>>> +       if (err)
>>> +               goto out;
>>> +
>>> +       if (pci_devs_no_flr && *pci_devs_no_flr && 
>>> !strncmp(pci_devs_no_flr, "(*)", 3))
>>> +               disable_all_flr = 1; /* check special wildcard noflr */
>>> +       else
>>> +               err = pciback_parse_device_params(pci_devs_no_flr, 
>>> PCIBACK_ID_TYPE_NOFLR, pcistub_device_id_add);
>>> +       if (err)
>>> +               goto out;
>>>
>>>        /* If we're the first PCI Device Driver to register, we're the
>>>         * first one to get offered PCI devices as they become
>>> @@ -1217,6 +1401,12 @@ static int __init pcistub_init(void)
>>>        if (!err)
>>>                err = driver_create_file(&pciback_pci_driver.driver,
>>>                                         &driver_attr_permissive);
>>> +       if (!err)
>>> +               err = driver_create_file(&pciback_pci_driver.driver,
>>> +                                        &driver_attr_do_flr);
>>> +       if (!err)
>>> +               err = driver_create_file(&pciback_pci_driver.driver,
>>> +                                        &driver_attr_resets);
>>>
>>>        if (!err)
>>>                err = register_msi_get_owner(pciback_get_owner);
>>> @@ -1225,11 +1415,6 @@ static int __init pcistub_init(void)
>>>
>>>       out:
>>>        return err;
>>> -
>>> -      parse_error:
>>> -       printk(KERN_ERR "pciback: Error parsing pci_devs_to_hide at 
>>> \"%s\"\n",
>>> -              pci_devs_to_hide + pos);
>>> -       return -EINVAL;
>>>  }
>>>
>>>  #ifndef MODULE
>>> diff -rupN --ignore-blank-lines-X diffignore 
>>> a/linux-2.6.18-xen.hg/drivers/xen/pciback/slot.c 
>>> b/linux-2.6.18-xen.hg/drivers/xen/pciback/slot.c
>>> --- a/linux-2.6.18-xen.hg/drivers/xen/pciback/slot.c    2009-06-07 
>>> 20:48:21.000000000 -0400
>>> +++ b/linux-2.6.18-xen.hg/drivers/xen/pciback/slot.c    2009-06-07 
>>> 19:04:11.000000000 -0400
>>> @@ -109,7 +109,7 @@ void pciback_release_pci_dev(struct pcib
>>>        spin_unlock_irqrestore(&slot_dev->lock, flags);
>>>
>>>        if (found_dev)
>>> -               pcistub_put_pci_dev(found_dev);
>>> +               pcistub_put_pci_dev(found_dev, 0);
>>>  }
>>>
>>>  int pciback_init_devices(struct pciback_device *pdev)
>>> @@ -149,7 +149,7 @@ void pciback_release_devices(struct pcib
>>>                for (slot = 0; slot < PCI_SLOT_MAX; slot++) {
>>>                        dev = slot_dev->slots[bus][slot];
>>>                        if (dev != NULL)
>>> -                               pcistub_put_pci_dev(dev);
>>> +                               pcistub_put_pci_dev(dev, 0);
>>>                }
>>>
>>>        kfree(slot_dev);
>>> diff -rupN --ignore-blank-lines-X diffignore 
>>> a/linux-2.6.18-xen.hg/drivers/xen/pciback/vpci.c 
>>> b/linux-2.6.18-xen.hg/drivers/xen/pciback/vpci.c
>>> --- a/linux-2.6.18-xen.hg/drivers/xen/pciback/vpci.c    2009-06-07 
>>> 20:48:21.000000000 -0400
>>> +++ b/linux-2.6.18-xen.hg/drivers/xen/pciback/vpci.c    2009-06-07 
>>> 19:04:11.000000000 -0400
>>> @@ -162,7 +162,7 @@ void pciback_release_pci_dev(struct pcib
>>>        spin_unlock_irqrestore(&vpci_dev->lock, flags);
>>>
>>>        if (found_dev)
>>> -               pcistub_put_pci_dev(found_dev);
>>> +               pcistub_put_pci_dev(found_dev, 0);
>>>  }
>>>
>>>  int pciback_init_devices(struct pciback_device *pdev)
>>> @@ -202,7 +202,7 @@ void pciback_release_devices(struct pcib
>>>                list_for_each_entry_safe(e, tmp, &vpci_dev->dev_list[slot],
>>>                                         list) {
>>>                        list_del(&e->list);
>>> -                       pcistub_put_pci_dev(e->dev);
>>> +                       pcistub_put_pci_dev(e->dev, 0);
>>>                        kfree(e);
>>>                }
>>>        }
>>> diff -rupN --ignore-blank-lines-X diffignore 
>>> a/linux-2.6.18-xen.hg/include/linux/pci_ids.h 
>>> b/linux-2.6.18-xen.hg/include/linux/pci_ids.h
>>> --- a/linux-2.6.18-xen.hg/include/linux/pci_ids.h       2009-06-07 
>>> 20:48:23.000000000 -0400
>>> +++ b/linux-2.6.18-xen.hg/include/linux/pci_ids.h       2009-06-07 
>>> 19:04:11.000000000 -0400
>>> @@ -2259,6 +2259,14 @@
>>>  #define PCI_DEVICE_ID_INTEL_IXP2800    0x9004
>>>  #define PCI_DEVICE_ID_INTEL_S21152BB   0xb152
>>>
>>> +#define PCI_DEVICE_ID_INTEL_GMCHQ45 0x2e10
>>> +#define PCI_DEVICE_ID_INTEL_GMCHG45 0x2e20
>>> +#define PCI_DEVICE_ID_INTEL_MCHP45  0x2e20
>>> +#define PCI_DEVICE_ID_INTEL_GMCHG41 0x2e30
>>> +#define PCI_DEVICE_ID_INTEL_GMCHGM45 0x2a40
>>> +
>>> +#define PCI_DEVICE_ID_INTEL_GMCHG41 0x2e30
>>> +
>>>  #define PCI_VENDOR_ID_SCALEMP          0x8686
>>>  #define PCI_DEVICE_ID_SCALEMP_VSMP_CTL 0x1010
>>>
>>> diff -rupN --ignore-blank-lines-X diffignore 
>>> a/linux-2.6.18-xen.hg/include/linux/pci_regs.h 
>>> b/linux-2.6.18-xen.hg/include/linux/pci_regs.h
>>> --- a/linux-2.6.18-xen.hg/include/linux/pci_regs.h      2009-06-07 
>>> 20:48:23.000000000 -0400
>>> +++ b/linux-2.6.18-xen.hg/include/linux/pci_regs.h      2009-06-07 
>>> 19:04:11.000000000 -0400
>>> @@ -201,6 +201,7 @@
>>>  #define  PCI_CAP_ID_SHPC       0x0C    /* PCI Standard Hot-Plug Controller 
>>> */
>>>  #define  PCI_CAP_ID_EXP        0x10    /* PCI Express */
>>>  #define  PCI_CAP_ID_MSIX       0x11    /* MSI-X */
>>> +#define  PCI_CAP_ID_AF      0x13    /* Advanced Features Capability */
>>>  #define PCI_CAP_LIST_NEXT      1       /* Next capability in the list */
>>>  #define PCI_CAP_FLAGS          2       /* Capability defined flags (16 
>>> bits) */
>>>  #define PCI_CAP_SIZEOF         4
>>> @@ -229,6 +230,11 @@
>>>  #define  PCI_PM_CTRL_DATA_SEL_MASK     0x1e00  /* Data select (??) */
>>>  #define  PCI_PM_CTRL_DATA_SCALE_MASK   0x6000  /* Data scale (??) */
>>>  #define  PCI_PM_CTRL_PME_STATUS        0x8000  /* PME pin status */
>>> +#define  PCI_PM_CTRL_DATA_DSTATE_MASK 0x3      /* D0 - D3 */
>>> +#define  PCI_PM_CTRL_D0 0x0
>>> +#define  PCI_PM_CTRL_D1 0x1
>>> +#define  PCI_PM_CTRL_D2 0x2
>>> +#define  PCI_PM_CTRL_D3HOT 0x3
>>>  #define PCI_PM_PPB_EXTENSIONS  6       /* PPB support extensions (??) */
>>>  #define  PCI_PM_PPB_B2_B3      0x40    /* Stop clock when in D3hot (??) */
>>>  #define  PCI_PM_BPCC_ENABLE    0x80    /* Bus power/clock control enable 
>>> (??) */
>>> @@ -346,6 +352,7 @@
>>>  #define  PCI_EXP_DEVCAP_PWR_IND        0x4000  /* Power Indicator Present 
>>> */
>>>  #define  PCI_EXP_DEVCAP_PWR_VAL        0x3fc0000 /* Slot Power Limit Value 
>>> */
>>>  #define  PCI_EXP_DEVCAP_PWR_SCL        0xc000000 /* Slot Power Limit Scale 
>>> */
>>> +#define  PCI_EXP_DEVCAP_FLR     0x10000000 /* Function Level Reset */
>>>  #define PCI_EXP_DEVCTL         8       /* Device Control */
>>>  #define  PCI_EXP_DEVCTL_CERE   0x0001  /* Correctable Error Reporting En. 
>>> */
>>>  #define  PCI_EXP_DEVCTL_NFERE  0x0002  /* Non-Fatal Error Reporting Enable 
>>> */
>>> @@ -358,6 +365,7 @@
>>>  #define  PCI_EXP_DEVCTL_AUX_PME        0x0400  /* Auxiliary Power PM 
>>> Enable */
>>>  #define  PCI_EXP_DEVCTL_NOSNOOP_EN 0x0800  /* Enable No Snoop */
>>>  #define  PCI_EXP_DEVCTL_READRQ 0x7000  /* Max_Read_Request_Size */
>>> +#define  PCI_EXP_DEVCTL_BCR_FLR 0x8000  /* Bridge Configuration Retry / 
>>> FLR */
>>>  #define PCI_EXP_DEVSTA         10      /* Device Status */
>>>  #define  PCI_EXP_DEVSTA_CED    0x01    /* Correctable Error Detected */
>>>  #define  PCI_EXP_DEVSTA_NFED   0x02    /* Non-Fatal Error Detected */
>>> @@ -482,6 +490,17 @@
>>>  #define  PCI_ARI_CTRL_ACS      0x0002  /* ACS Function Groups Enable */
>>>  #define  PCI_ARI_CTRL_FG(x)    (((x) >> 4) & 7) /* Function Group */
>>>
>>> +/* Advanced Features Capability */
>>> +#define PCI_AF_LENFLD    0x02 /* Device length offset */
>>> +#define  PCI_AF_LENGTH   0x06
>>> +#define PCI_AF_DEVCAP    0x03 /* Device capabilities offset */
>>> +#define  PCI_AF_CAP_TP   0x01
>>> +#define  PCI_AF_CAP_FLR  0x02
>>> +#define PCI_AF_CTRL      0x04 /* Device CTRL offset */
>>> +#define  PCI_AF_CTRL_FLR 0x01
>>> +#define PCI_AF_STA       0x05 /* Device STATUS offset */
>>> +#define  PCI_AF_STA_TP   0x01
>>> +
>>>  /* Single Root I/O Virtualization */
>>>  #define PCI_SRIOV_CAP          0x04    /* SR-IOV Capabilities */
>>>  #define  PCI_SRIOV_CAP_VFM     0x01    /* VF Migration Capable */
>>> diff -rupN --ignore-blank-lines-X diffignore 
>>> a/tools/firmware/hvmloader/hvmloader.c 
>>> b/tools/firmware/hvmloader/hvmloader.c
>>> --- a/tools/firmware/hvmloader/hvmloader.c      2009-06-07 
>>> 20:44:47.000000000 -0400
>>> +++ b/tools/firmware/hvmloader/hvmloader.c      2009-06-07 
>>> 19:04:11.000000000 -0400
>>> @@ -673,6 +673,7 @@ int main(void)
>>>         break;
>>>     default:
>>>         printf("No emulated VGA adaptor ...\n");
>>> +        vgabios_sz = round_option_rom((*(uint8_t 
>>> *)(VGABIOS_PHYSICAL_ADDRESS+2)) * 512);
>>>         break;
>>>     }
>>>
>>> diff -rupN --ignore-blank-lines-X diffignore a/tools/ioemu-remote/console.h 
>>> b/tools/ioemu-remote/console.h
>>> --- a/tools/ioemu-remote/console.h      2009-06-07 21:14:47.000000000 -0400
>>> +++ b/tools/ioemu-remote/console.h      2009-06-07 19:04:11.000000000 -0400
>>> @@ -290,6 +290,9 @@ void vga_hw_update(void);
>>>  void vga_hw_invalidate(void);
>>>  void vga_hw_screen_dump(const char *filename);
>>>
>>> +void unset_vga_acc(void);
>>> +void set_vga_acc(void);
>>> +
>>>  int is_graphic_console(void);
>>>  int is_fixedsize_console(void);
>>>  CharDriverState *text_console_init(const char *p);
>>> @@ -341,4 +344,9 @@ const char *readline_get_history(unsigne
>>>  void readline_start(const char *prompt, int is_password,
>>>                     ReadLineFunc *readline_func, void *opaque);
>>>
>>> +/* intel.c */
>>> +int intel_enter(void);
>>> +int intel_leave(void);
>>> +void intel_display_init(DisplayState *ds);
>>> +
>>>  #endif
>>> diff -rupN --ignore-blank-lines-X diffignore 
>>> a/tools/ioemu-remote/hw/pass-through.c 
>>> b/tools/ioemu-remote/hw/pass-through.c
>>> --- a/tools/ioemu-remote/hw/pass-through.c      2009-06-07 
>>> 21:14:48.000000000 -0400
>>> +++ b/tools/ioemu-remote/hw/pass-through.c      2009-06-07 
>>> 19:04:11.000000000 -0400
>>> @@ -90,6 +90,8 @@
>>>  #include "qemu-xen.h"
>>>  #include <unistd.h>
>>>
>>> +extern int vga_passthrough;
>>> +
>>>  struct php_dev {
>>>     struct pt_dev *pt_dev;
>>>     uint8_t valid;
>>> @@ -1573,10 +1575,11 @@ static int pt_dev_is_virtfn(struct pci_d
>>>
>>>  static int pt_register_regions(struct pt_dev *assigned_device)
>>>  {
>>> -    int i = 0;
>>> +    int i = 0, ret = 0;
>>>     uint32_t bar_data = 0;
>>>     struct pci_dev *pci_dev = assigned_device->pci_dev;
>>>     PCIDevice *d = &assigned_device->dev;
>>> +    uint16_t class, vendor_id;
>>>
>>>     /* Register PIO/MMIO BARs */
>>>     for ( i = 0; i < PCI_BAR_ENTRIES; i++ )
>>> @@ -1632,6 +1635,25 @@ static int pt_register_regions(struct pt
>>>             (uint32_t)(pci_dev->rom_size), 
>>> (uint32_t)(pci_dev->rom_base_addr));
>>>     }
>>>
>>> +    /* Map legacy ioport and iomem, for specific devices */
>>> +    vendor_id = pci_read_word(pci_dev, 0x00);
>>> +    class = pci_read_word(pci_dev, 0x0a);
>>> +
>>> +    PT_LOG("Real device vendor_id=0x%x class=0x%x\n", vendor_id, class);
>>> +    if ( vga_passthrough && class == 0x0300 )
>>> +    {
>>> +        PT_LOG("add an intel graphic card\n");
>>> +
>>> +        ret = xc_domain_ioport_mapping(xc_handle, domid, 0x3B0, 0x3B0, 
>>> 0xb, DPCI_ADD_MAPPING);
>>> +        ret = xc_domain_ioport_mapping(xc_handle, domid, 0x3C0, 0x3C0, 32, 
>>> DPCI_ADD_MAPPING);
>>> +        ret |= xc_domain_memory_mapping(xc_handle, domid, 0xa0, 0xa0, 32, 
>>> DPCI_ADD_MAPPING);
>>> +        if ( ret != 0 )
>>> +        {
>>> +            PT_LOG("legacy mapping failed!\n");
>>> +            return ret;
>>> +        }
>>> +    }
>>> +
>>>     return 0;
>>>  }
>>>
>>> @@ -1640,6 +1662,7 @@ static void pt_unregister_regions(struct
>>>     int i, type, ret;
>>>     uint32_t e_size;
>>>     PCIDevice *d = (PCIDevice*)assigned_device;
>>> +    uint16_t class, vendor_id;
>>>
>>>     for ( i = 0; i < PCI_NUM_REGIONS; i++ )
>>>     {
>>> @@ -1681,6 +1704,24 @@ static void pt_unregister_regions(struct
>>>
>>>     }
>>>
>>> +    /* unmap legacy ioport and iomem, for specific devices */
>>> +    vendor_id = pci_read_word(assigned_device->pci_dev, 0x00);
>>> +    class = pci_read_word(assigned_device->pci_dev, 0x0a);
>>> +
>>> +    PT_LOG("Real device vendor_id=0x%x class=0x%x\n", vendor_id, class);
>>> +    if ( vga_passthrough && class == 0x0300 )
>>> +    {
>>> +        PT_LOG("remove an intel graphic card\n");
>>> +
>>> +        ret = xc_domain_ioport_mapping(xc_handle, domid, 0x3B0, 0x3B0, 
>>> 0xb, DPCI_REMOVE_MAPPING);
>>> +        ret = xc_domain_ioport_mapping(xc_handle, domid, 0x3C0, 0x3C0, 32, 
>>> DPCI_REMOVE_MAPPING);
>>> +        ret |= xc_domain_memory_mapping(xc_handle, domid, 0xa0, 0xa0, 32, 
>>> DPCI_REMOVE_MAPPING);
>>> +        if ( ret != 0 )
>>> +        {
>>> +            PT_LOG("legacy unmapping failed !\n");
>>> +        }
>>> +    }
>>> +
>>>  }
>>>
>>>  static uint8_t find_cap_offset(struct pci_dev *pci_dev, uint8_t cap)
>>> @@ -3759,7 +3800,7 @@ static struct pt_dev * register_real_dev
>>>     struct pci_config_cf8 machine_bdf;
>>>     char *key, *val;
>>>     int msi_translate, power_mgmt;
>>> -
>>> +
>>>     PT_LOG("Assigning real physical device %02x:%02x.%x ...\n",
>>>         r_bus, r_dev, r_func);
>>>
>>> @@ -3931,7 +3972,7 @@ static struct pt_dev * register_real_dev
>>>     }
>>>
>>>  out:
>>> -    PT_LOG("Real physical device %02x:%02x.%x registered successfuly!\n"
>>> +    PT_LOG("Real physical device %02x:%02x.%x registered successfully!\n"
>>>            "IRQ type = %s\n", r_bus, r_dev, r_func,
>>>            assigned_device->msi_trans_en? "MSI-INTx":"INTx");
>>>
>>> @@ -4113,3 +4154,47 @@ err:
>>>     return status;
>>>  }
>>>
>>> +u8 pt_pci_host_read_byte(int bus, int dev, int fn, u32 addr)
>>> +{
>>> +    struct pci_dev *pci_dev;
>>> +    u8             val;
>>> +
>>> +    pci_dev = pci_get_dev(dpci_infos.pci_access, 0, bus, dev, fn);
>>> +    if (!pci_dev)
>>> +        return 0;
>>> +
>>> +    val = pci_read_byte(pci_dev, addr);
>>> +    pci_free_dev(pci_dev);
>>> +
>>> +    return val;
>>> +}
>>> +
>>> +u16 pt_pci_host_read_word(int bus, int dev, int fn, u32 addr)
>>> +{
>>> +    struct pci_dev *pci_dev;
>>> +    u16             val;
>>> +
>>> +    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);
>>> +
>>> +    return val;
>>> +}
>>> +
>>> +u32 pt_pci_host_read_long(int bus, int dev, int fn, u32 addr)
>>> +{
>>> +    struct pci_dev *pci_dev;
>>> +    u32             val;
>>> +
>>> +    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);
>>> +    pci_free_dev(pci_dev);
>>> +
>>> +    return val;
>>> +}
>>> diff -rupN --ignore-blank-lines-X diffignore a/tools/ioemu-remote/hw/pc.c 
>>> b/tools/ioemu-remote/hw/pc.c
>>> --- a/tools/ioemu-remote/hw/pc.c        2009-06-07 21:14:47.000000000 -0400
>>> +++ b/tools/ioemu-remote/hw/pc.c        2009-06-07 19:04:11.000000000 -0400
>>> @@ -65,6 +65,8 @@ void tpm_tis_init(SetIRQFunc *set_irq, v
>>>  extern uint8_t *acpi_tables;
>>>  extern size_t acpi_tables_len;
>>>
>>> +extern int vga_passthrough;
>>> +
>>>  static fdctrl_t *floppy_controller;
>>>  static RTCState *rtc_state;
>>>  static PITState *pit;
>>> @@ -984,6 +986,7 @@ vga_bios_error:
>>>
>>>     register_ioport_write(0xf0, 1, 1, ioportF0_write, NULL);
>>>
>>> +    if (!vga_passthrough) {
>>>     if (cirrus_vga_enabled) {
>>>         if (pci_enabled) {
>>>             pci_cirrus_vga_init(pci_bus,
>>> @@ -1010,6 +1013,7 @@ vga_bios_error:
>>>                          vga_ram_addr, vga_ram_size);
>>>         }
>>>     }
>>> +    }
>>>
>>>  #ifdef CONFIG_PASSTHROUGH
>>>     /* Pass-through Initialization
>>> diff -rupN --ignore-blank-lines-X diffignore a/tools/ioemu-remote/hw/pci.c 
>>> b/tools/ioemu-remote/hw/pci.c
>>> --- a/tools/ioemu-remote/hw/pci.c       2009-06-07 21:14:47.000000000 -0400
>>> +++ b/tools/ioemu-remote/hw/pci.c       2009-06-07 19:04:11.000000000 -0400
>>> @@ -28,11 +28,14 @@
>>>  #include "virtio-net.h"
>>>  #include "sysemu.h"
>>>
>>> +#include "pass-through.h"
>>>  #include "exec-all.h"
>>>  #include "qemu-xen.h"
>>>
>>>  //#define DEBUG_PCI
>>>
>>> +extern int vga_passthrough;
>>> +
>>>  struct PCIBus {
>>>     int bus_num;
>>>     int devfn_min;
>>> @@ -611,7 +614,24 @@ uint32_t pci_data_read(void *opaque, uin
>>>         goto the_end;
>>>     }
>>>     config_addr = addr & 0xff;
>>> -    val = pci_dev->config_read(pci_dev, config_addr, len);
>>> +    if (vga_passthrough && pci_dev->devfn == 0x00) //Host Bridge
>>> +    {
>>> +        val = pci_dev->config_read(pci_dev, config_addr, len);
>>> +
>>> +        if (config_addr == 0x52) // GMCH
>>> +            val = pt_pci_host_read_word(0, 0, 0, 0x52);
>>> +        if (config_addr == 0x02) // Device ID
>>> +        {
>>> +            if (len == 2)
>>> +                val = pt_pci_host_read_word(0, 0, 0, 0x00);
>>> +            else if (len == 4)
>>> +                val = pt_pci_host_read_long(0, 0, 0, 0x00);
>>> +        }
>>> +    } else if (vga_passthrough && pci_dev->devfn == 0x10 && // intel 
>>> graphic card
>>> +               config_addr == 0xfc) // OpRegion address
>>> +        val = 0; // force to fall back to SMI mode
>>> +    else
>>> +        val = pci_dev->config_read(pci_dev, config_addr, len);
>>>  #if defined(DEBUG_PCI)
>>>     printf("pci_config_read: %s: addr=%02x val=%08x len=%d\n",
>>>            pci_dev->name, config_addr, val, len);
>>> diff -rupN --ignore-blank-lines-X diffignore a/tools/ioemu-remote/hw/vga.c 
>>> b/tools/ioemu-remote/hw/vga.c
>>> --- a/tools/ioemu-remote/hw/vga.c       2009-06-07 21:14:47.000000000 -0400
>>> +++ b/tools/ioemu-remote/hw/vga.c       2009-06-07 19:04:11.000000000 -0400
>>> @@ -34,9 +34,9 @@
>>>
>>>  #include "qemu-timer.h"
>>>
>>> -//#define DEBUG_VGA
>>> -//#define DEBUG_VGA_MEM
>>> -//#define DEBUG_VGA_REG
>>> +#define DEBUG_VGA
>>> +#define DEBUG_VGA_MEM
>>> +#define DEBUG_VGA_REG
>>>
>>>  //#define DEBUG_BOCHS_VBE
>>>
>>> @@ -161,6 +161,18 @@ static uint8_t expand4to8[16];
>>>  static void vga_bios_init(VGAState *s);
>>>  static void vga_screen_dump(void *opaque, const char *filename);
>>>
>>> +static VGAState *xen_vga_state;
>>> +
>>> +void set_vga_acc(void)
>>> +{
>>> +    set_vram_mapping(xen_vga_state, xen_vga_state->lfb_addr, 
>>> xen_vga_state->lfb_end);
>>> +}
>>> +
>>> +void unset_vga_acc(void)
>>> +{
>>> +    unset_vram_mapping(xen_vga_state);
>>> +}
>>> +
>>>  static void vga_dumb_update_retrace_info(VGAState *s)
>>>  {
>>>     (void) s;
>>> @@ -2473,8 +2485,6 @@ static void vga_bios_init(VGAState *s)
>>>  }
>>>
>>>
>>> -static VGAState *xen_vga_state;
>>> -
>>>  /* Allocate video memory in the GPFN space */
>>>  void xen_vga_populate_vram(uint64_t vram_addr, uint32_t vga_ram_size)
>>>  {
>>> diff -rupN --ignore-blank-lines-X diffignore a/tools/ioemu-remote/intel.c 
>>> b/tools/ioemu-remote/intel.c
>>> --- a/tools/ioemu-remote/intel.c        1969-12-31 19:00:00.000000000 -0500
>>> +++ b/tools/ioemu-remote/intel.c        2009-06-07 19:04:11.000000000 -0400
>>> @@ -0,0 +1,494 @@
>>> +#include <stdio.h>
>>> +#include <stdlib.h>
>>> +#include <stdint.h>
>>> +#include <sys/mman.h>
>>> +#include <sys/types.h>
>>> +#include <sys/stat.h>
>>> +#include <fcntl.h>
>>> +#include <assert.h>
>>> +#include <signal.h>
>>> +#include <pci/pci.h>
>>> +
>>> +#include "qemu-common.h"
>>> +#include "console.h"
>>> +#include "sysemu.h"
>>> +
>>> +#define INTEL_DEBUG(format, args...)                                    \
>>> +    fprintf (stderr, "intel.c:%d:%s " format , __LINE__, __func__, ## args)
>>> +
>>> +#define TileW           128
>>> +#define TileH           8
>>> +
>>> +#define REG_DR_DSPASURF                0x7019C
>>> +#define REG_DR_DSPACNTR                0x70180
>>> +#define REG_DR_DSPASTRIDE      0x70188
>>> +#define REG_DR_PIPEACONF       0x70008
>>> +
>>> +#define REG_DR_DSPBSURF                0x7119C
>>> +#define REG_DR_DSPBCNTR                0x71180
>>> +#define REG_DR_DSPBSTRIDE      0x71188
>>> +#define REG_DR_PIPEBCONF       0x71008
>>> +
>>> +#define REG_DE_PIPEASRC                0x6001c
>>> +
>>> +extern int                      vga_passthrough;
>>> +uint32_t                        guest_framebuffer;
>>> +
>>> +static int                      display = 0;
>>> +
>>> +static int                      mmio_fd = -1;
>>> +static int                      mem_fd = -1;
>>> +static uint8_t                  *intel_mem = NULL;
>>> +static uint8_t                  *intel_mmio = NULL;
>>> +static int                      intel_force_full_update = 0;
>>> +static int                      intel_have_focus;
>>> +static int                      IntelPitch = 16;
>>> +static int                      IntelX = 1280;
>>> +static int                      IntelY = 1024;
>>> +static DisplayState             *lds = NULL;
>>> +static uint8_t                  *old_data = NULL;
>>> +static uint32_t                 intel_fb_base, intel_mmio_base;
>>> +static uint32_t                 map_s, map_d, map_size;
>>> +static int                      refresh;
>>> +
>>> +static void set_data_mappings(void);
>>> +static void unset_data_mappings(int mapping);
>>> +static void set_data_pointer(void);
>>> +static void intel_resize(DisplayState *ds);
>>> +
>>> +static inline unsigned int intel_get_reg(unsigned int reg)
>>> +{
>>> +    return *(unsigned int*)(intel_mmio + reg);
>>> +}
>>> +
>>> +static inline int is_linear(void)
>>> +{
>>> +    unsigned int *dspacntr = (unsigned int *)(intel_mmio + 
>>> REG_DR_DSPACNTR);
>>> +    if (((*dspacntr) & (1 << 10)) == 0)
>>> +        return 1;
>>> +    else
>>> +        return 0;
>>> +}
>>> +
>>> +static inline unsigned int intel_get_pitch(void)
>>> +{
>>> +    unsigned int *dspastride = (unsigned int *)(intel_mmio + 
>>> REG_DR_DSPASTRIDE);
>>> +    return *dspastride;
>>> +}
>>> +
>>> +static inline unsigned int intel_get_offset(DisplaySurface *ds, int x, int 
>>> y)
>>> +{
>>> +    return (y * ds->width + x) * 4;
>>> +}
>>> +
>>> +static void intel_update_linear(DisplaySurface *ds, int x, int y, int w, 
>>> int h)
>>> +{
>>> +    int i, bpp = ds->pf.depth / 8;
>>> +    unsigned char *s, *d;
>>> +    s = ds->data;
>>> +    d = (unsigned char *)(intel_mem + intel_get_reg(REG_DR_DSPASURF));
>>> +    s += (ds->linesize * y) + bpp * x;
>>> +    d += (ds->linesize * y) + bpp * x;
>>> +    for (i = 0; i < h; i++) {
>>> +        memcpy(d, s, w * bpp);
>>> +        s += ds->linesize;
>>> +        d += ds->linesize;
>>> +    }
>>> +}
>>> +
>>> +static void intel_force_linear(int linesize)
>>> +{
>>> +    unsigned int *dspacntr = (unsigned int *)(intel_mmio + 
>>> REG_DR_DSPACNTR);
>>> +    unsigned int *pipeaconf = (unsigned int *)(intel_mmio + 
>>> REG_DR_PIPEACONF);
>>> +    unsigned int *dspasurf = (unsigned int *)(intel_mmio + 
>>> REG_DR_DSPASURF);
>>> +    unsigned int *dspastride = (unsigned int *)(intel_mmio + 
>>> REG_DR_DSPASTRIDE);
>>> +
>>> +    unsigned int *dspbcntr = (unsigned int *)(intel_mmio + 
>>> REG_DR_DSPBCNTR);
>>> +    unsigned int *pipebconf = (unsigned int *)(intel_mmio + 
>>> REG_DR_PIPEBCONF);
>>> +    unsigned int *dspbsurf = (unsigned int *)(intel_mmio + 
>>> REG_DR_DSPBSURF);
>>> +    unsigned int *dspbstride = (unsigned int *)(intel_mmio + 
>>> REG_DR_DSPBSTRIDE);
>>> +
>>> +    unsigned int surfa = 0, surfb = 0, pipea = 0, pipeb = 0;
>>> +    char pipebenabled = !!(*pipebconf & (1 << 30));
>>> +
>>> +
>>> +    INTEL_DEBUG("DSPASURF CTRL: 0x%x\n", intel_get_reg(REG_DR_DSPACNTR));
>>> +
>>> +    /* Disable surface */
>>> +    pipea = *pipeaconf & (0x3 << 18);
>>> +    *pipeaconf &= ~(0x3 << 18);
>>> +    *dspacntr |= (1 << 31);
>>> +    /* Address of the surface to map to */
>>> +    surfa = *dspasurf;
>>> +    *dspasurf = 0x00000000;
>>> +    *dspacntr &= ~(1 << 31);
>>> +    *dspasurf = 0x00000000;
>>> +    *pipeaconf |= pipea;
>>> +
>>> +    if (pipebenabled) {
>>> +        INTEL_DEBUG("PIPEBCONF enabled.\n");
>>> +
>>> +        /* Disable surface */
>>> +        pipeb = *pipebconf & (0x3 << 18);
>>> +        *pipebconf &= ~(0x3 << 18);
>>> +        *dspbcntr |= (1 << 31);
>>> +        /* Address of the surface to map to */
>>> +        surfb = *dspbsurf;
>>> +        *dspbsurf = 0x00000000;
>>> +        *dspbcntr &= ~(1 << 31);
>>> +        *dspbsurf = 0x00000000;
>>> +        *pipebconf |= pipeb;
>>> +    }
>>> +
>>> +    usleep(20000);
>>> +
>>> +    *pipeaconf &= ~(0x3 << 18);
>>> +    /* Enable surface linear mode */
>>> +    *dspacntr &= ~(1 << 10);
>>> +    if (linesize) *dspastride = linesize;
>>> +    *dspasurf = surfa;
>>> +    *dspacntr |= (1 << 31);
>>> +    *pipeaconf |= pipea;
>>> +
>>> +    if (pipebenabled) {
>>> +        *pipebconf &= ~(0x3 << 18);
>>> +        /* Enable surface linear mode */
>>> +        *dspbcntr &= ~(1 << 10);
>>> +        if (linesize) *dspbstride = linesize;
>>> +        *dspbsurf = surfb;
>>> +        *dspbcntr |= (1 << 31);
>>> +        *pipebconf |= pipeb;
>>> +    }
>>> +
>>> +    usleep(20000);
>>> +}
>>> +
>>> +static void intel_update(DisplayState *ds, int x, int y, int w, int h)
>>> +{
>>> +    if (intel_have_focus && !old_data && !map_size)
>>> +        intel_update_linear(ds->surface, x, y, w, h);
>>> +}
>>> +
>>> +static void set_fb_mapping(void)
>>> +{
>>> +    DisplaySurface *surf = lds->surface;
>>> +    int rc;
>>> +    unsigned long nr_pfn;
>>> +
>>> +    unset_vga_acc();
>>> +    fprintf(stderr, "set_fb_mapping: %x %x\n", (intel_fb_base + 
>>> intel_get_reg(REG_DR_DSPASURF)), guest_framebuffer);
>>> +    nr_pfn = (surf->linesize * surf->height) >> TARGET_PAGE_BITS;
>>> +
>>> +    rc = xc_domain_memory_mapping(xc_handle,
>>> +            domid,
>>> +            (guest_framebuffer >> TARGET_PAGE_BITS),
>>> +            ((intel_fb_base + intel_get_reg(REG_DR_DSPASURF)) >> 
>>> TARGET_PAGE_BITS),
>>> +            nr_pfn,
>>> +            DPCI_ADD_MAPPING);
>>> +    if (rc) {
>>> +        fprintf(stderr, "xc_domain_memory_mapping failed %d\n", rc);
>>> +        return;
>>> +    }
>>> +    map_s = ((intel_fb_base + intel_get_reg(REG_DR_DSPASURF)) >> 
>>> TARGET_PAGE_BITS);
>>> +    map_d = (guest_framebuffer >> TARGET_PAGE_BITS);
>>> +    map_size = nr_pfn;
>>> +}
>>> +
>>> +static void unset_fb_mapping(void)
>>> +{
>>> +    int rc;
>>> +
>>> +    fprintf(stderr, "unset_fb_mapping: %x %x\n", map_d, map_s);
>>> +
>>> +    rc = xc_domain_memory_mapping(xc_handle,
>>> +            domid,
>>> +            map_d,
>>> +            map_s,
>>> +            map_size,
>>> +            DPCI_REMOVE_MAPPING);
>>> +    if (rc) {
>>> +        fprintf(stderr, "xc_domain_memory_mapping failed %d\n", rc);
>>> +        return;
>>> +    }
>>> +
>>> +    set_vga_acc();
>>> +    map_s = 0;
>>> +    map_d = 0;
>>> +    map_size = 0;
>>> +}
>>> +
>>> +static void intel_setdata(DisplayState *ds)
>>> +{
>>> +    if (map_size)
>>> +        unset_fb_mapping();
>>> +    set_fb_mapping();
>>> +}
>>> +
>>> +static void intel_resize_shared(DisplayState *ds, int w, int h, int depth, 
>>> int linesize, void *pixels)
>>> +{
>>> +    DisplaySurface *surf = ds->surface;
>>> +
>>> +    if (!intel_have_focus) {
>>> +        surf->width = w;
>>> +        surf->height = h;
>>> +        intel_resize(ds);
>>> +        return;
>>> +    }
>>> +    if (depth == 32 && w == IntelX && h == IntelY)
>>> +        surf->flags = QEMU_ALLOCATED_FLAG;
>>> +    else
>>> +        surf->flags &= ~QEMU_ALLOCATED_FLAG;
>>> +    if (surf->flags & QEMU_ALLOCATED_FLAG) {
>>> +        surf->width = w;
>>> +        surf->height = h;
>>> +        surf->pf.depth = 32;
>>> +        surf->linesize = linesize;
>>> +        /* adjust linesize */
>>> +        intel_force_linear(linesize);
>>> +        set_data_mappings();
>>> +        if (refresh) {
>>> +            memcpy(surf->data, pixels, surf->linesize * surf->height);
>>> +            refresh = 0;
>>> +        }
>>> +        surf->data = pixels;
>>> +        intel_setdata(ds);
>>> +    } else {
>>> +        surf->width = w;
>>> +        surf->height = h;
>>> +        intel_resize(ds);
>>> +    }
>>> +}
>>> +
>>> +static void intel_resize(DisplayState *ds)
>>> +{
>>> +    DisplaySurface *surf = ds->surface;
>>> +    int old_linesize = surf->linesize;
>>> +
>>> +    if (surf->pf.depth == 32 && surf->width == IntelX && surf->height == 
>>> IntelY)
>>> +      surf->flags = QEMU_ALLOCATED_FLAG;
>>> +    else
>>> +      surf->flags &= ~QEMU_ALLOCATED_FLAG;
>>> +
>>> +    if (is_buffer_shared(surf))
>>> +    {
>>> +      INTEL_DEBUG("intel_resize_shared: enable shared buffer, linesize 
>>> %d\n",
>>> +                  surf->linesize);
>>> +      intel_force_linear(surf->linesize);
>>> +      set_data_mappings();
>>> +      if (refresh)
>>> +      {
>>> +        // Pixels doesn't exist anymore ??
>>> +        //memcpy(surf->data, pixels, surf->linesize * surf->height);
>>> +        refresh = 0;
>>> +      }
>>> +      intel_setdata(ds);
>>> +      return;
>>> +    }
>>> +
>>> +    INTEL_DEBUG("intel_resize: no shared buffer, linesize=%d\n", 
>>> surf->linesize);
>>> +    surf->linesize = intel_get_pitch();
>>> +    if (map_size) {
>>> +        unset_fb_mapping();
>>> +        unset_data_mappings(1);
>>> +    }
>>> +    if (intel_have_focus && !is_linear()) {
>>> +        intel_force_linear(0);
>>> +    }
>>> +    surf->flags &= ~QEMU_ALLOCATED_FLAG;
>>> +    if (intel_have_focus && !old_data &&
>>> +        surf->width * surf->height <= IntelX * IntelY)
>>> +        set_data_mappings();
>>> +    else if (intel_have_focus && old_data &&
>>> +             surf->width * surf->height > IntelX * IntelY)
>>> +        unset_data_mappings(0);
>>> +    if (!old_data) {
>>> +        qemu_free(surf->data);
>>> +        surf->data = qemu_mallocz(surf->height * surf->linesize);
>>> +    } else {
>>> +        INTEL_DEBUG("intel_resize: set_data_pointer\n");
>>> +        set_data_pointer();
>>> +    }
>>> +    if (intel_have_focus)
>>> +        memset((unsigned char *)(intel_mem + 
>>> intel_get_reg(REG_DR_DSPASURF)), 0x0, IntelX * IntelY);
>>> +    if (refresh) {
>>> +        if (old_data) {
>>> +            unsigned char *s, *d;
>>> +            int i;
>>> +            s = old_data;
>>> +            d = surf->data;
>>> +            for (i = 0; i < surf->height; i++) {
>>> +                memcpy(d, s, surf->width * 4);
>>> +                s += old_linesize;
>>> +                d += surf->linesize;
>>> +            }
>>> +        }
>>> +        refresh = 0;
>>> +    }
>>> +}
>>> +
>>> +static void intel_refresh(DisplayState *ds)
>>> +{
>>> +    vga_hw_update();
>>> +}
>>> +
>>> +static void intel_init_mapping(void)
>>> +{
>>> +    struct pci_access   *pci_bus;
>>> +    struct pci_dev      *pci_dev;
>>> +
>>> +    mmio_fd = open("/dev/mem", O_RDWR);
>>> +    if (mmio_fd == -1)
>>> +    {
>>> +        perror("open");
>>> +        exit(1);
>>> +    }
>>> +    mem_fd = open("/dev/mem", O_RDWR);
>>> +    if (mem_fd == -1)
>>> +    {
>>> +        perror("open");
>>> +        exit(1);
>>> +    }
>>> +
>>> +    pci_bus = pci_alloc();
>>> +    pci_init(pci_bus);
>>> +    pci_dev = pci_get_dev(pci_bus, 0, 0, 2, 0);
>>> +    pci_fill_info(pci_dev, PCI_FILL_BASES);
>>> +    intel_fb_base = pci_dev->base_addr[2] & 0xfffff000;
>>> +    intel_mmio_base = pci_dev->base_addr[0] & 0xfffff000;
>>> +    pci_free_dev(pci_dev);
>>> +    pci_cleanup(pci_bus);
>>> +
>>> +    INTEL_DEBUG("Map intel main mem 0x%x\n", intel_fb_base);
>>> +    intel_mem = mmap(NULL, 0x10000000, PROT_READ | PROT_WRITE, MAP_SHARED,
>>> +                     mem_fd, intel_fb_base);
>>> +    if (intel_mem == MAP_FAILED)
>>> +    {
>>> +        perror("mmap");
>>> +        exit(1);
>>> +    }
>>> +
>>> +    INTEL_DEBUG("Map intel mmio 0x%x\n", intel_mmio_base);
>>> +    intel_mmio = mmap(NULL, 4 * 1024 * 1024, PROT_READ | PROT_WRITE, 
>>> MAP_SHARED,
>>> +                      mmio_fd, intel_mmio_base);
>>> +    if (intel_mem == MAP_FAILED)
>>> +    {
>>> +        perror("mmap");
>>> +        exit(1);
>>> +    }
>>> +}
>>> +
>>> +static void set_data_pointer(void)
>>> +{
>>> +    DisplaySurface *surf = lds->surface;
>>> +
>>> +    surf->data = (unsigned char *)(intel_mem + 
>>> intel_get_reg(REG_DR_DSPASURF));
>>> +    surf->data = surf->data +
>>> +                surf->linesize * ((IntelY - surf->height) / 2) +
>>> +                4 * ((IntelX - surf->width) / 2);
>>> +}
>>> +
>>> +static void set_data_mappings(void)
>>> +{
>>> +    INTEL_DEBUG("set_data_mappings\n");
>>> +    if (!old_data)
>>> +        old_data = lds->surface->data;
>>> +    set_data_pointer();
>>> +}
>>> +
>>> +static void unset_data_mappings(int mapping)
>>> +{
>>> +    DisplaySurface *surf = lds->surface;
>>> +    if (!old_data)
>>> +        return;
>>> +    if (mapping) {
>>> +        uint8_t * buffer_pointer = surf->data;
>>> +        surf->data = old_data;
>>> +        old_data = NULL;
>>> +        surf->data = realloc(surf->data, surf->linesize * surf->height);
>>> +        memcpy(surf->data,
>>> +                (unsigned char *)(intel_mem + 
>>> intel_get_reg(REG_DR_DSPASURF)),
>>> +                surf->linesize * surf->height);
>>> +        memcpy(buffer_pointer,
>>> +                surf->data,
>>> +                surf->linesize * surf->height);
>>> +    } else {
>>> +        uint8_t * buffer_pointer = surf->data;
>>> +        surf->data = old_data;
>>> +        old_data = NULL;
>>> +        surf->data = realloc(surf->data, surf->linesize * surf->height);
>>> +        memcpy(surf->data,
>>> +                buffer_pointer,
>>> +                surf->linesize * surf->height);
>>> +    }
>>> +    INTEL_DEBUG("unset_data_mappings %d: success\n", mapping);
>>> +}
>>> +
>>> +static int intel_getfocus(void)
>>> +{
>>> +    return intel_have_focus;
>>> +}
>>> +
>>> +static void intel_focus(int focus)
>>> +{
>>> +    if (intel_have_focus == focus)
>>> +        return;
>>> +
>>> +    INTEL_DEBUG("intel_focus %d\n", focus);
>>> +    intel_have_focus = focus;
>>> +    if (focus) {
>>> +        if (!is_linear()) {
>>> +           IntelPitch = intel_get_reg(REG_DR_DSPASTRIDE);
>>> +           IntelX = ((intel_get_reg(REG_DE_PIPEASRC) >> 16) & 0xfff) + 1;
>>> +           IntelY = (intel_get_reg(REG_DE_PIPEASRC) & 0xfff) + 1;
>>> +           INTEL_DEBUG("Resolution is %dx%d\n", IntelX, IntelY);
>>> +        }
>>> +        refresh = 1;
>>> +        lds->listeners->dpy_resize = intel_resize;
>>> +        lds->listeners->dpy_setdata = intel_setdata;
>>> +        vga_hw_invalidate();
>>> +    } else {
>>> +        if (map_size) {
>>> +            unset_fb_mapping();
>>> +            unset_data_mappings(1);
>>> +        } else if (old_data) {
>>> +            unset_data_mappings(0);
>>> +        }
>>> +        lds->listeners->dpy_resize = NULL;
>>> +        lds->listeners->dpy_setdata = NULL;
>>> +        lds->surface->flags &= ~QEMU_ALLOCATED_FLAG;
>>> +    }
>>> +}
>>> +
>>> +int intel_enter(void)
>>> +{
>>> +    intel_focus(1);
>>> +    return 1;
>>> +}
>>> +
>>> +int intel_leave(void)
>>> +{
>>> +    intel_focus(0);
>>> +    return 1;
>>> +}
>>> +
>>> +void intel_display_init(DisplayState *ds)
>>> +{
>>> +    DisplaySurface *surf = ds->surface;
>>> +
>>> +    INTEL_DEBUG("\n");
>>> +
>>> +    intel_init_mapping();
>>> +
>>> +    INTEL_DEBUG("Frambuffer is at 0x%x\n", intel_get_reg(REG_DR_DSPASURF));
>>> +
>>> +    surf->flags = 0;
>>> +    surf->width = 640;
>>> +    surf->height = 480;
>>> +    surf->pf.depth = 32;
>>> +    intel_resize(ds);
>>> +    lds = ds;
>>> +
>>> +    ds->listeners->dpy_update = intel_update;
>>> +    ds->listeners->dpy_resize = intel_resize;
>>> +    ds->listeners->dpy_refresh = intel_refresh;
>>> +}
>>> \ No newline at end of file
>>> diff -rupN --ignore-blank-lines-X diffignore a/tools/ioemu-remote/vl.c 
>>> b/tools/ioemu-remote/vl.c
>>> --- a/tools/ioemu-remote/vl.c   2009-06-07 21:14:47.000000000 -0400
>>> +++ b/tools/ioemu-remote/vl.c   2009-06-07 19:29:12.000000000 -0400
>>> @@ -233,6 +233,9 @@ CharDriverState *virtcon_hds[MAX_VIRTIO_
>>>  #ifdef TARGET_I386
>>>  int win2k_install_hack = 0;
>>>  int rtc_td_hack = 0;
>>> +int vga_passthrough = 0;
>>> +const char *dom0_input = NULL;
>>> +int intel = 0;
>>>  #endif
>>>  int usb_enabled = 0;
>>>  int smp_cpus = 1;
>>> @@ -4039,6 +4042,9 @@ static void help(int exitcode)
>>>            "-disable-opengl disable OpenGL rendering, using SDL"
>>>  #endif
>>>  #endif
>>> +           "-vga_passthrough enable graphics card passthrough\n"
>>> +           "-dom0-input     enable dom0 controlling qemu\n"
>>> +           "-intel          use intel gfx\n"
>>>            "-portrait       rotate graphical output 90 deg left (only PXA 
>>> LCD)\n"
>>>            "-vga [std|cirrus|vmware|none]\n"
>>>            "                select video card type\n"
>>> @@ -4275,6 +4281,9 @@ enum {
>>>     QEMU_OPTION_domainname,
>>>     QEMU_OPTION_acpi,
>>>     QEMU_OPTION_vcpus,
>>> +    QEMU_OPTION_vga_passthrough,
>>> +    QEMU_OPTION_dom0_input,
>>> +    QEMU_OPTION_intel,
>>>
>>>     /* Debug/Expert options: */
>>>     QEMU_OPTION_serial,
>>> @@ -4448,6 +4457,9 @@ static const QEMUOption qemu_options[] =
>>>     { "pciemulation", HAS_ARG, QEMU_OPTION_pci_emulation },
>>>     { "vncunused", 0, QEMU_OPTION_vncunused },
>>>     { "vcpus", HAS_ARG, QEMU_OPTION_vcpus },
>>> +    { "vga_passthrough", 0, QEMU_OPTION_vga_passthrough },
>>> +    { "dom0-input", HAS_ARG, QEMU_OPTION_dom0_input },
>>> +    { "intel", 0, QEMU_OPTION_intel },
>>>  #if defined(CONFIG_XEN) && !defined(CONFIG_DM)
>>>     { "xen-domid", HAS_ARG, QEMU_OPTION_xen_domid },
>>>     { "xen-create", 0, QEMU_OPTION_xen_create },
>>> @@ -5281,6 +5293,15 @@ int main(int argc, char **argv, char **e
>>>             case QEMU_OPTION_disable_opengl:
>>>                 opengl_enabled = 0;
>>>                 break;
>>> +            case QEMU_OPTION_vga_passthrough:
>>> +                vga_passthrough = 1;
>>> +                break;
>>> +            case QEMU_OPTION_dom0_input:
>>> +                dom0_input = optarg;
>>> +                break;
>>> +            case QEMU_OPTION_intel:
>>> +                intel = 1;
>>> +                break;
>>>             case QEMU_OPTION_direct_pci:
>>>                direct_pci = optarg;
>>>                 break;
>>> @@ -5876,6 +5897,14 @@ int main(int argc, char **argv, char **e
>>>             fprintf(stderr, "fatal: -nographic can't be used with 
>>> -curses\n");
>>>             exit(1);
>>>         }
>>> +
>>> +#ifdef CONFIG_DM
>>> +        if(vga_passthrough)
>>> +            fprintf(stderr, "Replace if initializing dom0_driver\n" );
>>> +#else
>>> +        dumb_display_init(ds);
>>> +#endif
>>> +
>>>     } else {
>>>  #if defined(CONFIG_CURSES)
>>>             if (curses) {
>>> diff -rupN --ignore-blank-lines-X diffignore 
>>> a/tools/ioemu-remote/xen-hooks.mak b/tools/ioemu-remote/xen-hooks.mak
>>> --- a/tools/ioemu-remote/xen-hooks.mak  2009-06-07 21:14:47.000000000 -0400
>>> +++ b/tools/ioemu-remote/xen-hooks.mak  2009-06-07 19:04:12.000000000 -0400
>>> @@ -35,6 +35,7 @@ OBJS += exec-dm.o
>>>  OBJS += pci_emulation.o
>>>  OBJS += helper2.o
>>>  OBJS += battery_mgmt.o
>>> +OBJS += intel.o
>>>
>>>  ifdef CONFIG_STUBDOM
>>>  CPPFLAGS += $(TARGET_CPPFLAGS) -DNEED_CPU_H \
>>> diff -rupN --ignore-blank-lines-X diffignore a/tools/libxc/xc_hvm_build.c 
>>> b/tools/libxc/xc_hvm_build.c
>>> --- a/tools/libxc/xc_hvm_build.c        2009-06-07 20:44:47.000000000 -0400
>>> +++ b/tools/libxc/xc_hvm_build.c        2009-06-07 19:04:12.000000000 -0400
>>> @@ -1,7 +1,3 @@
>>> -/******************************************************************************
>>> - * xc_hvm_build.c
>>> - */
>>> -
>>>  #include <stddef.h>
>>>  #include <inttypes.h>
>>>  #include <stdlib.h>
>>> @@ -66,6 +62,82 @@ static void build_hvm_info(void *hvm_inf
>>>     hvm_info->checksum = -sum;
>>>  }
>>>
>>> +static int init_vgabios(int            xc_handle,
>>> +                        uint32_t       dom,
>>> +                        unsigned char *buffer,
>>> +                        uint32_t       bios_size)
>>> +{
>>> +    char                *va_bios = NULL;
>>> +    uint32_t            va_size = 0;
>>> +
>>> +    va_size = bios_size + bios_size % XC_PAGE_SIZE;
>>> +    va_bios = xc_map_foreign_range(xc_handle, dom, va_size,
>>> +                                   PROT_READ | PROT_WRITE, 0xC0);
>>> +    if (!va_bios)
>>> +    {
>>> +        IPRINTF("Unable to map vga bios!\n");
>>> +        return -1;
>>> +    }
>>> +
>>> +    if ( buffer != NULL)
>>> +        memcpy(va_bios, buffer, bios_size);
>>> +    else
>>> +        memset(va_bios, 0, bios_size);
>>> +
>>> +    munmap(va_bios, va_size);
>>> +    return 0;
>>> +}
>>> +
>>> +static int  setup_vga_pt(int            xc_handle,
>>> +                         uint32_t       dom)
>>> +{
>>> +    int                 rc = 0;
>>> +    unsigned char       *bios = NULL;
>>> +    int                 bios_size = 0;
>>> +    char                *c = NULL;
>>> +    char                checksum = 0;
>>> +
>>> +    IPRINTF("Setting up vga passthrough.\n");
>>> +
>>> +    /* Allocated 64K for the vga bios */
>>> +    if (!(bios = malloc(64 * 1024))) {
>>> +        IPRINTF("Error allocating memory for vga bios.\n");
>>> +        return -1;
>>> +    }
>>> +
>>> +#ifdef __linux__
>>> +    bios_size = xc_get_vgabios(bios, 64 * 1024);
>>> +#else
>>> +    bios_size = 0;
>>> +#endif /* __linux__ */
>>> +
>>> +    if (bios_size == 0)
>>> +    {
>>> +        IPRINTF("vga bios size is 0!\n");
>>> +        rc = -1;
>>> +        goto error;
>>> +    }
>>> +
>>> +    /* Adjust the bios checksum */
>>> +    for ( c = (char*)bios; c < ((char*)bios + bios_size); c++ )
>>> +        checksum += *c;
>>> +    if (checksum)
>>> +        bios[bios_size - 1] -= checksum;
>>> +    init_vgabios(xc_handle, dom, bios, bios_size);
>>> +
>>> +error:
>>> +    free(bios);
>>> +
>>> +    if( rc == -1 ) {
>>> +        IPRINTF("Error setting up vga passthrough.\n");
>>> +    }
>>> +    else {
>>> +        IPRINTF("Success setting up vga passthrough.\n");
>>> +    }
>>> +
>>> +    return rc;
>>> +}
>>> +
>>>  static int loadelfimage(
>>>     struct elf_binary *elf, int xch, uint32_t dom, unsigned long *parray)
>>>  {
>>> @@ -381,7 +453,8 @@ int xc_hvm_build_target_mem(int xc_handl
>>>                            uint32_t domid,
>>>                            int memsize,
>>>                            int target,
>>> -                           const char *image_name)
>>> +                           const char *image_name,
>>> +                           int vga_pt_enabled)
>>>  {
>>>     char *image;
>>>     int  sts;
>>> @@ -392,6 +465,12 @@ int xc_hvm_build_target_mem(int xc_handl
>>>         return -1;
>>>
>>>     sts = xc_hvm_build_internal(xc_handle, domid, memsize, target, image, 
>>> image_size);
>>> +    if ( vga_pt_enabled ) {
>>> +        sts |= setup_vga_pt(xc_handle, domid);
>>> +    } else {
>>> +        sts |= init_vgabios(xc_handle, domid, NULL, 0x800);
>>> +    }
>>> +
>>>
>>>     free(image);
>>>
>>> diff -rupN --ignore-blank-lines-X diffignore a/tools/libxc/xc_linux.c 
>>> b/tools/libxc/xc_linux.c
>>> --- a/tools/libxc/xc_linux.c    2009-06-07 20:44:47.000000000 -0400
>>> +++ b/tools/libxc/xc_linux.c    2009-06-07 19:04:12.000000000 -0400
>>> @@ -562,6 +562,57 @@ int xc_gnttab_set_max_grants(int xcg_han
>>>     return 0;
>>>  }
>>>
>>> +int xc_get_vgabios(unsigned char        *buf,
>>> +                   int                  len)
>>> +{
>>> +    int         mem;
>>> +    uint32_t    start, size = 0;
>>> +    uint16_t    magic = 0;
>>> +
>>> +    start = 0xC0000;
>>> +    if (len < size)
>>> +        return 0;
>>> +    if ((mem = open("/dev/mem", O_RDONLY)) < 0)
>>> +        return 0;
>>> +
>>> +    /*
>>> +    ** Check if it a real bios extension.
>>> +    ** The magic number is 0xAA55.
>>> +    */
>>> +    if (start != lseek(mem, start, SEEK_SET))
>>> +        goto out;
>>> +    if (read(mem, &magic, 2) != 2)
>>> +        goto out;
>>> +    if (magic != 0xAA55)
>>> +        goto out;
>>> +
>>> +    /* Find the size of the rom extension */
>>> +    if (start != lseek(mem, start, SEEK_SET))
>>> +        goto out;
>>> +    if (lseek(mem, 2, SEEK_CUR) != (start + 2))
>>> +        goto out;
>>> +    if (read(mem, &size, 1) != 1)
>>> +        goto out;
>>> +    /* This size is in 512K */
>>> +    size *= 512;
>>> +
>>> +    /*
>>> +    ** Set the file to the begining of the rombios,
>>> +    ** to start the copy.
>>> +    */
>>> +    if (start != lseek(mem, start, SEEK_SET))
>>> +    {
>>> +        size = 0;
>>> +        goto out;
>>> +    }
>>> +    if (size != read(mem, buf, size))
>>> +        size = 0;
>>> +
>>> +out:
>>> +    close(mem);
>>> +    return size;
>>> +}
>>> +
>>>  /*
>>>  * Local variables:
>>>  * mode: C
>>> diff -rupN --ignore-blank-lines-X diffignore a/tools/libxc/xenctrl.h 
>>> b/tools/libxc/xenctrl.h
>>> --- a/tools/libxc/xenctrl.h     2009-06-07 20:44:47.000000000 -0400
>>> +++ b/tools/libxc/xenctrl.h     2009-06-07 19:04:12.000000000 -0400
>>> @@ -145,6 +145,10 @@ int xc_waitdomain(
>>>     int *status,
>>>     int options);
>>>
>>> +int xc_get_vgabios(
>>> +    unsigned char       *bios,
>>> +    int                 len);
>>> +
>>>  #endif /* __linux__ */
>>>
>>>  /*
>>> diff -rupN --ignore-blank-lines-X diffignore a/tools/libxc/xenguest.h 
>>> b/tools/libxc/xenguest.h
>>> --- a/tools/libxc/xenguest.h    2009-06-07 20:44:47.000000000 -0400
>>> +++ b/tools/libxc/xenguest.h    2009-06-07 19:04:12.000000000 -0400
>>> @@ -134,7 +134,8 @@ int xc_hvm_build_target_mem(int xc_handl
>>>                             uint32_t domid,
>>>                             int memsize,
>>>                             int target,
>>> -                            const char *image_name);
>>> +                            const char *image_name,
>>> +                            int vga_pt_enabled);
>>>
>>>  int xc_hvm_build_mem(int xc_handle,
>>>                      uint32_t domid,
>>> diff -rupN --ignore-blank-lines-X diffignore 
>>> a/tools/python/xen/lowlevel/xc/xc.c b/tools/python/xen/lowlevel/xc/xc.c
>>> --- a/tools/python/xen/lowlevel/xc/xc.c 2009-06-07 20:44:47.000000000 -0400
>>> +++ b/tools/python/xen/lowlevel/xc/xc.c 2009-06-07 19:04:12.000000000 -0400
>>> @@ -890,21 +890,21 @@ static PyObject *pyxc_hvm_build(XcObject
>>>     int i;
>>>  #endif
>>>     char *image;
>>> -    int memsize, target=-1, vcpus = 1, acpi = 0, apic = 1;
>>> +    int memsize, target=-1, vcpus = 1, acpi = 0, apic = 1, vga_pt = 0;
>>>
>>>     static char *kwd_list[] = { "domid",
>>>                                 "memsize", "image", "target", "vcpus", 
>>> "acpi",
>>> -                                "apic", NULL };
>>> -    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iis|iiii", kwd_list,
>>> +                                "apic", "vga_pt", NULL };
>>> +    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iis|iiiii", kwd_list,
>>>                                       &dom, &memsize, &image, &target, 
>>> &vcpus,
>>> -                                      &acpi, &apic) )
>>> +                                      &acpi, &apic, &vga_pt) )
>>>         return NULL;
>>>
>>>     if ( target == -1 )
>>>         target = memsize;
>>>
>>>     if ( xc_hvm_build_target_mem(self->xc_handle, dom, memsize,
>>> -                                 target, image) != 0 )
>>> +                                 target, image, vga_pt) != 0 )
>>>         return pyxc_error_to_exception();
>>>
>>>  #if !defined(__ia64__)
>>> diff -rupN --ignore-blank-lines-X diffignore 
>>> a/tools/python/xen/xend/image.py b/tools/python/xen/xend/image.py
>>> --- a/tools/python/xen/xend/image.py    2009-06-07 20:44:47.000000000 -0400
>>> +++ b/tools/python/xen/xend/image.py    2009-06-07 19:04:12.000000000 -0400
>>> @@ -279,6 +279,9 @@ class ImageHandler:
>>>         vnc_config = {}
>>>         has_vnc = int(vmConfig['platform'].get('vnc', 0)) != 0
>>>         has_sdl = int(vmConfig['platform'].get('sdl', 0)) != 0
>>> +        has_vga_passthrough = 
>>> int(vmConfig['platform'].get('vga_passthrough', 0)) != 0
>>> +        has_intel = int(vmConfig['platform'].get('intel', 0)) != 0
>>> +
>>>         opengl = 1
>>>         keymap = vmConfig['platform'].get("keymap")
>>>         for dev_uuid in vmConfig['console_refs']:
>>> @@ -302,7 +305,7 @@ class ImageHandler:
>>>             ret.append("-k")
>>>             ret.append(keymap)
>>>
>>> -        if has_vnc:
>>> +        if has_vnc and not has_vga_passthrough:
>>>             if not vnc_config:
>>>                 for key in ('vncunused', 'vnclisten', 'vncdisplay',
>>>                             'vncpasswd'):
>>> @@ -353,6 +356,15 @@ class ImageHandler:
>>>
>>>         if int(vmConfig['platform'].get('monitor', 0)) != 0:
>>>             ret = ret + ['-monitor', 'vc']
>>> +
>>> +        if has_vga_passthrough:
>>> +            ret.append('-vga_passthrough')
>>> +            dom0_input = str(vmConfig['platform'].get('dom0_input'))
>>> +            ret = ret + ['-dom0-input', dom0_input]
>>> +
>>> +        if has_intel:
>>> +            ret.append('-intel')
>>> +
>>>         return ret
>>>
>>>     def getDeviceModelArgs(self, restore = False):
>>> @@ -754,7 +766,9 @@ class HVMImageHandler(ImageHandler):
>>>         self.apic = int(vmConfig['platform'].get('apic', 0))
>>>         self.acpi = int(vmConfig['platform'].get('acpi', 0))
>>>         self.guest_os_type = vmConfig['platform'].get('guest_os_type')
>>> -
>>> +        self.vga_pt = int(vmConfig['platform'].get('vga_passthrough', 0))
>>> +        self.dom0_input = str(vmConfig['platform'].get('dom0_input'))
>>> +        self.intel = int(vmConfig['platform'].get('intel', 0))
>>>
>>>     # Return a list of cmd line args to the device models based on the
>>>     # xm config file
>>> @@ -869,6 +883,7 @@ class HVMImageHandler(ImageHandler):
>>>         log.debug("vcpus          = %d", self.vm.getVCpuCount())
>>>         log.debug("acpi           = %d", self.acpi)
>>>         log.debug("apic           = %d", self.apic)
>>> +        log.debug("vga_pt         = %d", self.vga_pt)
>>>
>>>         rc = xc.hvm_build(domid          = self.vm.getDomid(),
>>>                           image          = self.loader,
>>> @@ -876,7 +891,8 @@ class HVMImageHandler(ImageHandler):
>>>                           target         = mem_mb,
>>>                           vcpus          = self.vm.getVCpuCount(),
>>>                           acpi           = self.acpi,
>>> -                          apic           = self.apic)
>>> +                          apic           = self.apic,
>>> +                          vga_pt         = self.vga_pt)
>>>         rc['notes'] = { 'SUSPEND_CANCEL': 1 }
>>>
>>>         rc['store_mfn'] = xc.hvm_get_param(self.vm.getDomid(),
>>> diff -rupN --ignore-blank-lines-X diffignore 
>>> a/tools/python/xen/xend/XendConfig.py b/tools/python/xen/xend/XendConfig.py
>>> --- a/tools/python/xen/xend/XendConfig.py       2009-06-07 
>>> 20:44:47.000000000 -0400
>>> +++ b/tools/python/xen/xend/XendConfig.py       2009-06-07 
>>> 19:04:12.000000000 -0400
>>> @@ -171,6 +171,9 @@ XENAPI_PLATFORM_CFG_TYPES = {
>>>     'pci_msitranslate': int,
>>>     'pci_power_mgmt': int,
>>>     'xen_platform_pci': int,
>>> +    'vga_passthrough': int,
>>> +    'dom0_input': str,
>>> +    'intel': int,
>>>  }
>>>
>>>  # Xen API console 'other_config' keys.
>>> diff -rupN --ignore-blank-lines-X diffignore 
>>> a/tools/python/xen/xm/create.py b/tools/python/xen/xm/create.py
>>> --- a/tools/python/xen/xm/create.py     2009-06-07 20:44:47.000000000 -0400
>>> +++ b/tools/python/xen/xm/create.py     2009-06-07 19:04:12.000000000 -0400
>>> @@ -618,6 +618,18 @@ gopts.var('xen_platform_pci', val='0|1',
>>>            fn=set_int, default=1,
>>>            use="Is xen_platform_pci used?")
>>>
>>> +gopts.var('vga_passthrough', val='0|1',
>>> +           fn=set_int, default=None,
>>> +           use="Enable the passthrough for the graphic card.")
>>> +
>>> +gopts.var('dom0_input', val='DOM0_INPUT',
>>> +           fn=set_value, default=None,
>>> +           use="Input arguments for dom0 driver")
>>> +
>>> +gopts.var('intel', val='INTEL',
>>> +           fn=set_int, default=None,
>>> +           use="Use Intel GFX.")
>>> +
>>>  def err(msg):
>>>     """Print an error to stderr and exit.
>>>     """
>>> @@ -932,7 +944,8 @@ def configure_hvm(config_image, vals):
>>>              'acpi', 'apic', 'usb', 'usbdevice', 'keymap', 'pci', 'hpet',
>>>              'guest_os_type', 'hap', 'opengl', 'cpuid', 'cpuid_check',
>>>              'viridian', 'xen_extended_power_mgmt', 'pci_msitranslate',
>>> -             'vpt_align', 'pci_power_mgmt', 'xen_platform_pci' ]
>>> +             'vpt_align', 'pci_power_mgmt', 'xen_platform_pci',
>>> +             'vga_passthrough', 'dom0_input', 'intel' ]
>>>
>>>     for a in args:
>>>         if a in vals.__dict__ and vals.__dict__[a] is not None:
>>>
>>> _______________________________________________
>>> Xen-devel mailing list
>>> Xen-devel@xxxxxxxxxxxxxxxxxxx
>>> http://lists.xensource.com/xen-devel
>>>
>>>
>>
>> Where did this patch come from? I plan to try using a ati card with a
>> windows domU this week but first I need to port this patch to 2.6.29,
>> before I start I want to make sure I am working with the latest
>> version of the patch.
>>
>> Andy
>>
>> _______________________________________________
>> Xen-devel mailing list
>> Xen-devel@xxxxxxxxxxxxxxxxxxx
>> http://lists.xensource.com/xen-devel
>
>

_______________________________________________
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®.