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