arch/riscv/kernel/ftrace.c:15:5: sparse: sparse: context imbalance in 'ftrace_arch_code_modify_prepare' - wrong count at exit

From: kernel test robot
Date: Mon Aug 10 2020 - 22:25:57 EST


tree: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git master
head: 4bcf69e57063c9b1b15df1a293c969e80a1c97e6
commit: 0ff7c3b331276f584bde3ae9a16bacd8fa3d01e6 riscv: Use text_mutex instead of patch_lock
date: 3 months ago
config: riscv-randconfig-s032-20200810 (attached as .config)
compiler: riscv64-linux-gcc (GCC) 9.3.0
reproduce:
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# apt-get install sparse
# sparse version: v0.6.2-141-g19506bc2-dirty
git checkout 0ff7c3b331276f584bde3ae9a16bacd8fa3d01e6
# save the attached .config to linux build tree
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-9.3.0 make.cross C=1 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__' ARCH=riscv

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@xxxxxxxxx>


sparse warnings: (new ones prefixed by >>)

>> arch/riscv/kernel/ftrace.c:15:5: sparse: sparse: context imbalance in 'ftrace_arch_code_modify_prepare' - wrong count at exit
>> arch/riscv/kernel/ftrace.c:21:5: sparse: sparse: context imbalance in 'ftrace_arch_code_modify_post_process' - wrong count at exit

vim +/ftrace_arch_code_modify_prepare +15 arch/riscv/kernel/ftrace.c

13
14 #ifdef CONFIG_DYNAMIC_FTRACE
> 15 int ftrace_arch_code_modify_prepare(void) __acquires(&text_mutex)
16 {
17 mutex_lock(&text_mutex);
18 return 0;
19 }
20
> 21 int ftrace_arch_code_modify_post_process(void) __releases(&text_mutex)
22 {
23 mutex_unlock(&text_mutex);
24 return 0;
25 }
26
27 static int ftrace_check_current_call(unsigned long hook_pos,
28 unsigned int *expected)
29 {
30 unsigned int replaced[2];
31 unsigned int nops[2] = {NOP4, NOP4};
32
33 /* we expect nops at the hook position */
34 if (!expected)
35 expected = nops;
36
37 /*
38 * Read the text we want to modify;
39 * return must be -EFAULT on read error
40 */
41 if (probe_kernel_read(replaced, (void *)hook_pos, MCOUNT_INSN_SIZE))
42 return -EFAULT;
43
44 /*
45 * Make sure it is what we expect it to be;
46 * return must be -EINVAL on failed comparison
47 */
48 if (memcmp(expected, replaced, sizeof(replaced))) {
49 pr_err("%p: expected (%08x %08x) but got (%08x %08x)\n",
50 (void *)hook_pos, expected[0], expected[1], replaced[0],
51 replaced[1]);
52 return -EINVAL;
53 }
54
55 return 0;
56 }
57
58 static int __ftrace_modify_call(unsigned long hook_pos, unsigned long target,
59 bool enable)
60 {
61 unsigned int call[2];
62 unsigned int nops[2] = {NOP4, NOP4};
63
64 make_call(hook_pos, target, call);
65
66 /* Replace the auipc-jalr pair at once. Return -EPERM on write error. */
67 if (patch_text_nosync
68 ((void *)hook_pos, enable ? call : nops, MCOUNT_INSN_SIZE))
69 return -EPERM;
70
71 return 0;
72 }
73
74 int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
75 {
76 int ret = ftrace_check_current_call(rec->ip, NULL);
77
78 if (ret)
79 return ret;
80
81 return __ftrace_modify_call(rec->ip, addr, true);
82 }
83
84 int ftrace_make_nop(struct module *mod, struct dyn_ftrace *rec,
85 unsigned long addr)
86 {
87 unsigned int call[2];
88 int ret;
89
90 make_call(rec->ip, addr, call);
91 ret = ftrace_check_current_call(rec->ip, call);
92
93 if (ret)
94 return ret;
95
96 return __ftrace_modify_call(rec->ip, addr, false);
97 }
98
99 int ftrace_update_ftrace_func(ftrace_func_t func)
100 {
101 int ret = __ftrace_modify_call((unsigned long)&ftrace_call,
102 (unsigned long)func, true);
103 if (!ret) {
104 ret = __ftrace_modify_call((unsigned long)&ftrace_regs_call,
105 (unsigned long)func, true);
106 }
107
108 return ret;
109 }
110
111 int __init ftrace_dyn_arch_init(void)
112 {
113 return 0;
114 }
115 #endif
116
117 #ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS
118 int ftrace_modify_call(struct dyn_ftrace *rec, unsigned long old_addr,
119 unsigned long addr)
120 {
121 unsigned int call[2];
122 int ret;
123
124 make_call(rec->ip, old_addr, call);
125 ret = ftrace_check_current_call(rec->ip, call);
126
127 if (ret)
128 return ret;
129
130 return __ftrace_modify_call(rec->ip, addr, true);
131 }
132 #endif
133
134 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
135 /*
136 * Most of this function is copied from arm64.
137 */
> 138 void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr,
139 unsigned long frame_pointer)
140 {
141 unsigned long return_hooker = (unsigned long)&return_to_handler;
142 unsigned long old;
143
144 if (unlikely(atomic_read(&current->tracing_graph_pause)))
145 return;
146
147 /*
148 * We don't suffer access faults, so no extra fault-recovery assembly
149 * is needed here.
150 */
151 old = *parent;
152
153 if (!function_graph_enter(old, self_addr, frame_pointer, parent))
154 *parent = return_hooker;
155 }
156

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@xxxxxxxxxxxx

Attachment: .config.gz
Description: application/gzip