debuggers.hg
changeset 10891: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, ®, &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))