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

[Xen-changelog] [xen-unstable] Merge.



# HG changeset patch
# User sos22@xxxxxxxxxxxxxxxxxxxx
# Node ID fc0040fd13d8c72c095d90db2bf935f44134e97e
# Parent  4a669bd506577b075bc6cf2b0d7c8ac6e5a0dfc0
# Parent  1f7423795115cb1e18b1d56f28ae45f474d29ce3
Merge.
---
 docs/src/user.tex                                            |   48 ++
 linux-2.6-xen-sparse/drivers/xen/pciback/Makefile            |    3 
 linux-2.6-xen-sparse/drivers/xen/pciback/conf_space.c        |   76 ++-
 linux-2.6-xen-sparse/drivers/xen/pciback/conf_space.h        |   11 
 linux-2.6-xen-sparse/drivers/xen/pciback/conf_space_quirks.c |  128 ++++++
 linux-2.6-xen-sparse/drivers/xen/pciback/conf_space_quirks.h |   35 +
 linux-2.6-xen-sparse/drivers/xen/pciback/pci_stub.c          |  224 ++++++++++-
 linux-2.6-xen-sparse/drivers/xen/pciback/pciback.h           |    2 
 tools/examples/Makefile                                      |    2 
 tools/examples/xend-pci-permissive.sxp                       |   27 +
 tools/examples/xend-pci-quirks.sxp                           |   96 ++++
 tools/libxc/Makefile                                         |    3 
 tools/libxc/ia64/Makefile                                    |    8 
 tools/python/xen/util/pci.py                                 |   97 ++--
 tools/python/xen/xend/server/pciif.py                        |    7 
 tools/python/xen/xend/server/pciquirk.py                     |  145 +++++++
 16 files changed, 820 insertions(+), 92 deletions(-)

diff -r 4a669bd50657 -r fc0040fd13d8 docs/src/user.tex
--- a/docs/src/user.tex Fri Jul 28 14:06:27 2006 +0100
+++ b/docs/src/user.tex Fri Jul 28 14:09:05 2006 +0100
@@ -1287,8 +1287,8 @@ backend domain. The PCI Backend appears 
 backend domain. The PCI Backend appears to the Linux kernel as a regular PCI
 device driver. The PCI Backend ensures that no other device driver loads
 for the devices by binding itself as the device driver for those devices.
-PCI devices are identified by hexadecimal slot/funciton numbers (on Linux,
-use \path{lspci} to determine slot/funciton numbers of your devices) and
+PCI devices are identified by hexadecimal slot/function numbers (on Linux,
+use \path{lspci} to determine slot/function numbers of your devices) and
 can be specified with or without the PCI domain: \\
 \centerline{  {\tt ({\em bus}:{\em slot}.{\em func})} example {\tt (02:1d.3)}} 
\\
 \centerline{  {\tt ({\em domain}:{\em bus}:{\em slot}.{\em func})} example 
{\tt (0000:02:1d.3)}} \\
@@ -1343,6 +1343,50 @@ Unbind a device from its driver and bind
 
 Note that the "-n" option in the example is important as it causes echo to not
 output a new-line.
+
+\subsubsection{PCI Backend Configuration - User-space Quirks}
+Quirky devices (such as the Broadcom Tigon 3) may need write access to their
+configuration space registers.  Xen can be instructed to allow specified PCI
+devices write access to specific configuration space registers.  The policy may
+be found in:
+
+\centerline{ \path{/etc/xen/xend-pci-quirks.sxp} }
+
+The policy file is heavily commented and is intended to provide enough
+documentation for developers to extend it.
+
+\subsubsection{PCI Backend Configuration - Permissive Flag}
+If the user-space quirks approach doesn't meet your needs you may want to 
enable
+the permissive flag for that device.  To do so, first get the PCI domain, bus,
+slot, and function information from dom0 via \path{lspci}.  Then augment the
+user-space policy for permissive devices.  The permissive policy can be found
+in:
+
+\centerline{ \path{/etc/xen/xend-pci-permissive.sxp} }
+
+Currently, the only way to reset the permissive flag is to unbind the device
+from the PCI Backend driver.
+
+\subsubsection{PCI Backend - Checking Status}
+There two important sysfs nodes that provide a mechanism to view specifics on
+quirks and permissive devices:
+\begin{description}
+\item \path{/sys/bus/drivers/pciback/permissive} \\
+ Use \path{cat} on this file to view a list of permissive slots.
+\item \path{/sys/bus/drivers/pciback/quirks} \\
+ Use \path{cat} on this file view a hierarchical view of devices bound to the
+PCI backend, their PCI vendor/device ID, and any quirks that are associated 
with
+that particular slot.  
+\end{description}
+
+You may notice that every device bound to the PCI backend has 17 quirks 
standard 
+"quirks" regardless of \path{xend-pci-quirks.sxp}.  These default entries are
+necessary to support interactions between the PCI bus manager and the device 
bound
+to it.  Even non-quirky devices should have these standard entries.  
+
+In this case, preference was given to accuracy over aesthetics by choosing to
+show the standard quirks in the quirks list rather than hide them from the
+inquiring user 
 
 \subsubsection{PCI Frontend Configuration}
 To configure a domU to receive a PCI device:
diff -r 4a669bd50657 -r fc0040fd13d8 
linux-2.6-xen-sparse/drivers/xen/pciback/Makefile
--- a/linux-2.6-xen-sparse/drivers/xen/pciback/Makefile Fri Jul 28 14:06:27 
2006 +0100
+++ b/linux-2.6-xen-sparse/drivers/xen/pciback/Makefile Fri Jul 28 14:09:05 
2006 +0100
@@ -4,7 +4,8 @@ pciback-y += conf_space.o conf_space_hea
 pciback-y += conf_space.o conf_space_header.o \
             conf_space_capability.o \
             conf_space_capability_vpd.o \
-            conf_space_capability_pm.o
+            conf_space_capability_pm.o \
+             conf_space_quirks.o
 pciback-$(CONFIG_XEN_PCIDEV_BACKEND_VPCI) += vpci.o
 pciback-$(CONFIG_XEN_PCIDEV_BACKEND_PASS) += passthrough.o
 
diff -r 4a669bd50657 -r fc0040fd13d8 
linux-2.6-xen-sparse/drivers/xen/pciback/conf_space.c
--- a/linux-2.6-xen-sparse/drivers/xen/pciback/conf_space.c     Fri Jul 28 
14:06:27 2006 +0100
+++ b/linux-2.6-xen-sparse/drivers/xen/pciback/conf_space.c     Fri Jul 28 
14:09:05 2006 +0100
@@ -13,9 +13,7 @@
 #include <linux/pci.h>
 #include "pciback.h"
 #include "conf_space.h"
