Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

riscv: Use 64-bit variable for output in __get_user_asm

After commit f6bff7827a48 ("riscv: uaccess: use 'asm_goto_output' for
get_user()"), which was the first commit that started using asm goto
with outputs on RISC-V, builds of clang built with assertions enabled
start crashing in certain files that use get_user() with:

clang: llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp:12743: Register FollowCopyChain(MachineRegisterInfo &, Register): Assertion `MI->getOpcode() == TargetOpcode::COPY && "start of copy chain MUST be COPY"' failed.

Internally, LLVM generates an addiw instruction when the output of the
inline asm (which may be any scalar type) needs to be sign extended for
ABI reasons, such as a later function call, so that basic block does not
have to do it.

Use a temporary 64-bit variable as the output of the inline assembly in
__get_user_asm() and explicitly cast it to truncate it if necessary,
avoiding the addiw that triggers the assertion.

Link: https://github.com/ClangBuiltLinux/linux/issues/2092
Signed-off-by: Nathan Chancellor <nathan@kernel.org>
Link: https://patch.msgid.link/20260116-riscv-wa-llvm-asm-goto-outputs-assertion-failure-v3-1-55b5775f989b@kernel.org
Signed-off-by: Paul Walmsley <pjw@kernel.org>

authored by

Nathan Chancellor and committed by
Paul Walmsley
bdce162f 8fdc61fa

+12 -2
+12 -2
arch/riscv/include/asm/uaccess.h
··· 97 97 */ 98 98 99 99 #ifdef CONFIG_CC_HAS_ASM_GOTO_OUTPUT 100 + /* 101 + * Use a temporary variable for the output of the asm goto to avoid a 102 + * triggering an LLVM assertion due to sign extending the output when 103 + * it is used in later function calls: 104 + * https://github.com/llvm/llvm-project/issues/143795 105 + */ 100 106 #define __get_user_asm(insn, x, ptr, label) \ 107 + do { \ 108 + u64 __tmp; \ 101 109 asm_goto_output( \ 102 110 "1:\n" \ 103 111 " " insn " %0, %1\n" \ 104 112 _ASM_EXTABLE_UACCESS_ERR(1b, %l2, %0) \ 105 - : "=&r" (x) \ 106 - : "m" (*(ptr)) : : label) 113 + : "=&r" (__tmp) \ 114 + : "m" (*(ptr)) : : label); \ 115 + (x) = (__typeof__(x))__tmp; \ 116 + } while (0) 107 117 #else /* !CONFIG_CC_HAS_ASM_GOTO_OUTPUT */ 108 118 #define __get_user_asm(insn, x, ptr, label) \ 109 119 do { \