WARNING - OLD ARCHIVES

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

xen-devel

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

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
<Prev in Thread] Current Thread [Next in Thread>