tools/arch/loongarch/include/asm/inst.h | 12 ++++++++++++ tools/objtool/arch/loongarch/decode.c | 21 +++++++++++++++++++++ 2 files changed, 33 insertions(+)
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 a 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.
Signed-off-by: Tiezhu Yang <yangtiezhu@loongson.cn>
---
tools/arch/loongarch/include/asm/inst.h | 12 ++++++++++++
tools/objtool/arch/loongarch/decode.c | 21 +++++++++++++++++++++
2 files changed, 33 insertions(+)
diff --git a/tools/arch/loongarch/include/asm/inst.h b/tools/arch/loongarch/include/asm/inst.h
index c25b5853181d..d68fad63c8b7 100644
--- a/tools/arch/loongarch/include/asm/inst.h
+++ b/tools/arch/loongarch/include/asm/inst.h
@@ -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)
diff --git a/tools/objtool/arch/loongarch/decode.c b/tools/objtool/arch/loongarch/decode.c
index b6fdc68053cc..707f339b1840 100644
--- a/tools/objtool/arch/loongarch/decode.c
+++ b/tools/objtool/arch/loongarch/decode.c
@@ -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)
insn->type = INSN_NOP;
--
2.42.0
On Tue, Sep 16, 2025 at 2:11 PM Tiezhu Yang <yangtiezhu@loongson.cn> wrote: > > 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 a 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. LLVM lowers `llvm.trap()` to `amswap.w R0, R1, R0`. For x86, it lowers to `ud2`, and objtool marks it as INSN_BUG. https://github.com/llvm/llvm-project/blob/788a25a0f71bfa5e5e1c12ad093993b115d10e7a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td#L1376-L1381 LLVM and GCC handle this differently, GCC lowers it to a break instruction. Since the break instruction has other uses, can objtool mark all break instructions as INSN_BUG? or it should mark different types based on the break immediate code. https://github.com/torvalds/linux/blob/46a51f4f5edade43ba66b3c151f0e25ec8b69cb6/tools/objtool/arch/loongarch/decode.c#L315-L317 > > Signed-off-by: Tiezhu Yang <yangtiezhu@loongson.cn> > --- > tools/arch/loongarch/include/asm/inst.h | 12 ++++++++++++ > tools/objtool/arch/loongarch/decode.c | 21 +++++++++++++++++++++ > 2 files changed, 33 insertions(+) > > diff --git a/tools/arch/loongarch/include/asm/inst.h b/tools/arch/loongarch/include/asm/inst.h > index c25b5853181d..d68fad63c8b7 100644 > --- a/tools/arch/loongarch/include/asm/inst.h > +++ b/tools/arch/loongarch/include/asm/inst.h > @@ -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) > diff --git a/tools/objtool/arch/loongarch/decode.c b/tools/objtool/arch/loongarch/decode.c > index b6fdc68053cc..707f339b1840 100644 > --- a/tools/objtool/arch/loongarch/decode.c > +++ b/tools/objtool/arch/loongarch/decode.c > @@ -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) > insn->type = INSN_NOP; > -- > 2.42.0 > >
On 2025/9/16 下午5:02, WANG Rui wrote: > On Tue, Sep 16, 2025 at 2:11 PM Tiezhu Yang <yangtiezhu@loongson.cn> wrote: >> >> 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 a 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. > > LLVM lowers `llvm.trap()` to `amswap.w R0, R1, R0`. For x86, it lowers > to `ud2`, and objtool marks it as INSN_BUG. > > https://github.com/llvm/llvm-project/blob/788a25a0f71bfa5e5e1c12ad093993b115d10e7a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td#L1376-L1381 Thanks for the detailed explanation from the point of view of the compiler. > LLVM and GCC handle this differently, GCC lowers it to a break > instruction. Since the break instruction has other uses, can objtool > mark all break instructions as INSN_BUG? or it should mark different > types based on the break immediate code. If the break immediate code is 0, it should mark the type as INSN_TRAP. If the break immediate code is 1, it should mark the type as INSN_BUG. I will do it. Thanks, Tiezhu
© 2016 - 2025 Red Hat, Inc.