hc
2024-02-20 102a0743326a03cd1a1202ceda21e175b7d3575c
kernel/arch/riscv/kernel/ftrace.c
....@@ -1,4 +1,4 @@
1
-/* SPDX-License-Identifier: GPL-2.0 */
1
+// SPDX-License-Identifier: GPL-2.0
22 /*
33 * Copyright (C) 2013 Linaro Limited
44 * Author: AKASHI Takahiro <takahiro.akashi@linaro.org>
....@@ -7,9 +7,33 @@
77
88 #include <linux/ftrace.h>
99 #include <linux/uaccess.h>
10
+#include <linux/memory.h>
1011 #include <asm/cacheflush.h>
12
+#include <asm/patch.h>
1113
1214 #ifdef CONFIG_DYNAMIC_FTRACE
15
+int ftrace_arch_code_modify_prepare(void) __acquires(&text_mutex)
16
+{
17
+ mutex_lock(&text_mutex);
18
+
19
+ /*
20
+ * The code sequences we use for ftrace can't be patched while the
21
+ * kernel is running, so we need to use stop_machine() to modify them
22
+ * for now. This doesn't play nice with text_mutex, we use this flag
23
+ * to elide the check.
24
+ */
25
+ riscv_patch_in_stop_machine = true;
26
+
27
+ return 0;
28
+}
29
+
30
+int ftrace_arch_code_modify_post_process(void) __releases(&text_mutex)
31
+{
32
+ riscv_patch_in_stop_machine = false;
33
+ mutex_unlock(&text_mutex);
34
+ return 0;
35
+}
36
+
1337 static int ftrace_check_current_call(unsigned long hook_pos,
1438 unsigned int *expected)
1539 {
....@@ -24,7 +48,8 @@
2448 * Read the text we want to modify;
2549 * return must be -EFAULT on read error
2650 */
27
- if (probe_kernel_read(replaced, (void *)hook_pos, MCOUNT_INSN_SIZE))
51
+ if (copy_from_kernel_nofault(replaced, (void *)hook_pos,
52
+ MCOUNT_INSN_SIZE))
2853 return -EFAULT;
2954
3055 /*
....@@ -32,7 +57,7 @@
3257 * return must be -EINVAL on failed comparison
3358 */
3459 if (memcmp(expected, replaced, sizeof(replaced))) {
35
- pr_err("%p: expected (%08x %08x) but get (%08x %08x)",
60
+ pr_err("%p: expected (%08x %08x) but got (%08x %08x)\n",
3661 (void *)hook_pos, expected[0], expected[1], replaced[0],
3762 replaced[1]);
3863 return -EINVAL;
....@@ -46,19 +71,13 @@
4671 {
4772 unsigned int call[2];
4873 unsigned int nops[2] = {NOP4, NOP4};
49
- int ret = 0;
5074
5175 make_call(hook_pos, target, call);
5276
53
- /* replace the auipc-jalr pair at once */
54
- ret = probe_kernel_write((void *)hook_pos, enable ? call : nops,
55
- MCOUNT_INSN_SIZE);
56
- /* return must be -EPERM on write error */
57
- if (ret)
77
+ /* Replace the auipc-jalr pair at once. Return -EPERM on write error. */
78
+ if (patch_text_nosync
79
+ ((void *)hook_pos, enable ? call : nops, MCOUNT_INSN_SIZE))
5880 return -EPERM;
59
-
60
- smp_mb();
61
- flush_icache_range((void *)hook_pos, (void *)hook_pos + MCOUNT_INSN_SIZE);
6281
6382 return 0;
6483 }
....@@ -100,9 +119,9 @@
100119 {
101120 int out;
102121
103
- ftrace_arch_code_modify_prepare();
122
+ mutex_lock(&text_mutex);
104123 out = ftrace_make_nop(mod, rec, MCOUNT_ADDR);
105
- ftrace_arch_code_modify_post_process();
124
+ mutex_unlock(&text_mutex);
106125
107126 return out;
108127 }