arch/riscv/kernel/traps_misaligned.c:249:21: sparse: sparse: dereference of noderef expression
From: kernel test robot
Date: Fri Jan 05 2024 - 22:58:30 EST
tree: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git master
head: a4ab2706bb1280693e7dff1c5c42a8cb9d70c177
commit: 7c83232161f609bbc452a1255f823f41afc411dd riscv: add support for misaligned trap handling in S-mode
date: 9 weeks ago
config: riscv-randconfig-r122-20231115 (https://download.01.org/0day-ci/archive/20240106/202401061103.iYLnsFu2-lkp@xxxxxxxxx/config)
compiler: riscv64-linux-gcc (GCC) 13.2.0
reproduce: (https://download.01.org/0day-ci/archive/20240106/202401061103.iYLnsFu2-lkp@xxxxxxxxx/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@xxxxxxxxx>
| Closes: https://lore.kernel.org/oe-kbuild-all/202401061103.iYLnsFu2-lkp@xxxxxxxxx/
sparse warnings: (new ones prefixed by >>)
>> arch/riscv/kernel/traps_misaligned.c:249:21: sparse: sparse: dereference of noderef expression
arch/riscv/kernel/traps_misaligned.c:261:21: sparse: sparse: dereference of noderef expression
arch/riscv/kernel/traps_misaligned.c:269:21: sparse: sparse: dereference of noderef expression
>> arch/riscv/kernel/traps_misaligned.c:210:24: sparse: sparse: incorrect type in initializer (different address spaces) @@ expected unsigned char const [noderef] __user *__gu_ptr @@ got unsigned char const [usertype] *addr @@
arch/riscv/kernel/traps_misaligned.c:210:24: sparse: expected unsigned char const [noderef] __user *__gu_ptr
arch/riscv/kernel/traps_misaligned.c:210:24: sparse: got unsigned char const [usertype] *addr
>> arch/riscv/kernel/traps_misaligned.c:249:21: sparse: sparse: dereference of noderef expression
arch/riscv/kernel/traps_misaligned.c:261:21: sparse: sparse: dereference of noderef expression
arch/riscv/kernel/traps_misaligned.c:269:21: sparse: sparse: dereference of noderef expression
>> arch/riscv/kernel/traps_misaligned.c:220:24: sparse: sparse: incorrect type in initializer (different address spaces) @@ expected unsigned char [noderef] __user *__gu_ptr @@ got unsigned char [usertype] *addr @@
arch/riscv/kernel/traps_misaligned.c:220:24: sparse: expected unsigned char [noderef] __user *__gu_ptr
arch/riscv/kernel/traps_misaligned.c:220:24: sparse: got unsigned char [usertype] *addr
vim +249 arch/riscv/kernel/traps_misaligned.c
172
173 static inline int get_insn(struct pt_regs *regs, ulong mepc, ulong *r_insn)
174 {
175 register ulong __mepc asm ("a2") = mepc;
176 ulong val, rvc_mask = 3, tmp;
177
178 asm ("and %[tmp], %[addr], 2\n"
179 "bnez %[tmp], 1f\n"
180 #if defined(CONFIG_64BIT)
181 __stringify(LWU) " %[insn], (%[addr])\n"
182 #else
183 __stringify(LW) " %[insn], (%[addr])\n"
184 #endif
185 "and %[tmp], %[insn], %[rvc_mask]\n"
186 "beq %[tmp], %[rvc_mask], 2f\n"
187 "sll %[insn], %[insn], %[xlen_minus_16]\n"
188 "srl %[insn], %[insn], %[xlen_minus_16]\n"
189 "j 2f\n"
190 "1:\n"
191 "lhu %[insn], (%[addr])\n"
192 "and %[tmp], %[insn], %[rvc_mask]\n"
193 "bne %[tmp], %[rvc_mask], 2f\n"
194 "lhu %[tmp], 2(%[addr])\n"
195 "sll %[tmp], %[tmp], 16\n"
196 "add %[insn], %[insn], %[tmp]\n"
197 "2:"
198 : [insn] "=&r" (val), [tmp] "=&r" (tmp)
199 : [addr] "r" (__mepc), [rvc_mask] "r" (rvc_mask),
200 [xlen_minus_16] "i" (XLEN_MINUS_16));
201
202 *r_insn = val;
203
204 return 0;
205 }
206 #else
207 static inline int load_u8(struct pt_regs *regs, const u8 *addr, u8 *r_val)
208 {
209 if (user_mode(regs)) {
> 210 return __get_user(*r_val, addr);
211 } else {
212 *r_val = *addr;
213 return 0;
214 }
215 }
216
217 static inline int store_u8(struct pt_regs *regs, u8 *addr, u8 val)
218 {
219 if (user_mode(regs)) {
> 220 return __put_user(val, addr);
221 } else {
222 *addr = val;
223 return 0;
224 }
225 }
226
227 #define __read_insn(regs, insn, insn_addr) \
228 ({ \
229 int __ret; \
230 \
231 if (user_mode(regs)) { \
232 __ret = __get_user(insn, insn_addr); \
233 } else { \
234 insn = *insn_addr; \
235 __ret = 0; \
236 } \
237 \
238 __ret; \
239 })
240
241 static inline int get_insn(struct pt_regs *regs, ulong epc, ulong *r_insn)
242 {
243 ulong insn = 0;
244
245 if (epc & 0x2) {
246 ulong tmp = 0;
247 u16 __user *insn_addr = (u16 __user *)epc;
248
> 249 if (__read_insn(regs, insn, insn_addr))
250 return -EFAULT;
251 /* __get_user() uses regular "lw" which sign extend the loaded
252 * value make sure to clear higher order bits in case we "or" it
253 * below with the upper 16 bits half.
254 */
255 insn &= GENMASK(15, 0);
256 if ((insn & __INSN_LENGTH_MASK) != __INSN_LENGTH_32) {
257 *r_insn = insn;
258 return 0;
259 }
260 insn_addr++;
261 if (__read_insn(regs, tmp, insn_addr))
262 return -EFAULT;
263 *r_insn = (tmp << 16) | insn;
264
265 return 0;
266 } else {
267 u32 __user *insn_addr = (u32 __user *)epc;
268
269 if (__read_insn(regs, insn, insn_addr))
270 return -EFAULT;
271 if ((insn & __INSN_LENGTH_MASK) == __INSN_LENGTH_32) {
272 *r_insn = insn;
273 return 0;
274 }
275 insn &= GENMASK(15, 0);
276 *r_insn = insn;
277
278 return 0;
279 }
280 }
281 #endif
282
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki