]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
objtool/LoongArch: Mark special atomic instruction as INSN_BUG type
authorTiezhu Yang <yangtiezhu@loongson.cn>
Thu, 18 Sep 2025 11:43:36 +0000 (19:43 +0800)
committerHuacai Chen <chenhuacai@loongson.cn>
Thu, 18 Sep 2025 11:43:36 +0000 (19:43 +0800)
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>
tools/arch/loongarch/include/asm/inst.h
tools/objtool/arch/loongarch/decode.c

index c25b5853181dba4cb087c85af0e025cb18c53272..d68fad63c8b7327effb5d24a30f55bc3cd2fd560 100644 (file)
@@ -51,6 +51,10 @@ enum reg2i16_op {
        bgeu_op         = 0x1b,
 };
 
+enum reg3_op {
+       amswapw_op      = 0x70c0,
+};
+
 struct reg0i15_format {
        unsigned int immediate : 15;
        unsigned int opcode : 17;
@@ -96,6 +100,13 @@ struct reg2i16_format {
        unsigned int opcode : 6;
 };
 
+struct reg3_format {
+       unsigned int rd : 5;
+       unsigned int rj : 5;
+       unsigned int rk : 5;
+       unsigned int opcode : 17;
+};
+
 union loongarch_instruction {
        unsigned int word;
        struct reg0i15_format   reg0i15_format;
@@ -105,6 +116,7 @@ union loongarch_instruction {
        struct reg2i12_format   reg2i12_format;
        struct reg2i14_format   reg2i14_format;
        struct reg2i16_format   reg2i16_format;
+       struct reg3_format      reg3_format;
 };
 
 #define LOONGARCH_INSN_SIZE    sizeof(union loongarch_instruction)
index 428ba6de38219196506be4f3ba6eccd475df28c8..2e555c4060c5e4dbcea3f661412e34e636709315 100644 (file)
@@ -278,6 +278,25 @@ static bool decode_insn_reg2i16_fomat(union loongarch_instruction inst,
        return true;
 }
 
+static bool decode_insn_reg3_fomat(union loongarch_instruction inst,
+                                  struct instruction *insn)
+{
+       switch (inst.reg3_format.opcode) {
+       case amswapw_op:
+               if (inst.reg3_format.rd == LOONGARCH_GPR_ZERO &&
+                   inst.reg3_format.rk == LOONGARCH_GPR_RA &&
+                   inst.reg3_format.rj == LOONGARCH_GPR_ZERO) {
+                       /* amswap.w $zero, $ra, $zero */
+                       insn->type = INSN_BUG;
+               }
+               break;
+       default:
+               return false;
+       }
+
+       return true;
+}
+
 int arch_decode_instruction(struct objtool_file *file, const struct section *sec,
                            unsigned long offset, unsigned int maxlen,
                            struct instruction *insn)
@@ -309,6 +328,8 @@ int arch_decode_instruction(struct objtool_file *file, const struct section *sec
                return 0;
        if (decode_insn_reg2i16_fomat(inst, insn))
                return 0;
+       if (decode_insn_reg3_fomat(inst, insn))
+               return 0;
 
        if (inst.word == 0) {
                /* andi $zero, $zero, 0x0 */