150472Speter// SPDX-License-Identifier: GPL-2.0 21664Sphk#include <linux/ioport.h> 369040Sben#include <linux/printk.h> 469040Sben#include <asm/e820/api.h> 569040Sben#include <asm/pci_x86.h> 669040Sben 782604Salexstatic void resource_clip(struct resource *res, resource_size_t start, 882604Salex resource_size_t end) 982604Salex{ 1082604Salex resource_size_t low = 0, high = 0; 111664Sphk 123023Srgrimes if (res->end < start || res->start > end) 133023Srgrimes return; /* no conflict */ 1482604Salex 1582604Salex if (res->start < start) 1682604Salex low = start - res->start; 171664Sphk 1872679Skris if (res->end > end) 1972878Skris high = res->end - end; 2072878Skris 2172878Skris /* Keep the area above or below the conflict, whichever is larger */ 2272878Skris if (low > high) 2372878Skris res->end = start - 1; 2472878Skris else 2572878Skris res->start = end + 1; 2673145Skris} 2773145Skris 2873145Skrisstatic void remove_e820_regions(struct resource *avail) 2972878Skris{ 3072878Skris int i; 3172679Skris struct e820_entry *entry; 3272878Skris u64 e820_start, e820_end; 3372878Skris struct resource orig = *avail; 3474146Skris 3572878Skris if (!pci_use_e820) 3658648Skris return; 3768917Sdougb 3858648Skris for (i = 0; i < e820_table->nr_entries; i++) { 3968917Sdougb entry = &e820_table->entries[i]; 4058648Skris e820_start = entry->addr; 4158648Skris e820_end = entry->addr + entry->size - 1; 4258648Skris 431664Sphk resource_clip(avail, e820_start, e820_end); 4429281Sjkh if (orig.start != avail->start || orig.end != avail->end) { 451664Sphk pr_info("resource: avoiding allocation from e820 entry [mem %#010Lx-%#010Lx]\n", 4659006Sobrien e820_start, e820_end); 4759006Sobrien if (avail->end > avail->start) 4859006Sobrien /* 4959006Sobrien * Use %pa instead of %pR because "avail" 501664Sphk * is typically IORESOURCE_UNSET, so %pR 5159006Sobrien * shows the size instead of addresses. 5259006Sobrien */ 5362136Sobrien pr_info("resource: remaining [mem %pa-%pa] available\n", 5462136Sobrien &avail->start, &avail->end); 5580452Speter orig = *avail; 5680452Speter } 5762136Sobrien } 5882604Salex} 5982604Salex 6082604Salexvoid arch_remove_reservations(struct resource *avail) 6182604Salex{ 6262136Sobrien /* 6368917Sdougb * Trim out BIOS area (high 2MB) and E820 regions. We do not remove 6468263Sobrien * the low 1MB unconditionally, as this area is needed for some ISA 6568263Sobrien * cards requiring a memory range, e.g. the i82365 PCMCIA controller. 6668263Sobrien */ 6765380Sobrien if (avail->flags & IORESOURCE_MEM) { 6865380Sobrien resource_clip(avail, BIOS_ROM_BASE, BIOS_ROM_END); 6965380Sobrien 7081749Sobrien remove_e820_regions(avail); 7181749Sobrien } 7281749Sobrien} 7381749Sobrien