[Skiboot] [PATCH 3/3] core/mem_region: Print a useful error on overlap

Oliver O'Halloran oohall at gmail.com
Mon May 15 13:40:38 AEST 2017


New memory regions need to be either fully contained by an existing
region or completely disjoint. Right now we just fail silently or crash
with an assert which is less than helpful. Printing some basic
information, such as the names of the overlapping regions is helpful.

Signed-off-by: Oliver O'Halloran <oohall at gmail.com>
---
 core/mem_region.c | 29 ++++++++++++++++++++++++++++-
 1 file changed, 28 insertions(+), 1 deletion(-)

diff --git a/core/mem_region.c b/core/mem_region.c
index 567d260cdbdd..a3145583cd76 100644
--- a/core/mem_region.c
+++ b/core/mem_region.c
@@ -689,6 +689,14 @@ static bool overlaps(const struct mem_region *r1, const struct mem_region *r2)
 		&& r1->start < r2->start + r2->len);
 }
 
+static bool contains(const struct mem_region *r1, const struct mem_region *r2)
+{
+	u64 r1_end = r1->start + r1->len;
+	u64 r2_end = r2->start + r2->len;
+
+	return (r1->start <= r2->start && r2_end <= r1_end);
+}
+
 static struct mem_region *get_overlap(const struct mem_region *region)
 {
 	struct mem_region *i;
@@ -711,10 +719,29 @@ static bool add_region(struct mem_region *region)
 	}
 
 	/* First split any regions which intersect. */
-	list_for_each(&regions, r, list)
+	list_for_each(&regions, r, list) {
+		/*
+		 * The new region should be fully contained by an existing one.
+		 * If it's not then we have a problem where reservations
+		 * partially overlap which is probably broken.
+		 *
+		 * NB: There *might* be situations where this is legitimate,
+		 * but the region handling does not currently support this.
+		 */
+		if (overlaps(r, region) && !contains(r, region)) {
+			prerror("MEM: Partial overlap detected between regions:\n");
+			prerror("MEM: %s [0x%"PRIx64"-0x%"PRIx64"] (new)\n",
+				region->name, region->start,
+				region->start + region->len);
+			prerror("MEM: %s [0x%"PRIx64"-0x%"PRIx64"]\n",
+				r->name, r->start, r->start + r->len);
+			return false;
+		}
+
 		if (!maybe_split(r, region->start) ||
 		    !maybe_split(r, region->start + region->len))
 			return false;
+	}
 
 	/* Now we have only whole overlaps, if any. */
 	while ((r = get_overlap(region)) != NULL) {
-- 
2.9.3



More information about the Skiboot mailing list