[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] IOMMU VTD BUG: disable Extended Interrupt Mode when disabling Interupt
# HG changeset patch # User Andrew Cooper <andrew.cooper3@xxxxxxxxxx> # Date 1308150465 -3600 # Node ID 96f53d2b966ec86979d0080f15b8d86b2856c736 # Parent 8c75f35d55f60cb2f374e3b5c7c520f8633d733f IOMMU VTD BUG: disable Extended Interrupt Mode when disabling Interupt Remapping Experimental evidence shows that Extended Interrupt Mode remains in effect even after Interrupt Remapping is disabled in each DMAR Global Command Register. A consiquence of this is that when we switch from x2apic mode back to xapic mode, and disable interrupt remapping for the kdump kernel, interrupts passing through the IO APICs are in x2apic format as opposed xapic. This causes a triple fault in the kexec kernel. As EIM is explicitly set up each time Interrup Remapping is enabled, it is safe for us to clobber this when taring down. Also, change the header definition of IRTA_REG_EIME_SHIFT. It caused verbose and error-prone code, and was only used in 1 place before. We now have IRTA_EIME which is the specific bit in the register. Signed-off-by: Andrew Cooper <andrew.cooper3@xxxxxxxxxx> --- diff -r 8c75f35d55f6 -r 96f53d2b966e xen/drivers/passthrough/vtd/intremap.c --- a/xen/drivers/passthrough/vtd/intremap.c Wed Jun 15 16:06:48 2011 +0100 +++ b/xen/drivers/passthrough/vtd/intremap.c Wed Jun 15 16:07:45 2011 +0100 @@ -811,27 +811,12 @@ void disable_intremap(struct iommu *iommu) { u32 sts; + u64 irta; unsigned long flags; if ( !ecap_intr_remap(iommu->ecap) ) return; - /* If we are disabling Interrupt Remapping, make sure we dont stay in - * Extended Interrupt Mode, as this is unaffected by the Interrupt - * Remapping flag in each DMAR Global Control Register. - * Specifically, local apics in xapic mode do not like interrupts delivered - * in x2apic mode. Any code turning interrupt remapping back on will set - * EIME back correctly. - */ - if ( iommu_supports_eim() ) - { - u64 irta; - irta = dmar_readl(iommu->reg, DMAR_IRTA_REG); - dmar_writel(iommu->reg, DMAR_IRTA_REG, irta & ~IRTA_EIME); - IOMMU_WAIT_OP(iommu, DMAR_IRTA_REG, dmar_readl, - !(irta & IRTA_EIME), irta); - } - spin_lock_irqsave(&iommu->register_lock, flags); sts = dmar_readl(iommu->reg, DMAR_GSTS_REG); if ( !(sts & DMA_GSTS_IRES) ) @@ -841,6 +826,26 @@ IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG, dmar_readl, !(sts & DMA_GSTS_IRES), sts); + + /* If we are disabling Interrupt Remapping, make sure we dont stay in + * Extended Interrupt Mode, as this is unaffected by the Interrupt + * Remapping flag in each DMAR Global Control Register. + * Specifically, local apics in xapic mode do not like interrupts delivered + * in x2apic mode. Any code turning interrupt remapping back on will set + * EIME back correctly. + */ + if ( !ecap_eim(iommu->ecap) ) + goto out; + + /* Can't read the register unless we ecaps says we can */ + irta = dmar_readl(iommu->reg, DMAR_IRTA_REG); + if ( !(irta & IRTA_EIME) ) + goto out; + + dmar_writel(iommu->reg, DMAR_IRTA_REG, irta & ~IRTA_EIME); + IOMMU_WAIT_OP(iommu, DMAR_IRTA_REG, dmar_readl, + !(irta & IRTA_EIME), irta); + out: spin_unlock_irqrestore(&iommu->register_lock, flags); } diff -r 8c75f35d55f6 -r 96f53d2b966e xen/drivers/passthrough/vtd/iommu.h --- a/xen/drivers/passthrough/vtd/iommu.h Wed Jun 15 16:06:48 2011 +0100 +++ b/xen/drivers/passthrough/vtd/iommu.h Wed Jun 15 16:07:45 2011 +0100 @@ -471,7 +471,7 @@ #define IEC_GLOBAL_INVL 0 #define IEC_INDEX_INVL 1 -#define IRTA_EIME (1 << 11) +#define IRTA_EIME (((u64)1) << 11) /* 2^(IRTA_REG_TABLE_SIZE + 1) = IREMAP_ENTRY_NR */ #define IRTA_REG_TABLE_SIZE ( IREMAP_PAGE_ORDER + 7 ) _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |