All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] iommu: Force iommu shutdown on panic.
@ 2020-02-20 16:26 John Donnelly
  0 siblings, 0 replies; only message in thread
From: John Donnelly @ 2020-02-20 16:26 UTC (permalink / raw)
  To: linux-kernel


This eliminates intermitten kdump hangs reported on AMD/x86 servers 
with iommu enabled (iommu=on) regardless if iommu features are
used or not, on 5.4 kernels.  When kdump fails to initialize and run, no vmcore
(crash dumps) are captured.

Derived from the upsteam commit: iommu/vt-d: Turn off translations at shutdown.


Signed-off-by: John Donnelly <john.p.donnelly@oracle.com>
Reviewed-by: Jack Vogel <jack.vogel@oracle.com>
---
 arch/x86/include/asm/x86_init.h | 2 +-
 arch/x86/kernel/amd_gart_64.c   | 2 +-
 arch/x86/kernel/reboot.c        | 2 +-
 arch/x86/kernel/x86_init.c      | 2 +-
 drivers/iommu/amd_iommu_init.c  | 8 ++++----
 drivers/iommu/intel-iommu.c     | 9 ++++++---
 include/linux/dmar.h            | 4 ++--
 kernel/panic.c                  | 7 +++++++
 8 files changed, 23 insertions(+), 13 deletions(-)

diff --git a/arch/x86/include/asm/x86_init.h b/arch/x86/include/asm/x86_init.h
index 96d9cd208610..06233f57b7c9 100644
--- a/arch/x86/include/asm/x86_init.h
+++ b/arch/x86/include/asm/x86_init.h
@@ -270,7 +270,7 @@ struct x86_platform_ops {
 	unsigned long (*calibrate_tsc)(void);
 	void (*get_wallclock)(struct timespec64 *ts);
 	int (*set_wallclock)(const struct timespec64 *ts);
-	void (*iommu_shutdown)(void);
+	void (*iommu_shutdown)(int panic);
 	bool (*is_untracked_pat_range)(u64 start, u64 end);
 	void (*nmi_init)(void);
 	unsigned char (*get_nmi_reason)(void);
diff --git a/arch/x86/kernel/amd_gart_64.c b/arch/x86/kernel/amd_gart_64.c
index 4e5f50236048..2f805cc073ad 100644
--- a/arch/x86/kernel/amd_gart_64.c
+++ b/arch/x86/kernel/amd_gart_64.c
@@ -681,7 +681,7 @@ static const struct dma_map_ops gart_dma_ops = {
 	.get_required_mask		= dma_direct_get_required_mask,
 };
 
-static void gart_iommu_shutdown(void)
+static void gart_iommu_shutdown(int panic)
 {
 	struct pci_dev *dev;
 	int i;
diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c
index 0cc7c0b106bb..fd3c88a4f2e7 100644
--- a/arch/x86/kernel/reboot.c
+++ b/arch/x86/kernel/reboot.c
@@ -708,7 +708,7 @@ void native_machine_shutdown(void)
 #endif
 
 #ifdef CONFIG_X86_64
-	x86_platform.iommu_shutdown();
+	x86_platform.iommu_shutdown(0);
 #endif
 }
 
diff --git a/arch/x86/kernel/x86_init.c b/arch/x86/kernel/x86_init.c
index 85f1a90c55cd..e63719710097 100644
--- a/arch/x86/kernel/x86_init.c
+++ b/arch/x86/kernel/x86_init.c
@@ -28,7 +28,7 @@
 void x86_init_noop(void) { }
 void __init x86_init_uint_noop(unsigned int unused) { }
 static int __init iommu_init_noop(void) { return 0; }
-static void iommu_shutdown_noop(void) { }
+static void iommu_shutdown_noop(int panic) { }
 bool __init bool_x86_init_noop(void) { return false; }
 void x86_op_int_noop(int cpu) { }
 static __init int set_rtc_noop(const struct timespec64 *now) { return -EINVAL; }
diff --git a/drivers/iommu/amd_iommu_init.c b/drivers/iommu/amd_iommu_init.c
index 2759a8d57b7f..a1afc2e2a68c 100644
--- a/drivers/iommu/amd_iommu_init.c
+++ b/drivers/iommu/amd_iommu_init.c
@@ -2361,7 +2361,7 @@ static void enable_iommus(void)
 	enable_iommus_v2();
 }
 
