blob: 9ae64f9af956896cffc749d57009a1ba8e9bd46d [file] [log] [blame]
Greg Kroah-Hartmanb2441312017-11-01 15:07:57 +01001// SPDX-License-Identifier: GPL-2.0
Hans de Goede7f7b4232021-12-17 15:13:48 +01002#include <linux/dmi.h>
Bjorn Helgaas30919b02010-12-16 10:38:51 -07003#include <linux/ioport.h>
Ingo Molnar66441bd2017-01-27 10:27:10 +01004#include <asm/e820/api.h>
Bjorn Helgaas30919b02010-12-16 10:38:51 -07005
Bjorn Helgaas4dc22872010-12-16 10:38:56 -07006static void resource_clip(struct resource *res, resource_size_t start,
7 resource_size_t end)
8{
9 resource_size_t low = 0, high = 0;
10
11 if (res->end < start || res->start > end)
12 return; /* no conflict */
13
14 if (res->start < start)
15 low = start - res->start;
16
17 if (res->end > end)
18 high = res->end - end;
19
20 /* Keep the area above or below the conflict, whichever is larger */
21 if (low > high)
22 res->end = start - 1;
23 else
24 res->start = end + 1;
25}
26
Hans de Goede7f7b4232021-12-17 15:13:48 +010027/*
28 * Some BIOS-es contain a bug where they add addresses which map to
29 * system RAM in the PCI host bridge window returned by the ACPI _CRS
30 * method, see commit 4dc2287c1805 ("x86: avoid E820 regions when
31 * allocating address space"). To avoid this Linux by default excludes
32 * E820 reservations when allocating addresses since 2010.
33 * In 2019 some systems have shown-up with E820 reservations which cover
34 * the entire _CRS returned PCI host bridge window, causing all attempts
35 * to assign memory to PCI BARs to fail if Linux uses E820 reservations.
36 *
37 * Ideally Linux would fully stop using E820 reservations, but then
38 * the old systems this was added for will regress.
39 * Instead keep the old behavior for old systems, while ignoring the
40 * E820 reservations for any systems from now on.
41 */
Bjorn Helgaas4dc22872010-12-16 10:38:56 -070042static void remove_e820_regions(struct resource *avail)
43{
Hans de Goede7f7b4232021-12-17 15:13:48 +010044 int i, year = dmi_get_bios_year();
Ingo Molnar8ec67d92017-01-27 12:54:38 +010045 struct e820_entry *entry;
Bjorn Helgaas4dc22872010-12-16 10:38:56 -070046
Hans de Goede7f7b4232021-12-17 15:13:48 +010047 if (year >= 2018)
48 return;
49
50 pr_info_once("PCI: Removing E820 reservations from host bridge windows\n");
51
Ingo Molnarbf495572017-01-27 14:06:21 +010052 for (i = 0; i < e820_table->nr_entries; i++) {
53 entry = &e820_table->entries[i];
Bjorn Helgaas4dc22872010-12-16 10:38:56 -070054
55 resource_clip(avail, entry->addr,
56 entry->addr + entry->size - 1);
57 }
58}
59
Bjorn Helgaas30919b02010-12-16 10:38:51 -070060void arch_remove_reservations(struct resource *avail)
61{
Christoph Schulzcbace462014-07-16 10:00:57 +020062 /*
63 * Trim out BIOS area (high 2MB) and E820 regions. We do not remove
64 * the low 1MB unconditionally, as this area is needed for some ISA
65 * cards requiring a memory range, e.g. the i82365 PCMCIA controller.
66 */
Bjorn Helgaas30919b02010-12-16 10:38:51 -070067 if (avail->flags & IORESOURCE_MEM) {
Bjorn Helgaasa2c606d2010-12-16 10:39:02 -070068 resource_clip(avail, BIOS_ROM_BASE, BIOS_ROM_END);
Bjorn Helgaas4dc22872010-12-16 10:38:56 -070069
70 remove_e820_regions(avail);
Bjorn Helgaas30919b02010-12-16 10:38:51 -070071 }
72}