[PATCH] Replacement for Arm initrd memblock reserve and free inconsistency.
william.helsby at stfc.ac.uk
william.helsby at stfc.ac.uk
Tue Nov 15 07:45:55 PST 2016
The option of moving the initrd code later (after early_init_fdt_reserve_self(); early_init_fdt_scan_reserved_mem() )
was tested.
This resulted in the initrd being disabled because early_init_fdt_scan_reserved_mem
Has already reserved the initrd area.
With memblock=debug
Machine model: Xspress3 Mini in PicoZed Developement Board
bootconsole [earlycon0] enabled
memblock_add: [0x00000000000000-0x0000000fffffff] flags 0x0 arm_add_
memory+0x14c/0x174
memblock_reserve: [0x00000000100000-0x00000000b71de7] flags 0x0 arm_
memblock_init+0x1c/0x284
memblock_reserve: [0x00000000004000-0x00000000007fff] flags 0x0 arm_
memblock_init+0x20/0x284
memblock_reserve: [0x00000000000000-0x00000000003fff] flags 0x0 arm_
memblock_init+0x30/0x284
memblock_reserve: [0x0000000fa5f000-0x0000000fa6207f] flags 0x0 arm_
memblock_init+0x38/0x284
memblock_reserve: [0x0000000fa5f000-0x0000000fa61fff] flags 0x0 early_
init_fdt_scan_reserved_mem+0x54/0x78
memblock_reserve: [0x0000000fa65000-0x0000000ffff46a] flags 0x0 early_
init_fdt_scan_reserved_mem+0x54/0x78
memblock_reserve: [0x0000000e800000-0x0000000f7fffff] flags 0x0 membl
ock_alloc_range_nid+0x3c/0x50
cma: Reserved 16 MiB at 0x0e800000
INITRD: 0x0fa65000+0x0059a46b overlaps in-use memory region - disabling initrd
MEMBLOCK configuration:
With the initrd code back to its normal place
memblock_add: [0x00000000000000-0x0000000fffffff] flags 0x0 arm_add_
memory+0x14c/0x174
memblock_reserve: [0x00000000100000-0x00000000b71de7] flags 0x0 arm_m
emblock_init+0x24/0x284
memblock_reserve: [0x0000000fa65000-0x0000000fffffff] flags 0x0 arm_me
mblock_init+0x1e4/0x284
memblock_reserve: [0x00000000004000-0x00000000007fff] flags 0x0 arm_me
mblock_init+0x210/0x284
memblock_reserve: [0x00000000000000-0x00000000003fff] flags 0x0 arm_me
mblock_init+0x220/0x284
memblock_reserve: [0x0000000fa5f000-0x0000000fa6207f] flags 0x0 arm_me
mblock_init+0x224/0x284
memblock_reserve: [0x0000000fa5f000-0x0000000fa61fff] flags 0x0 early_ini
t_fdt_scan_reserved_mem+0x54/0x78
memblock_reserve: [0x0000000fa65000-0x0000000ffff46a] flags 0x0 early_in
it_fdt_scan_reserved_mem+0x54/0x78
memblock_reserve: [0x0000000e800000-0x0000000f7fffff] flags 0x0 memblo
ck_alloc_range_nid+0x3c/0x50
cma: Reserved 16 MiB at 0x0e800000
MEMBLOCK configuration:
memory size = 0x10000000 reserved size = 0x2017e68
memory.cnt = 0x1
memory[0x0] [0x00000000000000-0x0000000fffffff], 0x10000000 bytes f
lags: 0x0
reserved.cnt = 0x5
reserved[0x0] [0x00000000000000-0x00000000007fff], 0x8000 bytes fl
ags: 0x0
reserved[0x1] [0x00000000100000-0x00000000b71de7], 0xa71de8 bytes fl
ags: 0x0
reserved[0x2] [0x0000000e800000-0x0000000f7fffff], 0x1000000 bytes flags: 0x0
reserved[0x3] [0x0000000fa5f000-0x0000000fa6207f], 0x3080 bytes flag
s: 0x0
reserved[0x4] [0x0000000fa65000-0x0000000fffffff], 0x59b000 bytes fl
ags: 0x0
Memory policy: Data cache writealloc
So poison the memory all the way from the start to end I would now suggest:
--- ../linux-xlnx-4.6.0-orig/arch/arm/mm/init.c 2016-11-15 15:10:44.476001509 +0000
+++ arch/arm/mm/init.c 2016-11-15 14:05:19.640969244 +0000
@@ -49,6 +49,8 @@
static phys_addr_t phys_initrd_start __initdata = 0;
static unsigned long phys_initrd_size __initdata = 0;
+static unsigned long initrd_reservation_start __initdata = 0;
+static unsigned long initrd_reservation_end __initdata = 0;
static int __init early_initrd(char *p)
{
@@ -255,11 +257,38 @@
phys_initrd_start = phys_initrd_size = 0;
}
if (phys_initrd_size) {
- memblock_reserve(phys_initrd_start, phys_initrd_size);
+ /* try to round the initrd start and end down and up to page boundaries,
+ so when freed, whole pages can be released.
+ However the initrd image may be adjacent to something else, so check that this rounding is OK
+ */
+ /* First try rounding the start down and end up */
+ phys_addr_t phys_initrd_reservation_start = phys_initrd_start & PAGE_MASK;
+ unsigned long size_to_reserve = PAGE_ALIGN(phys_initrd_start+phys_initrd_size) - phys_initrd_reservation_start;
+ if (!memblock_is_region_memory(phys_initrd_reservation_start, size_to_reserve) ||
+ memblock_is_region_reserved(phys_initrd_reservation_start, size_to_reserve)) {
+ /* This either does fit or overlaps something else, so try just rounding end up */
+ phys_initrd_reservation_start = phys_initrd_start;
+ size_to_reserve = PAGE_ALIGN(phys_initrd_start+phys_initrd_size) - phys_initrd_reservation_start;
+ if (!memblock_is_region_memory(phys_initrd_reservation_start, size_to_reserve) ||
+ memblock_is_region_reserved(phys_initrd_reservation_start, size_to_reserve)) {
+ /* This either does not fit or overlaps something else, so try just rounding start down */
+ phys_initrd_reservation_start = phys_initrd_start & PAGE_MASK;
+ size_to_reserve = (phys_initrd_start+phys_initrd_size) - phys_initrd_reservation_start;
+ if (!memblock_is_region_memory(phys_initrd_reservation_start, size_to_reserve) ||
+ memblock_is_region_reserved(phys_initrd_reservation_start, size_to_reserve)) {
+ /* This either does not fit or overlaps something else, so do not round at all */
+ phys_initrd_reservation_start = phys_initrd_start;
+ size_to_reserve = (phys_initrd_start+phys_initrd_size) - phys_initrd_reservation_start;
+ }
+ }
+ }
+ memblock_reserve(phys_initrd_reservation_start, size_to_reserve);
/* Now convert initrd to virtual addresses */
initrd_start = __phys_to_virt(phys_initrd_start);
initrd_end = initrd_start + phys_initrd_size;
+ initrd_reservation_start = __phys_to_virt(phys_initrd_reservation_start);
+ initrd_reservation_end = initrd_reservation_start + size_to_reserve;
}
#endif
@@ -325,7 +354,12 @@
*/
static inline void poison_init_mem(void *s, size_t count)
{
- u32 *p = (u32 *)s;
+ u32 *p;
+ unsigned long start = (unsigned long)s, start_align;
+ start_align = (start+3) & ~3L; // Round up to 32 bit word boundary.
+ count -= (start_align-start);
+ p = (u32 *)start_align;
+ count &= ~3L;
for (; count != 0; count -= 4)
*p++ = 0xe7fddef0;
}
@@ -771,11 +805,11 @@
{
if (!keep_initrd) {
if (start == initrd_start)
- start = round_down(start, PAGE_SIZE);
+ start = initrd_reservation_start;
if (end == initrd_end)
- end = round_up(end, PAGE_SIZE);
+ end = initrd_reservation_end;
- poison_init_mem((void *)start, PAGE_ALIGN(end) - start);
+ poison_init_mem((void *)start, end-start);
free_reserved_area((void *)start, (void *)end, -1, "initrd");
}
}
More information about the linux-arm-kernel
mailing list