diff options
author | markj <markj@ccf9f872-aa2e-dd11-9fc8-001c23d0bc1f> | 2020-12-18 16:04:48 +0000 |
---|---|---|
committer | markj <markj@ccf9f872-aa2e-dd11-9fc8-001c23d0bc1f> | 2020-12-18 16:04:48 +0000 |
commit | 08d3bb4081071529219daf3f1d2485c5c229212e (patch) | |
tree | 4c22c04d9085aa0d6db60658b7f9ff554e03dcd3 | |
parent | 0d867e57b4ffff25755360ac4e0f81b93bd58334 (diff) | |
download | freebsd-08d3bb4081071529219daf3f1d2485c5c229212e.tar.gz freebsd-08d3bb4081071529219daf3f1d2485c5c229212e.tar.bz2 |
acpi: Ensure that adjacent memory affinity table entries are coalesced
The SRAT may contain multiple distinct entries that together describe a
contiguous region of physical memory. In this case we were not
coalescing the corresponding entries in the memory affinity table, which
led to fragmented phys_avail[] entries. Since r338431 the vm_phys_segs[]
entries derived from phys_avail[] will be coalesced, resulting in a
situation where vm_phys_segs[] entries do not have a covering
phys_avail[] entry. vm_page_startup() will not add such segments to the
physical memory allocator, leaving them unused.
Reported by: Don Morris <dgmorris@earthlink.net>
Reviewed by: kib, vangyzen
MFC after: 2 weeks
Sponsored by: The FreeBSD Foundation
Differential Revision: https://reviews.freebsd.org/D27620
git-svn-id: http://svn.freebsd.org/base/head@368763 ccf9f872-aa2e-dd11-9fc8-001c23d0bc1f
-rw-r--r-- | sys/dev/acpica/acpi_pxm.c | 37 |
1 files changed, 25 insertions, 12 deletions
diff --git a/sys/dev/acpica/acpi_pxm.c b/sys/dev/acpica/acpi_pxm.c index 04be00e96b5..808886d744f 100644 --- a/sys/dev/acpica/acpi_pxm.c +++ b/sys/dev/acpica/acpi_pxm.c @@ -265,6 +265,7 @@ srat_parse_entry(ACPI_SUBTABLE_HEADER *entry, void *arg) ACPI_SRAT_MEM_AFFINITY *mem; ACPI_SRAT_GICC_AFFINITY *gicc; static struct cpu_info *cpup; + uint64_t base, length; int domain, i, slot; switch (entry->Type) { @@ -327,20 +328,22 @@ srat_parse_entry(ACPI_SUBTABLE_HEADER *entry, void *arg) break; case ACPI_SRAT_TYPE_MEMORY_AFFINITY: mem = (ACPI_SRAT_MEM_AFFINITY *)entry; + base = mem->BaseAddress; + length = mem->Length; + domain = mem->ProximityDomain; + if (bootverbose) printf( "SRAT: Found memory domain %d addr 0x%jx len 0x%jx: %s\n", - mem->ProximityDomain, (uintmax_t)mem->BaseAddress, - (uintmax_t)mem->Length, + domain, (uintmax_t)base, (uintmax_t)length, (mem->Flags & ACPI_SRAT_MEM_ENABLED) ? "enabled" : "disabled"); if (!(mem->Flags & ACPI_SRAT_MEM_ENABLED)) break; - if (mem->BaseAddress >= maxphyaddr || - !overlaps_phys_avail(mem->BaseAddress, - mem->BaseAddress + mem->Length)) { + if (base >= maxphyaddr || + !overlaps_phys_avail(base, base + length)) { printf("SRAT: Ignoring memory at addr 0x%jx\n", - (uintmax_t)mem->BaseAddress); + (uintmax_t)base); break; } if (num_mem == VM_PHYSSEG_MAX) { @@ -350,10 +353,20 @@ srat_parse_entry(ACPI_SUBTABLE_HEADER *entry, void *arg) } slot = num_mem; for (i = 0; i < num_mem; i++) { - if (mem_info[i].end <= mem->BaseAddress) + if (mem_info[i].domain == domain) { + /* Try to extend an existing segment. */ + if (base == mem_info[i].end) { + mem_info[i].end += length; + return; + } + if (base + length == mem_info[i].start) { + mem_info[i].start -= length; + return; + } + } + if (mem_info[i].end <= base) continue; - if (mem_info[i].start < - (mem->BaseAddress + mem->Length)) { + if (mem_info[i].start < base + length) { printf("SRAT: Overlapping memory entries\n"); *(int *)arg = ENXIO; return; @@ -362,9 +375,9 @@ srat_parse_entry(ACPI_SUBTABLE_HEADER *entry, void *arg) } for (i = num_mem; i > slot; i--) mem_info[i] = mem_info[i - 1]; - mem_info[slot].start = mem->BaseAddress; - mem_info[slot].end = mem->BaseAddress + mem->Length; - mem_info[slot].domain = mem->ProximityDomain; + mem_info[slot].start = base; + mem_info[slot].end = base + length; + mem_info[slot].domain = domain; num_mem++; break; } |