]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blobdiff - arch/x86/kernel/aperture_64.c
x86/speculation: Consolidate CPU whitelists
[mirror_ubuntu-bionic-kernel.git] / arch / x86 / kernel / aperture_64.c
index f5d92bc3b8844422628b8e6d741be34d727aa45b..365fcc37b2a27bcd03334f7ae314e3915bd10bb2 100644 (file)
@@ -30,6 +30,7 @@
 #include <asm/dma.h>
 #include <asm/amd_nb.h>
 #include <asm/x86_init.h>
+#include <linux/crash_dump.h>
 
 /*
  * Using 512M as goal, in case kexec will load kernel_big
@@ -56,6 +57,33 @@ int fallback_aper_force __initdata;
 
 int fix_aperture __initdata = 1;
 
+#ifdef CONFIG_PROC_VMCORE
+/*
+ * If the first kernel maps the aperture over e820 RAM, the kdump kernel will
+ * use the same range because it will remain configured in the northbridge.
+ * Trying to dump this area via /proc/vmcore may crash the machine, so exclude
+ * it from vmcore.
+ */
+static unsigned long aperture_pfn_start, aperture_page_count;
+
+static int gart_oldmem_pfn_is_ram(unsigned long pfn)
+{
+       return likely((pfn < aperture_pfn_start) ||
+                     (pfn >= aperture_pfn_start + aperture_page_count));
+}
+
+static void exclude_from_vmcore(u64 aper_base, u32 aper_order)
+{
+       aperture_pfn_start = aper_base >> PAGE_SHIFT;
+       aperture_page_count = (32 * 1024 * 1024) << aper_order >> PAGE_SHIFT;
+       WARN_ON(register_oldmem_pfn_is_ram(&gart_oldmem_pfn_is_ram));
+}
+#else
+static void exclude_from_vmcore(u64 aper_base, u32 aper_order)
+{
+}
+#endif
+
 /* This code runs before the PCI subsystem is initialized, so just
    access the northbridge directly. */
 
@@ -92,32 +120,6 @@ static u32 __init allocate_aperture(void)
 }
 
 
-/* Find a PCI capability */
-static u32 __init find_cap(int bus, int slot, int func, int cap)
-{
-       int bytes;
-       u8 pos;
-
-       if (!(read_pci_config_16(bus, slot, func, PCI_STATUS) &
-                                               PCI_STATUS_CAP_LIST))
-               return 0;
-
-       pos = read_pci_config_byte(bus, slot, func, PCI_CAPABILITY_LIST);
-       for (bytes = 0; bytes < 48 && pos >= 0x40; bytes++) {
-               u8 id;
-
-               pos &= ~3;
-               id = read_pci_config_byte(bus, slot, func, pos+PCI_CAP_LIST_ID);
-               if (id == 0xff)
-                       break;
-               if (id == cap)
-                       return pos;
-               pos = read_pci_config_byte(bus, slot, func,
-                                               pos+PCI_CAP_LIST_NEXT);
-       }
-       return 0;
-}
-
 /* Read a standard AGPv3 bridge header */
 static u32 __init read_agp(int bus, int slot, int func, int cap, u32 *order)
 {
@@ -206,8 +208,8 @@ static u32 __init search_agp_bridge(u32 *order, int *valid_agp)
                                case PCI_CLASS_BRIDGE_HOST:
                                case PCI_CLASS_BRIDGE_OTHER: /* needed? */
                                        /* AGP bridge? */
-                                       cap = find_cap(bus, slot, func,
-                                                       PCI_CAP_ID_AGP);
+                                       cap = pci_early_find_cap(bus, slot,
+                                                func, PCI_CAP_ID_AGP);
                                        if (!cap)
                                                break;
                                        *valid_agp = 1;
@@ -435,8 +437,16 @@ int __init gart_iommu_hole_init(void)
 
 out:
        if (!fix && !fallback_aper_force) {
-               if (last_aper_base)
+               if (last_aper_base) {
+                       /*
+                        * If this is the kdump kernel, the first kernel
+                        * may have allocated the range over its e820 RAM
+                        * and fixed up the northbridge
+                        */
+                       exclude_from_vmcore(last_aper_base, last_aper_order);
+
                        return 1;
+               }
                return 0;
        }
 
@@ -473,6 +483,14 @@ out:
                return 0;
        }
 
+       /*
+        * If this is the kdump kernel _and_ the first kernel did not
+        * configure the aperture in the northbridge, this range may
+        * overlap with the first kernel's memory. We can't access the
+        * range through vmcore even though it should be part of the dump.
+        */
+       exclude_from_vmcore(aper_alloc, aper_order);
+
        /* Fix up the north bridges */
        for (i = 0; i < amd_nb_bus_dev_ranges[i].dev_limit; i++) {
                int bus, dev_base, dev_limit;