# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1216724186 -3600
# Node ID fc44e35b39136449247d3f9d013776f8fe3ba9db
# Parent 0bf73f557f417f7649304cca41d177fb1f36b332
x86: Fix the dom0 booting hang when VT-d is enabled.
Dom0 C/S 593 hooks the pci bus probe and remove function. When
probing a function at booting time, it will first add the device into
Dom0's list through a hypercall, then execute the driver's probe
function. If the probe function fails, another hypercall is called to
remove the device from Dom0's list. But for some RMRR devices, for
example, USB devices, they may still be in use for some operation by
BIOS at booting time. So when removing those kind of devices, we
should still keep the RMRR information.
Also add a small fix for "for_each_rmrr_device".
Signed-off-by: Dongxiao Xu <dongxiao.xu@xxxxxxxxx>
Signed-off-by: Weidong Han <weidong.han@xxxxxxxxx>
Signed-off-by: Yunhong Jiang <yunhong.jiang@xxxxxxxxx>
---
xen/drivers/passthrough/vtd/dmar.h | 2 -
xen/drivers/passthrough/vtd/iommu.c | 49 ++++++++++++++++++++++++++----------
2 files changed, 37 insertions(+), 14 deletions(-)
diff -r 0bf73f557f41 -r fc44e35b3913 xen/drivers/passthrough/vtd/dmar.h
--- a/xen/drivers/passthrough/vtd/dmar.h Tue Jul 22 11:55:06 2008 +0100
+++ b/xen/drivers/passthrough/vtd/dmar.h Tue Jul 22 11:56:26 2008 +0100
@@ -76,7 +76,7 @@ struct acpi_atsr_unit {
#define for_each_rmrr_device(rmrr, bdf, idx) \
list_for_each_entry(rmrr, &acpi_rmrr_units, list) \
/* assume there never is a bdf == 0 */ \
- for (idx = 0; (bdf = rmrr->scope.devices[i]) && \
+ for (idx = 0; (bdf = rmrr->scope.devices[idx]) && \
idx < rmrr->scope.devices_cnt; idx++)
struct acpi_drhd_unit * acpi_find_matched_drhd_unit(u8 bus, u8 devfn);
diff -r 0bf73f557f41 -r fc44e35b3913 xen/drivers/passthrough/vtd/iommu.c
--- a/xen/drivers/passthrough/vtd/iommu.c Tue Jul 22 11:55:06 2008 +0100
+++ b/xen/drivers/passthrough/vtd/iommu.c Tue Jul 22 11:56:26 2008 +0100
@@ -1294,11 +1294,18 @@ static int domain_context_mapping(struct
return ret;
}
-static int domain_context_unmap_one(struct iommu *iommu, u8 bus, u8 devfn)
+static int domain_context_unmap_one(
+ struct domain *domain,
+ struct iommu *iommu,
+ u8 bus, u8 devfn)
{
struct context_entry *context, *context_entries;
unsigned long flags;
u64 maddr;
+ struct acpi_rmrr_unit *rmrr;
+ u16 bdf;
+ int i;
+ unsigned int is_rmrr_device = 0;
maddr = bus_to_context_maddr(iommu, bus);
context_entries = (struct context_entry *)map_vtd_domain_page(maddr);
@@ -1311,18 +1318,32 @@ static int domain_context_unmap_one(stru
}
spin_lock_irqsave(&iommu->lock, flags);
- context_clear_present(*context);
- context_clear_entry(*context);
- iommu_flush_cache_entry(context);
- iommu_flush_context_global(iommu, 0);
- iommu_flush_iotlb_global(iommu, 0);
+ if ( domain->domain_id == 0 )
+ {
+ for_each_rmrr_device ( rmrr, bdf, i )
+ {
+ if ( PCI_BUS(bdf) == bus && PCI_DEVFN2(bdf) == devfn )
+ {
+ is_rmrr_device = 1;
+ break;
+ }
+ }
+ }
+ if ( !is_rmrr_device )
+ {
+ context_clear_present(*context);
+ context_clear_entry(*context);
+ iommu_flush_cache_entry(context);
+ iommu_flush_context_domain(iommu, domain_iommu_domid(domain), 0);
+ iommu_flush_iotlb_dsi(iommu, domain_iommu_domid(domain), 0);
+ }
unmap_vtd_domain_page(context_entries);
spin_unlock_irqrestore(&iommu->lock, flags);
return 0;
}
-static int domain_context_unmap(u8 bus, u8 devfn)
+static int domain_context_unmap(struct domain *domain, u8 bus, u8 devfn)
{
struct acpi_drhd_unit *drhd;
u16 sec_bus, sub_bus;
@@ -1345,18 +1366,18 @@ static int domain_context_unmap(u8 bus,
PCI_SUBORDINATE_BUS);
/*dmar_scope_remove_buses(&drhd->scope, sec_bus, sub_bus);*/
if ( DEV_TYPE_PCI_BRIDGE )
- ret = domain_context_unmap_one(drhd->iommu, bus, devfn);
+ ret = domain_context_unmap_one(domain, drhd->iommu, bus, devfn);
break;
case DEV_TYPE_PCIe_ENDPOINT:
- ret = domain_context_unmap_one(drhd->iommu, bus, devfn);
+ ret = domain_context_unmap_one(domain, drhd->iommu, bus, devfn);
break;
case DEV_TYPE_PCI:
if ( find_pcie_endpoint(&bus, &devfn, &secbus) )
- ret = domain_context_unmap_one(drhd->iommu, bus, devfn);
+ ret = domain_context_unmap_one(domain, drhd->iommu, bus, devfn);
if ( bus != secbus )
- domain_context_unmap_one(drhd->iommu, secbus, 0);
+ domain_context_unmap_one(domain, drhd->iommu, secbus, 0);
break;
default:
@@ -1386,7 +1407,7 @@ static int reassign_device_ownership(
drhd = acpi_find_matched_drhd_unit(bus, devfn);
pdev_iommu = drhd->iommu;
- domain_context_unmap(bus, devfn);
+ domain_context_unmap(source, bus, devfn);
write_lock(&pcidevs_lock);
list_move(&pdev->domain_list, &target->arch.pdev_list);
@@ -1584,7 +1605,9 @@ static int intel_iommu_add_device(struct
static int intel_iommu_remove_device(struct pci_dev *pdev)
{
- return domain_context_unmap(pdev->bus, pdev->devfn);
+ if ( !pdev->domain )
+ return -EINVAL;
+ return domain_context_unmap(pdev->domain, pdev->bus, pdev->devfn);
}
static void setup_dom0_devices(struct domain *d)
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|