From: Mike Rapoport <rppt@xxxxxxxxxxxxx> Several architecture have very similar implementation of the setup of the resource tree. The implementations loop over memory ranges registered in memblock, request a "System RAM" resource for each range and then reserve resource rages corresponding to various sections of the kernel image. If kexec/crash dump are enable the crashk_res region is also reserved. Move the implementation of resource tree setup from s390 to memblock. It will be then used by several other architectures as well. Signed-off-by: Mike Rapoport <rppt@xxxxxxxxxxxxx> --- arch/s390/kernel/setup.c | 73 +-------------------------------- include/linux/memblock.h | 2 + mm/memblock.c | 87 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 90 insertions(+), 72 deletions(-) diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c index 30430e7c1b03..6f3c82cc0b0d 100644 --- a/arch/s390/kernel/setup.c +++ b/arch/s390/kernel/setup.c @@ -481,80 +481,9 @@ static void __init setup_lowcore_dat_on(void) __ctl_set_bit(0, 28); } -static struct resource code_resource = { - .name = "Kernel code", - .flags = IORESOURCE_BUSY | IORESOURCE_SYSTEM_RAM, -}; - -static struct resource data_resource = { - .name = "Kernel data", - .flags = IORESOURCE_BUSY | IORESOURCE_SYSTEM_RAM, -}; - -static struct resource bss_resource = { - .name = "Kernel bss", - .flags = IORESOURCE_BUSY | IORESOURCE_SYSTEM_RAM, -}; - -static struct resource __initdata *standard_resources[] = { - &code_resource, - &data_resource, - &bss_resource, -#ifdef CONFIG_CRASH_DUMP - &crashk_res, -#endif -}; - static void __init setup_resources(void) { - struct resource *res, *std_res, *sub_res; - phys_addr_t start, end; - int j; - u64 i; - - code_resource.start = (unsigned long) _text; - code_resource.end = (unsigned long) _etext - 1; - data_resource.start = (unsigned long) _etext; - data_resource.end = (unsigned long) _edata - 1; - bss_resource.start = (unsigned long) __bss_start; - bss_resource.end = (unsigned long) __bss_stop - 1; - - for_each_mem_range(i, &start, &end) { - res = memblock_alloc(sizeof(*res), 8); - if (!res) - panic("%s: Failed to allocate %zu bytes align=0x%x\n", - __func__, sizeof(*res), 8); - res->flags = IORESOURCE_BUSY | IORESOURCE_SYSTEM_RAM; - - res->name = "System RAM"; - res->start = start; - /* - * In memblock, end points to the first byte after the - * range while in resourses, end points to the last byte in - * the range. - */ - res->end = end - 1; - request_resource(&iomem_resource, res); - - for (j = 0; j < ARRAY_SIZE(standard_resources); j++) { - std_res = standard_resources[j]; - if (!std_res->end || std_res->start < res->start || - std_res->start > res->end) - continue; - if (std_res->end > res->end) { - sub_res = memblock_alloc(sizeof(*sub_res), 8); - if (!sub_res) - panic("%s: Failed to allocate %zu bytes align=0x%x\n", - __func__, sizeof(*sub_res), 8); - *sub_res = *std_res; - sub_res->end = res->end; - std_res->start = res->end + 1; - request_resource(res, sub_res); - } else { - request_resource(res, std_res); - } - } - } + memblock_setup_resources(); } static void __init setup_ident_map_size(void) diff --git a/include/linux/memblock.h b/include/linux/memblock.h index 5984fff3f175..44c29ebae842 100644 --- a/include/linux/memblock.h +++ b/include/linux/memblock.h @@ -121,6 +121,8 @@ void memblock_free_all(void); void reset_node_managed_pages(pg_data_t *pgdat); void reset_all_zones_managed_pages(void); +void memblock_setup_resources(void); + /* Low level functions */ void __next_mem_range(u64 *idx, int nid, enum memblock_flags flags, struct memblock_type *type_a, diff --git a/mm/memblock.c b/mm/memblock.c index afaefa8fc6ab..504435753259 100644 --- a/mm/memblock.c +++ b/mm/memblock.c @@ -16,6 +16,8 @@ #include <linux/kmemleak.h> #include <linux/seq_file.h> #include <linux/memblock.h> +#include <linux/ioport.h> +#include <linux/kexec.h> #include <asm/sections.h> #include <linux/io.h> @@ -2062,6 +2064,91 @@ void __init memblock_free_all(void) totalram_pages_add(pages); } +static struct resource code_resource = { + .name = "Kernel code", + .flags = IORESOURCE_BUSY | IORESOURCE_SYSTEM_RAM, +}; + +static struct resource rodata_resource = { + .name = "Kernel rodata", + .flags = IORESOURCE_BUSY | IORESOURCE_SYSTEM_RAM, +}; + +static struct resource data_resource = { + .name = "Kernel data", + .flags = IORESOURCE_BUSY | IORESOURCE_SYSTEM_RAM, +}; + +static struct resource bss_resource = { + .name = "Kernel bss", + .flags = IORESOURCE_BUSY | IORESOURCE_SYSTEM_RAM, +}; + +static struct resource __initdata *standard_resources[] = { + &code_resource, + &rodata_resource, + &data_resource, + &bss_resource, +#ifdef CONFIG_KEXEC_CORE + &crashk_res, +#endif +}; + +void __init memblock_setup_resources(void) +{ + struct resource *res, *kres, *sub_res; + phys_addr_t start, end; + int j; + u64 i; + + code_resource.start = __pa_symbol(_text); + code_resource.end = __pa_symbol(_etext)-1; + rodata_resource.start = __pa_symbol(__start_rodata); + rodata_resource.end = __pa_symbol(__end_rodata)-1; + data_resource.start = __pa_symbol(_sdata); + data_resource.end = __pa_symbol(_edata)-1; + bss_resource.start = __pa_symbol(__bss_start); + bss_resource.end = __pa_symbol(__bss_stop)-1; + + for_each_mem_range(i, &start, &end) { + res = memblock_alloc(sizeof(*res), 8); + if (!res) + panic("%s: Failed to allocate %zu bytes align=0x%x\n", + __func__, sizeof(*res), 8); + res->flags = IORESOURCE_BUSY | IORESOURCE_SYSTEM_RAM; + + res->name = "System RAM"; + res->start = start; + + /* + * In memblock, end points to the first byte after the + * range while in resourses, end points to the last byte in + * the range. + */ + res->end = end - 1; + request_resource(&iomem_resource, res); + + for (j = 0; j < ARRAY_SIZE(standard_resources); j++) { + kres = standard_resources[j]; + if (!kres->end || kres->start < res->start || + kres->start > res->end) + continue; + if (kres->end > res->end) { + sub_res = memblock_alloc(sizeof(*sub_res), 8); + if (!sub_res) + panic("%s: Failed to allocate %zu bytes align=0x%x\n", + __func__, sizeof(*sub_res), 8); + *sub_res = *kres; + sub_res->end = res->end; + kres->start = res->end + 1; + request_resource(res, sub_res); + } else { + request_resource(res, kres); + } + } + } +} + #if defined(CONFIG_DEBUG_FS) && defined(CONFIG_ARCH_KEEP_MEMBLOCK) static int memblock_debug_show(struct seq_file *m, void *private) -- 2.28.0