- Split the logic to parse an SMAP entry out into a separate function on
amd64 similar to i386. This fixes a bug on amd64 where overlapping entries would not cause the SMAP parsing to stop. - Change the SMAP parsing code to do a sorted insertion into physmap[] instead of an append to support systems with out-of-order SMAP entries. PR: amd64/138220 Reported by: James R. Van Artsdalen james of jrv org MFC after: 3 days
This commit is contained in:
parent
fd3c9374ff
commit
07ee969179
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=197410
@ -1192,6 +1192,77 @@ isa_irq_pending(void)
|
||||
|
||||
u_int basemem;
|
||||
|
||||
static int
|
||||
add_smap_entry(struct bios_smap *smap, vm_paddr_t *physmap, int *physmap_idxp)
|
||||
{
|
||||
int i, insert_idx, physmap_idx;
|
||||
|
||||
physmap_idx = *physmap_idxp;
|
||||
|
||||
if (boothowto & RB_VERBOSE)
|
||||
printf("SMAP type=%02x base=%016lx len=%016lx\n",
|
||||
smap->type, smap->base, smap->length);
|
||||
|
||||
if (smap->type != SMAP_TYPE_MEMORY)
|
||||
return (1);
|
||||
|
||||
if (smap->length == 0)
|
||||
return (0);
|
||||
|
||||
/*
|
||||
* Find insertion point while checking for overlap. Start off by
|
||||
* assuming the new entry will be added to the end.
|
||||
*/
|
||||
insert_idx = physmap_idx + 2;
|
||||
for (i = 0; i <= physmap_idx; i += 2) {
|
||||
if (smap->base < physmap[i + 1]) {
|
||||
if (smap->base + smap->length <= physmap[i]) {
|
||||
insert_idx = i;
|
||||
break;
|
||||
}
|
||||
if (boothowto & RB_VERBOSE)
|
||||
printf(
|
||||
"Overlapping memory regions, ignoring second region\n");
|
||||
return (1);
|
||||
}
|
||||
}
|
||||
|
||||
/* See if we can prepend to the next entry. */
|
||||
if (insert_idx <= physmap_idx &&
|
||||
smap->base + smap->length == physmap[insert_idx]) {
|
||||
physmap[insert_idx] = smap->base;
|
||||
return (1);
|
||||
}
|
||||
|
||||
/* See if we can append to the previous entry. */
|
||||
if (insert_idx > 0 && smap->base == physmap[insert_idx - 1]) {
|
||||
physmap[insert_idx - 1] += smap->length;
|
||||
return (1);
|
||||
}
|
||||
|
||||
physmap_idx += 2;
|
||||
*physmap_idxp = physmap_idx;
|
||||
if (physmap_idx == PHYSMAP_SIZE) {
|
||||
printf(
|
||||
"Too many segments in the physical address map, giving up\n");
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Move the last 'N' entries down to make room for the new
|
||||
* entry if needed.
|
||||
*/
|
||||
for (i = physmap_idx; i > insert_idx; i -= 2) {
|
||||
physmap[i] = physmap[i - 2];
|
||||
physmap[i + 1] = physmap[i - 1];
|
||||
}
|
||||
|
||||
/* Insert the new entry. */
|
||||
physmap[insert_idx] = smap->base;
|
||||
physmap[insert_idx + 1] = smap->base + smap->length;
|
||||
return (1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Populate the (physmap) array with base/bound pairs describing the
|
||||
* available physical memory in the system, then test this memory and
|
||||
@ -1235,40 +1306,9 @@ getmemsize(caddr_t kmdp, u_int64_t first)
|
||||
smapsize = *((u_int32_t *)smapbase - 1);
|
||||
smapend = (struct bios_smap *)((uintptr_t)smapbase + smapsize);
|
||||
|
||||
for (smap = smapbase; smap < smapend; smap++) {
|
||||
if (boothowto & RB_VERBOSE)
|
||||
printf("SMAP type=%02x base=%016lx len=%016lx\n",
|
||||
smap->type, smap->base, smap->length);
|
||||
|
||||
if (smap->type != SMAP_TYPE_MEMORY)
|
||||
continue;
|
||||
|
||||
if (smap->length == 0)
|
||||
continue;
|
||||
|
||||
for (i = 0; i <= physmap_idx; i += 2) {
|
||||
if (smap->base < physmap[i + 1]) {
|
||||
if (boothowto & RB_VERBOSE)
|
||||
printf(
|
||||
"Overlapping or non-monotonic memory region, ignoring second region\n");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (smap->base == physmap[physmap_idx + 1]) {
|
||||
physmap[physmap_idx + 1] += smap->length;
|
||||
continue;
|
||||
}
|
||||
|
||||
physmap_idx += 2;
|
||||
if (physmap_idx == PHYSMAP_SIZE) {
|
||||
printf(
|
||||
"Too many segments in the physical address map, giving up\n");
|
||||
for (smap = smapbase; smap < smapend; smap++)
|
||||
if (!add_smap_entry(smap, physmap, &physmap_idx))
|
||||
break;
|
||||
}
|
||||
physmap[physmap_idx] = smap->base;
|
||||
physmap[physmap_idx + 1] = smap->base + smap->length;
|
||||
}
|
||||
|
||||
/*
|
||||
* Find the 'base memory' segment for SMP
|
||||
|
@ -1946,7 +1946,7 @@ sdtossd(sd, ssd)
|
||||
static int
|
||||
add_smap_entry(struct bios_smap *smap, vm_paddr_t *physmap, int *physmap_idxp)
|
||||
{
|
||||
int i, physmap_idx;
|
||||
int i, insert_idx, physmap_idx;
|
||||
|
||||
physmap_idx = *physmap_idxp;
|
||||
|
||||
@ -1968,17 +1968,34 @@ add_smap_entry(struct bios_smap *smap, vm_paddr_t *physmap, int *physmap_idxp)
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Find insertion point while checking for overlap. Start off by
|
||||
* assuming the new entry will be added to the end.
|
||||
*/
|
||||
insert_idx = physmap_idx + 2;
|
||||
for (i = 0; i <= physmap_idx; i += 2) {
|
||||
if (smap->base < physmap[i + 1]) {
|
||||
if (smap->base + smap->length <= physmap[i]) {
|
||||
insert_idx = i;
|
||||
break;
|
||||
}
|
||||
if (boothowto & RB_VERBOSE)
|
||||
printf(
|
||||
"Overlapping or non-monotonic memory region, ignoring second region\n");
|
||||
"Overlapping memory regions, ignoring second region\n");
|
||||
return (1);
|
||||
}
|
||||
}
|
||||
|
||||
if (smap->base == physmap[physmap_idx + 1]) {
|
||||
physmap[physmap_idx + 1] += smap->length;
|
||||
/* See if we can prepend to the next entry. */
|
||||
if (insert_idx <= physmap_idx &&
|
||||
smap->base + smap->length == physmap[insert_idx]) {
|
||||
physmap[insert_idx] = smap->base;
|
||||
return (1);
|
||||
}
|
||||
|
||||
/* See if we can append to the previous entry. */
|
||||
if (insert_idx > 0 && smap->base == physmap[insert_idx - 1]) {
|
||||
physmap[insert_idx - 1] += smap->length;
|
||||
return (1);
|
||||
}
|
||||
|
||||
@ -1989,8 +2006,19 @@ add_smap_entry(struct bios_smap *smap, vm_paddr_t *physmap, int *physmap_idxp)
|
||||
"Too many segments in the physical address map, giving up\n");
|
||||
return (0);
|
||||
}
|
||||
physmap[physmap_idx] = smap->base;
|
||||
physmap[physmap_idx + 1] = smap->base + smap->length;
|
||||
|
||||
/*
|
||||
* Move the last 'N' entries down to make room for the new
|
||||
* entry if needed.
|
||||
*/
|
||||
for (i = physmap_idx; i > insert_idx; i -= 2) {
|
||||
physmap[i] = physmap[i - 2];
|
||||
physmap[i + 1] = physmap[i - 1];
|
||||
}
|
||||
|
||||
/* Insert the new entry. */
|
||||
physmap[insert_idx] = smap->base;
|
||||
physmap[insert_idx + 1] = smap->base + smap->length;
|
||||
return (1);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user