aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMark Johnston <markj@FreeBSD.org>2020-12-18 16:04:48 +0000
committerMark Johnston <markj@FreeBSD.org>2020-12-18 16:04:48 +0000
commit0f8b212a1e41d6eabf2a17442bcbe4f128f023f8 (patch)
tree4c22c04d9085aa0d6db60658b7f9ff554e03dcd3
parent5120612664fbc54d69ee1a21d0abcbab58712709 (diff)
downloadsrc-0f8b212a1e41d6eabf2a17442bcbe4f128f023f8.tar.gz
src-0f8b212a1e41d6eabf2a17442bcbe4f128f023f8.zip
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
Notes
Notes: svn path=/head/; revision=368763
-rw-r--r--sys/dev/acpica/acpi_pxm.c37
1 files changed, 25 insertions, 12 deletions
diff --git a/sys/dev/acpica/acpi_pxm.c b/sys/dev/acpica/acpi_pxm.c
index 04be00e96b50..808886d744f0 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;
}