-
-static int permissive = 0;
-module_param(permissive, bool, 0644);
+#include "conf_space_quirks.h"
 
 #define DEFINE_PCI_CONFIG(op,size,type)                        \
 int pciback_##op##_config_##size                               \
@@ -81,7 +79,7 @@ static int conf_space_write(struct pci_d
        case 4:
                if (field->u.dw.write)
                        ret = field->u.dw.write(dev, offset, value,
-                                               entry->data);
+                                               entry->data);
                break;
        }
        return ret;
@@ -257,40 +255,60 @@ int pciback_config_write(struct pci_dev 
                 * This means that some fields may still be read-only because
                 * they have entries in the config_field list that intercept
                 * the write and do nothing. */
-               if (permissive) {
+               if (dev_data->permissive) {
                        switch (size) {
                        case 1:
                                err = pci_write_config_byte(dev, offset,
-                                                           (u8)value);
+                                                           (u8) value);
                                break;
                        case 2:
                                err = pci_write_config_word(dev, offset,
-                                                           (u16)value);
+                                                           (u16) value);
                                break;
                        case 4:
                                err = pci_write_config_dword(dev, offset,
-                                                            (u32)value);
+                                                            (u32) value);
                                break;
                        }
                } else if (!dev_data->warned_on_write) {
                        dev_data->warned_on_write = 1;
-                       dev_warn(&dev->dev, "Driver wrote to a read-only "
-                                "configuration space field!\n");
-                       dev_warn(&dev->dev, "Write at offset 0x%x size %d\n",
-                               offset, size);
-                       dev_warn(&dev->dev, "This may be harmless, but if\n");
-                       dev_warn(&dev->dev, "you have problems with your "
-                                "device:\n");
-                       dev_warn(&dev->dev, "1) see the permissive "
-                                "attribute in sysfs.\n");
-                       dev_warn(&dev->dev, "2) report problems to the "
-                                "xen-devel mailing list along\n");
-                       dev_warn(&dev->dev, "   with details of your device "
-                                "obtained from lspci.\n");
+                       dev_warn(&dev->dev, "Driver tried to write to a "
+                                "read-only configuration space field at offset 
"
+                                "0x%x, size %d. This may be harmless, but if "
+                                "you have problems with your device:\n"
+                                "1) see permissive attribute in sysfs\n"
+                                "2) report problems to the xen-devel "
+                                "mailing list along with details of your "
+                                "device obtained from lspci.\n", offset, size);
                }
        }
 
        return pcibios_err_to_errno(err);
