Subject: [PATCH] x86, kdump, 64bit: Try allocate crashkernel under 896M at first

On 64bit system, we try allocate crashkernel above 4G at first,
and does not set low range for crashkernel if the user does not
specify that.

That cause regressions on system that does not support intel_iommu
properly.

Chao said that his system does work well on 3.8 without extra parameter.
even iommu does not work with kdump.

Change to try use old 896M limit at first and then try to allocate above 4G.

Also update kernel parameters to make it clear when that is needed.

-v2: try 4G below and at last try MAXMEM according to Vivek.

Reported-by: WANG Chao <chaowang@redhat.com>
Suggested-by: Vivek Goyal <vgoyal@redhat.com>
Signed-off-by: Yinghai Lu <yinghai@kernel.org>

---
 Documentation/kernel-parameters.txt |   10 +++++++---
 arch/x86/kernel/setup.c             |   15 ++++++++++++++-
 2 files changed, 21 insertions(+), 4 deletions(-)

Index: linux-2.6/Documentation/kernel-parameters.txt
===================================================================
--- linux-2.6.orig/Documentation/kernel-parameters.txt
+++ linux-2.6/Documentation/kernel-parameters.txt
@@ -596,9 +596,6 @@ bytes respectively. Such letter suffixes
 			is selected automatically. Check
 			Documentation/kdump/kdump.txt for further details.
 
-	crashkernel_low=size[KMG]
-			[KNL, x86] parts under 4G.
-
 	crashkernel=range1:size1[,range2:size2,...][@offset]
 			[KNL] Same as above, but depends on the memory
 			in the running system. The syntax of range is
@@ -606,6 +603,13 @@ bytes respectively. Such letter suffixes
 			a memory unit (amount[KMG]). See also
 			Documentation/kdump/kdump.txt for an example.
 
+	crashkernel_low=size[KMG]
+			[KNL, x86_64] range under 4G. When crashkernel= request
+			more than 512M, kernel allocate physical memory region
+			above 4G, that cause second kernel crash on system that
+			need swiotlb later. This one let user to specify extra
+			low range under 4G for second kernel.
+
 	cs89x0_dma=	[HW,NET]
 			Format: <dma>
 
Index: linux-2.6/arch/x86/kernel/setup.c
===================================================================
--- linux-2.6.orig/arch/x86/kernel/setup.c
+++ linux-2.6/arch/x86/kernel/setup.c
@@ -507,11 +507,12 @@ static void __init memblock_x86_reserve_
 /*
  * Keep the crash kernel below this limit.  On 32 bits earlier kernels
  * would limit the kernel to the low 512 MiB due to mapping restrictions.
+ * On 64 bits, kexec-tools (before 2.0.4) limits us to 896 MiB.
  */
 #ifdef CONFIG_X86_32
 # define CRASH_KERNEL_ADDR_MAX	(512 << 20)
 #else
-# define CRASH_KERNEL_ADDR_MAX	MAXMEM
+# define CRASH_KERNEL_ADDR_MAX	(896 << 20)
 #endif
 
 static void __init reserve_crashkernel_low(void)
@@ -571,6 +572,18 @@ static void __init reserve_crashkernel(v
 		crash_base = memblock_find_in_range(alignment,
 			       CRASH_KERNEL_ADDR_MAX, crash_size, alignment);
 
+#ifdef CONFIG_X86_64
+		/* try under 4G at first */
+		if (!crash_base)
+			crash_base = memblock_find_in_range(alignment,
+				       1UL<<32, crash_size, alignment);
+		/* above 4G now */
+		if (!crash_base)
+			crash_base = memblock_find_in_range(alignment,
+				       MAXMEM, crash_size, alignment);
+
+#endif
+
 		if (!crash_base) {
 			pr_info("crashkernel reservation failed - No suitable area found.\n");
 			return;
