Skip to content

Commit

Permalink
initramfs: Provide a common initrd reserve function
Browse files Browse the repository at this point in the history
Some architectures(eg, ARM and riscv) have similar logic to
check and reserve the memory of initrd, let's provide a common
function reserve_initrd_mem() to reduce duplicated code.

Signed-off-by: Kefeng Wang <[email protected]>
Signed-off-by: Palmer Dabbelt <[email protected]>
  • Loading branch information
Kefeng Wang authored and palmer-dabbelt committed Feb 19, 2021
1 parent fade5ca commit c72160f
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 0 deletions.
6 changes: 6 additions & 0 deletions include/linux/initrd.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,12 @@ extern int initrd_below_start_ok;
extern unsigned long initrd_start, initrd_end;
extern void free_initrd_mem(unsigned long, unsigned long);

#ifdef CONFIG_BLK_DEV_INITRD
extern void __init reserve_initrd_mem(void);
#else
static inline void __init reserve_initrd_mem(void) {}
#endif

extern phys_addr_t phys_initrd_start;
extern unsigned long phys_initrd_size;

Expand Down
45 changes: 45 additions & 0 deletions init/initramfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -535,6 +535,51 @@ extern unsigned long __initramfs_size;
#include <linux/initrd.h>
#include <linux/kexec.h>

void __init reserve_initrd_mem(void)
{
phys_addr_t start;
unsigned long size;

/* Ignore the virtul address computed during device tree parsing */
initrd_start = initrd_end = 0;

if (!phys_initrd_size)
return;
/*
* Round the memory region to page boundaries as per free_initrd_mem()
* This allows us to detect whether the pages overlapping the initrd
* are in use, but more importantly, reserves the entire set of pages
* as we don't want these pages allocated for other purposes.
*/
start = round_down(phys_initrd_start, PAGE_SIZE);
size = phys_initrd_size + (phys_initrd_start - start);
size = round_up(size, PAGE_SIZE);

if (!memblock_is_region_memory(start, size)) {
pr_err("INITRD: 0x%08llx+0x%08lx is not a memory region",
(u64)start, size);
goto disable;
}

if (memblock_is_region_reserved(start, size)) {
pr_err("INITRD: 0x%08llx+0x%08lx overlaps in-use memory region\n",
(u64)start, size);
goto disable;
}

memblock_reserve(start, size);
/* Now convert initrd to virtual addresses */
initrd_start = (unsigned long)__va(phys_initrd_start);
initrd_end = initrd_start + phys_initrd_size;
initrd_below_start_ok = 1;

return;
disable:
pr_cont(" - disabling initrd\n");
initrd_start = 0;
initrd_end = 0;
}

void __weak __init free_initrd_mem(unsigned long start, unsigned long end)
{
#ifdef CONFIG_ARCH_KEEP_MEMBLOCK
Expand Down

0 comments on commit c72160f

Please sign in to comment.