Skip to content

Commit 2a3e83c

Browse files
jiribohacKAGA-KOKO
authored andcommitted
x86/gart: Exclude GART aperture from vmcore
On machines where the GART aperture is mapped over physical RAM /proc/vmcore contains the remapped range and reading it may cause hangs or reboots. In the past, the GART region was added into the resource map, implemented by commit 56dd669 ("[PATCH] Insert GART region into resource map") However, inserting the iomem_resource from the early GART code caused resource conflicts with some AGP drivers (bko#72201), which got avoided by reverting the patch in commit 707d4ee ("Revert [PATCH] Insert GART region into resource map"). This revert introduced the /proc/vmcore bug. The vmcore ELF header is either prepared by the kernel (when using the kexec_file_load syscall) or by the kexec userspace (when using the kexec_load syscall). Since we no longer have the GART iomem resource, the userspace kexec has no way of knowing which region to exclude from the ELF header. Changes from v1 of this patch: Instead of excluding the aperture from the ELF header, this patch makes /proc/vmcore return zeroes in the second kernel when attempting to read the aperture region. This is done by reusing the gart_oldmem_pfn_is_ram infrastructure originally intended to exclude XEN balooned memory. This works for both, the kexec_file_load and kexec_load syscalls. [Note that the GART region is the same in the first and second kernels: regardless whether the first kernel fixed up the northbridge/bios setting and mapped the aperture over physical memory, the second kernel finds the northbridge properly configured by the first kernel and the aperture never overlaps with e820 memory because the second kernel has a fake e820 map created from the crashkernel memory regions. Thus, the second kernel keeps the aperture address/size as configured by the first kernel.] register_oldmem_pfn_is_ram can only register one callback and returns an error if the callback has been registered already. Since XEN used to be the only user of this function, it never checks the return value. Now that we have more than one user, I added a WARN_ON just in case agp, XEN, or any other future user of register_oldmem_pfn_is_ram were to step on each other's toes. Fixes: 707d4ee ("Revert [PATCH] Insert GART region into resource map") Signed-off-by: Jiri Bohac <jbohac@suse.cz> Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Cc: Baoquan He <bhe@redhat.com> Cc: Toshi Kani <toshi.kani@hpe.com> Cc: David Airlie <airlied@linux.ie> Cc: yinghai@kernel.org Cc: joro@8bytes.org Cc: kexec@lists.infradead.org Cc: Borislav Petkov <bp@alien8.de> Cc: Bjorn Helgaas <bhelgaas@google.com> Cc: Dave Young <dyoung@redhat.com> Cc: Vivek Goyal <vgoyal@redhat.com> Link: https://lkml.kernel.org/r/20180106010013.73suskgxm7lox7g6@dwarf.suse.cz
1 parent b2cd1df commit 2a3e83c

File tree

2 files changed

+46
-2
lines changed

2 files changed

+46
-2
lines changed

arch/x86/kernel/aperture_64.c

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#include <asm/dma.h>
3131
#include <asm/amd_nb.h>
3232
#include <asm/x86_init.h>
33+
#include <linux/crash_dump.h>
3334

3435
/*
3536
* Using 512M as goal, in case kexec will load kernel_big
@@ -56,6 +57,33 @@ int fallback_aper_force __initdata;
5657

5758
int fix_aperture __initdata = 1;
5859

60+
#ifdef CONFIG_PROC_VMCORE
61+
/*
62+
* If the first kernel maps the aperture over e820 RAM, the kdump kernel will
63+
* use the same range because it will remain configured in the northbridge.
64+
* Trying to dump this area via /proc/vmcore may crash the machine, so exclude
65+
* it from vmcore.
66+
*/
67+
static unsigned long aperture_pfn_start, aperture_page_count;
68+
69+
static int gart_oldmem_pfn_is_ram(unsigned long pfn)
70+
{
71+
return likely((pfn < aperture_pfn_start) ||
72+
(pfn >= aperture_pfn_start + aperture_page_count));
73+
}
74+
75+
static void exclude_from_vmcore(u64 aper_base, u32 aper_order)
76+
{
77+
aperture_pfn_start = aper_base >> PAGE_SHIFT;
78+
aperture_page_count = (32 * 1024 * 1024) << aper_order >> PAGE_SHIFT;
79+
WARN_ON(register_oldmem_pfn_is_ram(&gart_oldmem_pfn_is_ram));
80+
}
81+
#else
82+
static void exclude_from_vmcore(u64 aper_base, u32 aper_order)
83+
{
84+
}
85+
#endif
86+
5987
/* This code runs before the PCI subsystem is initialized, so just
6088
access the northbridge directly. */
6189

@@ -435,8 +463,16 @@ int __init gart_iommu_hole_init(void)
435463

436464
out:
437465
if (!fix && !fallback_aper_force) {
438-
if (last_aper_base)
466+
if (last_aper_base) {
467+
/*
468+
* If this is the kdump kernel, the first kernel
469+
* may have allocated the range over its e820 RAM
470+
* and fixed up the northbridge
471+
*/
472+
exclude_from_vmcore(last_aper_base, last_aper_order);
473+
439474
return 1;
475+
}
440476
return 0;
441477
}
442478

@@ -473,6 +509,14 @@ int __init gart_iommu_hole_init(void)
473509
return 0;
474510
}
475511

512+
/*
513+
* If this is the kdump kernel _and_ the first kernel did not
514+
* configure the aperture in the northbridge, this range may
515+
* overlap with the first kernel's memory. We can't access the
516+
* range through vmcore even though it should be part of the dump.
517+
*/
518+
exclude_from_vmcore(aper_alloc, aper_order);
519+
476520
/* Fix up the north bridges */
477521
for (i = 0; i < amd_nb_bus_dev_ranges[i].dev_limit; i++) {
478522
int bus, dev_base, dev_limit;

arch/x86/xen/mmu_hvm.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,6 @@ void __init xen_hvm_init_mmu_ops(void)
7575
if (is_pagetable_dying_supported())
7676
pv_mmu_ops.exit_mmap = xen_hvm_exit_mmap;
7777
#ifdef CONFIG_PROC_VMCORE
78-
register_oldmem_pfn_is_ram(&xen_oldmem_pfn_is_ram);
78+
WARN_ON(register_oldmem_pfn_is_ram(&xen_oldmem_pfn_is_ram));
7979
#endif
8080
}

0 commit comments

Comments
 (0)