From: Kefeng Wang wangkefeng.wang@huawei.com
hulk inclusion category: feature bugzilla: 48159 CVE: N/A
------------------------------
It's better to make the non-upstreamed feature into stand-alone file, which make us easy to backport mainline patches.
No functional changes.
Cc: Sang Yan sangyan@huawei.com Signed-off-by: Kefeng Wang wangkefeng.wang@huawei.com Reviewed-by: Sang Yan sangyan@huawei.com Reviewed-by: Liu Shixin liushixin2@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- arch/arm64/include/asm/cpu_park.h | 29 +++ arch/arm64/include/asm/kexec.h | 5 - arch/arm64/include/asm/smp.h | 16 +- arch/arm64/kernel/Makefile | 2 +- arch/arm64/kernel/arm64_cpu_park.c | 289 +++++++++++++++++++++++++++++ arch/arm64/kernel/cpu-park.S | 2 +- arch/arm64/kernel/process.c | 3 +- arch/arm64/kernel/smp.c | 226 +--------------------- arch/arm64/mm/init.c | 54 +----- 9 files changed, 328 insertions(+), 298 deletions(-) create mode 100644 arch/arm64/include/asm/cpu_park.h create mode 100644 arch/arm64/kernel/arm64_cpu_park.c
diff --git a/arch/arm64/include/asm/cpu_park.h b/arch/arm64/include/asm/cpu_park.h new file mode 100644 index 000000000000..0aa4ebf6f830 --- /dev/null +++ b/arch/arm64/include/asm/cpu_park.h @@ -0,0 +1,29 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef __ASM_CPU_PARK_H +#define __ASM_CPU_PARK_H + +#ifdef CONFIG_ARM64_CPU_PARK + +/* CPU park state flag: "park" */ +#define PARK_MAGIC 0x7061726b + +#ifndef __ASSEMBLY__ +extern void enter_cpu_park(unsigned long text, unsigned long exit); +extern void do_cpu_park(unsigned long exit); +extern void reserve_park_mem(void); +extern int write_park_exit(unsigned int cpu); +extern int uninstall_cpu_park(unsigned int cpu); +extern void cpu_park_stop(void); +extern int kexec_smp_send_park(void); +#endif /* ifndef __ASSEMBLY__ */ + +#else +static inline void reserve_park_mem(void) {} +static inline int write_park_exit(unsigned int cpu) { return -EINVAL; } +static inline int uninstall_cpu_park(unsigned int cpu) { return -EINVAL; } +static inline void cpu_park_stop(void) {} +static inline int kexec_smp_send_park(void) { return -EINVAL; } +#endif + +#endif /* ifndef __ASM_CPU_PARK_H */ diff --git a/arch/arm64/include/asm/kexec.h b/arch/arm64/include/asm/kexec.h index 20bee23b6503..e19c0af3b53d 100644 --- a/arch/arm64/include/asm/kexec.h +++ b/arch/arm64/include/asm/kexec.h @@ -32,11 +32,6 @@
#define CRASH_ADDR_HIGH_MAX MEMBLOCK_ALLOC_ACCESSIBLE
-#ifdef CONFIG_ARM64_CPU_PARK -/* CPU park state flag: "park" */ -#define PARK_MAGIC 0x7061726b -#endif - #ifndef __ASSEMBLY__
/** diff --git a/arch/arm64/include/asm/smp.h b/arch/arm64/include/asm/smp.h index 8c5d2d650b8a..f4b19b8f323a 100644 --- a/arch/arm64/include/asm/smp.h +++ b/arch/arm64/include/asm/smp.h @@ -145,21 +145,7 @@ bool cpus_are_stuck_in_kernel(void);
extern void crash_smp_send_stop(void); extern bool smp_crash_stop_failed(void); -#ifdef CONFIG_ARM64_CPU_PARK -#define PARK_SECTION_SIZE 1024 -struct cpu_park_info { - /* Physical address of reserved park memory. */ - unsigned long start; - /* park reserve mem len should be PARK_SECTION_SIZE * NR_CPUS */ - unsigned long len; - /* Virtual address of reserved park memory. */ - unsigned long start_v; -}; -extern struct cpu_park_info park_info; -extern void enter_cpu_park(unsigned long text, unsigned long exit); -extern void do_cpu_park(unsigned long exit); -extern int kexec_smp_send_park(void); -#endif +extern void smp_cross_send_stop(cpumask_t *cpumask);
#endif /* ifndef __ASSEMBLY__ */
diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile index 169d90f11cf5..4cf75b247461 100644 --- a/arch/arm64/kernel/Makefile +++ b/arch/arm64/kernel/Makefile @@ -56,7 +56,7 @@ obj-$(CONFIG_RANDOMIZE_BASE) += kaslr.o obj-$(CONFIG_HIBERNATION) += hibernate.o hibernate-asm.o obj-$(CONFIG_KEXEC_CORE) += machine_kexec.o relocate_kernel.o \ cpu-reset.o -obj-$(CONFIG_ARM64_CPU_PARK) += cpu-park.o +obj-$(CONFIG_ARM64_CPU_PARK) += cpu-park.o arm64_cpu_park.o obj-$(CONFIG_KEXEC_FILE) += machine_kexec_file.o kexec_image.o obj-$(CONFIG_ARM64_RELOC_TEST) += arm64-reloc-test.o arm64-reloc-test-y := reloc_test_core.o reloc_test_syms.o diff --git a/arch/arm64/kernel/arm64_cpu_park.c b/arch/arm64/kernel/arm64_cpu_park.c new file mode 100644 index 000000000000..c54ffa26a2c7 --- /dev/null +++ b/arch/arm64/kernel/arm64_cpu_park.c @@ -0,0 +1,289 @@ +// SPDX-License-Identifier: GPL-2.0-only + +#define pr_fmt(fmt) "arm64 cpu-park: " fmt + +#include <linux/arm_sdei.h> +#include <linux/delay.h> +#include <linux/kexec.h> +#include <linux/memblock.h> +#include <linux/ioport.h> +#include <linux/io.h> +#include <linux/types.h> + +#include <asm/cacheflush.h> +#include <asm/cpu_ops.h> +#include <asm/cpu_park.h> +#include <asm/mmu_context.h> + +#define PARK_SECTION_SIZE 1024 + +struct cpu_park_section { + unsigned long exit; /* exit address of park look */ + unsigned long magic; /* maigc represent park state */ + char text[0]; /* text section of park */ +}; + +struct cpu_park_info { + /* Physical address of reserved park memory. */ + unsigned long start; + /* park reserve mem len should be PARK_SECTION_SIZE * NR_CPUS */ + unsigned long len; + /* Virtual address of reserved park memory. */ + unsigned long start_v; +}; + +static struct cpu_park_info park_info = { + .start = 0, + .len = PARK_SECTION_SIZE * NR_CPUS, + .start_v = 0, +}; + +static int __init parse_park_mem(char *p) +{ + if (!p) + return 0; + + park_info.start = PAGE_ALIGN(memparse(p, NULL)); + if (park_info.start == 0) + pr_info("cpu park mem params[%s]", p); + + return 0; +} +early_param("cpuparkmem", parse_park_mem); + +void __init reserve_park_mem(void) +{ + if (park_info.start == 0 || park_info.len == 0) + return; + + park_info.start = PAGE_ALIGN(park_info.start); + park_info.len = PAGE_ALIGN(park_info.len); + + if (!memblock_is_region_memory(park_info.start, park_info.len)) { + pr_warn("region is not memory!"); + goto out; + } + + if (memblock_is_region_reserved(park_info.start, park_info.len)) { + pr_warn("region overlaps reserved memory!"); + goto out; + } + + memblock_remove(park_info.start, park_info.len); + pr_info("mem reserved: 0x%016lx - 0x%016lx (%ld MB)", + park_info.start, park_info.start + park_info.len, + park_info.len >> 20); + + return; +out: + park_info.start = 0; + park_info.len = 0; + return; +} + +static int mmap_cpu_park_mem(void) +{ + if (!park_info.start) + return -ENOMEM; + + if (park_info.start_v) + return 0; + + park_info.start_v = (unsigned long)__ioremap(park_info.start, + park_info.len, + PAGE_KERNEL_EXEC); + if (!park_info.start_v) { + pr_warn("map park memory failed."); + return -ENOMEM; + } + + return 0; +} + +static inline unsigned long cpu_park_section_v(unsigned int cpu) +{ + return park_info.start_v + PARK_SECTION_SIZE * (cpu - 1); +} + +static inline unsigned long cpu_park_section_p(unsigned int cpu) +{ + return park_info.start + PARK_SECTION_SIZE * (cpu - 1); +} + +/* + * Write the secondary_entry to exit section of park state. + * Then the secondary cpu will jump straight into the kernel + * by the secondary_entry. + */ +int write_park_exit(unsigned int cpu) +{ + struct cpu_park_section *park_section; + unsigned long *park_exit; + unsigned long *park_text; + + if (mmap_cpu_park_mem() != 0) + return -EPERM; + + park_section = (struct cpu_park_section *)cpu_park_section_v(cpu); + park_exit = &park_section->exit; + park_text = (unsigned long *)park_section->text; + pr_debug("park_text 0x%lx : 0x%lx, do_cpu_park text 0x%lx : 0x%lx", + (unsigned long)park_text, *park_text, + (unsigned long)do_cpu_park, + *(unsigned long *)do_cpu_park); + + /* + * Test first 8 bytes to determine + * whether needs to write cpu park exit. + */ + if (*park_text == *(unsigned long *)do_cpu_park) { + writeq_relaxed(__pa_symbol(secondary_entry), park_exit); + __flush_dcache_area((__force void *)park_exit, + sizeof(unsigned long)); + flush_icache_range((unsigned long)park_exit, + (unsigned long)(park_exit + 1)); + sev(); + dsb(sy); + isb(); + + pr_debug("Write cpu %u secondary entry 0x%lx to 0x%lx.", + cpu, *park_exit, (unsigned long)park_exit); + pr_info("Boot cpu %u from PARK state.", cpu); + return 0; + } + + return -EPERM; +} + +/* Install cpu park sections for the specific cpu. */ +static void install_cpu_park(unsigned int cpu) +{ + struct cpu_park_section *park_section; + unsigned long *park_exit; + unsigned long *park_magic; + unsigned long park_text_len; + + park_section = (struct cpu_park_section *)cpu_park_section_v(cpu); + pr_debug("Install cpu park on cpu %u park exit 0x%lx park text 0x%lx", + cpu, (unsigned long)park_section, + (unsigned long)(park_section->text)); + + park_exit = &park_section->exit; + park_magic = &park_section->magic; + park_text_len = PARK_SECTION_SIZE - sizeof(struct cpu_park_section); + + *park_exit = 0UL; + *park_magic = 0UL; + memcpy((void *)park_section->text, do_cpu_park, park_text_len); + __flush_dcache_area((void *)park_section, PARK_SECTION_SIZE); +} + +int uninstall_cpu_park(unsigned int cpu) +{ + unsigned long park_section; + + if (mmap_cpu_park_mem() != 0) + return -EPERM; + + park_section = cpu_park_section_v(cpu); + memset((void *)park_section, 0, PARK_SECTION_SIZE); + __flush_dcache_area((void *)park_section, PARK_SECTION_SIZE); + + return 0; +} + +static int cpu_wait_park(unsigned int cpu) +{ + long timeout; + struct cpu_park_section *park_section; + + volatile unsigned long *park_magic; + + park_section = (struct cpu_park_section *)cpu_park_section_v(cpu); + park_magic = &park_section->magic; + + timeout = USEC_PER_SEC; + while (*park_magic != PARK_MAGIC && timeout--) + udelay(1); + + if (timeout > 0) + pr_debug("cpu %u park done.", cpu); + else + pr_err("cpu %u park failed.", cpu); + + return *park_magic == PARK_MAGIC; +} + +static void cpu_park(unsigned int cpu) +{ + unsigned long park_section_p; + unsigned long park_exit_phy; + unsigned long do_park; + typeof(enter_cpu_park) *park; + + park_section_p = cpu_park_section_p(cpu); + park_exit_phy = park_section_p; + pr_debug("Go to park cpu %u exit address 0x%lx", cpu, park_exit_phy); + + do_park = park_section_p + sizeof(struct cpu_park_section); + park = (void *)__pa_symbol(enter_cpu_park); + + cpu_install_idmap(); + park(do_park, park_exit_phy); + unreachable(); +} + +void cpu_park_stop(void) +{ + int cpu = smp_processor_id(); + const struct cpu_operations *ops = NULL; + /* + * Go to cpu park state. + * Otherwise go to cpu die. + */ + if (kexec_in_progress && park_info.start_v) { + machine_kexec_mask_interrupts(); + cpu_park(cpu); + + ops = get_cpu_ops(cpu); + if (ops && ops->cpu_die) + ops->cpu_die(cpu); + } +} + +int kexec_smp_send_park(void) +{ + unsigned long cpu; + + if (WARN_ON(!kexec_in_progress)) { + pr_crit("%s called not in kexec progress.", __func__); + return -EPERM; + } + + if (mmap_cpu_park_mem() != 0) { + pr_info("no cpuparkmem, goto normal way."); + return -EPERM; + } + + local_irq_disable(); + + if (num_online_cpus() > 1) { + cpumask_t mask; + + cpumask_copy(&mask, cpu_online_mask); + cpumask_clear_cpu(smp_processor_id(), &mask); + + for_each_cpu(cpu, &mask) + install_cpu_park(cpu); + smp_cross_send_stop(&mask); + + /* Wait for other CPUs to park */ + for_each_cpu(cpu, &mask) + cpu_wait_park(cpu); + pr_info("smp park other cpus done\n"); + } + + sdei_mask_local_cpu(); + + return 0; +} diff --git a/arch/arm64/kernel/cpu-park.S b/arch/arm64/kernel/cpu-park.S index 07290dabe10c..8bcfcf0dc0f5 100644 --- a/arch/arm64/kernel/cpu-park.S +++ b/arch/arm64/kernel/cpu-park.S @@ -11,7 +11,7 @@
#include <linux/linkage.h> #include <asm/assembler.h> -#include <asm/kexec.h> +#include <asm/cpu_park.h> #include <asm/sysreg.h> #include <asm/virt.h>
diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c index da5ed561e962..d7c90d8e25d1 100644 --- a/arch/arm64/kernel/process.c +++ b/arch/arm64/kernel/process.c @@ -57,6 +57,7 @@ #include <asm/pointer_auth.h> #include <asm/stacktrace.h> #include <asm/mpam_sched.h> +#include <asm/cpu_park.h>
#if defined(CONFIG_STACKPROTECTOR) && !defined(CONFIG_STACKPROTECTOR_PER_TASK) #include <linux/stackprotector.h> @@ -151,10 +152,8 @@ void arch_cpu_idle_dead(void) */ void machine_shutdown(void) { -#ifdef CONFIG_ARM64_CPU_PARK if (kexec_smp_send_park() == 0) return; -#endif smp_shutdown_nonboot_cpus(reboot_cpu); }
diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c index fc099cda70a3..dd4c76ed8ca6 100644 --- a/arch/arm64/kernel/smp.c +++ b/arch/arm64/kernel/smp.c @@ -55,6 +55,7 @@ #include <asm/tlbflush.h> #include <asm/ptrace.h> #include <asm/virt.h> +#include <asm/cpu_park.h>
#define CREATE_TRACE_POINTS #include <trace/events/ipi.h> @@ -98,167 +99,6 @@ static inline int op_cpu_kill(unsigned int cpu) } #endif
-#ifdef CONFIG_ARM64_CPU_PARK -struct cpu_park_section { - unsigned long exit; /* exit address of park look */ - unsigned long magic; /* maigc represent park state */ - char text[0]; /* text section of park */ -}; - -static int mmap_cpu_park_mem(void) -{ - if (!park_info.start) - return -ENOMEM; - - if (park_info.start_v) - return 0; - - park_info.start_v = (unsigned long)__ioremap(park_info.start, - park_info.len, - PAGE_KERNEL_EXEC); - if (!park_info.start_v) { - pr_warn("map park memory failed."); - return -ENOMEM; - } - - return 0; -} - -static inline unsigned long cpu_park_section_v(unsigned int cpu) -{ - return park_info.start_v + PARK_SECTION_SIZE * (cpu - 1); -} - -static inline unsigned long cpu_park_section_p(unsigned int cpu) -{ - return park_info.start + PARK_SECTION_SIZE * (cpu - 1); -} - -/* - * Write the secondary_entry to exit section of park state. - * Then the secondary cpu will jump straight into the kernel - * by the secondary_entry. - */ -static int write_park_exit(unsigned int cpu) -{ - struct cpu_park_section *park_section; - unsigned long *park_exit; - unsigned long *park_text; - - if (mmap_cpu_park_mem() != 0) - return -EPERM; - - park_section = (struct cpu_park_section *)cpu_park_section_v(cpu); - park_exit = &park_section->exit; - park_text = (unsigned long *)park_section->text; - pr_debug("park_text 0x%lx : 0x%lx, do_cpu_park text 0x%lx : 0x%lx", - (unsigned long)park_text, *park_text, - (unsigned long)do_cpu_park, - *(unsigned long *)do_cpu_park); - - /* - * Test first 8 bytes to determine - * whether needs to write cpu park exit. - */ - if (*park_text == *(unsigned long *)do_cpu_park) { - writeq_relaxed(__pa_symbol(secondary_entry), park_exit); - __flush_dcache_area((__force void *)park_exit, - sizeof(unsigned long)); - flush_icache_range((unsigned long)park_exit, - (unsigned long)(park_exit + 1)); - sev(); - dsb(sy); - isb(); - - pr_debug("Write cpu %u secondary entry 0x%lx to 0x%lx.", - cpu, *park_exit, (unsigned long)park_exit); - pr_info("Boot cpu %u from PARK state.", cpu); - return 0; - } - - return -EPERM; -} - -/* Install cpu park sections for the specific cpu. */ -static int install_cpu_park(unsigned int cpu) -{ - struct cpu_park_section *park_section; - unsigned long *park_exit; - unsigned long *park_magic; - unsigned long park_text_len; - - park_section = (struct cpu_park_section *)cpu_park_section_v(cpu); - pr_debug("Install cpu park on cpu %u park exit 0x%lx park text 0x%lx", - cpu, (unsigned long)park_section, - (unsigned long)(park_section->text)); - - park_exit = &park_section->exit; - park_magic = &park_section->magic; - park_text_len = PARK_SECTION_SIZE - sizeof(struct cpu_park_section); - - *park_exit = 0UL; - *park_magic = 0UL; - memcpy((void *)park_section->text, do_cpu_park, park_text_len); - __flush_dcache_area((void *)park_section, PARK_SECTION_SIZE); - - return 0; -} - -static int uninstall_cpu_park(unsigned int cpu) -{ - unsigned long park_section; - - if (mmap_cpu_park_mem() != 0) - return -EPERM; - - park_section = cpu_park_section_v(cpu); - memset((void *)park_section, 0, PARK_SECTION_SIZE); - __flush_dcache_area((void *)park_section, PARK_SECTION_SIZE); - - return 0; -} - -static int cpu_wait_park(unsigned int cpu) -{ - long timeout; - struct cpu_park_section *park_section; - - volatile unsigned long *park_magic; - - park_section = (struct cpu_park_section *)cpu_park_section_v(cpu); - park_magic = &park_section->magic; - - timeout = USEC_PER_SEC; - while (*park_magic != PARK_MAGIC && timeout--) - udelay(1); - - if (timeout > 0) - pr_debug("cpu %u park done.", cpu); - else - pr_err("cpu %u park failed.", cpu); - - return *park_magic == PARK_MAGIC; -} - -static void cpu_park(unsigned int cpu) -{ - unsigned long park_section_p; - unsigned long park_exit_phy; - unsigned long do_park; - typeof(enter_cpu_park) *park; - - park_section_p = cpu_park_section_p(cpu); - park_exit_phy = park_section_p; - pr_debug("Go to park cpu %u exit address 0x%lx", cpu, park_exit_phy); - - do_park = park_section_p + sizeof(struct cpu_park_section); - park = (void *)__pa_symbol(enter_cpu_park); - - cpu_install_idmap(); - park(do_park, park_exit_phy); - unreachable(); -} -#endif
/* * Boot a secondary CPU, and assign it the specified idle task. @@ -268,10 +108,8 @@ static int boot_secondary(unsigned int cpu, struct task_struct *idle) { const struct cpu_operations *ops = get_cpu_ops(cpu);
-#ifdef CONFIG_ARM64_CPU_PARK if (write_park_exit(cpu) == 0) return 0; -#endif if (ops->cpu_boot) return ops->cpu_boot(cpu);
@@ -307,9 +145,8 @@ int __cpu_up(unsigned int cpu, struct task_struct *idle) */ wait_for_completion_timeout(&cpu_running, msecs_to_jiffies(5000)); -#ifdef CONFIG_ARM64_CPU_PARK uninstall_cpu_park(cpu); -#endif + if (cpu_online(cpu)) return 0;
@@ -1057,31 +894,12 @@ void arch_irq_work_raise(void)
static void local_cpu_stop(void) { -#ifdef CONFIG_ARM64_CPU_PARK - int cpu; - const struct cpu_operations *ops = NULL; -#endif - set_cpu_online(smp_processor_id(), false);
local_daif_mask(); sdei_mask_local_cpu();
-#ifdef CONFIG_ARM64_CPU_PARK - /* - * Go to cpu park state. - * Otherwise go to cpu die. - */ - cpu = smp_processor_id(); - if (kexec_in_progress && park_info.start_v) { - machine_kexec_mask_interrupts(); - cpu_park(cpu); - - ops = get_cpu_ops(cpu); - if (ops && ops->cpu_die) - ops->cpu_die(cpu); - } -#endif + cpu_park_stop();
cpu_park_loop(); } @@ -1295,44 +1113,10 @@ void smp_send_stop(void) sdei_mask_local_cpu(); }
-#ifdef CONFIG_ARM64_CPU_PARK -int kexec_smp_send_park(void) +void smp_cross_send_stop(cpumask_t *mask) { - unsigned long cpu; - - if (WARN_ON(!kexec_in_progress)) { - pr_crit("%s called not in kexec progress.", __func__); - return -EPERM; - } - - if (mmap_cpu_park_mem() != 0) { - pr_info("no cpuparkmem, goto normal way."); - return -EPERM; - } - - local_irq_disable(); - - if (num_online_cpus() > 1) { - cpumask_t mask; - - cpumask_copy(&mask, cpu_online_mask); - cpumask_clear_cpu(smp_processor_id(), &mask); - - for_each_cpu(cpu, &mask) - install_cpu_park(cpu); - smp_cross_call(&mask, IPI_CPU_STOP); - - /* Wait for other CPUs to park */ - for_each_cpu(cpu, &mask) - cpu_wait_park(cpu); - pr_info("smp park other cpus done\n"); - } - - sdei_mask_local_cpu(); - - return 0; + smp_cross_call(mask, IPI_CPU_STOP); } -#endif
#ifdef CONFIG_KEXEC_CORE void crash_smp_send_stop(void) diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c index 90411356b8b2..2f3910beb4cf 100644 --- a/arch/arm64/mm/init.c +++ b/arch/arm64/mm/init.c @@ -44,6 +44,7 @@ #include <linux/sizes.h> #include <asm/tlb.h> #include <asm/alternative.h> +#include <asm/cpu_park.h>
#include "internal.h"
@@ -268,57 +269,6 @@ static void __init fdt_enforce_memory_region(void) memblock_add(usable_rgns[1].base, usable_rgns[1].size); }
-#ifdef CONFIG_ARM64_CPU_PARK -struct cpu_park_info park_info = { - .start = 0, - .len = PARK_SECTION_SIZE * NR_CPUS, - .start_v = 0, -}; - -static int __init parse_park_mem(char *p) -{ - if (!p) - return 0; - - park_info.start = PAGE_ALIGN(memparse(p, NULL)); - if (park_info.start == 0) - pr_info("cpu park mem params[%s]", p); - - return 0; -} -early_param("cpuparkmem", parse_park_mem); - -static int __init reserve_park_mem(void) -{ - if (park_info.start == 0 || park_info.len == 0) - return 0; - - park_info.start = PAGE_ALIGN(park_info.start); - park_info.len = PAGE_ALIGN(park_info.len); - - if (!memblock_is_region_memory(park_info.start, park_info.len)) { - pr_warn("cannot reserve park mem: region is not memory!"); - goto out; - } - - if (memblock_is_region_reserved(park_info.start, park_info.len)) { - pr_warn("cannot reserve park mem: region overlaps reserved memory!"); - goto out; - } - - memblock_remove(park_info.start, park_info.len); - pr_info("cpu park mem reserved: 0x%016lx - 0x%016lx (%ld MB)", - park_info.start, park_info.start + park_info.len, - park_info.len >> 20); - - return 0; -out: - park_info.start = 0; - park_info.len = 0; - return -EINVAL; -} -#endif - static int need_remove_real_memblock __initdata;
static int __init parse_memmap_one(char *p) @@ -542,9 +492,7 @@ void __init bootmem_init(void) * So reserve park memory firstly is better, but it may cause * crashkernel or quickkexec reserving failed. */ -#ifdef CONFIG_ARM64_CPU_PARK reserve_park_mem(); -#endif
/* * request_standard_resources() depends on crashkernel's memory being