-static void disable_iommus(void)
+static void disable_iommus(int panic)
 {
 	struct amd_iommu *iommu;
 
@@ -2395,7 +2395,7 @@ static void amd_iommu_resume(void)
 static int amd_iommu_suspend(void)
 {
 	/* disable IOMMUs to go out of the way for BIOS */
-	disable_iommus();
+	disable_iommus(0);
 
 	return 0;
 }
@@ -2612,7 +2612,7 @@ static int __init early_amd_iommu_init(void)
 
 	/* Disable any previously enabled IOMMUs */
 	if (!is_kdump_kernel() || amd_iommu_disabled)
-		disable_iommus();
+		disable_iommus(0);
 
 	if (amd_iommu_irq_remap)
 		amd_iommu_irq_remap = check_ioapic_information();
@@ -2762,7 +2762,7 @@ static int __init state_next(void)
 	if (ret) {
 		free_dma_resources();
 		if (!irq_remapping_enabled) {
-			disable_iommus();
+			disable_iommus(0);
 			free_iommu_resources();
 		} else {
 			struct amd_iommu *iommu;
diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c
index 9dc37672bf89..8bc95f4e7d3e 100644
--- a/drivers/iommu/intel-iommu.c
+++ b/drivers/iommu/intel-iommu.c
@@ -4903,7 +4903,7 @@ static void intel_disable_iommus(void)
 		iommu_disable_translation(iommu);
 }
 
-void intel_iommu_shutdown(void)
+void intel_iommu_shutdown(int panic)
 {
 	struct dmar_drhd_unit *drhd;
 	struct intel_iommu *iommu = NULL;
@@ -4911,7 +4911,8 @@ void intel_iommu_shutdown(void)
 	if (no_iommu || dmar_disabled)
 		return;
 
-	down_write(&dmar_global_lock);
+	if (!panic)
+		down_write(&dmar_global_lock);
 
 	/* Disable PMRs explicitly here. */
 	for_each_iommu(iommu, drhd)
@@ -4920,7 +4921,9 @@ void intel_iommu_shutdown(void)
 	/* Make sure the IOMMUs are switched off */
 	intel_disable_iommus();
 
-	up_write(&dmar_global_lock);
+	if (!panic)
+		up_write(&dmar_global_lock);
+	
 }
 
 static inline struct intel_iommu *dev_to_intel_iommu(struct device *dev)
diff --git a/include/linux/dmar.h b/include/linux/dmar.h
index f64ca27dc210..c4f24bc41169 100644
--- a/include/linux/dmar.h
+++ b/include/linux/dmar.h
@@ -129,7 +129,7 @@ static inline int dmar_res_noop(struct acpi_dmar_header *hdr, void *arg)
 #ifdef CONFIG_INTEL_IOMMU
 extern int iommu_detected, no_iommu;
 extern int intel_iommu_init(void);
-extern void intel_iommu_shutdown(void);
+extern void intel_iommu_shutdown(int panic);
 extern int dmar_parse_one_rmrr(struct acpi_dmar_header *header, void *arg);
 extern int dmar_parse_one_atsr(struct acpi_dmar_header *header, void *arg);
 extern int dmar_check_one_atsr(struct acpi_dmar_header *hdr, void *arg);
@@ -138,7 +138,7 @@ extern int dmar_iommu_hotplug(struct dmar_drhd_unit *dmaru, bool insert);
 extern int dmar_iommu_notify_scope_dev(struct dmar_pci_notify_info *info);
 #else /* !CONFIG_INTEL_IOMMU: */
 static inline int intel_iommu_init(void) { return -ENODEV; }
-static inline void intel_iommu_shutdown(void) { }
+static inline void intel_iommu_shutdown(int panic) { }
 
 #define	dmar_parse_one_rmrr		dmar_res_noop
 #define	dmar_parse_one_atsr		dmar_res_noop
diff --git a/kernel/panic.c b/kernel/panic.c
index b69ee9e76cb2..ee81462d5b1f 100644
--- a/kernel/panic.c
+++ b/kernel/panic.c
@@ -32,6 +32,7 @@
 #include <linux/ratelimit.h>
 #include <linux/debugfs.h>
 #include <asm/sections.h>
+#include <linux/dmar.h>
 
 #define PANIC_TIMER_STEP 100
 #define PANIC_BLINK_SPD 18
@@ -213,6 +214,12 @@ void panic(const char *fmt, ...)
 		buf[len - 1] = '\0';
 
 	pr_emerg("Kernel panic - not syncing: %s\n", buf);
+
+#ifdef CONFIG_X86
+	pr_emerg("Shutting down iommu.\n");
+	x86_platform.iommu_shutdown(1); 
+#endif
+
 #ifdef CONFIG_DEBUG_BUGVERBOSE
 	/*
 	 * Avoid nested stack-dumping if a panic occurs during oops processing
-- 
2.20.1


^ permalink raw reply related	[flat|nested] only message in thread

only message in thread, other threads:[~2020-02-20 16:26 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-02-20 16:26 [PATCH] iommu: Force iommu shutdown on panic John Donnelly

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.