debuggers.hg

changeset 20879:961acb357740

VT-d: improve RMRR validity checking

Currently, Xen checks RMRR range and disables VT-d if RMRR range is
set incorrectly in BIOS rigorously. But, actually we can ignore the
RMRR if the device under its scope are not pci discoverable, because
the RMRR won't be used by non-existed or disabled devices.

This patch ignores the RMRR if the device under its scope are not pci
discoverable, and only checks the validity of RMRRs that are actually
used. In order to avoid duplicate pci device detection code, this
patch defines a function pci_device_detect for it.

Signed-off-by: Weidong Han <weidong.han@intel.com>
author Keir Fraser <keir.fraser@citrix.com>
date Thu Jan 21 09:12:01 2010 +0000 (2010-01-21)
parents acd7d3f06d9a
children ea02c95af387
files xen/drivers/passthrough/pci.c xen/drivers/passthrough/vtd/dmar.c xen/include/xen/pci.h
line diff
     1.1 --- a/xen/drivers/passthrough/pci.c	Thu Jan 21 09:11:06 2010 +0000
     1.2 +++ b/xen/drivers/passthrough/pci.c	Thu Jan 21 09:12:01 2010 +0000
     1.3 @@ -362,6 +362,21 @@ out:
     1.4  }
     1.5  
     1.6  /*
     1.7 + * detect pci device, return 0 if it exists, or return 0
     1.8 + */
     1.9 +int pci_device_detect(u8 bus, u8 dev, u8 func)
    1.10 +{
    1.11 +    u32 vendor;
    1.12 +
    1.13 +    vendor = pci_conf_read32(bus, dev, func, PCI_VENDOR_ID);
    1.14 +    /* some broken boards return 0 or ~0 if a slot is empty: */
    1.15 +    if ( (vendor == 0xffffffff) || (vendor == 0x00000000) ||
    1.16 +         (vendor == 0x0000ffff) || (vendor == 0xffff0000) )
    1.17 +        return 0;
    1.18 +    return 1;
    1.19 +}
    1.20 +
    1.21 +/*
    1.22   * scan pci devices to add all existed PCI devices to alldevs_list,
    1.23   * and setup pci hierarchy in array bus2bridge. This function is only
    1.24   * called in VT-d hardware setup
    1.25 @@ -372,7 +387,6 @@ int __init scan_pci_devices(void)
    1.26      int bus, dev, func;
    1.27      u8 sec_bus, sub_bus;
    1.28      int type;
    1.29 -    u32 l;
    1.30  
    1.31      spin_lock(&pcidevs_lock);
    1.32      for ( bus = 0; bus < 256; bus++ )
    1.33 @@ -381,10 +395,7 @@ int __init scan_pci_devices(void)
    1.34          {
    1.35              for ( func = 0; func < 8; func++ )
    1.36              {
    1.37 -                l = pci_conf_read32(bus, dev, func, PCI_VENDOR_ID);
    1.38 -                /* some broken boards return 0 or ~0 if a slot is empty: */
    1.39 -                if ( (l == 0xffffffff) || (l == 0x00000000) ||
    1.40 -                     (l == 0x0000ffff) || (l == 0xffff0000) )
    1.41 +                if ( pci_device_detect(bus, dev, func) == 0 )
    1.42                      continue;
    1.43  
    1.44                  pdev = alloc_pdev(bus, PCI_DEVFN(dev, func));
     2.1 --- a/xen/drivers/passthrough/vtd/dmar.c	Thu Jan 21 09:11:06 2010 +0000
     2.2 +++ b/xen/drivers/passthrough/vtd/dmar.c	Thu Jan 21 09:12:01 2010 +0000
     2.3 @@ -410,14 +410,6 @@ acpi_parse_one_rmrr(struct acpi_dmar_ent
     2.4      u64 base_addr = rmrr->base_address, end_addr = rmrr->end_address;
     2.5      int ret = 0;
     2.6  
     2.7 -    if ( base_addr >= end_addr )
     2.8 -    {
     2.9 -        dprintk(XENLOG_ERR VTDPREFIX,
    2.10 -                "RMRR error: base_addr %"PRIx64" end_address %"PRIx64"\n",
    2.11 -                base_addr, end_addr);
    2.12 -        return -EFAULT;
    2.13 -    }
    2.14 -
    2.15  #ifdef CONFIG_X86
    2.16      /* This check is here simply to detect when RMRR values are
    2.17       * not properly represented in the system memory map and
    2.18 @@ -441,9 +433,6 @@ acpi_parse_one_rmrr(struct acpi_dmar_ent
    2.19  
    2.20      rmrru->base_address = base_addr;
    2.21      rmrru->end_address = end_addr;
    2.22 -    dprintk(XENLOG_INFO VTDPREFIX,
    2.23 -            "  RMRR region: base_addr %"PRIx64" end_address %"PRIx64"\n",
    2.24 -            rmrru->base_address, rmrru->end_address);
    2.25  
    2.26      dev_scope_start = (void *)(rmrr + 1);
    2.27      dev_scope_end   = ((void *)rmrr) + header->length;
    2.28 @@ -453,7 +442,50 @@ acpi_parse_one_rmrr(struct acpi_dmar_ent
    2.29      if ( ret || (rmrru->scope.devices_cnt == 0) )
    2.30          xfree(rmrru);
    2.31      else
    2.32 -        acpi_register_rmrr_unit(rmrru);
    2.33 +    {
    2.34 +        u8 b, d, f;
    2.35 +        int i, ignore = 0;
    2.36 +
    2.37 +        for ( i = 0; i < rmrru->scope.devices_cnt; i++ )
    2.38 +        {
    2.39 +            b = PCI_BUS(rmrru->scope.devices[i]);
    2.40 +            d = PCI_SLOT(rmrru->scope.devices[i]);
    2.41 +            f = PCI_FUNC(rmrru->scope.devices[i]);
    2.42 +
    2.43 +            if ( pci_device_detect(b, d, f) == 0 )
    2.44 +                ignore = 1;
    2.45 +            else
    2.46 +            {
    2.47 +                ignore = 0;
    2.48 +                break;
    2.49 +            }
    2.50 +        }
    2.51 +
    2.52 +        if ( ignore )
    2.53 +        {
    2.54 +            dprintk(XENLOG_WARNING VTDPREFIX,
    2.55 +                "  Ignore the RMRR (%"PRIx64", %"PRIx64") due to "
    2.56 +                "devices under its scope are not PCI discoverable!\n",
    2.57 +                rmrru->base_address, rmrru->end_address);
    2.58 +            xfree(rmrru);
    2.59 +        }
    2.60 +        else if ( base_addr > end_addr )
    2.61 +        {
    2.62 +            dprintk(XENLOG_WARNING VTDPREFIX,
    2.63 +                "  The RMRR (%"PRIx64", %"PRIx64") is incorrect!\n",
    2.64 +                rmrru->base_address, rmrru->end_address);
    2.65 +            xfree(rmrru);
    2.66 +            ret = -EFAULT;
    2.67 +        }
    2.68 +        else
    2.69 +        {
    2.70 +            dprintk(XENLOG_INFO VTDPREFIX,
    2.71 +                "  RMRR region: base_addr %"PRIx64" end_address %"PRIx64"\n",
    2.72 +                rmrru->base_address, rmrru->end_address);
    2.73 +            acpi_register_rmrr_unit(rmrru);
    2.74 +        }
    2.75 +    }
    2.76 +
    2.77      return ret;
    2.78  }
    2.79  
     3.1 --- a/xen/include/xen/pci.h	Thu Jan 21 09:11:06 2010 +0000
     3.2 +++ b/xen/include/xen/pci.h	Thu Jan 21 09:12:01 2010 +0000
     3.3 @@ -74,6 +74,7 @@ enum {
     3.4      DEV_TYPE_PCI,
     3.5  };
     3.6  
     3.7 +int pci_device_detect(u8 bus, u8 dev, u8 func);
     3.8  int scan_pci_devices(void);
     3.9  int pdev_type(u8 bus, u8 devfn);
    3.10  int find_upstream_bridge(u8 *bus, u8 *devfn, u8 *secbus);