aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOliver O'Halloran <oohall@gmail.com>2017-05-15 13:40:38 +1000
committerStewart Smith <stewart@linux.vnet.ibm.com>2017-05-16 15:41:35 +1000
commit5d1abb640e0bc400257233992956d430226b0d6b (patch)
tree8e99eac889dc899159b79673338d2ad1209054bf
parent76a7a130b2084a8fbb0122061044b945a39dc401 (diff)
downloadskiboot-5d1abb640e0bc400257233992956d430226b0d6b.zip
skiboot-5d1abb640e0bc400257233992956d430226b0d6b.tar.gz
skiboot-5d1abb640e0bc400257233992956d430226b0d6b.tar.bz2
core/mem_region: Print a useful error on overlap
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@gmail.com> Signed-off-by: Stewart Smith <stewart@linux.vnet.ibm.com>
-rw-r--r--core/mem_region.c29
1 files changed, 28 insertions, 1 deletions
diff --git a/core/mem_region.c b/core/mem_region.c
index 567d260..a314558 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) {