diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/arm/boot/dts/Makefile | 2 | ||||
-rw-r--r-- | arch/arm/kernel/ftrace.c | 34 |
2 files changed, 36 insertions, 0 deletions
diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index 5ebb44fe826a..5f39c8ea900b 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -144,6 +144,8 @@ dtb-$(CONFIG_ARCH_TEGRA) += tegra20-harmony.dtb \ tegra20-whistler.dtb \ tegra30-cardhu-a02.dtb \ tegra30-cardhu-a04.dtb +dtb-$(CONFIG_ARCH_VERSATILE) += versatile-ab.dtb \ + versatile-pb.dtb dtb-$(CONFIG_ARCH_VEXPRESS) += vexpress-v2p-ca5s.dtb \ vexpress-v2p-ca9.dtb \ vexpress-v2p-ca15-tc1.dtb \ diff --git a/arch/arm/kernel/ftrace.c b/arch/arm/kernel/ftrace.c index 6a740a93f4bb..b0505289b6ec 100644 --- a/arch/arm/kernel/ftrace.c +++ b/arch/arm/kernel/ftrace.c @@ -15,6 +15,7 @@ #include <linux/ftrace.h> #include <linux/module.h> #include <linux/uaccess.h> +#include <linux/stop_machine.h> #include <asm/cacheflush.h> #include <asm/opcodes.h> @@ -171,6 +172,39 @@ int ftrace_make_nop(struct module *mod, return ret; } +struct afmc_data { + int command; + atomic_t cpu; + atomic_t done; +}; + +static int __arch_ftrace_modify_code(void *data) +{ + struct afmc_data *afmcd = data; + + if (atomic_inc_return(&afmcd->cpu) == num_online_cpus()) { + /* Last cpu to get into this function does the actual work */ + ftrace_modify_all_code(afmcd->command); + wmb(); + atomic_set(&afmcd->done, true); + } else { + /* Other cpus wait for the code modifications to be done */ + rmb(); + while (!atomic_read(&afmcd->done)) + cpu_relax(); + /* Ensure icache is consistent with the code changes */ + __flush_icache_all(); + } + + return 0; +} + +void arch_ftrace_update_code(int command) +{ + struct afmc_data afmcd = { command }; + stop_machine(__arch_ftrace_modify_code, &afmcd, cpu_online_mask); +} + int __init ftrace_dyn_arch_init(void *data) { *(unsigned long *)data = 0; |