From d0d378ff451a66e486488eec842e507d28145813 Mon Sep 17 00:00:00 2001 From: Ethan Tuttle Date: Tue, 19 Jun 2018 21:31:08 -0700 Subject: [PATCH 1/2] ARM: mvebu: declare asm symbols as character arrays in pmsu.c With CONFIG_FORTIFY_SOURCE, memcpy uses the declared size of operands to detect buffer overflows. If src or dest is declared as a char, attempts to copy more than byte will result in a fortify_panic(). Address this problem in mvebu_setup_boot_addr_wa() by declaring mvebu_boot_wa_start and mvebu_boot_wa_end as character arrays. Also remove a couple addressof operators to avoid "arithmetic on pointer to an incomplete type" compiler error. See commit 54a7d50b9205 ("x86: mark kprobe templates as character arrays, not single characters") for a similar fix. Fixes "detected buffer overflow in memcpy" error during init on some mvebu systems (armada-370-xp, armada-375): (fortify_panic) from (mvebu_setup_boot_addr_wa+0xb0/0xb4) (mvebu_setup_boot_addr_wa) from (mvebu_v7_cpu_pm_init+0x154/0x204) (mvebu_v7_cpu_pm_init) from (do_one_initcall+0x7c/0x1a8) (do_one_initcall) from (kernel_init_freeable+0x1bc/0x254) (kernel_init_freeable) from (kernel_init+0x8/0x114) (kernel_init) from (ret_from_fork+0x14/0x2c) Signed-off-by: Ethan Tuttle Tested-by: Ethan Tuttle Signed-off-by: Gregory CLEMENT --- arch/arm/mach-mvebu/pmsu.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/arm/mach-mvebu/pmsu.c b/arch/arm/mach-mvebu/pmsu.c index 27a78c80e5b1..73d5d72dfc3e 100644 --- a/arch/arm/mach-mvebu/pmsu.c +++ b/arch/arm/mach-mvebu/pmsu.c @@ -116,8 +116,8 @@ void mvebu_pmsu_set_cpu_boot_addr(int hw_cpu, void *boot_addr) PMSU_BOOT_ADDR_REDIRECT_OFFSET(hw_cpu)); } -extern unsigned char mvebu_boot_wa_start; -extern unsigned char mvebu_boot_wa_end; +extern unsigned char mvebu_boot_wa_start[]; +extern unsigned char mvebu_boot_wa_end[]; /* * This function sets up the boot address workaround needed for SMP @@ -130,7 +130,7 @@ int mvebu_setup_boot_addr_wa(unsigned int crypto_eng_target, phys_addr_t resume_addr_reg) { void __iomem *sram_virt_base; - u32 code_len = &mvebu_boot_wa_end - &mvebu_boot_wa_start; + u32 code_len = mvebu_boot_wa_end - mvebu_boot_wa_start; mvebu_mbus_del_window(BOOTROM_BASE, BOOTROM_SIZE); mvebu_mbus_add_window_by_id(crypto_eng_target, crypto_eng_attribute, From 77bc8c28ddac90287bc42c129002eb703288d550 Mon Sep 17 00:00:00 2001 From: Lucas Stach Date: Mon, 18 Jun 2018 17:32:30 +0200 Subject: [PATCH 2/2] ARM: mvebu: convert secondary CPU clock sync to hotplug state The current call site in boot_secondary is causing sleep in invalid context warnings, as this part of the code is running with interrrupts disabled and some of the calls into the clock framework might sleep on a mutex. Convert the secondary CPU clock sync to a hotplug state, which allows to call it from a sleepable context. Signed-off-by: Lucas Stach Signed-off-by: Gregory CLEMENT --- arch/arm/mach-mvebu/platsmp.c | 49 ++++++++++++++++------------------- include/linux/cpuhotplug.h | 1 + 2 files changed, 24 insertions(+), 26 deletions(-) diff --git a/arch/arm/mach-mvebu/platsmp.c b/arch/arm/mach-mvebu/platsmp.c index 4ffbbd217e82..c130497dc6cc 100644 --- a/arch/arm/mach-mvebu/platsmp.c +++ b/arch/arm/mach-mvebu/platsmp.c @@ -35,6 +35,8 @@ #define AXP_BOOTROM_BASE 0xfff00000 #define AXP_BOOTROM_SIZE 0x100000 +static struct clk *boot_cpu_clk; + static struct clk *get_cpu_clk(int cpu) { struct clk *cpu_clk; @@ -48,30 +50,6 @@ static struct clk *get_cpu_clk(int cpu) return cpu_clk; } -static void set_secondary_cpu_clock(unsigned int cpu) -{ - int thiscpu; - unsigned long rate; - struct clk *cpu_clk; - - thiscpu = get_cpu(); - - cpu_clk = get_cpu_clk(thiscpu); - if (!cpu_clk) - goto out; - clk_prepare_enable(cpu_clk); - rate = clk_get_rate(cpu_clk); - - cpu_clk = get_cpu_clk(cpu); - if (!cpu_clk) - goto out; - clk_set_rate(cpu_clk, rate); - clk_prepare_enable(cpu_clk); - -out: - put_cpu(); -} - static int armada_xp_boot_secondary(unsigned int cpu, struct task_struct *idle) { int ret, hw_cpu; @@ -79,7 +57,6 @@ static int armada_xp_boot_secondary(unsigned int cpu, struct task_struct *idle) pr_info("Booting CPU %d\n", cpu); hw_cpu = cpu_logical_map(cpu); - set_secondary_cpu_clock(hw_cpu); mvebu_pmsu_set_cpu_boot_addr(hw_cpu, armada_xp_secondary_startup); /* @@ -122,6 +99,19 @@ static void __init armada_xp_smp_init_cpus(void) panic("Invalid number of CPUs in DT\n"); } +static int armada_xp_sync_secondary_clk(unsigned int cpu) +{ + struct clk *cpu_clk = get_cpu_clk(cpu); + + if (!cpu_clk || !boot_cpu_clk) + return 0; + + clk_prepare_enable(cpu_clk); + clk_set_rate(cpu_clk, clk_get_rate(boot_cpu_clk)); + + return 0; +} + static void __init armada_xp_smp_prepare_cpus(unsigned int max_cpus) { struct device_node *node; @@ -131,6 +121,14 @@ static void __init armada_xp_smp_prepare_cpus(unsigned int max_cpus) flush_cache_all(); set_cpu_coherent(); + boot_cpu_clk = get_cpu_clk(smp_processor_id()); + if (boot_cpu_clk) { + clk_prepare_enable(boot_cpu_clk); + cpuhp_setup_state_nocalls(CPUHP_AP_ARM_MVEBU_SYNC_CLOCKS, + "arm/mvebu/sync_clocks:online", + armada_xp_sync_secondary_clk, NULL); + } + /* * In order to boot the secondary CPUs we need to ensure * the bootROM is mapped at the correct address. @@ -223,7 +221,6 @@ static int mv98dx3236_boot_secondary(unsigned int cpu, struct task_struct *idle) int ret, hw_cpu; hw_cpu = cpu_logical_map(cpu); - set_secondary_cpu_clock(hw_cpu); mv98dx3236_resume_set_cpu_boot_addr(hw_cpu, armada_xp_secondary_startup); diff --git a/include/linux/cpuhotplug.h b/include/linux/cpuhotplug.h index 8796ba387152..fa54e5fbea38 100644 --- a/include/linux/cpuhotplug.h +++ b/include/linux/cpuhotplug.h @@ -143,6 +143,7 @@ enum cpuhp_state { CPUHP_AP_SMPBOOT_THREADS, CPUHP_AP_X86_VDSO_VMA_ONLINE, CPUHP_AP_IRQ_AFFINITY_ONLINE, + CPUHP_AP_ARM_MVEBU_SYNC_CLOCKS, CPUHP_AP_PERF_ONLINE, CPUHP_AP_PERF_X86_ONLINE, CPUHP_AP_PERF_X86_UNCORE_ONLINE,