This patchset does:
1. Moves MM related code from kernel/setup.c to mm/init.c
2. Implements compile-time fixed mappings
Using fixed mappings available, we can now get earlyprints
even without SBI calls. For example, we can use kernel
parameter "earlycon=uart8250,mmio,0x10000000" to get early
prints on QEMU virt machine without using SBI calls.
The patchset is tested on QEMU virt machine. It is based on
Linux-5.0-rc6 and can be found at riscv_fixmap_v4 branch of:
https://github.com/avpatel/linux.git.
Changes since v3:
- Re-worked and simplified PATCH6
Changes since v2:
- Fixed commit description of PATCH6
- Ensured commit description of all PATCH use upto 72
characters per line
Changes since v1:
- Use more characters per line in changelog of PATCH3
- Removed #ifndef __ASSEMBLY__ from PATCH5
- Use more characters per line in commets of PATCH5
- Added PATCH6 to implement keepinitrd kernel parameter
Anup Patel (6):
RISC-V: Move free_initrd_mem() to kernel/setup.c
RISC-V: Setup init_mm before parse_early_param()
RISC-V: Move setup_bootmem() to mm/init.c
RISC-V: Move setup_vm() to mm/init.c
RISC-V: Implement compile-time fixed mappings
RISC-V: Free-up initrd in free_initrd_mem()
arch/riscv/Kconfig | 3 +
arch/riscv/include/asm/fixmap.h | 44 +++++++++++
arch/riscv/include/asm/pgtable.h | 1 +
arch/riscv/kernel/setup.c | 107 +++-----------------------
arch/riscv/mm/init.c | 124 ++++++++++++++++++++++++++++++-
5 files changed, 180 insertions(+), 99 deletions(-)
create mode 100644 arch/riscv/include/asm/fixmap.h
--
2.17.1
The setup_bootmem() mainly populates memblocks and does early memory
reservations. The right location for this function is mm/init.c.
Signed-off-by: Anup Patel <[email protected]>
Reviewed-by: Christoph Hellwig <[email protected]>
Reviewed-by: Palmer Dabbelt <[email protected]>
---
arch/riscv/include/asm/pgtable.h | 1 +
arch/riscv/kernel/setup.c | 48 ++++----------------------------
arch/riscv/mm/init.c | 40 ++++++++++++++++++++++++++
3 files changed, 46 insertions(+), 43 deletions(-)
diff --git a/arch/riscv/include/asm/pgtable.h b/arch/riscv/include/asm/pgtable.h
index 16301966d65b..35893810cba3 100644
--- a/arch/riscv/include/asm/pgtable.h
+++ b/arch/riscv/include/asm/pgtable.h
@@ -404,6 +404,7 @@ static inline int ptep_clear_flush_young(struct vm_area_struct *vma,
#define kern_addr_valid(addr) (1) /* FIXME */
#endif
+extern void setup_bootmem(void);
extern void paging_init(void);
static inline void pgtable_cache_init(void)
diff --git a/arch/riscv/kernel/setup.c b/arch/riscv/kernel/setup.c
index 9e6395b7d409..ab29a66a17fc 100644
--- a/arch/riscv/kernel/setup.c
+++ b/arch/riscv/kernel/setup.c
@@ -163,49 +163,6 @@ void __init parse_dtb(unsigned int hartid, void *dtb)
#endif
}
-static void __init setup_bootmem(void)
-{
- struct memblock_region *reg;
- phys_addr_t mem_size = 0;
-
- /* Find the memory region containing the kernel */
- for_each_memblock(memory, reg) {
- phys_addr_t vmlinux_end = __pa(_end);
- phys_addr_t end = reg->base + reg->size;
-
- if (reg->base <= vmlinux_end && vmlinux_end <= end) {
- /*
- * Reserve from the start of the region to the end of
- * the kernel
- */
- memblock_reserve(reg->base, vmlinux_end - reg->base);
- mem_size = min(reg->size, (phys_addr_t)-PAGE_OFFSET);
- }
- }
- BUG_ON(mem_size == 0);
-
- set_max_mapnr(PFN_DOWN(mem_size));
- max_low_pfn = PFN_DOWN(memblock_end_of_DRAM());
-
-#ifdef CONFIG_BLK_DEV_INITRD
- setup_initrd();
-#endif /* CONFIG_BLK_DEV_INITRD */
-
- early_init_fdt_reserve_self();
- early_init_fdt_scan_reserved_mem();
- memblock_allow_resize();
- memblock_dump_all();
-
- for_each_memblock(memory, reg) {
- unsigned long start_pfn = memblock_region_memory_base_pfn(reg);
- unsigned long end_pfn = memblock_region_memory_end_pfn(reg);
-
- memblock_set_node(PFN_PHYS(start_pfn),
- PFN_PHYS(end_pfn - start_pfn),
- &memblock.memory, 0);
- }
-}
-
void __init setup_arch(char **cmdline_p)
{
init_mm.start_code = (unsigned long) _stext;
@@ -218,6 +175,11 @@ void __init setup_arch(char **cmdline_p)
parse_early_param();
setup_bootmem();
+
+#ifdef CONFIG_BLK_DEV_INITRD
+ setup_initrd();
+#endif /* CONFIG_BLK_DEV_INITRD */
+
paging_init();
unflatten_device_tree();
diff --git a/arch/riscv/mm/init.c b/arch/riscv/mm/init.c
index 504a5e491f5a..a57dba8ac9e7 100644
--- a/arch/riscv/mm/init.c
+++ b/arch/riscv/mm/init.c
@@ -16,6 +16,7 @@
#include <linux/memblock.h>
#include <linux/swap.h>
#include <linux/sizes.h>
+#include <linux/of_fdt.h>
#include <asm/tlbflush.h>
#include <asm/sections.h>
@@ -63,3 +64,42 @@ void free_initmem(void)
{
free_initmem_default(0);
}
+
+void __init setup_bootmem(void)
+{
+ struct memblock_region *reg;
+ phys_addr_t mem_size = 0;
+
+ /* Find the memory region containing the kernel */
+ for_each_memblock(memory, reg) {
+ phys_addr_t vmlinux_end = __pa(_end);
+ phys_addr_t end = reg->base + reg->size;
+
+ if (reg->base <= vmlinux_end && vmlinux_end <= end) {
+ /*
+ * Reserve from the start of the region to the end of
+ * the kernel
+ */
+ memblock_reserve(reg->base, vmlinux_end - reg->base);
+ mem_size = min(reg->size, (phys_addr_t)-PAGE_OFFSET);
+ }
+ }
+ BUG_ON(mem_size == 0);
+
+ set_max_mapnr(PFN_DOWN(mem_size));
+ max_low_pfn = memblock_end_of_DRAM();
+
+ early_init_fdt_reserve_self();
+ early_init_fdt_scan_reserved_mem();
+ memblock_allow_resize();
+ memblock_dump_all();
+
+ for_each_memblock(memory, reg) {
+ unsigned long start_pfn = memblock_region_memory_base_pfn(reg);
+ unsigned long end_pfn = memblock_region_memory_end_pfn(reg);
+
+ memblock_set_node(PFN_PHYS(start_pfn),
+ PFN_PHYS(end_pfn - start_pfn),
+ &memblock.memory, 0);
+ }
+}
--
2.17.1
This patch implements compile-time virtual to physical mappings. These
compile-time fixed mappings can be used by earlycon, ACPI, and early
ioremap for creating fixed mappings when FIX_EARLYCON_MEM=y.
To start with, we have enabled compile-time fixed mappings for earlycon.
Signed-off-by: Anup Patel <[email protected]>
Reviewed-by: Christoph Hellwig <[email protected]>
Reviewed-by: Palmer Dabbelt <[email protected]>
---
arch/riscv/Kconfig | 3 +++
arch/riscv/include/asm/fixmap.h | 44 +++++++++++++++++++++++++++++++++
arch/riscv/mm/init.c | 34 +++++++++++++++++++++++++
3 files changed, 81 insertions(+)
create mode 100644 arch/riscv/include/asm/fixmap.h
diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
index 515fc3cc9687..3cfd10d35a28 100644
--- a/arch/riscv/Kconfig
+++ b/arch/riscv/Kconfig
@@ -89,6 +89,9 @@ config GENERIC_CSUM
config GENERIC_HWEIGHT
def_bool y
+config FIX_EARLYCON_MEM
+ def_bool y
+
config PGTABLE_LEVELS
int
default 3 if 64BIT
diff --git a/arch/riscv/include/asm/fixmap.h b/arch/riscv/include/asm/fixmap.h
new file mode 100644
index 000000000000..57afe604b495
--- /dev/null
+++ b/arch/riscv/include/asm/fixmap.h
@@ -0,0 +1,44 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2019 Western Digital Corporation or its affiliates.
+ */
+
+#ifndef _ASM_RISCV_FIXMAP_H
+#define _ASM_RISCV_FIXMAP_H
+
+#include <linux/kernel.h>
+#include <linux/sizes.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+
+/*
+ * Here we define all the compile-time 'special' virtual addresses.
+ * The point is to have a constant address at compile time, but to
+ * set the physical address only in the boot process.
+ *
+ * These 'compile-time allocated' memory buffers are page-sized. Use
+ * set_fixmap(idx,phys) to associate physical memory with fixmap indices.
+ */
+enum fixed_addresses {
+ FIX_HOLE,
+ FIX_EARLYCON_MEM_BASE,
+ __end_of_fixed_addresses
+};
+
+#define FIXADDR_SIZE (__end_of_fixed_addresses * PAGE_SIZE)
+#define FIXADDR_TOP (PAGE_OFFSET)
+#define FIXADDR_START (FIXADDR_TOP - FIXADDR_SIZE)
+
+#define FIXMAP_PAGE_IO PAGE_KERNEL
+
+#define __early_set_fixmap __set_fixmap
+
+#define __late_set_fixmap __set_fixmap
+#define __late_clear_fixmap(idx) __set_fixmap((idx), 0, FIXMAP_PAGE_CLEAR)
+
+extern void __set_fixmap(enum fixed_addresses idx,
+ phys_addr_t phys, pgprot_t prot);
+
+#include <asm-generic/fixmap.h>
+
+#endif /* _ASM_RISCV_FIXMAP_H */
diff --git a/arch/riscv/mm/init.c b/arch/riscv/mm/init.c
index 7ed6ae90cf6b..efcbdb9b3da3 100644
--- a/arch/riscv/mm/init.c
+++ b/arch/riscv/mm/init.c
@@ -18,6 +18,7 @@
#include <linux/sizes.h>
#include <linux/of_fdt.h>
+#include <asm/fixmap.h>
#include <asm/tlbflush.h>
#include <asm/sections.h>
#include <asm/pgtable.h>
@@ -111,8 +112,28 @@ pgd_t trampoline_pg_dir[PTRS_PER_PGD] __initdata __aligned(PAGE_SIZE);
#define NUM_SWAPPER_PMDS ((uintptr_t)-PAGE_OFFSET >> PGDIR_SHIFT)
pmd_t swapper_pmd[PTRS_PER_PMD*((-PAGE_OFFSET)/PGDIR_SIZE)] __page_aligned_bss;
pmd_t trampoline_pmd[PTRS_PER_PGD] __initdata __aligned(PAGE_SIZE);
+pmd_t fixmap_pmd[PTRS_PER_PMD] __page_aligned_bss;
#endif
+pte_t fixmap_pte[PTRS_PER_PTE] __page_aligned_bss;
+
+void __set_fixmap(enum fixed_addresses idx, phys_addr_t phys, pgprot_t prot)
+{
+ unsigned long addr = __fix_to_virt(idx);
+ pte_t *ptep;
+
+ BUG_ON(idx <= FIX_HOLE || idx >= __end_of_fixed_addresses);
+
+ ptep = &fixmap_pte[pte_index(addr)];
+
+ if (pgprot_val(prot)) {
+ set_pte(ptep, pfn_pte(phys >> PAGE_SHIFT, prot));
+ } else {
+ pte_clear(&init_mm, addr, ptep);
+ local_flush_tlb_page(addr);
+ }
+}
+
asmlinkage void __init setup_vm(void)
{
extern char _start;
@@ -135,20 +156,33 @@ asmlinkage void __init setup_vm(void)
for (i = 0; i < (-PAGE_OFFSET)/PGDIR_SIZE; ++i) {
size_t o = (PAGE_OFFSET >> PGDIR_SHIFT) % PTRS_PER_PGD + i;
+
swapper_pg_dir[o] =
pfn_pgd(PFN_DOWN((uintptr_t)swapper_pmd) + i,
__pgprot(_PAGE_TABLE));
}
for (i = 0; i < ARRAY_SIZE(swapper_pmd); i++)
swapper_pmd[i] = pfn_pmd(PFN_DOWN(pa + i * PMD_SIZE), prot);
+
+ swapper_pg_dir[(FIXADDR_START >> PGDIR_SHIFT) % PTRS_PER_PGD] =
+ pfn_pgd(PFN_DOWN((uintptr_t)fixmap_pmd),
+ __pgprot(_PAGE_TABLE));
+ fixmap_pmd[(FIXADDR_START >> PMD_SHIFT) % PTRS_PER_PMD] =
+ pfn_pmd(PFN_DOWN((uintptr_t)fixmap_pte),
+ __pgprot(_PAGE_TABLE));
#else
trampoline_pg_dir[(PAGE_OFFSET >> PGDIR_SHIFT) % PTRS_PER_PGD] =
pfn_pgd(PFN_DOWN(pa), prot);
for (i = 0; i < (-PAGE_OFFSET)/PGDIR_SIZE; ++i) {
size_t o = (PAGE_OFFSET >> PGDIR_SHIFT) % PTRS_PER_PGD + i;
+
swapper_pg_dir[o] =
pfn_pgd(PFN_DOWN(pa + i * PGDIR_SIZE), prot);
}
+
+ swapper_pg_dir[(FIXADDR_START >> PGDIR_SHIFT) % PTRS_PER_PGD] =
+ pfn_pgd(PFN_DOWN((uintptr_t)fixmap_pte),
+ __pgprot(_PAGE_TABLE));
#endif
}
--
2.17.1
We move free_initrd_mem() to kernel/setup.c so that all initrd related
functions are in one place.
Signed-off-by: Anup Patel <[email protected]>
Reviewed-by: Christoph Hellwig <[email protected]>
Reviewed-by: Palmer Dabbelt <[email protected]>
---
arch/riscv/kernel/setup.c | 4 ++++
arch/riscv/mm/init.c | 7 -------
2 files changed, 4 insertions(+), 7 deletions(-)
diff --git a/arch/riscv/kernel/setup.c b/arch/riscv/kernel/setup.c
index 77564310235f..36f60b4d2147 100644
--- a/arch/riscv/kernel/setup.c
+++ b/arch/riscv/kernel/setup.c
@@ -96,6 +96,10 @@ static void __init setup_initrd(void)
initrd_start = 0;
initrd_end = 0;
}
+
+void free_initrd_mem(unsigned long start, unsigned long end)
+{
+}
#endif /* CONFIG_BLK_DEV_INITRD */
pgd_t swapper_pg_dir[PTRS_PER_PGD] __page_aligned_bss;
diff --git a/arch/riscv/mm/init.c b/arch/riscv/mm/init.c
index 658ebf645f42..504a5e491f5a 100644
--- a/arch/riscv/mm/init.c
+++ b/arch/riscv/mm/init.c
@@ -14,7 +14,6 @@
#include <linux/init.h>
#include <linux/mm.h>
#include <linux/memblock.h>
-#include <linux/initrd.h>
#include <linux/swap.h>
#include <linux/sizes.h>
@@ -64,9 +63,3 @@ void free_initmem(void)
{
free_initmem_default(0);
}
-
-#ifdef CONFIG_BLK_DEV_INITRD
-void free_initrd_mem(unsigned long start, unsigned long end)
-{
-}
-#endif /* CONFIG_BLK_DEV_INITRD */
--
2.17.1
The setup_vm() is responsible for setting up initial page table hence
should be placed in mm/init.c.
Signed-off-by: Anup Patel <[email protected]>
Reviewed-by: Christoph Hellwig <[email protected]>
Reviewed-by: Palmer Dabbelt <[email protected]>
---
arch/riscv/kernel/setup.c | 49 ---------------------------------------
arch/riscv/mm/init.c | 49 +++++++++++++++++++++++++++++++++++++++
2 files changed, 49 insertions(+), 49 deletions(-)
diff --git a/arch/riscv/kernel/setup.c b/arch/riscv/kernel/setup.c
index ab29a66a17fc..9cd583b6d1cd 100644
--- a/arch/riscv/kernel/setup.c
+++ b/arch/riscv/kernel/setup.c
@@ -102,55 +102,6 @@ void free_initrd_mem(unsigned long start, unsigned long end)
}
#endif /* CONFIG_BLK_DEV_INITRD */
-pgd_t swapper_pg_dir[PTRS_PER_PGD] __page_aligned_bss;
-pgd_t trampoline_pg_dir[PTRS_PER_PGD] __initdata __aligned(PAGE_SIZE);
-
-#ifndef __PAGETABLE_PMD_FOLDED
-#define NUM_SWAPPER_PMDS ((uintptr_t)-PAGE_OFFSET >> PGDIR_SHIFT)
-pmd_t swapper_pmd[PTRS_PER_PMD*((-PAGE_OFFSET)/PGDIR_SIZE)] __page_aligned_bss;
-pmd_t trampoline_pmd[PTRS_PER_PGD] __initdata __aligned(PAGE_SIZE);
-#endif
-
-asmlinkage void __init setup_vm(void)
-{
- extern char _start;
- uintptr_t i;
- uintptr_t pa = (uintptr_t) &_start;
- pgprot_t prot = __pgprot(pgprot_val(PAGE_KERNEL) | _PAGE_EXEC);
-
- va_pa_offset = PAGE_OFFSET - pa;
- pfn_base = PFN_DOWN(pa);
-
- /* Sanity check alignment and size */
- BUG_ON((PAGE_OFFSET % PGDIR_SIZE) != 0);
- BUG_ON((pa % (PAGE_SIZE * PTRS_PER_PTE)) != 0);
-
-#ifndef __PAGETABLE_PMD_FOLDED
- trampoline_pg_dir[(PAGE_OFFSET >> PGDIR_SHIFT) % PTRS_PER_PGD] =
- pfn_pgd(PFN_DOWN((uintptr_t)trampoline_pmd),
- __pgprot(_PAGE_TABLE));
- trampoline_pmd[0] = pfn_pmd(PFN_DOWN(pa), prot);
-
- for (i = 0; i < (-PAGE_OFFSET)/PGDIR_SIZE; ++i) {
- size_t o = (PAGE_OFFSET >> PGDIR_SHIFT) % PTRS_PER_PGD + i;
- swapper_pg_dir[o] =
- pfn_pgd(PFN_DOWN((uintptr_t)swapper_pmd) + i,
- __pgprot(_PAGE_TABLE));
- }
- for (i = 0; i < ARRAY_SIZE(swapper_pmd); i++)
- swapper_pmd[i] = pfn_pmd(PFN_DOWN(pa + i * PMD_SIZE), prot);
-#else
- trampoline_pg_dir[(PAGE_OFFSET >> PGDIR_SHIFT) % PTRS_PER_PGD] =
- pfn_pgd(PFN_DOWN(pa), prot);
-
- for (i = 0; i < (-PAGE_OFFSET)/PGDIR_SIZE; ++i) {
- size_t o = (PAGE_OFFSET >> PGDIR_SHIFT) % PTRS_PER_PGD + i;
- swapper_pg_dir[o] =
- pfn_pgd(PFN_DOWN(pa + i * PGDIR_SIZE), prot);
- }
-#endif
-}
-
void __init parse_dtb(unsigned int hartid, void *dtb)
{
if (!early_init_dt_scan(__va(dtb)))
diff --git a/arch/riscv/mm/init.c b/arch/riscv/mm/init.c
index a57dba8ac9e7..7ed6ae90cf6b 100644
--- a/arch/riscv/mm/init.c
+++ b/arch/riscv/mm/init.c
@@ -103,3 +103,52 @@ void __init setup_bootmem(void)
&memblock.memory, 0);
}
}
+
+pgd_t swapper_pg_dir[PTRS_PER_PGD] __page_aligned_bss;
+pgd_t trampoline_pg_dir[PTRS_PER_PGD] __initdata __aligned(PAGE_SIZE);
+
+#ifndef __PAGETABLE_PMD_FOLDED
+#define NUM_SWAPPER_PMDS ((uintptr_t)-PAGE_OFFSET >> PGDIR_SHIFT)
+pmd_t swapper_pmd[PTRS_PER_PMD*((-PAGE_OFFSET)/PGDIR_SIZE)] __page_aligned_bss;
+pmd_t trampoline_pmd[PTRS_PER_PGD] __initdata __aligned(PAGE_SIZE);
+#endif
+
+asmlinkage void __init setup_vm(void)
+{
+ extern char _start;
+ uintptr_t i;
+ uintptr_t pa = (uintptr_t) &_start;
+ pgprot_t prot = __pgprot(pgprot_val(PAGE_KERNEL) | _PAGE_EXEC);
+
+ va_pa_offset = PAGE_OFFSET - pa;
+ pfn_base = PFN_DOWN(pa);
+
+ /* Sanity check alignment and size */
+ BUG_ON((PAGE_OFFSET % PGDIR_SIZE) != 0);
+ BUG_ON((pa % (PAGE_SIZE * PTRS_PER_PTE)) != 0);
+
+#ifndef __PAGETABLE_PMD_FOLDED
+ trampoline_pg_dir[(PAGE_OFFSET >> PGDIR_SHIFT) % PTRS_PER_PGD] =
+ pfn_pgd(PFN_DOWN((uintptr_t)trampoline_pmd),
+ __pgprot(_PAGE_TABLE));
+ trampoline_pmd[0] = pfn_pmd(PFN_DOWN(pa), prot);
+
+ for (i = 0; i < (-PAGE_OFFSET)/PGDIR_SIZE; ++i) {
+ size_t o = (PAGE_OFFSET >> PGDIR_SHIFT) % PTRS_PER_PGD + i;
+ swapper_pg_dir[o] =
+ pfn_pgd(PFN_DOWN((uintptr_t)swapper_pmd) + i,
+ __pgprot(_PAGE_TABLE));
+ }
+ for (i = 0; i < ARRAY_SIZE(swapper_pmd); i++)
+ swapper_pmd[i] = pfn_pmd(PFN_DOWN(pa + i * PMD_SIZE), prot);
+#else
+ trampoline_pg_dir[(PAGE_OFFSET >> PGDIR_SHIFT) % PTRS_PER_PGD] =
+ pfn_pgd(PFN_DOWN(pa), prot);
+
+ for (i = 0; i < (-PAGE_OFFSET)/PGDIR_SIZE; ++i) {
+ size_t o = (PAGE_OFFSET >> PGDIR_SHIFT) % PTRS_PER_PGD + i;
+ swapper_pg_dir[o] =
+ pfn_pgd(PFN_DOWN(pa + i * PGDIR_SIZE), prot);
+ }
+#endif
+}
--
2.17.1
We should setup init_mm before doing parse_early_param() in setup_arch()
to be consistent with setup_arch() of other architectures such as x86,
ARM, and ARM64.
Signed-off-by: Anup Patel <[email protected]>
Reviewed-by: Christoph Hellwig <[email protected]>
Reviewed-by: Palmer Dabbelt <[email protected]>
---
arch/riscv/kernel/setup.c | 9 ++++-----
1 file changed, 4 insertions(+), 5 deletions(-)
diff --git a/arch/riscv/kernel/setup.c b/arch/riscv/kernel/setup.c
index 36f60b4d2147..9e6395b7d409 100644
--- a/arch/riscv/kernel/setup.c
+++ b/arch/riscv/kernel/setup.c
@@ -208,15 +208,15 @@ static void __init setup_bootmem(void)
void __init setup_arch(char **cmdline_p)
{
- *cmdline_p = boot_command_line;
-
- parse_early_param();
-
init_mm.start_code = (unsigned long) _stext;
init_mm.end_code = (unsigned long) _etext;
init_mm.end_data = (unsigned long) _edata;
init_mm.brk = (unsigned long) _end;
+ *cmdline_p = boot_command_line;
+
+ parse_early_param();
+
setup_bootmem();
paging_init();
unflatten_device_tree();
@@ -235,4 +235,3 @@ void __init setup_arch(char **cmdline_p)
riscv_fill_hwcap();
}
-
--
2.17.1
We should free-up initrd memory in free_initrd_mem() instead
of doing nothing.
Signed-off-by: Anup Patel <[email protected]>
---
arch/riscv/kernel/setup.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/arch/riscv/kernel/setup.c b/arch/riscv/kernel/setup.c
index 9cd583b6d1cd..c22b873de856 100644
--- a/arch/riscv/kernel/setup.c
+++ b/arch/riscv/kernel/setup.c
@@ -97,8 +97,9 @@ static void __init setup_initrd(void)
initrd_end = 0;
}
-void free_initrd_mem(unsigned long start, unsigned long end)
+void __init free_initrd_mem(unsigned long start, unsigned long end)
{
+ memblock_free(__pa(start), end - start);
}
#endif /* CONFIG_BLK_DEV_INITRD */
--
2.17.1
On Wed, Feb 13, 2019 at 06:32:24AM +0000, Anup Patel wrote:
> index 9cd583b6d1cd..c22b873de856 100644
> --- a/arch/riscv/kernel/setup.c
> +++ b/arch/riscv/kernel/setup.c
> @@ -97,8 +97,9 @@ static void __init setup_initrd(void)
> initrd_end = 0;
> }
>
> -void free_initrd_mem(unsigned long start, unsigned long end)
> +void __init free_initrd_mem(unsigned long start, unsigned long end)
> {
> + memblock_free(__pa(start), end - start);
I'm pretty sure this should be a call to free_reserved_area instead.
All regions reserved using memblock_reserved and not freed before
initializing the MM are marked reserved and don't have valid page
counts, etc.
So we need the actions in free_reserved_area to actually make the
memory useful. Now every other architecture except for arm64
seems to do fine without a memblock_free. I'm not an expert on
memblock (but I've CCed one), but I guess the reason is that once
the kernel has booted we don't really care about freeing memblock
area.
Hi,
On Tue, Feb 12, 2019 at 10:44:19PM -0800, Christoph Hellwig wrote:
> On Wed, Feb 13, 2019 at 06:32:24AM +0000, Anup Patel wrote:
> > index 9cd583b6d1cd..c22b873de856 100644
> > --- a/arch/riscv/kernel/setup.c
> > +++ b/arch/riscv/kernel/setup.c
> > @@ -97,8 +97,9 @@ static void __init setup_initrd(void)
> > initrd_end = 0;
> > }
> >
> > -void free_initrd_mem(unsigned long start, unsigned long end)
> > +void __init free_initrd_mem(unsigned long start, unsigned long end)
> > {
> > + memblock_free(__pa(start), end - start);
>
> I'm pretty sure this should be a call to free_reserved_area instead.
>
> All regions reserved using memblock_reserved and not freed before
> initializing the MM are marked reserved and don't have valid page
> counts, etc.
>
> So we need the actions in free_reserved_area to actually make the
> memory useful. Now every other architecture except for arm64
> seems to do fine without a memblock_free. I'm not an expert on
> memblock (but I've CCed one), but I guess the reason is that once
> the kernel has booted we don't really care about freeing memblock
> area.
This late in the boot process there should be a call to
free_reserved_area() to give pages to the buddy allocator.
memblock_free() is has no real effect at this point, no idea why arm64
calls it.
--
Sincerely yours,
Mike.
> -----Original Message-----
> From: Mike Rapoport [mailto:[email protected]]
> Sent: Wednesday, February 13, 2019 1:09 PM
> To: Christoph Hellwig <[email protected]>
> Cc: Anup Patel <[email protected]>; Palmer Dabbelt
> <[email protected]>; Albert Ou <[email protected]>; Atish Patra
> <[email protected]>; Paul Walmsley <[email protected]>; linux-
> [email protected]; [email protected]
> Subject: Re: [PATCH v4 6/6] RISC-V: Free-up initrd in free_initrd_mem()
>
> Hi,
>
> On Tue, Feb 12, 2019 at 10:44:19PM -0800, Christoph Hellwig wrote:
> > On Wed, Feb 13, 2019 at 06:32:24AM +0000, Anup Patel wrote:
> > > index 9cd583b6d1cd..c22b873de856 100644
> > > --- a/arch/riscv/kernel/setup.c
> > > +++ b/arch/riscv/kernel/setup.c
> > > @@ -97,8 +97,9 @@ static void __init setup_initrd(void)
> > > initrd_end = 0;
> > > }
> > >
> > > -void free_initrd_mem(unsigned long start, unsigned long end)
> > > +void __init free_initrd_mem(unsigned long start, unsigned long end)
> > > {
> > > + memblock_free(__pa(start), end - start);
> >
> > I'm pretty sure this should be a call to free_reserved_area instead.
> >
> > All regions reserved using memblock_reserved and not freed before
> > initializing the MM are marked reserved and don't have valid page
> > counts, etc.
> >
> > So we need the actions in free_reserved_area to actually make the
> > memory useful. Now every other architecture except for arm64 seems to
> > do fine without a memblock_free. I'm not an expert on memblock (but
> > I've CCed one), but I guess the reason is that once the kernel has
> > booted we don't really care about freeing memblock area.
>
> This late in the boot process there should be a call to
> free_reserved_area() to give pages to the buddy allocator.
>
> memblock_free() is has no real effect at this point, no idea why arm64 calls it.
Thanks for the info. I will update this patch to use free_reserved_area().
Regards,
Anup
On Wed, Feb 13, 2019 at 09:38:36AM +0200, Mike Rapoport wrote:
> memblock_free() is has no real effect at this point, no idea why arm64
> calls it.
Looks like the call was added fairly recently by:
commit 05c58752f9dce11e396676eb731a620541590ed0
Author: CHANDAN VN <[email protected]>
Date: Mon Apr 30 09:50:18 2018 +0530
arm64: To remove initrd reserved area entry from memblock
which claims it is to work around the initrd being displayed in
/sys/kernel/debug/memblock/reserved.
I really think we need to have common behavior there - either do this
for all architectures or none. I've just sent a series that
consolidates all but a handful of the free_initrd_mem, so implementing
any common behavior on top of that would be good.
On Wed, Feb 13, 2019 at 09:54:15AM -0800, Christoph Hellwig wrote:
> On Wed, Feb 13, 2019 at 09:38:36AM +0200, Mike Rapoport wrote:
> > memblock_free() is has no real effect at this point, no idea why arm64
> > calls it.
>
> Looks like the call was added fairly recently by:
>
> commit 05c58752f9dce11e396676eb731a620541590ed0
> Author: CHANDAN VN <[email protected]>
> Date: Mon Apr 30 09:50:18 2018 +0530
>
> arm64: To remove initrd reserved area entry from memblock
>
> which claims it is to work around the initrd being displayed in
> /sys/kernel/debug/memblock/reserved.
>
> I really think we need to have common behavior there - either do this
> for all architectures or none. I've just sent a series that
> consolidates all but a handful of the free_initrd_mem, so implementing
> any common behavior on top of that would be good.
I've just started to look into it today :)
I'll reply on that thread.
--
Sincerely yours,
Mike.
Hi,
> On Wed, Feb 13, 2019 at 09:54:15AM -0800, Christoph Hellwig wrote:
> > On Wed, Feb 13, 2019 at 09:38:36AM +0200, Mike Rapoport wrote:
> > > memblock_free() is has no real effect at this point, no idea why arm64
> > > calls it.
> >
> > Looks like the call was added fairly recently by:
> >
> > commit 05c58752f9dce11e396676eb731a620541590ed0
> > Author: CHANDAN VN <[email protected]>
> > Date: Mon Apr 30 09:50:18 2018 +0530
> >
> > arm64: To remove initrd reserved area entry from memblock
> >
> > which claims it is to work around the initrd being displayed in
> > /sys/kernel/debug/memblock/reserved.
> >
> > I really think we need to have common behavior there - either do this
> > for all architectures or none. I've just sent a series that
> > consolidates all but a handful of the free_initrd_mem, so implementing
> > any common behavior on top of that would be good.
>
> I've just started to look into it today :)
> I'll reply on that thread.
INITRD reserved area entry is not removed from memblock
even though initrd reserved area is freed. The same can be
checked from /sys/kernel/debug/memblock/reserved.
We did not face this issue on arm32 architecture.
Though the changes which i had submitted does not fix any memory leak,
it does make sure that the entries freed from memblock are actually removed
from the sys entry as well.
Also the implementation of arm64 is quite different from arm32. I feel a generic
implementation can be taken up only if its a real necessity.