+}
+
+void pciback_config_free_dyn_fields(struct pci_dev *dev)
+{
+       struct pciback_dev_data *dev_data = pci_get_drvdata(dev);
+       struct config_field_entry *cfg_entry, *t;
+       struct config_field *field;
+
+       dev_dbg(&dev->dev,
+               "free-ing dynamically allocated virtual configuration space 
fields\n");
+
+       list_for_each_entry_safe(cfg_entry, t, &dev_data->config_fields, list) {
+               field = cfg_entry->field;
+
+               if (field->clean) {
+                       field->clean(field);
+
+                       if (cfg_entry->data)
+                               kfree(cfg_entry->data);
+
+                       list_del(&cfg_entry->list);
+                       kfree(cfg_entry);
+               }
+
+       }
 }
 
 void pciback_config_reset_dev(struct pci_dev *dev)
@@ -337,6 +355,10 @@ int pciback_config_add_field_offset(stru
        struct pciback_dev_data *dev_data = pci_get_drvdata(dev);
        struct config_field_entry *cfg_entry;
        void *tmp;
+
+       /* silently ignore duplicate fields */
+       if (pciback_field_is_dup(dev, field->offset))
+               goto out;
 
        cfg_entry = kmalloc(sizeof(*cfg_entry), GFP_KERNEL);
        if (!cfg_entry) {
@@ -388,6 +410,10 @@ int pciback_config_init_dev(struct pci_d
                goto out;
 
        err = pciback_config_capability_add_fields(dev);
+       if (err)
+               goto out;
+
+       err = pciback_config_quirks_init(dev);
 
       out:
        return err;
@@ -395,9 +421,5 @@ int pciback_config_init_dev(struct pci_d
 
 int pciback_config_init(void)
 {
-       int err;
-
-       err = pciback_config_capability_init();
-
-       return err;
-}
+       return pciback_config_capability_init();
+}
diff -r 4a669bd50657 -r fc0040fd13d8 
linux-2.6-xen-sparse/drivers/xen/pciback/conf_space.h
--- a/linux-2.6-xen-sparse/drivers/xen/pciback/conf_space.h     Fri Jul 28 
14:06:27 2006 +0100
+++ b/linux-2.6-xen-sparse/drivers/xen/pciback/conf_space.h     Fri Jul 28 
14:09:05 2006 +0100
@@ -33,11 +33,13 @@ typedef int (*conf_byte_read) (struct pc
  * values.
  */
 struct config_field {
-       unsigned int     offset;
-       unsigned int     size;
-       conf_field_init  init;
+       unsigned int offset;
+       unsigned int size;
+       unsigned int mask;
+       conf_field_init init;
        conf_field_reset reset;
-       conf_field_free  release;
+       conf_field_free release;
+       void (*clean) (struct config_field * field);
        union {
                struct {
                        conf_dword_write write;
@@ -52,6 +54,7 @@ struct config_field {
                        conf_byte_read read;
                } b;
        } u;
+       struct list_head list;
 };
 
 struct config_field_entry {
diff -r 4a669bd50657 -r fc0040fd13d8 
linux-2.6-xen-sparse/drivers/xen/pciback/pci_stub.c
--- a/linux-2.6-xen-sparse/drivers/xen/pciback/pci_stub.c       Fri Jul 28 
14:06:27 2006 +0100
+++ b/linux-2.6-xen-sparse/drivers/xen/pciback/pci_stub.c       Fri Jul 28 
14:09:05 2006 +0100
@@ -1,7 +1,8 @@
 /*
  * PCI Stub Driver - Grabs devices in backend to be exported later
  *
- *   Author: Ryan Wilson <hap9@xxxxxxxxxxxxxx>
+ * Ryan Wilson <hap9@xxxxxxxxxxxxxx>
+ * Chris Bookholt <hap10@xxxxxxxxxxxxxx>
  */
 #include <linux/module.h>
 #include <linux/init.h>
@@ -10,6 +11,8 @@
 #include <linux/kref.h>
 #include <asm/atomic.h>
 #include "pciback.h"
+#include "conf_space.h"
+#include "conf_space_quirks.h"
 
 static char *pci_devs_to_hide = NULL;
 module_param_named(hide, pci_devs_to_hide, charp, 0444);
@@ -31,6 +34,7 @@ struct pcistub_device {
        struct pci_dev *dev;
        struct pciback_device *pdev;    /* non-NULL if struct pci_dev is in use 
*/
 };
+
 /* Access to pcistub_devices & seized_devices lists and the initialize_devices
  * flag must be locked with pcistub_devices_lock
  */
@@ -76,6 +80,7 @@ static void pcistub_device_release(struc
 
        /* Clean-up the device */
        pciback_reset_device(psdev->dev);
+       pciback_config_free_dyn_fields(psdev->dev);
        pciback_config_free_dev(psdev->dev);
        kfree(pci_get_drvdata(psdev->dev));
        pci_set_drvdata(psdev->dev, NULL);
@@ -93,6 +98,32 @@ static inline void pcistub_device_put(st
 static inline void pcistub_device_put(struct pcistub_device *psdev)
 {
        kref_put(&psdev->kref, pcistub_device_release);
+}
+
+static struct pcistub_device *pcistub_device_find(int domain, int bus,
+                                                 int slot, int func)
+{
+       struct pcistub_device *psdev = NULL;
+       unsigned long flags;
+
+       spin_lock_irqsave(&pcistub_devices_lock, flags);
+
+       list_for_each_entry(psdev, &pcistub_devices, dev_list) {
+               if (psdev->dev != NULL
+                   && domain == pci_domain_nr(psdev->dev->bus)
+                   && bus == psdev->dev->bus->number
+                   && PCI_DEVFN(slot, func) == psdev->dev->devfn) {
+                       pcistub_device_get(psdev);
+                       goto out;
+               }
+       }
+
+       /* didn't find it */
+       psdev = NULL;
+
+      out:
+       spin_unlock_irqrestore(&pcistub_devices_lock, flags);
+       return psdev;
 }
 
 static struct pci_dev *pcistub_device_get_pci_dev(struct pciback_device *pdev,
@@ -180,6 +211,7 @@ void pcistub_put_pci_dev(struct pci_dev 
         * (so it's ready for the next domain)
         */
        pciback_reset_device(found_psdev->dev);
+       pciback_config_free_dyn_fields(found_psdev->dev);
        pciback_config_reset_dev(found_psdev->dev);
 
        spin_lock_irqsave(&found_psdev->lock, flags);
@@ -392,6 +424,8 @@ static void pcistub_remove(struct pci_de
 
        spin_lock_irqsave(&pcistub_devices_lock, flags);
 
+       pciback_config_quirk_release(dev);
+
        list_for_each_entry(psdev, &pcistub_devices, dev_list) {
                if (psdev->dev == dev) {
                        found_psdev = psdev;
@@ -471,6 +505,19 @@ static inline int str_to_slot(const char
        return -EINVAL;
 }
 
+static inline int str_to_quirk(const char *buf, int *domain, int *bus, int
+                              *slot, int *func, int *reg, int *size, int *mask)
+{
+       int err;
+
+       err =
+           sscanf(buf, " %04x:%02x:%02x.%1x-%08x:%1x:%08x", domain, bus, slot,
+                  func, reg, size, mask);
+       if (err == 7)
+               return 0;
+       return -EINVAL;
+}
+
 static int pcistub_device_id_add(int domain, int bus, int slot, int func)
 {
        struct pcistub_device_id *pci_dev_id;
@@ -523,6 +570,46 @@ static int pcistub_device_id_remove(int 
        return err;
 }
 
+static int pcistub_reg_add(int domain, int bus, int slot, int func, int reg,
+                          int size, int mask)
+{
+       int err = 0;
+       struct pcistub_device *psdev;
+       struct pci_dev *dev;
+       struct config_field *field;
+
+       psdev = pcistub_device_find(domain, bus, slot, func);
+       if (!psdev || !psdev->dev) {
+               err = -ENODEV;
+               goto out;
+       }
+       dev = psdev->dev;
+
+       /* check for duplicate field */
+       if (pciback_field_is_dup(dev, reg))
+               goto out;
+
+       field = kzalloc(sizeof(*field), GFP_ATOMIC);
+       if (!field) {
+               err = -ENOMEM;
+               goto out;
+       }
+
+       field->offset = reg;
+       field->size = size;
+       field->mask = mask;
+       field->init = NULL;
+       field->reset = NULL;
+       field->release = NULL;
+       field->clean = pciback_config_field_free;
+
+       err = pciback_config_quirks_add_field(dev, field);
+       if (err)
+               kfree(field);
+      out:
+       return err;
+}
+
 static ssize_t pcistub_slot_add(struct device_driver *drv, const char *buf,
                                size_t count)
 {
@@ -586,6 +673,137 @@ static ssize_t pcistub_slot_show(struct 
 }
 
 DRIVER_ATTR(slots, S_IRUSR, pcistub_slot_show, NULL);
+
+static ssize_t pcistub_quirk_add(struct device_driver *drv, const char *buf,
+                                size_t count)
+{
+       int domain, bus, slot, func, reg, size, mask;
+       int err;
+
+       err = str_to_quirk(buf, &domain, &bus, &slot, &func, &reg, &size,
+                          &mask);
+       if (err)
+               goto out;
+
+       err = pcistub_reg_add(domain, bus, slot, func, reg, size, mask);
+
+      out:
+       if (!err)
+               err = count;
+       return err;
+}
+
+static ssize_t pcistub_quirk_show(struct device_driver *drv, char *buf)
+{
+       int count = 0;
+       unsigned long flags;
+       extern struct list_head pciback_quirks;
+       struct pciback_config_quirk *quirk;
+       struct pciback_dev_data *dev_data;
+       struct config_field *field;
+       struct config_field_entry *cfg_entry;
+
+       spin_lock_irqsave(&device_ids_lock, flags);
+       list_for_each_entry(quirk, &pciback_quirks, quirks_list) {
+               if (count >= PAGE_SIZE)
+                       goto out;
+
+               count += scnprintf(buf + count, PAGE_SIZE - count,
+                                  "%02x:%02x.%01x\n\t%04x:%04x:%04x:%04x\n",
+                                  quirk->pdev->bus->number,
+                                  PCI_SLOT(quirk->pdev->devfn),
+                                  PCI_FUNC(quirk->pdev->devfn),
+                                  quirk->devid.vendor, quirk->devid.device,
+                                  quirk->devid.subvendor,
+                                  quirk->devid.subdevice);
+
+               dev_data = pci_get_drvdata(quirk->pdev);
+
+               list_for_each_entry(cfg_entry, &dev_data->config_fields, list) {
+                       field = cfg_entry->field;
+                       if (count >= PAGE_SIZE)
+                               goto out;
+
+                       count += scnprintf(buf + count, PAGE_SIZE -
+                                          count, "\t\t%08x:%01x:%08x\n",
+                                          field->offset, field->size,
+                                          field->mask);
+               }
+       }
+
+      out:
+       spin_unlock_irqrestore(&device_ids_lock, flags);
+
+       return count;
+}
+
+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,
+                             size_t count)
+{
+       int domain, bus, slot, func;
+       int err;
+       struct pcistub_device *psdev;
+       struct pciback_dev_data *dev_data;
+       err = str_to_slot(buf, &domain, &bus, &slot, &func);
+       if (err)
+               goto out;
+       psdev = pcistub_device_find(domain, bus, slot, func);
+       if (!psdev) {
+               err = -ENODEV;
+               goto out;
+       }
+       if (!psdev->dev) {
+               err = -ENODEV;
+               goto release;
+       }
+       dev_data = pci_get_drvdata(psdev->dev);
+       /* the driver data for a device should never be null at this point */
+       if (!dev_data) {
+               err = -ENXIO;
+               goto release;
+       }
+       if (!dev_data->permissive) {
+               dev_data->permissive = 1;
+               /* Let user know that what they're doing could be unsafe */
+               dev_warn(&psdev->dev->dev,
+                        "enabling permissive mode configuration space 
accesses!\n");
+               dev_warn(&psdev->dev->dev,
+                        "permissive mode is potentially unsafe!\n");
+       }
+      release:
+       pcistub_device_put(psdev);
+      out:
+       if (!err)
+               err = count;
+       return err;
+}
+
+static ssize_t permissive_show(struct device_driver *drv, char *buf)
+{
+       struct pcistub_device *psdev;
+       struct pciback_dev_data *dev_data;
+       size_t count = 0;
+       unsigned long flags;
+       spin_lock_irqsave(&pcistub_devices_lock, flags);
+       list_for_each_entry(psdev, &pcistub_devices, dev_list) {
+               if (count >= PAGE_SIZE)
+                       break;
+               if (!psdev->dev)
+                       continue;
+               dev_data = pci_get_drvdata(psdev->dev);
+               if (!dev_data || !dev_data->permissive)
+                       continue;
+               count +=
+                   scnprintf(buf + count, PAGE_SIZE - count, "%s\n",
+                             pci_name(psdev->dev));
+       }
+       spin_unlock_irqrestore(&pcistub_devices_lock, flags);
+       return count;
+}
+
+DRIVER_ATTR(permissive, S_IRUSR | S_IWUSR, permissive_show, permissive_add);
 
 static int __init pcistub_init(void)
 {
@@ -631,6 +849,8 @@ static int __init pcistub_init(void)
        driver_create_file(&pciback_pci_driver.driver,
                           &driver_attr_remove_slot);
        driver_create_file(&pciback_pci_driver.driver, &driver_attr_slots);
+       driver_create_file(&pciback_pci_driver.driver, &driver_attr_quirks);
+       driver_create_file(&pciback_pci_driver.driver, &driver_attr_permissive);
 
       out:
        return err;
@@ -680,6 +900,8 @@ static void __exit pciback_cleanup(void)
        driver_remove_file(&pciback_pci_driver.driver,
                           &driver_attr_remove_slot);
        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);
 
        pci_unregister_driver(&pciback_pci_driver);
 }
diff -r 4a669bd50657 -r fc0040fd13d8 
linux-2.6-xen-sparse/drivers/xen/pciback/pciback.h
--- a/linux-2.6-xen-sparse/drivers/xen/pciback/pciback.h        Fri Jul 28 
14:06:27 2006 +0100
+++ b/linux-2.6-xen-sparse/drivers/xen/pciback/pciback.h        Fri Jul 28 
14:09:05 2006 +0100
@@ -44,6 +44,7 @@ struct pciback_device {
 
 struct pciback_dev_data {
        struct list_head config_fields;
+       int permissive;
        int warned_on_write;
 };
 
@@ -61,6 +62,7 @@ void pciback_reset_device(struct pci_dev
 /* Access a virtual configuration space for a PCI device */
 int pciback_config_init(void);
 int pciback_config_init_dev(struct pci_dev *dev);
+void pciback_config_free_dyn_fields(struct pci_dev *dev);
 void pciback_config_reset_dev(struct pci_dev *dev);
 void pciback_config_free_dev(struct pci_dev *dev);
 int pciback_config_read(struct pci_dev *dev, int offset, int size,
diff -r 4a669bd50657 -r fc0040fd13d8 tools/examples/Makefile
--- a/tools/examples/Makefile   Fri Jul 28 14:06:27 2006 +0100
+++ b/tools/examples/Makefile   Fri Jul 28 14:09:05 2006 +0100
@@ -18,6 +18,8 @@ XEN_CONFIGS += xmexample2
 XEN_CONFIGS += xmexample2
 XEN_CONFIGS += xmexample.hvm
 XEN_CONFIGS += xmexample.vti
+XEN_CONFIGS += xend-pci-quirks.sxp
+XEN_CONFIGS += xend-pci-permissive.sxp
 
 # Xen script dir and scripts to go there.
 XEN_SCRIPT_DIR = /etc/xen/scripts
diff -r 4a669bd50657 -r fc0040fd13d8 tools/libxc/Makefile
--- a/tools/libxc/Makefile      Fri Jul 28 14:06:27 2006 +0100
+++ b/tools/libxc/Makefile      Fri Jul 28 14:09:05 2006 +0100
@@ -35,8 +35,7 @@ GUEST_SRCS-$(CONFIG_MIGRATE) += xc_linux
 GUEST_SRCS-$(CONFIG_MIGRATE) += xc_linux_restore.c xc_linux_save.c
 GUEST_SRCS-$(CONFIG_HVM) += xc_hvm_build.c
 
-# This Makefile only adds files if CONFIG_IA64 is y.
-include ia64/Makefile
+-include $(XEN_TARGET_ARCH)/Makefile
 
 CFLAGS   += -Werror
 CFLAGS   += -fno-strict-aliasing
diff -r 4a669bd50657 -r fc0040fd13d8 tools/libxc/ia64/Makefile
--- a/tools/libxc/ia64/Makefile Fri Jul 28 14:06:27 2006 +0100
+++ b/tools/libxc/ia64/Makefile Fri Jul 28 14:09:05 2006 +0100
@@ -1,5 +1,5 @@ CTRL_SRCS-$(CONFIG_IA64) += ia64/xc_ia64
-CTRL_SRCS-$(CONFIG_IA64) += ia64/xc_ia64_stubs.c
+CTRL_SRCS-y += ia64/xc_ia64_stubs.c
 
-GUEST_SRCS-$(CONFIG_IA64) += ia64/xc_ia64_hvm_build.c
-GUEST_SRCS-$(CONFIG_IA64) += ia64/xc_ia64_linux_save.c
-GUEST_SRCS-$(CONFIG_IA64) += ia64/xc_ia64_linux_restore.c
+GUEST_SRCS-y += ia64/xc_ia64_hvm_build.c
+GUEST_SRCS-y += ia64/xc_ia64_linux_save.c
+GUEST_SRCS-y += ia64/xc_ia64_linux_restore.c
diff -r 4a669bd50657 -r fc0040fd13d8 tools/python/xen/util/pci.py
--- a/tools/python/xen/util/pci.py      Fri Jul 28 14:06:27 2006 +0100
+++ b/tools/python/xen/util/pci.py      Fri Jul 28 14:09:05 2006 +0100
@@ -16,6 +16,10 @@ SYSFS_PCI_DEV_RESOURCE_PATH = '/resource
 SYSFS_PCI_DEV_RESOURCE_PATH = '/resource'
 SYSFS_PCI_DEV_IRQ_PATH = '/irq'
 SYSFS_PCI_DEV_DRIVER_DIR_PATH = '/driver'
+SYSFS_PCI_DEV_VENDOR_PATH = '/vendor'
+SYSFS_PCI_DEV_DEVICE_PATH = '/device'
+SYSFS_PCI_DEV_SUBVENDOR_PATH = '/subsystem_vendor'
+SYSFS_PCI_DEV_SUBDEVICE_PATH = '/subsystem_device'
 
 PCI_BAR_IO = 0x01
 PCI_BAR_IO_MASK = ~0x03
@@ -66,9 +70,12 @@ class PciDevice:
         self.iomem = []
         self.ioports = []
         self.driver = None
+        self.vendor = None
+        self.device = None
+        self.subvendor = None
+        self.subdevice = None
 
-        if not self.get_info_from_sysfs():
-            self.get_info_from_proc()
+        self.get_info_from_sysfs()
 
     def get_info_from_sysfs(self):
         try:
@@ -85,7 +92,7 @@ class PciDevice:
         try:
             resource_file = open(path,'r')
 
-            for i in range(7):
+            for i in range(PROC_PCI_NUM_RESOURCES):
                 line = resource_file.readline()
                 sline = line.split()
                 if len(sline)<3:
@@ -122,53 +129,39 @@ class PciDevice:
             raise PciDeviceParseError(('Failed to read %s: %s (%d)' %
                 (path, strerr, errno)))
 
+        path = sysfs_mnt+SYSFS_PCI_DEVS_PATH+'/'+ \
+                self.name+SYSFS_PCI_DEV_VENDOR_PATH
+        try:
+            self.vendor = int(open(path,'r').readline(), 16)
+        except IOError, (errno, strerr):
+            raise PciDeviceParseError(('Failed to open & read %s: %s (%d)' %
+                (path, strerr, errno)))
+
+        path = sysfs_mnt+SYSFS_PCI_DEVS_PATH+'/'+ \
+                self.name+SYSFS_PCI_DEV_DEVICE_PATH
+        try:
+            self.device = int(open(path,'r').readline(), 16)
+        except IOError, (errno, strerr):
+            raise PciDeviceParseError(('Failed to open & read %s: %s (%d)' %
+                (path, strerr, errno)))
+
+        path = sysfs_mnt+SYSFS_PCI_DEVS_PATH+'/'+ \
+                self.name+SYSFS_PCI_DEV_SUBVENDOR_PATH
+        try:
+            self.subvendor = int(open(path,'r').readline(), 16)
+        except IOError, (errno, strerr):
+            raise PciDeviceParseError(('Failed to open & read %s: %s (%d)' %
+                (path, strerr, errno)))
+
+        path = sysfs_mnt+SYSFS_PCI_DEVS_PATH+'/'+ \
+                self.name+SYSFS_PCI_DEV_SUBDEVICE_PATH
+        try:
+            self.subdevice = int(open(path,'r').readline(), 16)
+        except IOError, (errno, strerr):
+            raise PciDeviceParseError(('Failed to open & read %s: %s (%d)' %
+                (path, strerr, errno)))
+
         return True
-        
-    def get_info_from_proc(self):
-        bus_devfn = '%02x%02x' % (self.bus,PCI_DEVFN(self.slot,self.func))
-
-        # /proc/bus/pci/devices doesn't expose domains
-        if self.domain!=0:
-            raise PciDeviceParseError("Can't yet detect resource usage by "+
-                    "devices in other domains through proc!")
-
-        try:
-            proc_pci_file = open(PROC_PCI_PATH,'r')
-        except IOError, (errno, strerr):
-            raise PciDeviceParseError(('Failed to open %s: %s (%d)' %
-                (PROC_PCI_PATH, strerr, errno)))
-
-        for line in proc_pci_file:
-            sline = line.split()
-            if len(sline)<(PROC_PCI_NUM_RESOURCES*2+3):
-                continue
-
-            if sline[0]==bus_devfn:
-                self.dissect_proc_pci_line(sline)
-                break
-        else:
-            raise PciDeviceNotFoundError(self.domain, self.bus,
-                    self.slot, self.func)
-
-    def dissect_proc_pci_line(self, sline):
-        self.irq = int(sline[2],16)
-        start_idx = 3
-        for i in range(PROC_PCI_NUM_RESOURCES):
-            flags = int(sline[start_idx+i],16)
-            size = int(sline[start_idx+i+PROC_PCI_NUM_RESOURCES],16)
-            if flags&PCI_BAR_IO:
-                start = flags&PCI_BAR_IO_MASK
-                if start!=0:
-                    self.ioports.append( (start,size) )
-            else:
-                start = flags&PCI_BAR_MEM_MASK
-                if start!=0:
-                    self.iomem.append( (start,size) )
-
-        # detect driver module name
-        driver_idx = PROC_PCI_NUM_RESOURCES*2+3
-        if len(sline)>driver_idx:
-            self.driver = sline[driver_idx]
 
     def __str__(self):
         str = "PCI Device %s\n" % (self.name)
@@ -176,7 +169,11 @@ class PciDevice:
             str = str + "IO Port 0x%02x [size=%d]\n"%(start,size)
         for (start,size) in self.iomem:
             str = str + "IO Mem 0x%02x [size=%d]\n"%(start,size)
-        str = str + "IRQ %d"%(self.irq)
+        str = str + "IRQ %d\n"%(self.irq)
+        str = str + "Vendor ID 0x%04x\n"%(self.vendor)
+        str = str + "Device ID 0x%04x\n"%(self.device)
+        str = str + "Sybsystem Vendor ID 0x%04x\n"%(self.subvendor)
+        str = str + "Subsystem Device ID 0x%04x"%(self.subdevice)
         return str
 
 def main():
diff -r 4a669bd50657 -r fc0040fd13d8 tools/python/xen/xend/server/pciif.py
--- a/tools/python/xen/xend/server/pciif.py     Fri Jul 28 14:06:27 2006 +0100
+++ b/tools/python/xen/xend/server/pciif.py     Fri Jul 28 14:09:05 2006 +0100
@@ -32,6 +32,8 @@ from xen.util.pci import PciDevice
 from xen.util.pci import PciDevice
 import resource
 import re
+
+from xen.xend.server.pciquirk import *
 
 xc = xen.lowlevel.xc.xc()
 
@@ -150,7 +152,10 @@ class PciController(DevController):
                     "bind your slot/device to the PCI backend using sysfs" \
                     )%(dev.name))
 
-        for (start, size) in dev.ioports:
+        PCIQuirk(dev.vendor, dev.device, dev.subvendor, dev.subdevice, domain, 
+                bus, slot, func)
+
+       for (start, size) in dev.ioports:
             log.debug('pci: enabling ioport 0x%x/0x%x'%(start,size))
             rc = xc.domain_ioport_permission(dom = fe_domid, first_port = 
start,
                     nr_ports = size, allow_access = True)
diff -r 4a669bd50657 -r fc0040fd13d8 
linux-2.6-xen-sparse/drivers/xen/pciback/conf_space_quirks.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/linux-2.6-xen-sparse/drivers/xen/pciback/conf_space_quirks.c      Fri Jul 
28 14:09:05 2006 +0100
@@ -0,0 +1,128 @@
+/*
+ * PCI Backend - Handle special overlays for broken devices.
+ *
+ * Author: Ryan Wilson <hap9@xxxxxxxxxxxxxx>
+ * Author: Chris Bookholt <hap10@xxxxxxxxxxxxxx>
+ */
+
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include "pciback.h"
+#include "conf_space.h"
+#include "conf_space_quirks.h"
+
+LIST_HEAD(pciback_quirks);
+
+struct pciback_config_quirk *pciback_find_quirk(struct pci_dev *dev)
+{
+       struct pciback_config_quirk *tmp_quirk;
+
+       list_for_each_entry(tmp_quirk, &pciback_quirks, quirks_list)
+           if (pci_match_id(&tmp_quirk->devid, dev))
+               goto out;
+       tmp_quirk = NULL;
+       printk(KERN_DEBUG
+              "quirk didn't match any device pciback knows about\n");
+      out:
+       return tmp_quirk;
+}
+
+static inline void register_quirk(struct pciback_config_quirk *quirk)
+{
+       list_add_tail(&quirk->quirks_list, &pciback_quirks);
+}
+
+int pciback_field_is_dup(struct pci_dev *dev, int reg)
+{
+       int ret = 0;
+       struct pciback_dev_data *dev_data = pci_get_drvdata(dev);
+       struct config_field *field;
+       struct config_field_entry *cfg_entry;
+
+       list_for_each_entry(cfg_entry, &dev_data->config_fields, list) {
+               field = cfg_entry->field;
+               if (field->offset == reg) {
+                       ret = 1;
+                       break;
+               }
+       }
+       return ret;
+}
+
+int pciback_config_quirks_add_field(struct pci_dev *dev, struct config_field
+                                   *field)
+{
+       int err = 0;
+
+       switch (field->size) {
+       case 1:
+               field->u.b.read = pciback_read_config_byte;
+               field->u.b.write = pciback_write_config_byte;
+               break;
+       case 2:
+               field->u.w.read = pciback_read_config_word;
+               field->u.w.write = pciback_write_config_word;
+               break;
+       case 4:
+               field->u.dw.read = pciback_read_config_dword;
+               field->u.dw.write = pciback_write_config_dword;
+               break;
+       default:
+               err = -EINVAL;
+               goto out;
+       }
+
+       pciback_config_add_field(dev, field);
+
+      out:
+       return err;
+}
+
+int pciback_config_quirks_init(struct pci_dev *dev)
+{
+       struct pciback_config_quirk *quirk;
+       int ret = 0;
+
+       quirk = kzalloc(sizeof(*quirk), GFP_ATOMIC);
+       if (!quirk) {
+               ret = -ENOMEM;
+               goto out;
+       }
+
+       quirk->devid.vendor = dev->vendor;
+       quirk->devid.device = dev->device;
+       quirk->devid.subvendor = dev->subsystem_vendor;
+       quirk->devid.subdevice = dev->subsystem_device;
+       quirk->devid.class = 0;
+       quirk->devid.class_mask = 0;
+       quirk->devid.driver_data = 0UL;
+
+       quirk->pdev = dev;
+
+       register_quirk(quirk);
+      out:
+       return ret;
+}
+
+void pciback_config_field_free(struct config_field *field)
+{
+       kfree(field);
+}
+
+int pciback_config_quirk_release(struct pci_dev *dev)
+{
+       struct pciback_config_quirk *quirk;
+       int ret = 0;
+
+       quirk = pciback_find_quirk(dev);
+       if (!quirk) {
+               ret = -ENXIO;
+               goto out;
+       }
+
+       list_del(&quirk->quirks_list);
+       kfree(quirk);
+
+      out:
+       return ret;
+}
diff -r 4a669bd50657 -r fc0040fd13d8 
linux-2.6-xen-sparse/drivers/xen/pciback/conf_space_quirks.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/linux-2.6-xen-sparse/drivers/xen/pciback/conf_space_quirks.h      Fri Jul 
28 14:09:05 2006 +0100
@@ -0,0 +1,35 @@
+/*
+ * PCI Backend - Data structures for special overlays for broken devices.
+ *
+ * Ryan Wilson <hap9@xxxxxxxxxxxxxx>
+ * Chris Bookholt <hap10@xxxxxxxxxxxxxx>
+ */
+
+#ifndef __XEN_PCIBACK_CONF_SPACE_QUIRKS_H__
+#define __XEN_PCIBACK_CONF_SPACE_QUIRKS_H__
+
+#include <linux/pci.h>
+#include <linux/list.h>
+
+struct pciback_config_quirk {
+       struct list_head quirks_list;
+       struct pci_device_id devid;
+       struct pci_dev *pdev;
+};
+
+struct pciback_config_quirk *pciback_find_quirk(struct pci_dev *dev);
+
+int pciback_config_quirks_add_field(struct pci_dev *dev, struct config_field
+                                   *field);
+
+int pciback_config_quirks_remove_field(struct pci_dev *dev, int reg);
+
+int pciback_config_quirks_init(struct pci_dev *dev);
+
+void pciback_config_field_free(struct config_field *field);
+
+int pciback_config_quirk_release(struct pci_dev *dev);
+
+int pciback_field_is_dup(struct pci_dev *dev, int reg);
+
+#endif
diff -r 4a669bd50657 -r fc0040fd13d8 tools/examples/xend-pci-permissive.sxp
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/examples/xend-pci-permissive.sxp    Fri Jul 28 14:09:05 2006 +0100
@@ -0,0 +1,27 @@
+###############################################################################
+# Configuration file for granting quiry PCI devices full write access to their 
+# configuration space.  This file should only be used when you are unable to 
+# determine the exact registers required by your device.  Even so, it should 
+# be used only temporarily.
+# 
+# SEND A MESSAGE TO xen-devel@xxxxxxxxxxxxxxxxxxx IF YOU USE THIS FILE.
+# 
+# Using this file should NOT be necessary.  If you must use it to make some
+# device work, send a message to the above list with as much information about 
+# your device as possible so the developers can make accomodations for it.  
+# Once developers make the necessary updates you can remove the corresponding
+# entry for your device. 
+###############################################################################
+# Entries are formated as follows:  <vendor>:<device>[:<subvendor>:<subdevice>]
+# 
+# Example: Appending to an existing list
+#  
+# (unconstrained_dev_ids
+#     ('XXXX:XXXX:XXXX:XXXX'   # existing entry
+#      'YYYY:YYYY:YYYY:YYYY'   # new entry 1
+#      'ZZZZ:ZZZZ')            # new entry 2
+# )
+###############################################################################
+(unconstrained_dev_ids
+     #('0123:4567:89AB:CDEF')
+)
diff -r 4a669bd50657 -r fc0040fd13d8 tools/examples/xend-pci-quirks.sxp
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/examples/xend-pci-quirks.sxp        Fri Jul 28 14:09:05 2006 +0100
@@ -0,0 +1,96 @@
+###############################################################################
+# Configuration file for quirky PCI devices that require write-access to 
+# parts of the configuration space.  Use this file to specific PCI device
+# IDs and the configuration space fields to which those devices must be
+# able to write.
+#
+# Length is important, so be sure to match new entries with the 
+# lengths of comparable existing entries. 
+#
+# Additions to this file take effect as soon as a new domain with a 
+# matching device is started.  However, to remove a field that was 
+# previously applied to a device you must unbind the device from 
+# pciback.
+###############################################################################
+# This is a bogus entry to show how a new device would be added to the list
+#
+# (new_quirky_dev_name
+#    (pci_ids 
+#       ('0123:4567:890A:BCEF') 
+#    )
+#
+#    (pci_config_space_fields 
+#       ('12345678:1:00000000')
+#    )
+# )
+###############################################################################
+
+(tg3
+    (pci_ids
+       # Entries are formated as follows:  
+       #     <vendor>:<device>[:<subvendor>:<subdevice>]
+        ('14e4:1644'   # Broadcom Tigon3 5700
+        '14e4:1645'   # Broadcom Tigon3 5701
+         '14e4:1646'   # Broadcom Tigon3 5702
+         '14e4:1647'   # Broadcom Tigon3 5703
+         '14e4:1648'   # Broadcom Tigon3 5704
+         '14e4:164d'   # Broadcom Tigon3 5702FE
+         '14e4:1653'   # Broadcom Tigon3 5705
+         '14e4:1654'   # Broadcom Tigon3 5705_2
+         '14e4:165d'   # Broadcom Tigon3 5705M
+         '14e4:165e'   # Broadcom Tigon3 5705M_2
+         '14e4:16a6'   # Broadcom Tigon3 5702X
+         '14e4:16a7'   # Broadcom Tigon3 5703X
+         '14e4:16a8'   # Broadcom Tigon3 5704S
+         '14e4:16c6'   # Broadcom Tigon3 5702A3
+         '14e4:16c7'   # Broadcom Tigon3 5703A3
+         '14e4:1696'   # Broadcom Tigon3 5782
+         '14e4:169c'   # Broadcom Tigon3 5788
+         '14e4:169d'   # Broadcom Tigon3 5789
+         '14e4:170d'   # Broadcom Tigon3 5901
+         '14e4:1649'   # Broadcom Tigon3 5704S_2
+         '14e4:166e'   # Broadcom Tigon3 5705F
+         '14e4:1658'   # Broadcom Tigon3 5720
+         '14e4:1659'   # Broadcom Tigon3 5721
+         '14e4:1676'   # Broadcom Tigon3 5750
+         '14e4:1677'   # Broadcom Tigon3 5751
+         '14e4:167c'   # Broadcom Tigon3 5750M
+         '14e4:167d'   # Broadcom Tigon3 5751M
+         '14e4:167e'   # Broadcom Tigon3 5751F
+         '14e4:1600'   # Broadcom Tigon3 5752
+         '14e4:1601'   # Broadcom Tigon3 5752M
+         '14e4:16f7'   # Broadcom Tigon3 5753
+         '14e4:16fd'   # Broadcom Tigon3 5753M
+         '14e4:16fe'   # Broadcom Tigon3 5753F
+         '14e4:1668'   # Broadcom Tigon3 5714
+         '14e4:1678'   # Broadcom Tigon3 5715
+         '14e4:166a'   # Broadcom Tigon3 5780
+         '14e4:166b'   # Broadcom Tigon3 5780S
+         '14e4:16dd'   # Broadcom Tigon3 5781
+         '1148:4400'   # Syskonnect 9DXX
+         '1148:4500'   # Syskonnect 9MXX
+         '173b:03e8'   # Altima AC1000
+         '173b:03e9'   # Altima AC1001
+         '173b:03eb'   # Altima AC1003
+         '173b:03ea'   # Altima AC9100
+         '106b:1645')  # Apple Tigon3
+    )
+
+    (pci_config_space_fields
+       # Entries are formated as follows:  
+       #     <register>:<size>:<mask>
+       # size is measured in bytes (1,2,4 are valid sizes)
+       # mask is currently unused; use all zero's
+        ('00000078:4:00000000'   # TG3PCI_REG_BASE_ADDR
+         '0000007c:4:00000000'   # TG3PCI_MEM_WIN_BASE_ADDR
+         '00000080:4:00000000'   # TG3PCI_REG_DATA
+         '00000084:4:00000000'   # TG3PCI_MEM_WIN_DATA
+         '00000090:4:00000000'   # TG3PCI_MISC_LOCAL_CTRL
+         '00000068:4:00000000'   # TG3PCI_MISC_HOST_CTRL
+         '0000009C:4:00000000'   # TG3PCI_STD_RING_PROD_IDX + TG3_64BIT_REG_LOW
+         '00000098:4:00000000'   # TG3PCI_STD_RING_PROD_IDX + 
TG3_64BIT_REG_HIGH
+         '000000a4:4:00000000'   # TG3PCI_RCV_RET_RING_CON_IDX + 
TG3_64BIT_REG_LOW
+         '000000a0:4:00000000'   # TG3PCI_RCV_RET_RING_CON_IDX + 
TG3_64BIT_REG_HIGH
+         '00000070:4:00000000')  # TG3PCI_PCISTATE
+    )
+)
diff -r 4a669bd50657 -r fc0040fd13d8 tools/python/xen/xend/server/pciquirk.py
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/python/xen/xend/server/pciquirk.py  Fri Jul 28 14:09:05 2006 +0100
@@ -0,0 +1,145 @@
+from xen.xend.XendLogging import log
+from xen.xend.XendError import XendError
+import sys
+import os.path
+from xen.xend.sxp import *
+
+QUIRK_SYSFS_NODE = "/sys/bus/pci/drivers/pciback/quirks"
+QUIRK_CONFIG_FILE = "/etc/xen/xend-pci-quirks.sxp"
+PERMISSIVE_CONFIG_FILE = "/etc/xen/xend-pci-permissive.sxp"
+PERMISSIVE_SYSFS_NODE = "/sys/bus/pci/drivers/pciback/permissive"
+
+class PCIQuirk:
+    def __init__( self, vendor, device, subvendor, subdevice, domain, bus, 
slot, func):
+        self.vendor = vendor
+        self.device = device
+        self.subvendor = subvendor
+        self.subdevice = subdevice
+       self.domain = domain
+       self.bus = bus
+       self.slot = slot
+       self.func = func
+
+        self.devid = "%04x:%04x:%04x:%04x" % (vendor, device, subvendor, 
subdevice)
+       self.pciid = "%04x:%02x:%02x.%01x" % (domain, bus, slot, func)
+
+        self.quirks = self.__getQuirksByID( )
+
+       self.__sendQuirks( )
+       self.__sendPermDevs( )
+
+    def __matchPCIdev( self, list ):
+        ret = False
+        if list == None:
+            return False
+        for id in list:
+            if id.startswith( self.devid[:9] ): # id's vendor and device ID 
match
+                skey = id.split(':')
+                size = len(skey)
+                if (size == 2):                # subvendor/subdevice not 
suplied
+                    ret = True
+                    break
+                elif (size == 4):      # check subvendor/subdevice
+                    # check subvendor
+                   subven = '%04x' % self.subvendor
+                    if ((skey[2] != 'FFFF') and 
+                        (skey[2] != 'ffff') and 
+                        (skey[2] != subven)):
+                            continue
+                    # check subdevice
+                   subdev = '%04x' % self.subdevice
+                    if ((skey[3] != 'FFFF') and 
+                        (skey[3] != 'ffff') and 
+                        (skey[3] != subdev)):
+                            continue
+                    ret = True
+                    break
+                else:
+                    log.debug("WARNING: invalid configuration entry: %s" % id)
+                    ret = False
+                    break
+        return ret
+        
+    def __getQuirksByID( self ):
+        if os.path.exists(QUIRK_CONFIG_FILE):
+            try:
+                fin = file(QUIRK_CONFIG_FILE, 'rb')
+                try:
+                    pci_quirks_config = parse(fin)
+                finally:
+                    fin.close()
+                if pci_quirks_config is None:
+                    pci_quirks_config = ['xend-pci-quirks']
+                else:
+                    pci_quirks_config.insert(0, 'xend-pci-quirks')
+                self.pci_quirks_config = pci_quirks_config
+            except Exception, ex:
+                raise XendError("Reading config file %s: %s" %
+                               (QUIRK_CONFIG_FILE, str(ex)))
+        else:
+            log.info("Config file does not exist: %s" % QUIRK_CONFIG_FILE)
+            self.pci_quirks_config = ['xend-pci-quirks']
+
+        devices = children(self.pci_quirks_config)
+        for dev in devices:
+            ids = child_at(child(dev,'pci_ids'),0)
+            fields = child_at(child(dev,'pci_config_space_fields'),0)
+           if self.__matchPCIdev( ids ):
+                log.info("Quirks found for PCI device [%s]" % self.devid)
+                return fields
+
+        log.info("NO quirks found for PCI device [%s]" % self.devid)
+        return []
+
+    def __sendQuirks(self):
+        for quirk in self.quirks:
+            log.debug("Quirk Info: %04x:%02x:%02x.%1x-%s" % (self.domain,
+                   self.bus, self.slot, self.func, quirk))
+            try:
+                f = file(QUIRK_SYSFS_NODE ,"w")
+                f.write( "%04x:%02x:%02x.%1x-%s" % (self.domain, self.bus,
+                       self.slot, self.func, quirk) )
+                f.close()
+            except Exception, e:
+                raise VmError("pci: failed to open/write/close quirks sysfs " 
+ \
+                       "node - " + str(e))
+
+    def __devIsUnconstrained( self ):
+        if os.path.exists(PERMISSIVE_CONFIG_FILE):
+            try:
+                fin = file(PERMISSIVE_CONFIG_FILE, 'rb')
+                try:
+                    pci_perm_dev_config = parse(fin)
+                finally:
+                    fin.close()
+                if pci_perm_dev_config is None:
+                    pci_perm_dev_config = ['']
+                else:
+                    pci_perm_dev_config.insert(0, '')
+                self.pci_perm_dev_config = pci_perm_dev_config
+            except Exception, ex:
+                raise XendError("Reading config file %s: %s" %
+                               (PERMISSIVE_CONFIG_FILE,str(ex)))
+        else:
+            log.info("Config file does not exist: %s" % PERMISSIVE_CONFIG_FILE)
+            self.pci_perm_dev_config = ['xend-pci-perm-devs']
+
+        devices = child_at(child(pci_perm_dev_config, 
'unconstrained_dev_ids'),0)
+       if self.__matchPCIdev( devices ):
+            log.debug("Permissive mode enabled for PCI device [%s]" % 
self.devid)
+            return True
+        log.debug("Permissive mode NOT enabled for PCI device [%s]" % 
self.devid)
+        return False
+
+    def __sendPermDevs(self):
+       if self.__devIsUnconstrained( ):
+            log.debug("Unconstrained device: %04x:%02x:%02x.%1x" % 
(self.domain,
+                   self.bus, self.slot, self.func))
+            try:
+                f = file(PERMISSIVE_SYSFS_NODE ,"w")
+                f.write( "%04x:%02x:%02x.%1x" % (self.domain, self.bus,
+                       self.slot, self.func) )
+                f.close()
+            except Exception, e:
+                raise VmError("pci: failed to open/write/close permissive " + \
+               "sysfs node: " + str(e))

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

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