ia64/xen-unstable

changeset 10853:fc0040fd13d8

Merge.
author sos22@douglas.cl.cam.ac.uk
date Fri Jul 28 14:09:05 2006 +0100 (2006-07-28)
parents 4a669bd50657 1f7423795115
children 1fb835267a50
files
line diff
     1.1 --- a/docs/src/user.tex	Fri Jul 28 14:06:27 2006 +0100
     1.2 +++ b/docs/src/user.tex	Fri Jul 28 14:09:05 2006 +0100
     1.3 @@ -1287,8 +1287,8 @@ Section~\ref{s:configure}). Note that de
     1.4  backend domain. The PCI Backend appears to the Linux kernel as a regular PCI
     1.5  device driver. The PCI Backend ensures that no other device driver loads
     1.6  for the devices by binding itself as the device driver for those devices.
     1.7 -PCI devices are identified by hexadecimal slot/funciton numbers (on Linux,
     1.8 -use \path{lspci} to determine slot/funciton numbers of your devices) and
     1.9 +PCI devices are identified by hexadecimal slot/function numbers (on Linux,
    1.10 +use \path{lspci} to determine slot/function numbers of your devices) and
    1.11  can be specified with or without the PCI domain: \\
    1.12  \centerline{  {\tt ({\em bus}:{\em slot}.{\em func})} example {\tt (02:1d.3)}} \\
    1.13  \centerline{  {\tt ({\em domain}:{\em bus}:{\em slot}.{\em func})} example {\tt (0000:02:1d.3)}} \\
    1.14 @@ -1344,6 +1344,50 @@ Unbind a device from its driver and bind
    1.15  Note that the "-n" option in the example is important as it causes echo to not
    1.16  output a new-line.
    1.17  
    1.18 +\subsubsection{PCI Backend Configuration - User-space Quirks}
    1.19 +Quirky devices (such as the Broadcom Tigon 3) may need write access to their
    1.20 +configuration space registers.  Xen can be instructed to allow specified PCI
    1.21 +devices write access to specific configuration space registers.  The policy may
    1.22 +be found in:
    1.23 +
    1.24 +\centerline{ \path{/etc/xen/xend-pci-quirks.sxp} }
    1.25 +
    1.26 +The policy file is heavily commented and is intended to provide enough
    1.27 +documentation for developers to extend it.
    1.28 +
    1.29 +\subsubsection{PCI Backend Configuration - Permissive Flag}
    1.30 +If the user-space quirks approach doesn't meet your needs you may want to enable
    1.31 +the permissive flag for that device.  To do so, first get the PCI domain, bus,
    1.32 +slot, and function information from dom0 via \path{lspci}.  Then augment the
    1.33 +user-space policy for permissive devices.  The permissive policy can be found
    1.34 +in:
    1.35 +
    1.36 +\centerline{ \path{/etc/xen/xend-pci-permissive.sxp} }
    1.37 +
    1.38 +Currently, the only way to reset the permissive flag is to unbind the device
    1.39 +from the PCI Backend driver.
    1.40 +
    1.41 +\subsubsection{PCI Backend - Checking Status}
    1.42 +There two important sysfs nodes that provide a mechanism to view specifics on
    1.43 +quirks and permissive devices:
    1.44 +\begin{description}
    1.45 +\item \path{/sys/bus/drivers/pciback/permissive} \\
    1.46 + Use \path{cat} on this file to view a list of permissive slots.
    1.47 +\item \path{/sys/bus/drivers/pciback/quirks} \\
    1.48 + Use \path{cat} on this file view a hierarchical view of devices bound to the
    1.49 +PCI backend, their PCI vendor/device ID, and any quirks that are associated with
    1.50 +that particular slot.  
    1.51 +\end{description}
    1.52 +
    1.53 +You may notice that every device bound to the PCI backend has 17 quirks standard 
    1.54 +"quirks" regardless of \path{xend-pci-quirks.sxp}.  These default entries are
    1.55 +necessary to support interactions between the PCI bus manager and the device bound
    1.56 +to it.  Even non-quirky devices should have these standard entries.  
    1.57 +
    1.58 +In this case, preference was given to accuracy over aesthetics by choosing to
    1.59 +show the standard quirks in the quirks list rather than hide them from the
    1.60 +inquiring user 
    1.61 +
    1.62  \subsubsection{PCI Frontend Configuration}
    1.63  To configure a domU to receive a PCI device:
    1.64  
     2.1 --- a/linux-2.6-xen-sparse/drivers/xen/pciback/Makefile	Fri Jul 28 14:06:27 2006 +0100
     2.2 +++ b/linux-2.6-xen-sparse/drivers/xen/pciback/Makefile	Fri Jul 28 14:09:05 2006 +0100
     2.3 @@ -4,7 +4,8 @@ pciback-y := pci_stub.o pciback_ops.o xe
     2.4  pciback-y += conf_space.o conf_space_header.o \
     2.5  	     conf_space_capability.o \
     2.6  	     conf_space_capability_vpd.o \
     2.7 -	     conf_space_capability_pm.o
     2.8 +	     conf_space_capability_pm.o \
     2.9 +             conf_space_quirks.o
    2.10  pciback-$(CONFIG_XEN_PCIDEV_BACKEND_VPCI) += vpci.o
    2.11  pciback-$(CONFIG_XEN_PCIDEV_BACKEND_PASS) += passthrough.o
    2.12  
     3.1 --- a/linux-2.6-xen-sparse/drivers/xen/pciback/conf_space.c	Fri Jul 28 14:06:27 2006 +0100
     3.2 +++ b/linux-2.6-xen-sparse/drivers/xen/pciback/conf_space.c	Fri Jul 28 14:09:05 2006 +0100
     3.3 @@ -13,9 +13,7 @@
     3.4  #include <linux/pci.h>
     3.5  #include "pciback.h"
     3.6  #include "conf_space.h"
     3.7 -
     3.8 -static int permissive = 0;
     3.9 -module_param(permissive, bool, 0644);
    3.10 +#include "conf_space_quirks.h"
    3.11  
    3.12  #define DEFINE_PCI_CONFIG(op,size,type) 			\
    3.13  int pciback_##op##_config_##size 				\
    3.14 @@ -81,7 +79,7 @@ static int conf_space_write(struct pci_d
    3.15  	case 4:
    3.16  		if (field->u.dw.write)
    3.17  			ret = field->u.dw.write(dev, offset, value,
    3.18 -					        entry->data);
    3.19 +						entry->data);
    3.20  		break;
    3.21  	}
    3.22  	return ret;
    3.23 @@ -257,42 +255,62 @@ int pciback_config_write(struct pci_dev 
    3.24  		 * This means that some fields may still be read-only because
    3.25  		 * they have entries in the config_field list that intercept
    3.26  		 * the write and do nothing. */
    3.27 -		if (permissive) {
    3.28 +		if (dev_data->permissive) {
    3.29  			switch (size) {
    3.30  			case 1:
    3.31  				err = pci_write_config_byte(dev, offset,
    3.32 -							    (u8)value);
    3.33 +							    (u8) value);
    3.34  				break;
    3.35  			case 2:
    3.36  				err = pci_write_config_word(dev, offset,
    3.37 -							    (u16)value);
    3.38 +							    (u16) value);
    3.39  				break;
    3.40  			case 4:
    3.41  				err = pci_write_config_dword(dev, offset,
    3.42 -							     (u32)value);
    3.43 +							     (u32) value);
    3.44  				break;
    3.45  			}
    3.46  		} else if (!dev_data->warned_on_write) {
    3.47  			dev_data->warned_on_write = 1;
    3.48 -			dev_warn(&dev->dev, "Driver wrote to a read-only "
    3.49 -				 "configuration space field!\n");
    3.50 -			dev_warn(&dev->dev, "Write at offset 0x%x size %d\n",
    3.51 -				offset, size);
    3.52 -			dev_warn(&dev->dev, "This may be harmless, but if\n");
    3.53 -			dev_warn(&dev->dev, "you have problems with your "
    3.54 -				 "device:\n");
    3.55 -			dev_warn(&dev->dev, "1) see the permissive "
    3.56 -				 "attribute in sysfs.\n");
    3.57 -			dev_warn(&dev->dev, "2) report problems to the "
    3.58 -				 "xen-devel mailing list along\n");
    3.59 -			dev_warn(&dev->dev, "   with details of your device "
    3.60 -				 "obtained from lspci.\n");
    3.61 +			dev_warn(&dev->dev, "Driver tried to write to a "
    3.62 +				 "read-only configuration space field at offset "
    3.63 +				 "0x%x, size %d. This may be harmless, but if "
    3.64 +				 "you have problems with your device:\n"
    3.65 +				 "1) see permissive attribute in sysfs\n"
    3.66 +				 "2) report problems to the xen-devel "
    3.67 +				 "mailing list along with details of your "
    3.68 +				 "device obtained from lspci.\n", offset, size);
    3.69  		}
    3.70  	}
    3.71  
    3.72  	return pcibios_err_to_errno(err);
    3.73  }
    3.74  
    3.75 +void pciback_config_free_dyn_fields(struct pci_dev *dev)
    3.76 +{
    3.77 +	struct pciback_dev_data *dev_data = pci_get_drvdata(dev);
    3.78 +	struct config_field_entry *cfg_entry, *t;
    3.79 +	struct config_field *field;
    3.80 +
    3.81 +	dev_dbg(&dev->dev,
    3.82 +		"free-ing dynamically allocated virtual configuration space fields\n");
    3.83 +
    3.84 +	list_for_each_entry_safe(cfg_entry, t, &dev_data->config_fields, list) {
    3.85 +		field = cfg_entry->field;
    3.86 +
    3.87 +		if (field->clean) {
    3.88 +			field->clean(field);
    3.89 +
    3.90 +			if (cfg_entry->data)
    3.91 +				kfree(cfg_entry->data);
    3.92 +
    3.93 +			list_del(&cfg_entry->list);
    3.94 +			kfree(cfg_entry);
    3.95 +		}
    3.96 +
    3.97 +	}
    3.98 +}
    3.99 +
   3.100  void pciback_config_reset_dev(struct pci_dev *dev)
   3.101  {
   3.102  	struct pciback_dev_data *dev_data = pci_get_drvdata(dev);
   3.103 @@ -338,6 +356,10 @@ int pciback_config_add_field_offset(stru
   3.104  	struct config_field_entry *cfg_entry;
   3.105  	void *tmp;
   3.106  
   3.107 +	/* silently ignore duplicate fields */
   3.108 +	if (pciback_field_is_dup(dev, field->offset))
   3.109 +		goto out;
   3.110 +
   3.111  	cfg_entry = kmalloc(sizeof(*cfg_entry), GFP_KERNEL);
   3.112  	if (!cfg_entry) {
   3.113  		err = -ENOMEM;
   3.114 @@ -388,6 +410,10 @@ int pciback_config_init_dev(struct pci_d
   3.115  		goto out;
   3.116  
   3.117  	err = pciback_config_capability_add_fields(dev);
   3.118 +	if (err)
   3.119 +		goto out;
   3.120 +
   3.121 +	err = pciback_config_quirks_init(dev);
   3.122  
   3.123        out:
   3.124  	return err;
   3.125 @@ -395,9 +421,5 @@ int pciback_config_init_dev(struct pci_d
   3.126  
   3.127  int pciback_config_init(void)
   3.128  {
   3.129 -	int err;
   3.130 -
   3.131 -	err = pciback_config_capability_init();
   3.132 -
   3.133 -	return err;
   3.134 +	return pciback_config_capability_init();
   3.135  }
     4.1 --- a/linux-2.6-xen-sparse/drivers/xen/pciback/conf_space.h	Fri Jul 28 14:06:27 2006 +0100
     4.2 +++ b/linux-2.6-xen-sparse/drivers/xen/pciback/conf_space.h	Fri Jul 28 14:09:05 2006 +0100
     4.3 @@ -33,11 +33,13 @@ typedef int (*conf_byte_read) (struct pc
     4.4   * values.
     4.5   */
     4.6  struct config_field {
     4.7 -	unsigned int     offset;
     4.8 -	unsigned int     size;
     4.9 -	conf_field_init  init;
    4.10 +	unsigned int offset;
    4.11 +	unsigned int size;
    4.12 +	unsigned int mask;
    4.13 +	conf_field_init init;
    4.14  	conf_field_reset reset;
    4.15 -	conf_field_free  release;
    4.16 +	conf_field_free release;
    4.17 +	void (*clean) (struct config_field * field);
    4.18  	union {
    4.19  		struct {
    4.20  			conf_dword_write write;
    4.21 @@ -52,6 +54,7 @@ struct config_field {
    4.22  			conf_byte_read read;
    4.23  		} b;
    4.24  	} u;
    4.25 +	struct list_head list;
    4.26  };
    4.27  
    4.28  struct config_field_entry {
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/linux-2.6-xen-sparse/drivers/xen/pciback/conf_space_quirks.c	Fri Jul 28 14:09:05 2006 +0100
     5.3 @@ -0,0 +1,128 @@
     5.4 +/*
     5.5 + * PCI Backend - Handle special overlays for broken devices.
     5.6 + *
     5.7 + * Author: Ryan Wilson <hap9@epoch.ncsc.mil>
     5.8 + * Author: Chris Bookholt <hap10@epoch.ncsc.mil>
     5.9 + */
    5.10 +
    5.11 +#include <linux/kernel.h>
    5.12 +#include <linux/pci.h>
    5.13 +#include "pciback.h"
    5.14 +#include "conf_space.h"
    5.15 +#include "conf_space_quirks.h"
    5.16 +
    5.17 +LIST_HEAD(pciback_quirks);
    5.18 +
    5.19 +struct pciback_config_quirk *pciback_find_quirk(struct pci_dev *dev)
    5.20 +{
    5.21 +	struct pciback_config_quirk *tmp_quirk;
    5.22 +
    5.23 +	list_for_each_entry(tmp_quirk, &pciback_quirks, quirks_list)
    5.24 +	    if (pci_match_id(&tmp_quirk->devid, dev))
    5.25 +		goto out;
    5.26 +	tmp_quirk = NULL;
    5.27 +	printk(KERN_DEBUG
    5.28 +	       "quirk didn't match any device pciback knows about\n");
    5.29 +      out:
    5.30 +	return tmp_quirk;
    5.31 +}
    5.32 +
    5.33 +static inline void register_quirk(struct pciback_config_quirk *quirk)
    5.34 +{
    5.35 +	list_add_tail(&quirk->quirks_list, &pciback_quirks);
    5.36 +}
    5.37 +
    5.38 +int pciback_field_is_dup(struct pci_dev *dev, int reg)
    5.39 +{
    5.40 +	int ret = 0;
    5.41 +	struct pciback_dev_data *dev_data = pci_get_drvdata(dev);
    5.42 +	struct config_field *field;
    5.43 +	struct config_field_entry *cfg_entry;
    5.44 +
    5.45 +	list_for_each_entry(cfg_entry, &dev_data->config_fields, list) {
    5.46 +		field = cfg_entry->field;
    5.47 +		if (field->offset == reg) {
    5.48 +			ret = 1;
    5.49 +			break;
    5.50 +		}
    5.51 +	}
    5.52 +	return ret;
    5.53 +}
    5.54 +
    5.55 +int pciback_config_quirks_add_field(struct pci_dev *dev, struct config_field
    5.56 +				    *field)
    5.57 +{
    5.58 +	int err = 0;
    5.59 +
    5.60 +	switch (field->size) {
    5.61 +	case 1:
    5.62 +		field->u.b.read = pciback_read_config_byte;
    5.63 +		field->u.b.write = pciback_write_config_byte;
    5.64 +		break;
    5.65 +	case 2:
    5.66 +		field->u.w.read = pciback_read_config_word;
    5.67 +		field->u.w.write = pciback_write_config_word;
    5.68 +		break;
    5.69 +	case 4:
    5.70 +		field->u.dw.read = pciback_read_config_dword;
    5.71 +		field->u.dw.write = pciback_write_config_dword;
    5.72 +		break;
    5.73 +	default:
    5.74 +		err = -EINVAL;
    5.75 +		goto out;
    5.76 +	}
    5.77 +
    5.78 +	pciback_config_add_field(dev, field);
    5.79 +
    5.80 +      out:
    5.81 +	return err;
    5.82 +}
    5.83 +
    5.84 +int pciback_config_quirks_init(struct pci_dev *dev)
    5.85 +{
    5.86 +	struct pciback_config_quirk *quirk;
    5.87 +	int ret = 0;
    5.88 +
    5.89 +	quirk = kzalloc(sizeof(*quirk), GFP_ATOMIC);
    5.90 +	if (!quirk) {
    5.91 +		ret = -ENOMEM;
    5.92 +		goto out;
    5.93 +	}
    5.94 +
    5.95 +	quirk->devid.vendor = dev->vendor;
    5.96 +	quirk->devid.device = dev->device;
    5.97 +	quirk->devid.subvendor = dev->subsystem_vendor;
    5.98 +	quirk->devid.subdevice = dev->subsystem_device;
    5.99 +	quirk->devid.class = 0;
   5.100 +	quirk->devid.class_mask = 0;
   5.101 +	quirk->devid.driver_data = 0UL;
   5.102 +
   5.103 +	quirk->pdev = dev;
   5.104 +
   5.105 +	register_quirk(quirk);
   5.106 +      out:
   5.107 +	return ret;
   5.108 +}
   5.109 +
   5.110 +void pciback_config_field_free(struct config_field *field)
   5.111 +{
   5.112 +	kfree(field);
   5.113 +}
   5.114 +
   5.115 +int pciback_config_quirk_release(struct pci_dev *dev)
   5.116 +{
   5.117 +	struct pciback_config_quirk *quirk;
   5.118 +	int ret = 0;
   5.119 +
   5.120 +	quirk = pciback_find_quirk(dev);
   5.121 +	if (!quirk) {
   5.122 +		ret = -ENXIO;
   5.123 +		goto out;
   5.124 +	}
   5.125 +
   5.126 +	list_del(&quirk->quirks_list);
   5.127 +	kfree(quirk);
   5.128 +
   5.129 +      out:
   5.130 +	return ret;
   5.131 +}
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/linux-2.6-xen-sparse/drivers/xen/pciback/conf_space_quirks.h	Fri Jul 28 14:09:05 2006 +0100
     6.3 @@ -0,0 +1,35 @@
     6.4 +/*
     6.5 + * PCI Backend - Data structures for special overlays for broken devices.
     6.6 + *
     6.7 + * Ryan Wilson <hap9@epoch.ncsc.mil>
     6.8 + * Chris Bookholt <hap10@epoch.ncsc.mil>
     6.9 + */
    6.10 +
    6.11 +#ifndef __XEN_PCIBACK_CONF_SPACE_QUIRKS_H__
    6.12 +#define __XEN_PCIBACK_CONF_SPACE_QUIRKS_H__
    6.13 +
    6.14 +#include <linux/pci.h>
    6.15 +#include <linux/list.h>
    6.16 +
    6.17 +struct pciback_config_quirk {
    6.18 +	struct list_head quirks_list;
    6.19 +	struct pci_device_id devid;
    6.20 +	struct pci_dev *pdev;
    6.21 +};
    6.22 +
    6.23 +struct pciback_config_quirk *pciback_find_quirk(struct pci_dev *dev);
    6.24 +
    6.25 +int pciback_config_quirks_add_field(struct pci_dev *dev, struct config_field
    6.26 +				    *field);
    6.27 +
    6.28 +int pciback_config_quirks_remove_field(struct pci_dev *dev, int reg);
    6.29 +
    6.30 +int pciback_config_quirks_init(struct pci_dev *dev);
    6.31 +
    6.32 +void pciback_config_field_free(struct config_field *field);
    6.33 +
    6.34 +int pciback_config_quirk_release(struct pci_dev *dev);
    6.35 +
    6.36 +int pciback_field_is_dup(struct pci_dev *dev, int reg);
    6.37 +
    6.38 +#endif
     7.1 --- a/linux-2.6-xen-sparse/drivers/xen/pciback/pci_stub.c	Fri Jul 28 14:06:27 2006 +0100
     7.2 +++ b/linux-2.6-xen-sparse/drivers/xen/pciback/pci_stub.c	Fri Jul 28 14:09:05 2006 +0100
     7.3 @@ -1,7 +1,8 @@
     7.4  /*
     7.5   * PCI Stub Driver - Grabs devices in backend to be exported later
     7.6   *
     7.7 - *   Author: Ryan Wilson <hap9@epoch.ncsc.mil>
     7.8 + * Ryan Wilson <hap9@epoch.ncsc.mil>
     7.9 + * Chris Bookholt <hap10@epoch.ncsc.mil>
    7.10   */
    7.11  #include <linux/module.h>
    7.12  #include <linux/init.h>
    7.13 @@ -10,6 +11,8 @@
    7.14  #include <linux/kref.h>
    7.15  #include <asm/atomic.h>
    7.16  #include "pciback.h"
    7.17 +#include "conf_space.h"
    7.18 +#include "conf_space_quirks.h"
    7.19  
    7.20  static char *pci_devs_to_hide = NULL;
    7.21  module_param_named(hide, pci_devs_to_hide, charp, 0444);
    7.22 @@ -31,6 +34,7 @@ struct pcistub_device {
    7.23  	struct pci_dev *dev;
    7.24  	struct pciback_device *pdev;	/* non-NULL if struct pci_dev is in use */
    7.25  };
    7.26 +
    7.27  /* Access to pcistub_devices & seized_devices lists and the initialize_devices
    7.28   * flag must be locked with pcistub_devices_lock
    7.29   */
    7.30 @@ -76,6 +80,7 @@ static void pcistub_device_release(struc
    7.31  
    7.32  	/* Clean-up the device */
    7.33  	pciback_reset_device(psdev->dev);
    7.34 +	pciback_config_free_dyn_fields(psdev->dev);
    7.35  	pciback_config_free_dev(psdev->dev);
    7.36  	kfree(pci_get_drvdata(psdev->dev));
    7.37  	pci_set_drvdata(psdev->dev, NULL);
    7.38 @@ -95,6 +100,32 @@ static inline void pcistub_device_put(st
    7.39  	kref_put(&psdev->kref, pcistub_device_release);
    7.40  }
    7.41  
    7.42 +static struct pcistub_device *pcistub_device_find(int domain, int bus,
    7.43 +						  int slot, int func)
    7.44 +{
    7.45 +	struct pcistub_device *psdev = NULL;
    7.46 +	unsigned long flags;
    7.47 +
    7.48 +	spin_lock_irqsave(&pcistub_devices_lock, flags);
    7.49 +
    7.50 +	list_for_each_entry(psdev, &pcistub_devices, dev_list) {
    7.51 +		if (psdev->dev != NULL
    7.52 +		    && domain == pci_domain_nr(psdev->dev->bus)
    7.53 +		    && bus == psdev->dev->bus->number
    7.54 +		    && PCI_DEVFN(slot, func) == psdev->dev->devfn) {
    7.55 +			pcistub_device_get(psdev);
    7.56 +			goto out;
    7.57 +		}
    7.58 +	}
    7.59 +
    7.60 +	/* didn't find it */
    7.61 +	psdev = NULL;
    7.62 +
    7.63 +      out:
    7.64 +	spin_unlock_irqrestore(&pcistub_devices_lock, flags);
    7.65 +	return psdev;
    7.66 +}
    7.67 +
    7.68  static struct pci_dev *pcistub_device_get_pci_dev(struct pciback_device *pdev,
    7.69  						  struct pcistub_device *psdev)
    7.70  {
    7.71 @@ -180,6 +211,7 @@ void pcistub_put_pci_dev(struct pci_dev 
    7.72  	 * (so it's ready for the next domain)
    7.73  	 */
    7.74  	pciback_reset_device(found_psdev->dev);
    7.75 +	pciback_config_free_dyn_fields(found_psdev->dev);
    7.76  	pciback_config_reset_dev(found_psdev->dev);
    7.77  
    7.78  	spin_lock_irqsave(&found_psdev->lock, flags);
    7.79 @@ -392,6 +424,8 @@ static void pcistub_remove(struct pci_de
    7.80  
    7.81  	spin_lock_irqsave(&pcistub_devices_lock, flags);
    7.82  
    7.83 +	pciback_config_quirk_release(dev);
    7.84 +
    7.85  	list_for_each_entry(psdev, &pcistub_devices, dev_list) {
    7.86  		if (psdev->dev == dev) {
    7.87  			found_psdev = psdev;
    7.88 @@ -471,6 +505,19 @@ static inline int str_to_slot(const char
    7.89  	return -EINVAL;
    7.90  }
    7.91  
    7.92 +static inline int str_to_quirk(const char *buf, int *domain, int *bus, int
    7.93 +			       *slot, int *func, int *reg, int *size, int *mask)
    7.94 +{
    7.95 +	int err;
    7.96 +
    7.97 +	err =
    7.98 +	    sscanf(buf, " %04x:%02x:%02x.%1x-%08x:%1x:%08x", domain, bus, slot,
    7.99 +		   func, reg, size, mask);
   7.100 +	if (err == 7)
   7.101 +		return 0;
   7.102 +	return -EINVAL;
   7.103 +}
   7.104 +
   7.105  static int pcistub_device_id_add(int domain, int bus, int slot, int func)
   7.106  {
   7.107  	struct pcistub_device_id *pci_dev_id;
   7.108 @@ -523,6 +570,46 @@ static int pcistub_device_id_remove(int 
   7.109  	return err;
   7.110  }
   7.111  
   7.112 +static int pcistub_reg_add(int domain, int bus, int slot, int func, int reg,
   7.113 +			   int size, int mask)
   7.114 +{
   7.115 +	int err = 0;
   7.116 +	struct pcistub_device *psdev;
   7.117 +	struct pci_dev *dev;
   7.118 +	struct config_field *field;
   7.119 +
   7.120 +	psdev = pcistub_device_find(domain, bus, slot, func);
   7.121 +	if (!psdev || !psdev->dev) {
   7.122 +		err = -ENODEV;
   7.123 +		goto out;
   7.124 +	}
   7.125 +	dev = psdev->dev;
   7.126 +
   7.127 +	/* check for duplicate field */
   7.128 +	if (pciback_field_is_dup(dev, reg))
   7.129 +		goto out;
   7.130 +
   7.131 +	field = kzalloc(sizeof(*field), GFP_ATOMIC);
   7.132 +	if (!field) {
   7.133 +		err = -ENOMEM;
   7.134 +		goto out;
   7.135 +	}
   7.136 +
   7.137 +	field->offset = reg;
   7.138 +	field->size = size;
   7.139 +	field->mask = mask;
   7.140 +	field->init = NULL;
   7.141 +	field->reset = NULL;
   7.142 +	field->release = NULL;
   7.143 +	field->clean = pciback_config_field_free;
   7.144 +
   7.145 +	err = pciback_config_quirks_add_field(dev, field);
   7.146 +	if (err)
   7.147 +		kfree(field);
   7.148 +      out:
   7.149 +	return err;
   7.150 +}
   7.151 +
   7.152  static ssize_t pcistub_slot_add(struct device_driver *drv, const char *buf,
   7.153  				size_t count)
   7.154  {
   7.155 @@ -587,6 +674,137 @@ static ssize_t pcistub_slot_show(struct 
   7.156  
   7.157  DRIVER_ATTR(slots, S_IRUSR, pcistub_slot_show, NULL);
   7.158  
   7.159 +static ssize_t pcistub_quirk_add(struct device_driver *drv, const char *buf,
   7.160 +				 size_t count)
   7.161 +{
   7.162 +	int domain, bus, slot, func, reg, size, mask;
   7.163 +	int err;
   7.164 +
   7.165 +	err = str_to_quirk(buf, &domain, &bus, &slot, &func, &reg, &size,
   7.166 +			   &mask);
   7.167 +	if (err)
   7.168 +		goto out;
   7.169 +
   7.170 +	err = pcistub_reg_add(domain, bus, slot, func, reg, size, mask);
   7.171 +
   7.172 +      out:
   7.173 +	if (!err)
   7.174 +		err = count;
   7.175 +	return err;
   7.176 +}
   7.177 +
   7.178 +static ssize_t pcistub_quirk_show(struct device_driver *drv, char *buf)
   7.179 +{
   7.180 +	int count = 0;
   7.181 +	unsigned long flags;
   7.182 +	extern struct list_head pciback_quirks;
   7.183 +	struct pciback_config_quirk *quirk;
   7.184 +	struct pciback_dev_data *dev_data;
   7.185 +	struct config_field *field;
   7.186 +	struct config_field_entry *cfg_entry;
   7.187 +
   7.188 +	spin_lock_irqsave(&device_ids_lock, flags);
   7.189 +	list_for_each_entry(quirk, &pciback_quirks, quirks_list) {
   7.190 +		if (count >= PAGE_SIZE)
   7.191 +			goto out;
   7.192 +
   7.193 +		count += scnprintf(buf + count, PAGE_SIZE - count,
   7.194 +				   "%02x:%02x.%01x\n\t%04x:%04x:%04x:%04x\n",
   7.195 +				   quirk->pdev->bus->number,
   7.196 +				   PCI_SLOT(quirk->pdev->devfn),
   7.197 +				   PCI_FUNC(quirk->pdev->devfn),
   7.198 +				   quirk->devid.vendor, quirk->devid.device,
   7.199 +				   quirk->devid.subvendor,
   7.200 +				   quirk->devid.subdevice);
   7.201 +
   7.202 +		dev_data = pci_get_drvdata(quirk->pdev);
   7.203 +
   7.204 +		list_for_each_entry(cfg_entry, &dev_data->config_fields, list) {
   7.205 +			field = cfg_entry->field;
   7.206 +			if (count >= PAGE_SIZE)
   7.207 +				goto out;
   7.208 +
   7.209 +			count += scnprintf(buf + count, PAGE_SIZE -
   7.210 +					   count, "\t\t%08x:%01x:%08x\n",
   7.211 +					   field->offset, field->size,
   7.212 +					   field->mask);
   7.213 +		}
   7.214 +	}
   7.215 +
   7.216 +      out:
   7.217 +	spin_unlock_irqrestore(&device_ids_lock, flags);
   7.218 +
   7.219 +	return count;
   7.220 +}
   7.221 +
   7.222 +DRIVER_ATTR(quirks, S_IRUSR | S_IWUSR, pcistub_quirk_show, pcistub_quirk_add);
   7.223 +
   7.224 +static ssize_t permissive_add(struct device_driver *drv, const char *buf,
   7.225 +			      size_t count)
   7.226 +{
   7.227 +	int domain, bus, slot, func;
   7.228 +	int err;
   7.229 +	struct pcistub_device *psdev;
   7.230 +	struct pciback_dev_data *dev_data;
   7.231 +	err = str_to_slot(buf, &domain, &bus, &slot, &func);
   7.232 +	if (err)
   7.233 +		goto out;
   7.234 +	psdev = pcistub_device_find(domain, bus, slot, func);
   7.235 +	if (!psdev) {
   7.236 +		err = -ENODEV;
   7.237 +		goto out;
   7.238 +	}
   7.239 +	if (!psdev->dev) {
   7.240 +		err = -ENODEV;
   7.241 +		goto release;
   7.242 +	}
   7.243 +	dev_data = pci_get_drvdata(psdev->dev);
   7.244 +	/* the driver data for a device should never be null at this point */
   7.245 +	if (!dev_data) {
   7.246 +		err = -ENXIO;
   7.247 +		goto release;
   7.248 +	}
   7.249 +	if (!dev_data->permissive) {
   7.250 +		dev_data->permissive = 1;
   7.251 +		/* Let user know that what they're doing could be unsafe */
   7.252 +		dev_warn(&psdev->dev->dev,
   7.253 +			 "enabling permissive mode configuration space accesses!\n");
   7.254 +		dev_warn(&psdev->dev->dev,
   7.255 +			 "permissive mode is potentially unsafe!\n");
   7.256 +	}
   7.257 +      release:
   7.258 +	pcistub_device_put(psdev);
   7.259 +      out:
   7.260 +	if (!err)
   7.261 +		err = count;
   7.262 +	return err;
   7.263 +}
   7.264 +
   7.265 +static ssize_t permissive_show(struct device_driver *drv, char *buf)
   7.266 +{
   7.267 +	struct pcistub_device *psdev;
   7.268 +	struct pciback_dev_data *dev_data;
   7.269 +	size_t count = 0;
   7.270 +	unsigned long flags;
   7.271 +	spin_lock_irqsave(&pcistub_devices_lock, flags);
   7.272 +	list_for_each_entry(psdev, &pcistub_devices, dev_list) {
   7.273 +		if (count >= PAGE_SIZE)
   7.274 +			break;
   7.275 +		if (!psdev->dev)
   7.276 +			continue;
   7.277 +		dev_data = pci_get_drvdata(psdev->dev);
   7.278 +		if (!dev_data || !dev_data->permissive)
   7.279 +			continue;
   7.280 +		count +=
   7.281 +		    scnprintf(buf + count, PAGE_SIZE - count, "%s\n",
   7.282 +			      pci_name(psdev->dev));
   7.283 +	}
   7.284 +	spin_unlock_irqrestore(&pcistub_devices_lock, flags);
   7.285 +	return count;
   7.286 +}
   7.287 +
   7.288 +DRIVER_ATTR(permissive, S_IRUSR | S_IWUSR, permissive_show, permissive_add);
   7.289 +
   7.290  static int __init pcistub_init(void)
   7.291  {
   7.292  	int pos = 0;
   7.293 @@ -631,6 +849,8 @@ static int __init pcistub_init(void)
   7.294  	driver_create_file(&pciback_pci_driver.driver,
   7.295  			   &driver_attr_remove_slot);
   7.296  	driver_create_file(&pciback_pci_driver.driver, &driver_attr_slots);
   7.297 +	driver_create_file(&pciback_pci_driver.driver, &driver_attr_quirks);
   7.298 +	driver_create_file(&pciback_pci_driver.driver, &driver_attr_permissive);
   7.299  
   7.300        out:
   7.301  	return err;
   7.302 @@ -680,6 +900,8 @@ static void __exit pciback_cleanup(void)
   7.303  	driver_remove_file(&pciback_pci_driver.driver,
   7.304  			   &driver_attr_remove_slot);
   7.305  	driver_remove_file(&pciback_pci_driver.driver, &driver_attr_slots);
   7.306 +	driver_remove_file(&pciback_pci_driver.driver, &driver_attr_quirks);
   7.307 +	driver_remove_file(&pciback_pci_driver.driver, &driver_attr_permissive);
   7.308  
   7.309  	pci_unregister_driver(&pciback_pci_driver);
   7.310  }
     8.1 --- a/linux-2.6-xen-sparse/drivers/xen/pciback/pciback.h	Fri Jul 28 14:06:27 2006 +0100
     8.2 +++ b/linux-2.6-xen-sparse/drivers/xen/pciback/pciback.h	Fri Jul 28 14:09:05 2006 +0100
     8.3 @@ -44,6 +44,7 @@ struct pciback_device {
     8.4  
     8.5  struct pciback_dev_data {
     8.6  	struct list_head config_fields;
     8.7 +	int permissive;
     8.8  	int warned_on_write;
     8.9  };
    8.10  
    8.11 @@ -61,6 +62,7 @@ void pciback_reset_device(struct pci_dev
    8.12  /* Access a virtual configuration space for a PCI device */
    8.13  int pciback_config_init(void);
    8.14  int pciback_config_init_dev(struct pci_dev *dev);
    8.15 +void pciback_config_free_dyn_fields(struct pci_dev *dev);
    8.16  void pciback_config_reset_dev(struct pci_dev *dev);
    8.17  void pciback_config_free_dev(struct pci_dev *dev);
    8.18  int pciback_config_read(struct pci_dev *dev, int offset, int size,
     9.1 --- a/tools/examples/Makefile	Fri Jul 28 14:06:27 2006 +0100
     9.2 +++ b/tools/examples/Makefile	Fri Jul 28 14:09:05 2006 +0100
     9.3 @@ -18,6 +18,8 @@ XEN_CONFIGS += xmexample1
     9.4  XEN_CONFIGS += xmexample2
     9.5  XEN_CONFIGS += xmexample.hvm
     9.6  XEN_CONFIGS += xmexample.vti
     9.7 +XEN_CONFIGS += xend-pci-quirks.sxp
     9.8 +XEN_CONFIGS += xend-pci-permissive.sxp
     9.9  
    9.10  # Xen script dir and scripts to go there.
    9.11  XEN_SCRIPT_DIR = /etc/xen/scripts
    10.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.2 +++ b/tools/examples/xend-pci-permissive.sxp	Fri Jul 28 14:09:05 2006 +0100
    10.3 @@ -0,0 +1,27 @@
    10.4 +###############################################################################
    10.5 +# Configuration file for granting quiry PCI devices full write access to their 
    10.6 +# configuration space.  This file should only be used when you are unable to 
    10.7 +# determine the exact registers required by your device.  Even so, it should 
    10.8 +# be used only temporarily.
    10.9 +# 
   10.10 +# SEND A MESSAGE TO xen-devel@lists.xensource.com IF YOU USE THIS FILE.
   10.11 +# 
   10.12 +# Using this file should NOT be necessary.  If you must use it to make some
   10.13 +# device work, send a message to the above list with as much information about 
   10.14 +# your device as possible so the developers can make accomodations for it.  
   10.15 +# Once developers make the necessary updates you can remove the corresponding
   10.16 +# entry for your device. 
   10.17 +###############################################################################
   10.18 +# Entries are formated as follows:  <vendor>:<device>[:<subvendor>:<subdevice>]
   10.19 +# 
   10.20 +# Example: Appending to an existing list
   10.21 +#  
   10.22 +# (unconstrained_dev_ids
   10.23 +#     ('XXXX:XXXX:XXXX:XXXX'	# existing entry
   10.24 +#      'YYYY:YYYY:YYYY:YYYY' 	# new entry 1
   10.25 +#      'ZZZZ:ZZZZ')		# new entry 2
   10.26 +# )
   10.27 +###############################################################################
   10.28 +(unconstrained_dev_ids
   10.29 +     #('0123:4567:89AB:CDEF')
   10.30 +)
    11.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.2 +++ b/tools/examples/xend-pci-quirks.sxp	Fri Jul 28 14:09:05 2006 +0100
    11.3 @@ -0,0 +1,96 @@
    11.4 +###############################################################################
    11.5 +# Configuration file for quirky PCI devices that require write-access to 
    11.6 +# parts of the configuration space.  Use this file to specific PCI device
    11.7 +# IDs and the configuration space fields to which those devices must be
    11.8 +# able to write.
    11.9 +#
   11.10 +# Length is important, so be sure to match new entries with the 
   11.11 +# lengths of comparable existing entries. 
   11.12 +#
   11.13 +# Additions to this file take effect as soon as a new domain with a 
   11.14 +# matching device is started.  However, to remove a field that was 
   11.15 +# previously applied to a device you must unbind the device from 
   11.16 +# pciback.
   11.17 +###############################################################################
   11.18 +# This is a bogus entry to show how a new device would be added to the list
   11.19 +#
   11.20 +# (new_quirky_dev_name
   11.21 +#    (pci_ids 
   11.22 +#       ('0123:4567:890A:BCEF') 
   11.23 +#    )
   11.24 +#
   11.25 +#    (pci_config_space_fields 
   11.26 +#       ('12345678:1:00000000')
   11.27 +#    )
   11.28 +# )
   11.29 +###############################################################################
   11.30 +
   11.31 +(tg3
   11.32 +    (pci_ids
   11.33 +	# Entries are formated as follows:  
   11.34 +	#     <vendor>:<device>[:<subvendor>:<subdevice>]
   11.35 +        ('14e4:1644'   # Broadcom Tigon3 5700
   11.36 +    	 '14e4:1645'   # Broadcom Tigon3 5701
   11.37 +         '14e4:1646'   # Broadcom Tigon3 5702
   11.38 +         '14e4:1647'   # Broadcom Tigon3 5703
   11.39 +         '14e4:1648'   # Broadcom Tigon3 5704
   11.40 +         '14e4:164d'   # Broadcom Tigon3 5702FE
   11.41 +         '14e4:1653'   # Broadcom Tigon3 5705
   11.42 +         '14e4:1654'   # Broadcom Tigon3 5705_2
   11.43 +         '14e4:165d'   # Broadcom Tigon3 5705M
   11.44 +         '14e4:165e'   # Broadcom Tigon3 5705M_2
   11.45 +         '14e4:16a6'   # Broadcom Tigon3 5702X
   11.46 +         '14e4:16a7'   # Broadcom Tigon3 5703X
   11.47 +         '14e4:16a8'   # Broadcom Tigon3 5704S
   11.48 +         '14e4:16c6'   # Broadcom Tigon3 5702A3
   11.49 +         '14e4:16c7'   # Broadcom Tigon3 5703A3
   11.50 +         '14e4:1696'   # Broadcom Tigon3 5782
   11.51 +         '14e4:169c'   # Broadcom Tigon3 5788
   11.52 +         '14e4:169d'   # Broadcom Tigon3 5789
   11.53 +         '14e4:170d'   # Broadcom Tigon3 5901
   11.54 +         '14e4:1649'   # Broadcom Tigon3 5704S_2
   11.55 +         '14e4:166e'   # Broadcom Tigon3 5705F
   11.56 +         '14e4:1658'   # Broadcom Tigon3 5720
   11.57 +         '14e4:1659'   # Broadcom Tigon3 5721
   11.58 +         '14e4:1676'   # Broadcom Tigon3 5750
   11.59 +         '14e4:1677'   # Broadcom Tigon3 5751
   11.60 +         '14e4:167c'   # Broadcom Tigon3 5750M
   11.61 +         '14e4:167d'   # Broadcom Tigon3 5751M
   11.62 +         '14e4:167e'   # Broadcom Tigon3 5751F
   11.63 +         '14e4:1600'   # Broadcom Tigon3 5752
   11.64 +         '14e4:1601'   # Broadcom Tigon3 5752M
   11.65 +         '14e4:16f7'   # Broadcom Tigon3 5753
   11.66 +         '14e4:16fd'   # Broadcom Tigon3 5753M
   11.67 +         '14e4:16fe'   # Broadcom Tigon3 5753F
   11.68 +         '14e4:1668'   # Broadcom Tigon3 5714
   11.69 +         '14e4:1678'   # Broadcom Tigon3 5715
   11.70 +         '14e4:166a'   # Broadcom Tigon3 5780
   11.71 +         '14e4:166b'   # Broadcom Tigon3 5780S
   11.72 +         '14e4:16dd'   # Broadcom Tigon3 5781
   11.73 +         '1148:4400'   # Syskonnect 9DXX
   11.74 +         '1148:4500'   # Syskonnect 9MXX
   11.75 +         '173b:03e8'   # Altima AC1000
   11.76 +         '173b:03e9'   # Altima AC1001
   11.77 +         '173b:03eb'   # Altima AC1003
   11.78 +         '173b:03ea'   # Altima AC9100
   11.79 +         '106b:1645')  # Apple Tigon3
   11.80 +    )
   11.81 +
   11.82 +    (pci_config_space_fields
   11.83 +	# Entries are formated as follows:  
   11.84 +    	#     <register>:<size>:<mask>
   11.85 +    	# size is measured in bytes (1,2,4 are valid sizes)
   11.86 +    	# mask is currently unused; use all zero's
   11.87 +        ('00000078:4:00000000'   # TG3PCI_REG_BASE_ADDR
   11.88 +         '0000007c:4:00000000'   # TG3PCI_MEM_WIN_BASE_ADDR
   11.89 +         '00000080:4:00000000'   # TG3PCI_REG_DATA
   11.90 +         '00000084:4:00000000'   # TG3PCI_MEM_WIN_DATA
   11.91 +         '00000090:4:00000000'   # TG3PCI_MISC_LOCAL_CTRL
   11.92 +         '00000068:4:00000000'   # TG3PCI_MISC_HOST_CTRL
   11.93 +         '0000009C:4:00000000'   # TG3PCI_STD_RING_PROD_IDX + TG3_64BIT_REG_LOW
   11.94 +         '00000098:4:00000000'   # TG3PCI_STD_RING_PROD_IDX + TG3_64BIT_REG_HIGH
   11.95 +         '000000a4:4:00000000'   # TG3PCI_RCV_RET_RING_CON_IDX + TG3_64BIT_REG_LOW
   11.96 +         '000000a0:4:00000000'   # TG3PCI_RCV_RET_RING_CON_IDX + TG3_64BIT_REG_HIGH
   11.97 +         '00000070:4:00000000')  # TG3PCI_PCISTATE
   11.98 +    )
   11.99 +)
    12.1 --- a/tools/libxc/Makefile	Fri Jul 28 14:06:27 2006 +0100
    12.2 +++ b/tools/libxc/Makefile	Fri Jul 28 14:09:05 2006 +0100
    12.3 @@ -35,8 +35,7 @@ GUEST_SRCS-$(CONFIG_IA64) += xc_linux_bu
    12.4  GUEST_SRCS-$(CONFIG_MIGRATE) += xc_linux_restore.c xc_linux_save.c
    12.5  GUEST_SRCS-$(CONFIG_HVM) += xc_hvm_build.c
    12.6  
    12.7 -# This Makefile only adds files if CONFIG_IA64 is y.
    12.8 -include ia64/Makefile
    12.9 +-include $(XEN_TARGET_ARCH)/Makefile
   12.10  
   12.11  CFLAGS   += -Werror
   12.12  CFLAGS   += -fno-strict-aliasing
    13.1 --- a/tools/libxc/ia64/Makefile	Fri Jul 28 14:06:27 2006 +0100
    13.2 +++ b/tools/libxc/ia64/Makefile	Fri Jul 28 14:09:05 2006 +0100
    13.3 @@ -1,5 +1,5 @@
    13.4 -CTRL_SRCS-$(CONFIG_IA64) += ia64/xc_ia64_stubs.c
    13.5 +CTRL_SRCS-y += ia64/xc_ia64_stubs.c
    13.6  
    13.7 -GUEST_SRCS-$(CONFIG_IA64) += ia64/xc_ia64_hvm_build.c
    13.8 -GUEST_SRCS-$(CONFIG_IA64) += ia64/xc_ia64_linux_save.c
    13.9 -GUEST_SRCS-$(CONFIG_IA64) += ia64/xc_ia64_linux_restore.c
   13.10 +GUEST_SRCS-y += ia64/xc_ia64_hvm_build.c
   13.11 +GUEST_SRCS-y += ia64/xc_ia64_linux_save.c
   13.12 +GUEST_SRCS-y += ia64/xc_ia64_linux_restore.c
    14.1 --- a/tools/python/xen/util/pci.py	Fri Jul 28 14:06:27 2006 +0100
    14.2 +++ b/tools/python/xen/util/pci.py	Fri Jul 28 14:09:05 2006 +0100
    14.3 @@ -16,6 +16,10 @@ SYSFS_PCI_DEVS_PATH = '/bus/pci/devices'
    14.4  SYSFS_PCI_DEV_RESOURCE_PATH = '/resource'
    14.5  SYSFS_PCI_DEV_IRQ_PATH = '/irq'
    14.6  SYSFS_PCI_DEV_DRIVER_DIR_PATH = '/driver'
    14.7 +SYSFS_PCI_DEV_VENDOR_PATH = '/vendor'
    14.8 +SYSFS_PCI_DEV_DEVICE_PATH = '/device'
    14.9 +SYSFS_PCI_DEV_SUBVENDOR_PATH = '/subsystem_vendor'
   14.10 +SYSFS_PCI_DEV_SUBDEVICE_PATH = '/subsystem_device'
   14.11  
   14.12  PCI_BAR_IO = 0x01
   14.13  PCI_BAR_IO_MASK = ~0x03
   14.14 @@ -66,9 +70,12 @@ class PciDevice:
   14.15          self.iomem = []
   14.16          self.ioports = []
   14.17          self.driver = None
   14.18 +        self.vendor = None
   14.19 +        self.device = None
   14.20 +        self.subvendor = None
   14.21 +        self.subdevice = None
   14.22  
   14.23 -        if not self.get_info_from_sysfs():
   14.24 -            self.get_info_from_proc()
   14.25 +        self.get_info_from_sysfs()
   14.26  
   14.27      def get_info_from_sysfs(self):
   14.28          try:
   14.29 @@ -85,7 +92,7 @@ class PciDevice:
   14.30          try:
   14.31              resource_file = open(path,'r')
   14.32  
   14.33 -            for i in range(7):
   14.34 +            for i in range(PROC_PCI_NUM_RESOURCES):
   14.35                  line = resource_file.readline()
   14.36                  sline = line.split()
   14.37                  if len(sline)<3:
   14.38 @@ -122,53 +129,39 @@ class PciDevice:
   14.39              raise PciDeviceParseError(('Failed to read %s: %s (%d)' %
   14.40                  (path, strerr, errno)))
   14.41  
   14.42 -        return True
   14.43 -        
   14.44 -    def get_info_from_proc(self):
   14.45 -        bus_devfn = '%02x%02x' % (self.bus,PCI_DEVFN(self.slot,self.func))
   14.46 -
   14.47 -        # /proc/bus/pci/devices doesn't expose domains
   14.48 -        if self.domain!=0:
   14.49 -            raise PciDeviceParseError("Can't yet detect resource usage by "+
   14.50 -                    "devices in other domains through proc!")
   14.51 +        path = sysfs_mnt+SYSFS_PCI_DEVS_PATH+'/'+ \
   14.52 +                self.name+SYSFS_PCI_DEV_VENDOR_PATH
   14.53 +        try:
   14.54 +            self.vendor = int(open(path,'r').readline(), 16)
   14.55 +        except IOError, (errno, strerr):
   14.56 +            raise PciDeviceParseError(('Failed to open & read %s: %s (%d)' %
   14.57 +                (path, strerr, errno)))
   14.58  
   14.59 +        path = sysfs_mnt+SYSFS_PCI_DEVS_PATH+'/'+ \
   14.60 +                self.name+SYSFS_PCI_DEV_DEVICE_PATH
   14.61          try:
   14.62 -            proc_pci_file = open(PROC_PCI_PATH,'r')
   14.63 +            self.device = int(open(path,'r').readline(), 16)
   14.64          except IOError, (errno, strerr):
   14.65 -            raise PciDeviceParseError(('Failed to open %s: %s (%d)' %
   14.66 -                (PROC_PCI_PATH, strerr, errno)))
   14.67 -
   14.68 -        for line in proc_pci_file:
   14.69 -            sline = line.split()
   14.70 -            if len(sline)<(PROC_PCI_NUM_RESOURCES*2+3):
   14.71 -                continue
   14.72 +            raise PciDeviceParseError(('Failed to open & read %s: %s (%d)' %
   14.73 +                (path, strerr, errno)))
   14.74  
   14.75 -            if sline[0]==bus_devfn:
   14.76 -                self.dissect_proc_pci_line(sline)
   14.77 -                break
   14.78 -        else:
   14.79 -            raise PciDeviceNotFoundError(self.domain, self.bus,
   14.80 -                    self.slot, self.func)
   14.81 +        path = sysfs_mnt+SYSFS_PCI_DEVS_PATH+'/'+ \
   14.82 +                self.name+SYSFS_PCI_DEV_SUBVENDOR_PATH
   14.83 +        try:
   14.84 +            self.subvendor = int(open(path,'r').readline(), 16)
   14.85 +        except IOError, (errno, strerr):
   14.86 +            raise PciDeviceParseError(('Failed to open & read %s: %s (%d)' %
   14.87 +                (path, strerr, errno)))
   14.88  
   14.89 -    def dissect_proc_pci_line(self, sline):
   14.90 -        self.irq = int(sline[2],16)
   14.91 -        start_idx = 3
   14.92 -        for i in range(PROC_PCI_NUM_RESOURCES):
   14.93 -            flags = int(sline[start_idx+i],16)
   14.94 -            size = int(sline[start_idx+i+PROC_PCI_NUM_RESOURCES],16)
   14.95 -            if flags&PCI_BAR_IO:
   14.96 -                start = flags&PCI_BAR_IO_MASK
   14.97 -                if start!=0:
   14.98 -                    self.ioports.append( (start,size) )
   14.99 -            else:
  14.100 -                start = flags&PCI_BAR_MEM_MASK
  14.101 -                if start!=0:
  14.102 -                    self.iomem.append( (start,size) )
  14.103 +        path = sysfs_mnt+SYSFS_PCI_DEVS_PATH+'/'+ \
  14.104 +                self.name+SYSFS_PCI_DEV_SUBDEVICE_PATH
  14.105 +        try:
  14.106 +            self.subdevice = int(open(path,'r').readline(), 16)
  14.107 +        except IOError, (errno, strerr):
  14.108 +            raise PciDeviceParseError(('Failed to open & read %s: %s (%d)' %
  14.109 +                (path, strerr, errno)))
  14.110  
  14.111 -        # detect driver module name
  14.112 -        driver_idx = PROC_PCI_NUM_RESOURCES*2+3
  14.113 -        if len(sline)>driver_idx:
  14.114 -            self.driver = sline[driver_idx]
  14.115 +        return True
  14.116  
  14.117      def __str__(self):
  14.118          str = "PCI Device %s\n" % (self.name)
  14.119 @@ -176,7 +169,11 @@ class PciDevice:
  14.120              str = str + "IO Port 0x%02x [size=%d]\n"%(start,size)
  14.121          for (start,size) in self.iomem:
  14.122              str = str + "IO Mem 0x%02x [size=%d]\n"%(start,size)
  14.123 -        str = str + "IRQ %d"%(self.irq)
  14.124 +        str = str + "IRQ %d\n"%(self.irq)
  14.125 +        str = str + "Vendor ID 0x%04x\n"%(self.vendor)
  14.126 +        str = str + "Device ID 0x%04x\n"%(self.device)
  14.127 +        str = str + "Sybsystem Vendor ID 0x%04x\n"%(self.subvendor)
  14.128 +        str = str + "Subsystem Device ID 0x%04x"%(self.subdevice)
  14.129          return str
  14.130  
  14.131  def main():
    15.1 --- a/tools/python/xen/xend/server/pciif.py	Fri Jul 28 14:06:27 2006 +0100
    15.2 +++ b/tools/python/xen/xend/server/pciif.py	Fri Jul 28 14:09:05 2006 +0100
    15.3 @@ -33,6 +33,8 @@ from xen.util.pci import PciDevice
    15.4  import resource
    15.5  import re
    15.6  
    15.7 +from xen.xend.server.pciquirk import *
    15.8 +
    15.9  xc = xen.lowlevel.xc.xc()
   15.10  
   15.11  #Calculate PAGE_SHIFT: number of bits to shift an address to get the page number
   15.12 @@ -150,7 +152,10 @@ class PciController(DevController):
   15.13                      "bind your slot/device to the PCI backend using sysfs" \
   15.14                      )%(dev.name))
   15.15  
   15.16 -        for (start, size) in dev.ioports:
   15.17 +        PCIQuirk(dev.vendor, dev.device, dev.subvendor, dev.subdevice, domain, 
   15.18 +                bus, slot, func)
   15.19 +
   15.20 +	for (start, size) in dev.ioports:
   15.21              log.debug('pci: enabling ioport 0x%x/0x%x'%(start,size))
   15.22              rc = xc.domain_ioport_permission(dom = fe_domid, first_port = start,
   15.23                      nr_ports = size, allow_access = True)
    16.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    16.2 +++ b/tools/python/xen/xend/server/pciquirk.py	Fri Jul 28 14:09:05 2006 +0100
    16.3 @@ -0,0 +1,145 @@
    16.4 +from xen.xend.XendLogging import log
    16.5 +from xen.xend.XendError import XendError
    16.6 +import sys
    16.7 +import os.path
    16.8 +from xen.xend.sxp import *
    16.9 +
   16.10 +QUIRK_SYSFS_NODE = "/sys/bus/pci/drivers/pciback/quirks"
   16.11 +QUIRK_CONFIG_FILE = "/etc/xen/xend-pci-quirks.sxp"
   16.12 +PERMISSIVE_CONFIG_FILE = "/etc/xen/xend-pci-permissive.sxp"
   16.13 +PERMISSIVE_SYSFS_NODE = "/sys/bus/pci/drivers/pciback/permissive"
   16.14 +
   16.15 +class PCIQuirk:
   16.16 +    def __init__( self, vendor, device, subvendor, subdevice, domain, bus, slot, func):
   16.17 +        self.vendor = vendor
   16.18 +        self.device = device
   16.19 +        self.subvendor = subvendor
   16.20 +        self.subdevice = subdevice
   16.21 +	self.domain = domain
   16.22 +	self.bus = bus
   16.23 +	self.slot = slot
   16.24 +	self.func = func
   16.25 +
   16.26 +        self.devid = "%04x:%04x:%04x:%04x" % (vendor, device, subvendor, subdevice)
   16.27 +	self.pciid = "%04x:%02x:%02x.%01x" % (domain, bus, slot, func)
   16.28 +
   16.29 +        self.quirks = self.__getQuirksByID( )
   16.30 +
   16.31 +	self.__sendQuirks( )
   16.32 +	self.__sendPermDevs( )
   16.33 +
   16.34 +    def __matchPCIdev( self, list ):
   16.35 +        ret = False
   16.36 +        if list == None:
   16.37 +            return False
   16.38 +        for id in list:
   16.39 +            if id.startswith( self.devid[:9] ): # id's vendor and device ID match
   16.40 +                skey = id.split(':')
   16.41 +                size = len(skey)
   16.42 +                if (size == 2):		# subvendor/subdevice not suplied
   16.43 +                    ret = True
   16.44 +                    break
   16.45 +                elif (size == 4):	# check subvendor/subdevice
   16.46 +                    # check subvendor
   16.47 +		    subven = '%04x' % self.subvendor
   16.48 +                    if ((skey[2] != 'FFFF') and 
   16.49 +                        (skey[2] != 'ffff') and 
   16.50 +                        (skey[2] != subven)):
   16.51 +                            continue
   16.52 +                    # check subdevice
   16.53 +		    subdev = '%04x' % self.subdevice
   16.54 +                    if ((skey[3] != 'FFFF') and 
   16.55 +                        (skey[3] != 'ffff') and 
   16.56 +                        (skey[3] != subdev)):
   16.57 +                            continue
   16.58 +                    ret = True
   16.59 +                    break
   16.60 +                else:
   16.61 +                    log.debug("WARNING: invalid configuration entry: %s" % id)
   16.62 +                    ret = False
   16.63 +                    break
   16.64 +        return ret
   16.65 +        
   16.66 +    def __getQuirksByID( self ):
   16.67 +        if os.path.exists(QUIRK_CONFIG_FILE):
   16.68 +            try:
   16.69 +                fin = file(QUIRK_CONFIG_FILE, 'rb')
   16.70 +                try:
   16.71 +                    pci_quirks_config = parse(fin)
   16.72 +                finally:
   16.73 +                    fin.close()
   16.74 +                if pci_quirks_config is None:
   16.75 +                    pci_quirks_config = ['xend-pci-quirks']
   16.76 +                else:
   16.77 +                    pci_quirks_config.insert(0, 'xend-pci-quirks')
   16.78 +                self.pci_quirks_config = pci_quirks_config
   16.79 +            except Exception, ex:
   16.80 +                raise XendError("Reading config file %s: %s" %
   16.81 +				(QUIRK_CONFIG_FILE, str(ex)))
   16.82 +        else:
   16.83 +            log.info("Config file does not exist: %s" % QUIRK_CONFIG_FILE)
   16.84 +            self.pci_quirks_config = ['xend-pci-quirks']
   16.85 +
   16.86 +        devices = children(self.pci_quirks_config)
   16.87 +        for dev in devices:
   16.88 +            ids = child_at(child(dev,'pci_ids'),0)
   16.89 +            fields = child_at(child(dev,'pci_config_space_fields'),0)
   16.90 +	    if self.__matchPCIdev( ids ):
   16.91 +                log.info("Quirks found for PCI device [%s]" % self.devid)
   16.92 +                return fields
   16.93 +
   16.94 +        log.info("NO quirks found for PCI device [%s]" % self.devid)
   16.95 +        return []
   16.96 +
   16.97 +    def __sendQuirks(self):
   16.98 +        for quirk in self.quirks:
   16.99 +            log.debug("Quirk Info: %04x:%02x:%02x.%1x-%s" % (self.domain,
  16.100 +		    self.bus, self.slot, self.func, quirk))
  16.101 +            try:
  16.102 +                f = file(QUIRK_SYSFS_NODE ,"w")
  16.103 +                f.write( "%04x:%02x:%02x.%1x-%s" % (self.domain, self.bus,
  16.104 +			self.slot, self.func, quirk) )
  16.105 +                f.close()
  16.106 +            except Exception, e:
  16.107 +                raise VmError("pci: failed to open/write/close quirks sysfs " + \
  16.108 +			"node - " + str(e))
  16.109 +
  16.110 +    def __devIsUnconstrained( self ):
  16.111 +        if os.path.exists(PERMISSIVE_CONFIG_FILE):
  16.112 +            try:
  16.113 +                fin = file(PERMISSIVE_CONFIG_FILE, 'rb')
  16.114 +                try:
  16.115 +                    pci_perm_dev_config = parse(fin)
  16.116 +                finally:
  16.117 +                    fin.close()
  16.118 +                if pci_perm_dev_config is None:
  16.119 +                    pci_perm_dev_config = ['']
  16.120 +                else:
  16.121 +                    pci_perm_dev_config.insert(0, '')
  16.122 +                self.pci_perm_dev_config = pci_perm_dev_config
  16.123 +            except Exception, ex:
  16.124 +                raise XendError("Reading config file %s: %s" %
  16.125 +				(PERMISSIVE_CONFIG_FILE,str(ex)))
  16.126 +        else:
  16.127 +            log.info("Config file does not exist: %s" % PERMISSIVE_CONFIG_FILE)
  16.128 +            self.pci_perm_dev_config = ['xend-pci-perm-devs']
  16.129 +
  16.130 +        devices = child_at(child(pci_perm_dev_config, 'unconstrained_dev_ids'),0)
  16.131 +	if self.__matchPCIdev( devices ):
  16.132 +            log.debug("Permissive mode enabled for PCI device [%s]" % self.devid)
  16.133 +            return True
  16.134 +        log.debug("Permissive mode NOT enabled for PCI device [%s]" % self.devid)
  16.135 +        return False
  16.136 +
  16.137 +    def __sendPermDevs(self):
  16.138 +	if self.__devIsUnconstrained( ):
  16.139 +            log.debug("Unconstrained device: %04x:%02x:%02x.%1x" % (self.domain,
  16.140 +		    self.bus, self.slot, self.func))
  16.141 +            try:
  16.142 +                f = file(PERMISSIVE_SYSFS_NODE ,"w")
  16.143 +                f.write( "%04x:%02x:%02x.%1x" % (self.domain, self.bus,
  16.144 +			self.slot, self.func) )
  16.145 +                f.close()
  16.146 +            except Exception, e:
  16.147 +                raise VmError("pci: failed to open/write/close permissive " + \
  16.148 +		"sysfs node: " + str(e))