diff --git a/usr.sbin/bhyve/amd64/e820.c b/usr.sbin/bhyve/amd64/e820.c --- a/usr.sbin/bhyve/amd64/e820.c +++ b/usr.sbin/bhyve/amd64/e820.c @@ -156,6 +156,7 @@ { struct e820_element *new_element; struct e820_element *element; + struct e820_element *sib_element; struct e820_element *ram_element; assert(end >= base); @@ -273,6 +274,33 @@ element->base = end; } + /* + * If the previous element has the same type and ends at our base + * boundary, we can merge both entries. + */ + sib_element = TAILQ_PREV(new_element, e820_table, chain); + if (sib_element != NULL && + sib_element->type == new_element->type && + sib_element->end == new_element->base) { + new_element->base = sib_element->base; + TAILQ_REMOVE(&e820_table, sib_element, chain); + free(sib_element); + } + + /* + * If the next element has the same type and starts at our end + * boundary, we can merge both entries. + */ + sib_element = TAILQ_NEXT(new_element, chain); + if (sib_element != NULL && + sib_element->type == new_element->type && + sib_element->base == new_element->end) { + /* Merge new element into subsequent one. */ + new_element->end = sib_element->end; + TAILQ_REMOVE(&e820_table, sib_element, chain); + free(sib_element); + } + return (0); }