Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > fc11cd6e1c513a17304da94a5390f3cd > files > 4074

kernel-2.6.18-194.11.1.el5.src.rpm

From: Bhavna Sarathy <bnagendr@redhat.com>
Date: Thu, 11 Jun 2009 15:21:31 -0400
Subject: [x86_64] amd iommu: fix kdump unknown partition table
Message-id: 20090611192238.13312.58542.sendpatchset@localhost.localdomain
O-Subject: [RHEL5.4 PATCH] Fix kdump unknown partition table on AMD IOMMU system
Bugzilla: 504751
RH-Acked-by: Chris Wright <chrisw@redhat.com>
RH-Acked-by: Neil Horman <nhorman@redhat.com>
RH-Acked-by: Don Dutile <ddutile@redhat.com>

Resolves BZ 504751

While testing kdump/kexec Neil Horman found that on AMD IOMMU system, kdump is
unable to detect logical volumes because of unknown partition table.   The root
cause to this issue is that the IOMMU hardware needs to be disabled for kdump
to work properly. This patch changes the code so the hardware gets disabled
at a crash.  The patch also allows for IOMMU to function in the kdump/kexec kernel.

Patch tested succesfully by Neil Horman, and Chris Wright (thanks for a cleaner
patch!), on AMD IOMMU system.

Please ACK for RHEL5.4 beta.

diff --git a/arch/x86_64/kernel/amd_iommu.c b/arch/x86_64/kernel/amd_iommu.c
index 75176eb..e17b779 100644
--- a/arch/x86_64/kernel/amd_iommu.c
+++ b/arch/x86_64/kernel/amd_iommu.c
@@ -422,6 +422,16 @@ static void iommu_flush_tlb(struct amd_iommu *iommu, u16 domid)
 	iommu_queue_inv_iommu_pages(iommu, address, domid, 0, 1);
 }
 
+/* Flush the whole IO/TLB for a given protection domain - including PDE */
+static void iommu_flush_tlb_pde(struct amd_iommu *iommu, u16 domid)
+{
+	u64 address = CMD_INV_IOMMU_ALL_PAGES_ADDRESS;
+
+	INC_STATS_COUNTER(domain_flush_single);
+
+	iommu_queue_inv_iommu_pages(iommu, address, domid, 1, 1);
+}
+
 /*
  * This function is used to flush the IO/TLB for a given protection domain
  * on every IOMMU in the system
@@ -931,7 +941,13 @@ static void attach_device(struct amd_iommu *iommu,
 	amd_iommu_pd_table[devid] = domain;
 	write_unlock_irqrestore(&amd_iommu_devtable_lock, flags);
 
+	/*
+	 * We might boot into a crash-kernel here. The crashed kernel
+	 * left the caches in the IOMMU dirty. So we have to flush
+	 * here to evict all dirty stuff.
+	 */
 	iommu_queue_inv_dev_entry(iommu, devid);
+	iommu_flush_tlb_pde(iommu, domain->id);
 }
 
 /*
diff --git a/arch/x86_64/kernel/amd_iommu_init.c b/arch/x86_64/kernel/amd_iommu_init.c
index e74dfb5..34dc114 100644
--- a/arch/x86_64/kernel/amd_iommu_init.c
+++ b/arch/x86_64/kernel/amd_iommu_init.c
@@ -420,6 +420,9 @@ static u8 * __init alloc_command_buffer(struct amd_iommu *iommu)
 
 	iommu->cmd_buf_size = CMD_BUFFER_SIZE;
 
+	/* disable command buffer processing while setting it up */
+	iommu_feature_disable(iommu, CONTROL_CMDBUF_EN);
+
 	entry = (u64)virt_to_phys(cmd_buf);
 	entry |= MMIO_CMD_SIZE_512;
 	memcpy_toio(iommu->mmio_base + MMIO_CMD_BUF_OFFSET,