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

objtool/LoongArch: Mark special atomic instruction as INSN_BUG type

When compiling with LLVM and CONFIG_RUST is set, there exists the
following objtool warning:

rust/compiler_builtins.o: warning: objtool: __rust__unordsf2(): unexpected end of section .text.unlikely.

objdump shows that the end of section .text.unlikely is an atomic
instruction:

amswap.w $zero, $ra, $zero

According to the LoongArch Reference Manual, if the amswap.w atomic
memory access instruction has the same register number as rd and rj,
the execution will trigger an Instruction Non-defined Exception, so
mark the above instruction as INSN_BUG type to fix the warning.

Cc: stable@vger.kernel.org
Signed-off-by: Tiezhu Yang <yangtiezhu@loongson.cn>
Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>

authored by

Tiezhu Yang and committed by
Huacai Chen
539d7344 baad7830

+33
+12
tools/arch/loongarch/include/asm/inst.h
··· 51 51 bgeu_op = 0x1b, 52 52 }; 53 53 54 + enum reg3_op { 55 + amswapw_op = 0x70c0, 56 + }; 57 + 54 58 struct reg0i15_format { 55 59 unsigned int immediate : 15; 56 60 unsigned int opcode : 17; ··· 100 96 unsigned int opcode : 6; 101 97 }; 102 98 99 + struct reg3_format { 100 + unsigned int rd : 5; 101 + unsigned int rj : 5; 102 + unsigned int rk : 5; 103 + unsigned int opcode : 17; 104 + }; 105 + 103 106 union loongarch_instruction { 104 107 unsigned int word; 105 108 struct reg0i15_format reg0i15_format; ··· 116 105 struct reg2i12_format reg2i12_format; 117 106 struct reg2i14_format reg2i14_format; 118 107 struct reg2i16_format reg2i16_format; 108 + struct reg3_format reg3_format; 119 109 }; 120 110 121 111 #define LOONGARCH_INSN_SIZE sizeof(union loongarch_instruction)
+21
tools/objtool/arch/loongarch/decode.c
··· 278 278 return true; 279 279 } 280 280 281 + static bool decode_insn_reg3_fomat(union loongarch_instruction inst, 282 + struct instruction *insn) 283 + { 284 + switch (inst.reg3_format.opcode) { 285 + case amswapw_op: 286 + if (inst.reg3_format.rd == LOONGARCH_GPR_ZERO && 287 + inst.reg3_format.rk == LOONGARCH_GPR_RA && 288 + inst.reg3_format.rj == LOONGARCH_GPR_ZERO) { 289 + /* amswap.w $zero, $ra, $zero */ 290 + insn->type = INSN_BUG; 291 + } 292 + break; 293 + default: 294 + return false; 295 + } 296 + 297 + return true; 298 + } 299 + 281 300 int arch_decode_instruction(struct objtool_file *file, const struct section *sec, 282 301 unsigned long offset, unsigned int maxlen, 283 302 struct instruction *insn) ··· 327 308 if (decode_insn_reg2i14_fomat(inst, insn, ops_list, op)) 328 309 return 0; 329 310 if (decode_insn_reg2i16_fomat(inst, insn)) 311 + return 0; 312 + if (decode_insn_reg3_fomat(inst, insn)) 330 313 return 0; 331 314 332 315 if (inst.word == 0) {