9fd34708c1
guest 21971-pod-accounting.patch - bnc#584204 - xm usb-list broken usb-list.patch - bnc#625520 - TP-L3: NMI cannot be triggered for xen kernel 21926-x86-pv-NMI-inject.patch - bnc#613529 - TP-L3: kdump kernel hangs when crash was initiated from xen kernel 21886-kexec-shutdown.patch - Upstream Intel patches to improve X2APIC handling. 21716-iommu-alloc.patch 21717-ir-qi.patch 21718-x2apic-logic.patch 21933-vtd-ioapic-write.patch 21953-msi-enable.patch OBS-URL: https://build.opensuse.org/package/show/Virtualization/xen?expand=0&rev=71
212 lines
6.9 KiB
Diff
212 lines
6.9 KiB
Diff
# HG changeset patch
|
|
# User Keir Fraser <keir.fraser@citrix.com>
|
|
# Date 1279186958 -3600
|
|
# Node ID 4ba86edf38f816a0d94cfb85b90074a72113e41c
|
|
# Parent 57859775f88f5339fa256e43ee2744be7226c093
|
|
x2APIC/VT-d: allocate iommu when create a drhd
|
|
|
|
A drhd is created when parse ACPI DMAR table, but drhd->iommu is not
|
|
allocated until iommu setup. But iommu is needed by x2APIC which will
|
|
enable interrupt remapping before iommu setup. This patch allocates
|
|
iommu when create drhd. And then drhd->ecap can be removed because
|
|
it's the same as iommu->ecap.
|
|
|
|
Signed-off-by: Weidong Han <weidong.han@intel.com>
|
|
xen-unstable changeset: 21716:64a80813978f
|
|
xen-unstable date: Mon Jul 05 08:29:10 2010 +0100
|
|
|
|
Index: xen-4.0.0-testing/xen/drivers/passthrough/vtd/dmar.c
|
|
===================================================================
|
|
--- xen-4.0.0-testing.orig/xen/drivers/passthrough/vtd/dmar.c
|
|
+++ xen-4.0.0-testing/xen/drivers/passthrough/vtd/dmar.c
|
|
@@ -32,6 +32,7 @@
|
|
#include "dmar.h"
|
|
#include "iommu.h"
|
|
#include "extern.h"
|
|
+#include "vtd.h"
|
|
|
|
#undef PREFIX
|
|
#define PREFIX VTDPREFIX "ACPI DMAR:"
|
|
@@ -378,7 +379,6 @@ acpi_parse_one_drhd(struct acpi_dmar_ent
|
|
struct acpi_table_drhd * drhd = (struct acpi_table_drhd *)header;
|
|
void *dev_scope_start, *dev_scope_end;
|
|
struct acpi_drhd_unit *dmaru;
|
|
- void *addr;
|
|
int ret;
|
|
static int include_all = 0;
|
|
|
|
@@ -397,8 +397,9 @@ acpi_parse_one_drhd(struct acpi_dmar_ent
|
|
dprintk(VTDPREFIX, " dmaru->address = %"PRIx64"\n",
|
|
dmaru->address);
|
|
|
|
- addr = map_to_nocache_virt(0, drhd->address);
|
|
- dmaru->ecap = dmar_readq(addr, DMAR_ECAP_REG);
|
|
+ ret = iommu_alloc(dmaru);
|
|
+ if ( ret )
|
|
+ goto out;
|
|
|
|
dev_scope_start = (void *)(drhd + 1);
|
|
dev_scope_end = ((void *)drhd) + header->length;
|
|
@@ -420,7 +421,7 @@ acpi_parse_one_drhd(struct acpi_dmar_ent
|
|
}
|
|
|
|
if ( ret )
|
|
- xfree(dmaru);
|
|
+ goto out;
|
|
else if ( force_iommu || dmaru->include_all )
|
|
acpi_register_drhd_unit(dmaru);
|
|
else
|
|
@@ -451,14 +452,15 @@ acpi_parse_one_drhd(struct acpi_dmar_ent
|
|
|
|
if ( invalid_cnt )
|
|
{
|
|
- xfree(dmaru);
|
|
-
|
|
if ( iommu_workaround_bios_bug &&
|
|
invalid_cnt == dmaru->scope.devices_cnt )
|
|
{
|
|
dprintk(XENLOG_WARNING VTDPREFIX,
|
|
" Workaround BIOS bug: ignore the DRHD due to all "
|
|
"devices under its scope are not PCI discoverable!\n");
|
|
+
|
|
+ iommu_free(dmaru);
|
|
+ xfree(dmaru);
|
|
}
|
|
else
|
|
{
|
|
@@ -474,6 +476,12 @@ acpi_parse_one_drhd(struct acpi_dmar_ent
|
|
acpi_register_drhd_unit(dmaru);
|
|
}
|
|
|
|
+out:
|
|
+ if ( ret )
|
|
+ {
|
|
+ iommu_free(dmaru);
|
|
+ xfree(dmaru);
|
|
+ }
|
|
return ret;
|
|
}
|
|
|
|
Index: xen-4.0.0-testing/xen/drivers/passthrough/vtd/dmar.h
|
|
===================================================================
|
|
--- xen-4.0.0-testing.orig/xen/drivers/passthrough/vtd/dmar.h
|
|
+++ xen-4.0.0-testing/xen/drivers/passthrough/vtd/dmar.h
|
|
@@ -50,7 +50,6 @@ struct acpi_drhd_unit {
|
|
struct dmar_scope scope; /* must be first member of struct */
|
|
struct list_head list;
|
|
u64 address; /* register base address of the unit */
|
|
- u64 ecap;
|
|
u8 include_all:1;
|
|
struct iommu *iommu;
|
|
struct list_head ioapic_list;
|
|
Index: xen-4.0.0-testing/xen/drivers/passthrough/vtd/intremap.c
|
|
===================================================================
|
|
--- xen-4.0.0-testing.orig/xen/drivers/passthrough/vtd/intremap.c
|
|
+++ xen-4.0.0-testing/xen/drivers/passthrough/vtd/intremap.c
|
|
@@ -135,15 +135,20 @@ int iommu_supports_eim(void)
|
|
/* We MUST have a DRHD unit for each IOAPIC. */
|
|
for ( apic = 0; apic < nr_ioapics; apic++ )
|
|
if ( !ioapic_to_drhd(IO_APIC_ID(apic)) )
|
|
+ {
|
|
+ dprintk(XENLOG_WARNING VTDPREFIX,
|
|
+ "There is not a DRHD for IOAPIC 0x%x (id: 0x%x)!\n",
|
|
+ apic, IO_APIC_ID(apic));
|
|
return 0;
|
|
+ }
|
|
|
|
if ( list_empty(&acpi_drhd_units) )
|
|
return 0;
|
|
|
|
for_each_drhd_unit ( drhd )
|
|
- if ( !ecap_queued_inval(drhd->ecap) ||
|
|
- !ecap_intr_remap(drhd->ecap) ||
|
|
- !ecap_eim(drhd->ecap) )
|
|
+ if ( !ecap_queued_inval(drhd->iommu->ecap) ||
|
|
+ !ecap_intr_remap(drhd->iommu->ecap) ||
|
|
+ !ecap_eim(drhd->iommu->ecap) )
|
|
return 0;
|
|
|
|
return 1;
|
|
Index: xen-4.0.0-testing/xen/drivers/passthrough/vtd/iommu.c
|
|
===================================================================
|
|
--- xen-4.0.0-testing.orig/xen/drivers/passthrough/vtd/iommu.c
|
|
+++ xen-4.0.0-testing/xen/drivers/passthrough/vtd/iommu.c
|
|
@@ -143,15 +143,18 @@ struct iommu_flush *iommu_get_flush(stru
|
|
return iommu ? &iommu->intel->flush : NULL;
|
|
}
|
|
|
|
-static unsigned int clflush_size;
|
|
static int iommus_incoherent;
|
|
static void __iommu_flush_cache(void *addr, unsigned int size)
|
|
{
|
|
int i;
|
|
+ static unsigned int clflush_size = 0;
|
|
|
|
if ( !iommus_incoherent )
|
|
return;
|
|
|
|
+ if ( clflush_size == 0 )
|
|
+ clflush_size = get_cache_line_size();
|
|
+
|
|
for ( i = 0; i < size; i += clflush_size )
|
|
cacheline_flush((char *)addr + i);
|
|
}
|
|
@@ -1036,7 +1039,7 @@ static int iommu_set_interrupt(struct io
|
|
return irq;
|
|
}
|
|
|
|
-static int iommu_alloc(struct acpi_drhd_unit *drhd)
|
|
+int __init iommu_alloc(struct acpi_drhd_unit *drhd)
|
|
{
|
|
struct iommu *iommu;
|
|
unsigned long sagaw, nr_dom;
|
|
@@ -1130,7 +1133,7 @@ static int iommu_alloc(struct acpi_drhd_
|
|
return 0;
|
|
}
|
|
|
|
-static void iommu_free(struct acpi_drhd_unit *drhd)
|
|
+void __init iommu_free(struct acpi_drhd_unit *drhd)
|
|
{
|
|
struct iommu *iommu = drhd->iommu;
|
|
|
|
@@ -1938,8 +1941,6 @@ int intel_vtd_setup(void)
|
|
|
|
platform_quirks();
|
|
|
|
- clflush_size = get_cache_line_size();
|
|
-
|
|
irq_to_iommu = xmalloc_array(struct iommu*, nr_irqs);
|
|
BUG_ON(!irq_to_iommu);
|
|
memset(irq_to_iommu, 0, nr_irqs * sizeof(struct iommu*));
|
|
@@ -1953,9 +1954,6 @@ int intel_vtd_setup(void)
|
|
*/
|
|
for_each_drhd_unit ( drhd )
|
|
{
|
|
- if ( iommu_alloc(drhd) != 0 )
|
|
- goto error;
|
|
-
|
|
iommu = drhd->iommu;
|
|
|
|
if ( iommu_snoop && !ecap_snp_ctl(iommu->ecap) )
|
|
@@ -1995,8 +1993,6 @@ int intel_vtd_setup(void)
|
|
return 0;
|
|
|
|
error:
|
|
- for_each_drhd_unit ( drhd )
|
|
- iommu_free(drhd);
|
|
iommu_enabled = 0;
|
|
iommu_snoop = 0;
|
|
iommu_passthrough = 0;
|
|
Index: xen-4.0.0-testing/xen/drivers/passthrough/vtd/vtd.h
|
|
===================================================================
|
|
--- xen-4.0.0-testing.orig/xen/drivers/passthrough/vtd/vtd.h
|
|
+++ xen-4.0.0-testing/xen/drivers/passthrough/vtd/vtd.h
|
|
@@ -108,4 +108,7 @@ void unmap_vtd_domain_page(void *va);
|
|
void iommu_flush_cache_entry(void *addr, unsigned int size);
|
|
void iommu_flush_cache_page(void *addr, unsigned long npages);
|
|
|
|
+int iommu_alloc(struct acpi_drhd_unit *drhd);
|
|
+void iommu_free(struct acpi_drhd_unit *drhd);
|
|
+
|
|
#endif // _VTD_H_
|