diff options
author | Mitchel Humpherys <mitchelh@codeaurora.org> | 2015-09-15 21:30:36 -0400 |
---|---|---|
committer | Rob Herring <robh@kernel.org> | 2015-09-17 15:52:06 -0400 |
commit | ae1add247bf8c22facacbd818142f1f66e735802 (patch) | |
tree | 693ae0d5d7cc8503d8beee9d3e6b722d2f254a75 | |
parent | 4f59d7119c7cb5f32ca91662a74c217ea7c4ddca (diff) |
of: Check for overlap in reserved memory regions
Any overlap in the reserved memory regions (those specified in the
reserved-memory DT node) is a bug. These bugs might go undetected as
long as the contested region isn't used simultaneously by multiple
software agents, which makes such bugs hard to debug. Fix this by
printing a scary warning during boot if overlap is detected.
Signed-off-by: Mitchel Humpherys <mitchelh@codeaurora.org>
Signed-off-by: Rob Herring <robh@kernel.org>
-rw-r--r-- | drivers/of/of_reserved_mem.c | 43 |
1 files changed, 42 insertions, 1 deletions
diff --git a/drivers/of/of_reserved_mem.c b/drivers/of/of_reserved_mem.c index 726ebe792813..62f467b8ccae 100644 --- a/drivers/of/of_reserved_mem.c +++ b/drivers/of/of_reserved_mem.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * Device tree based initialization code for reserved memory. | 2 | * Device tree based initialization code for reserved memory. |
3 | * | 3 | * |
4 | * Copyright (c) 2013, The Linux Foundation. All Rights Reserved. | 4 | * Copyright (c) 2013, 2015 The Linux Foundation. All Rights Reserved. |
5 | * Copyright (c) 2013,2014 Samsung Electronics Co., Ltd. | 5 | * Copyright (c) 2013,2014 Samsung Electronics Co., Ltd. |
6 | * http://www.samsung.com | 6 | * http://www.samsung.com |
7 | * Author: Marek Szyprowski <m.szyprowski@samsung.com> | 7 | * Author: Marek Szyprowski <m.szyprowski@samsung.com> |
@@ -20,6 +20,7 @@ | |||
20 | #include <linux/mm.h> | 20 | #include <linux/mm.h> |
21 | #include <linux/sizes.h> | 21 | #include <linux/sizes.h> |
22 | #include <linux/of_reserved_mem.h> | 22 | #include <linux/of_reserved_mem.h> |
23 | #include <linux/sort.h> | ||
23 | 24 | ||
24 | #define MAX_RESERVED_REGIONS 16 | 25 | #define MAX_RESERVED_REGIONS 16 |
25 | static struct reserved_mem reserved_mem[MAX_RESERVED_REGIONS]; | 26 | static struct reserved_mem reserved_mem[MAX_RESERVED_REGIONS]; |
@@ -197,12 +198,52 @@ static int __init __reserved_mem_init_node(struct reserved_mem *rmem) | |||
197 | return -ENOENT; | 198 | return -ENOENT; |
198 | } | 199 | } |
199 | 200 | ||
201 | static int __init __rmem_cmp(const void *a, const void *b) | ||
202 | { | ||
203 | const struct reserved_mem *ra = a, *rb = b; | ||
204 | |||
205 | return ra->base - rb->base; | ||
206 | } | ||
207 | |||
208 | static void __init __rmem_check_for_overlap(void) | ||
209 | { | ||
210 | int i; | ||
211 | |||
212 | if (reserved_mem_count < 2) | ||
213 | return; | ||
214 | |||
215 | sort(reserved_mem, reserved_mem_count, sizeof(reserved_mem[0]), | ||
216 | __rmem_cmp, NULL); | ||
217 | for (i = 0; i < reserved_mem_count - 1; i++) { | ||
218 | struct reserved_mem *this, *next; | ||
219 | |||
220 | this = &reserved_mem[i]; | ||
221 | next = &reserved_mem[i + 1]; | ||
222 | if (!(this->base && next->base)) | ||
223 | continue; | ||
224 | if (this->base + this->size > next->base) { | ||
225 | phys_addr_t this_end, next_end; | ||
226 | |||
227 | this_end = this->base + this->size; | ||
228 | next_end = next->base + next->size; | ||
229 | WARN(1, | ||
230 | "Reserved memory: OVERLAP DETECTED!\n%s (%pa--%pa) overlaps with %s (%pa--%pa)\n", | ||
231 | this->name, &this->base, &this_end, | ||
232 | next->name, &next->base, &next_end); | ||
233 | } | ||
234 | } | ||
235 | } | ||
236 | |||
200 | /** | 237 | /** |
201 | * fdt_init_reserved_mem - allocate and init all saved reserved memory regions | 238 | * fdt_init_reserved_mem - allocate and init all saved reserved memory regions |
202 | */ | 239 | */ |
203 | void __init fdt_init_reserved_mem(void) | 240 | void __init fdt_init_reserved_mem(void) |
204 | { | 241 | { |
205 | int i; | 242 | int i; |
243 | |||
244 | /* check for overlapping reserved regions */ | ||
245 | __rmem_check_for_overlap(); | ||
246 | |||
206 | for (i = 0; i < reserved_mem_count; i++) { | 247 | for (i = 0; i < reserved_mem_count; i++) { |
207 | struct reserved_mem *rmem = &reserved_mem[i]; | 248 | struct reserved_mem *rmem = &reserved_mem[i]; |
208 | unsigned long node = rmem->fdt_node; | 249 | unsigned long node = rmem->fdt_node; |