* [PATCH v3 01/12] objtool/LoongArch: Add arch_adjusted_addend() for KLP support
2026-07-07 7:20 [PATCH v3 00/12] LoongArch: Add livepatch build (KLP) support George Guo
@ 2026-07-07 7:20 ` George Guo
2026-07-07 7:20 ` [PATCH v3 02/12] LoongArch: Mark special sections " George Guo
` (10 subsequent siblings)
11 siblings, 0 replies; 18+ messages in thread
From: George Guo @ 2026-07-07 7:20 UTC (permalink / raw)
To: chenhuacai, jpoimboe, peterz, jikos, mbenes, pmladek
Cc: kernel, joe.lawrence, rostedt, ardb, nathan,
nick.desaulniers+lkml, yangtiezhu, jiaxun.yang, liukexin,
guodongtai, xry111, wangyuli, loongarch, live-patching, llvm,
linux-kernel
From: George Guo <guodongtai@kylinos.cn>
Implement arch_adjusted_addend() to return the relocation addend value.
Co-developed-by: Kexin Liu <liukexin@kylinos.cn>
Signed-off-by: Kexin Liu <liukexin@kylinos.cn>
Signed-off-by: George Guo <guodongtai@kylinos.cn>
---
tools/objtool/arch/loongarch/decode.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/tools/objtool/arch/loongarch/decode.c b/tools/objtool/arch/loongarch/decode.c
index 6cd288150f49..674e4efd138f 100644
--- a/tools/objtool/arch/loongarch/decode.c
+++ b/tools/objtool/arch/loongarch/decode.c
@@ -34,6 +34,11 @@ s64 arch_insn_adjusted_addend(struct instruction *insn, struct reloc *reloc)
return reloc_addend(reloc);
}
+u64 arch_adjusted_addend(struct reloc *reloc)
+{
+ return reloc_addend(reloc);
+}
+
bool arch_pc_relative_reloc(struct reloc *reloc)
{
return false;
--
2.25.1
^ permalink raw reply related [flat|nested] 18+ messages in thread* [PATCH v3 02/12] LoongArch: Mark special sections for KLP support
2026-07-07 7:20 [PATCH v3 00/12] LoongArch: Add livepatch build (KLP) support George Guo
2026-07-07 7:20 ` [PATCH v3 01/12] objtool/LoongArch: Add arch_adjusted_addend() for KLP support George Guo
@ 2026-07-07 7:20 ` George Guo
2026-07-07 7:20 ` [PATCH v3 03/12] livepatch/klp-build: disable direct-extern-access for LoongArch to fix kernel panic George Guo
` (9 subsequent siblings)
11 siblings, 0 replies; 18+ messages in thread
From: George Guo @ 2026-07-07 7:20 UTC (permalink / raw)
To: chenhuacai, jpoimboe, peterz, jikos, mbenes, pmladek
Cc: kernel, joe.lawrence, rostedt, ardb, nathan,
nick.desaulniers+lkml, yangtiezhu, jiaxun.yang, liukexin,
guodongtai, xry111, wangyuli, loongarch, live-patching, llvm,
linux-kernel
From: George Guo <guodongtai@kylinos.cn>
objtool needs to split the kernel's special sections into per-entry
symbols when generating livepatch modules. Mark them so it can:
- .altinstructions and __ex_table are read-only, so set an explicit
entry size via SHF_MERGE (ALT_INSTR_SIZE / EXTABLE_SIZE).
- __bug_table and __jump_table are writable. SHF_MERGE cannot be
combined with SHF_WRITE (Clang rejects it), so annotate each entry
with ANNOTATE_DATA_SPECIAL instead, mirroring x86/arm64.
Co-developed-by: Kexin Liu <liukexin@kylinos.cn>
Signed-off-by: Kexin Liu <liukexin@kylinos.cn>
Signed-off-by: George Guo <guodongtai@kylinos.cn>
---
arch/loongarch/include/asm/alternative-asm.h | 5 +++--
arch/loongarch/include/asm/alternative.h | 6 ++++--
arch/loongarch/include/asm/asm-extable.h | 10 ++++++++--
arch/loongarch/include/asm/bug.h | 1 +
arch/loongarch/include/asm/jump_label.h | 2 ++
arch/loongarch/kernel/asm-offsets.c | 20 ++++++++++++++++++++
6 files changed, 38 insertions(+), 6 deletions(-)
diff --git a/arch/loongarch/include/asm/alternative-asm.h b/arch/loongarch/include/asm/alternative-asm.h
index 7dc29bd9b2f0..d940d9d2c0e1 100644
--- a/arch/loongarch/include/asm/alternative-asm.h
+++ b/arch/loongarch/include/asm/alternative-asm.h
@@ -5,6 +5,7 @@
#ifdef __ASSEMBLER__
#include <asm/asm.h>
+#include <generated/asm-offsets.h>
/*
* Issue one struct alt_instr descriptor entry (need to put it into
@@ -33,7 +34,7 @@
.fill - (((144f-143f)-(141b-140b)) > 0) * ((144f-143f)-(141b-140b)) / 4, 4, 0x03400000
142 :
- .pushsection .altinstructions, "a"
+ .pushsection .altinstructions, "aM", @progbits, ALT_INSTR_SIZE
altinstruction_entry 140b, 143f, \feature, 142b-140b, 144f-143f
.popsection
@@ -63,7 +64,7 @@
(alt_max_short(new_len1, new_len2) - (old_len)) / 4, 4, 0x03400000
142 :
- .pushsection .altinstructions, "a"
+ .pushsection .altinstructions, "aM", @progbits, ALT_INSTR_SIZE
altinstruction_entry 140b, 143f, \feature1, 142b-140b, 144f-143f, 142b-141b
altinstruction_entry 140b, 144f, \feature2, 142b-140b, 145f-144f, 142b-141b
.popsection
diff --git a/arch/loongarch/include/asm/alternative.h b/arch/loongarch/include/asm/alternative.h
index b5bae21fb3c8..8f7712ed2f4e 100644
--- a/arch/loongarch/include/asm/alternative.h
+++ b/arch/loongarch/include/asm/alternative.h
@@ -70,7 +70,8 @@ extern void apply_alternatives(struct alt_instr *start, struct alt_instr *end);
/* alternative assembly primitive: */
#define ALTERNATIVE(oldinstr, newinstr, feature) \
OLDINSTR(oldinstr, 1) \
- ".pushsection .altinstructions,\"a\"\n" \
+ ".pushsection .altinstructions, \"aM\", @progbits, " \
+ __stringify(ALT_INSTR_SIZE) "\n" \
ALTINSTR_ENTRY(feature, 1) \
".popsection\n" \
".subsection 1\n" \
@@ -79,7 +80,8 @@ extern void apply_alternatives(struct alt_instr *start, struct alt_instr *end);
#define ALTERNATIVE_2(oldinstr, newinstr1, feature1, newinstr2, feature2)\
OLDINSTR_2(oldinstr, 1, 2) \
- ".pushsection .altinstructions,\"a\"\n" \
+ ".pushsection .altinstructions, \"aM\", @progbits, " \
+ __stringify(ALT_INSTR_SIZE) "\n" \
ALTINSTR_ENTRY(feature1, 1) \
ALTINSTR_ENTRY(feature2, 2) \
".popsection\n" \
diff --git a/arch/loongarch/include/asm/asm-extable.h b/arch/loongarch/include/asm/asm-extable.h
index d60bdf2e6377..2d7eef7c0b39 100644
--- a/arch/loongarch/include/asm/asm-extable.h
+++ b/arch/loongarch/include/asm/asm-extable.h
@@ -7,10 +7,15 @@
#define EX_TYPE_UACCESS_ERR_ZERO 2
#define EX_TYPE_BPF 3
+#ifndef COMPILE_OFFSETS
+#include <asm/asm-offsets.h>
+#endif
+
#ifdef __ASSEMBLER__
#define __ASM_EXTABLE_RAW(insn, fixup, type, data) \
- .pushsection __ex_table, "a"; \
+ .pushsection __ex_table, "aM", @progbits, \
+ EXTABLE_SIZE; \
.balign 4; \
.long ((insn) - .); \
.long ((fixup) - .); \
@@ -29,7 +34,8 @@
#include <asm/gpr-num.h>
#define __ASM_EXTABLE_RAW(insn, fixup, type, data) \
- ".pushsection __ex_table, \"a\"\n" \
+ ".pushsection __ex_table, \"aM\", @progbits, "\
+ __stringify(EXTABLE_SIZE) "\n" \
".balign 4\n" \
".long ((" insn ") - .)\n" \
".long ((" fixup ") - .)\n" \
diff --git a/arch/loongarch/include/asm/bug.h b/arch/loongarch/include/asm/bug.h
index d090a5bec5eb..14e3acbaad8d 100644
--- a/arch/loongarch/include/asm/bug.h
+++ b/arch/loongarch/include/asm/bug.h
@@ -25,6 +25,7 @@
#define __BUG_ENTRY(cond_str, flags) \
.pushsection __bug_table, "aw"; \
.align 2; \
+ __ANNOTATE_DATA_SPECIAL; \
10000: .long 10001f - .; \
_BUGVERBOSE_LOCATION(WARN_CONDITION_STR(cond_str) __FILE__, __LINE__) \
.short flags; \
diff --git a/arch/loongarch/include/asm/jump_label.h b/arch/loongarch/include/asm/jump_label.h
index 7ef4ae3abf08..d20f0fa24b6b 100644
--- a/arch/loongarch/include/asm/jump_label.h
+++ b/arch/loongarch/include/asm/jump_label.h
@@ -12,6 +12,7 @@
#include <linux/types.h>
#include <linux/stringify.h>
#include <asm/asm.h>
+#include <linux/objtool.h>
#define HAVE_JUMP_LABEL_BATCH
@@ -27,6 +28,7 @@
#define JUMP_TABLE_ENTRY(key, label) \
".pushsection __jump_table, \"aw\" \n\t" \
".align " __stringify(PTRLOG) " \n\t" \
+ ANNOTATE_DATA_SPECIAL "\n\t" \
".long 1b - ., " label " - . \n\t" \
JUMP_LABEL_TYPE key " - . \n\t" \
".popsection \n\t"
diff --git a/arch/loongarch/kernel/asm-offsets.c b/arch/loongarch/kernel/asm-offsets.c
index 2cc953f113ac..470323aa022c 100644
--- a/arch/loongarch/kernel/asm-offsets.c
+++ b/arch/loongarch/kernel/asm-offsets.c
@@ -18,6 +18,8 @@
#include <asm/ftrace.h>
#include <asm/sigframe.h>
#include <vdso/datapage.h>
+#include <asm/alternative.h>
+#include <asm/extable.h>
static void __used output_ptreg_defines(void)
{
@@ -323,3 +325,21 @@ static void __used output_vdso_defines(void)
DEFINE(__VDSO_PAGES, VDSO_NR_PAGES);
BLANK();
}
+
+static void __used output_extable_defines(void)
+{
+ COMMENT("LoongArch exception table entry offsets.");
+
+ DEFINE(EXTABLE_SIZE, sizeof(struct exception_table_entry));
+ BLANK();
+}
+
+static void __used output_alt_instr_defines(void)
+{
+ COMMENT("LoongArch alternative instructions offsets.");
+
+ DEFINE(ALT_INSTR_SIZE, sizeof(struct alt_instr));
+ BLANK();
+}
+
+
--
2.25.1
^ permalink raw reply related [flat|nested] 18+ messages in thread* [PATCH v3 03/12] livepatch/klp-build: disable direct-extern-access for LoongArch to fix kernel panic
2026-07-07 7:20 [PATCH v3 00/12] LoongArch: Add livepatch build (KLP) support George Guo
2026-07-07 7:20 ` [PATCH v3 01/12] objtool/LoongArch: Add arch_adjusted_addend() for KLP support George Guo
2026-07-07 7:20 ` [PATCH v3 02/12] LoongArch: Mark special sections " George Guo
@ 2026-07-07 7:20 ` George Guo
2026-07-07 7:20 ` [PATCH v3 04/12] livepatch/klp-build: build LoongArch with -fPIC to keep GOT-indirect symbol references George Guo
` (8 subsequent siblings)
11 siblings, 0 replies; 18+ messages in thread
From: George Guo @ 2026-07-07 7:20 UTC (permalink / raw)
To: chenhuacai, jpoimboe, peterz, jikos, mbenes, pmladek
Cc: kernel, joe.lawrence, rostedt, ardb, nathan,
nick.desaulniers+lkml, yangtiezhu, jiaxun.yang, liukexin,
guodongtai, xry111, wangyuli, loongarch, live-patching, llvm,
linux-kernel
From: George Guo <guodongtai@kylinos.cn>
On LoongArch systems, livepatch modules containing references to
EXTERNAL global variables trigger kernel panics when the core kernel is
built with the -mdirect-extern-access optimization.
Root cause:
The -mdirect-extern-access optimization replaces GOT-based external
symbol access with direct addressing for improved performance. However,
this breaks the kernel module loading mechanism, which relies on GOT
entries for proper relocation of EXTERNAL symbol references. Direct
access to global variables from livepatch modules causes invalid memory
accesses and kernel panics.
Solution:
For LoongArch klp builds, conditionally disable direct-extern-access by
adding:
- -mno-direct-extern-access for GCC builds
- -fno-direct-access-external-data for Clang builds
See also commit 38b10b269d04 ("LoongArch: Tweak CFLAGS for Clang
compatibility"), which added -mdirect-extern-access to the kernel as a
nice-to-have optimization that reduces GOT accesses.
Note this is passed as a command-line KBUILD_CFLAGS_KERNEL= assignment,
which replaces arch/loongarch/Makefile's KBUILD_CFLAGS_KERNEL wholesale
rather than appending to it. As a side effect it also drops the -fPIE
that the arch adds under CONFIG_RELOCATABLE. That is intentional and
relied upon by the next patch ("LoongArch: ... -fPIC ..."), which adds
-fPIC via KCFLAGS: kbuild applies KBUILD_CFLAGS_KERNEL after KCFLAGS for
built-in objects (see modkern_cflags in scripts/Makefile.lib), so a
retained -fPIE would otherwise win over that -fPIC. The two patches must
stay together.
Co-developed-by: Kexin Liu <liukexin@kylinos.cn>
Signed-off-by: Kexin Liu <liukexin@kylinos.cn>
Signed-off-by: George Guo <guodongtai@kylinos.cn>
---
scripts/livepatch/klp-build | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)
diff --git a/scripts/livepatch/klp-build b/scripts/livepatch/klp-build
index e83973567c87..27fe8824ef12 100755
--- a/scripts/livepatch/klp-build
+++ b/scripts/livepatch/klp-build
@@ -556,6 +556,24 @@ build_kernel() {
local log="$TMP_DIR/build.log"
local cmd=()
+ local ARCH_KBUILD_CFLAGS_KERNEL=""
+
+ if [[ -v CONFIG_LOONGARCH && "$CONFIG_LOONGARCH" == "y" ]]; then
+ # -mdirect-extern-access only exists under explicit relocs, and this
+ # function replaces KBUILD_CFLAGS_KERNEL wholesale (safe only then;
+ # the non-explicit build puts -Wa,-mla-global-with-pcrel there).
+ [[ "${CONFIG_AS_HAS_EXPLICIT_RELOCS:-}" == "y" ]] || \
+ die "LoongArch klp-build requires CONFIG_AS_HAS_EXPLICIT_RELOCS=y"
+
+ if [[ "${CONFIG_CC_IS_CLANG:-}" == "y" ]]; then
+ ARCH_KBUILD_CFLAGS_KERNEL="-fno-direct-access-external-data"
+ else
+ ARCH_KBUILD_CFLAGS_KERNEL="-mno-direct-extern-access"
+ fi
+
+ status "LoongArch detected: adding $ARCH_KBUILD_CFLAGS_KERNEL to KBUILD_CFLAGS_KERNEL"
+ fi
+
cmd=("make")
# When a patch to a kernel module references a newly created unexported
@@ -582,6 +600,7 @@ build_kernel() {
fi
cmd+=("-j$JOBS")
cmd+=("KCFLAGS=-ffunction-sections -fdata-sections")
+ cmd+=("KBUILD_CFLAGS_KERNEL=$ARCH_KBUILD_CFLAGS_KERNEL")
cmd+=("vmlinux")
cmd+=("modules")
--
2.25.1
^ permalink raw reply related [flat|nested] 18+ messages in thread* [PATCH v3 04/12] livepatch/klp-build: build LoongArch with -fPIC to keep GOT-indirect symbol references
2026-07-07 7:20 [PATCH v3 00/12] LoongArch: Add livepatch build (KLP) support George Guo
` (2 preceding siblings ...)
2026-07-07 7:20 ` [PATCH v3 03/12] livepatch/klp-build: disable direct-extern-access for LoongArch to fix kernel panic George Guo
@ 2026-07-07 7:20 ` George Guo
2026-07-08 15:05 ` Joe Lawrence
2026-07-07 7:20 ` [PATCH v3 05/12] LoongArch: Fix EFI linking with -fdata-sections George Guo
` (7 subsequent siblings)
11 siblings, 1 reply; 18+ messages in thread
From: George Guo @ 2026-07-07 7:20 UTC (permalink / raw)
To: chenhuacai, jpoimboe, peterz, jikos, mbenes, pmladek
Cc: kernel, joe.lawrence, rostedt, ardb, nathan,
nick.desaulniers+lkml, yangtiezhu, jiaxun.yang, liukexin,
guodongtai, xry111, wangyuli, loongarch, live-patching, llvm,
linux-kernel
From: George Guo <guodongtai@kylinos.cn>
On LoongArch, klp-build livepatch modules panic when a patched function
references a global defined in the same compilation unit (e.g.
SYSCALL_DEFINE1(newuname) -> 'uts_sem' in kernel/sys.c).
With CONFIG_RELOCATABLE=y the kernel is already -fPIE, so this is not
absolute addressing; the problem is GOT indirection. For a same-unit
global, -fPIE emits a direct PC-relative reference (R_LARCH_PCALA_*) and
skips the GOT, while -fPIC routes it through the GOT (R_LARCH_GOT_PC_*).
klp-build extracts the patched function into a separate module while
'uts_sem' stays in the core kernel, and the klp relocation machinery can
only redirect such a cross-object reference through a GOT entry. The
direct -fPIE reference has no GOT slot to fix up, so once the function is
relocated its target is wrong and it faults.
Force -fPIC for LoongArch KLP builds; -fPIE is not enough, as it
optimizes away the very GOT indirection KLP relies on.
This depends on the preceding patch: -fPIC is passed via KCFLAGS, but the
arch adds -fPIE via KBUILD_CFLAGS_KERNEL, which kbuild applies after
KCFLAGS (so -fPIE would win). That patch's command-line
KBUILD_CFLAGS_KERNEL= assignment replaces the arch value and drops -fPIE,
letting -fPIC take effect. The two patches must stay together.
Co-developed-by: Kexin Liu <liukexin@kylinos.cn>
Signed-off-by: Kexin Liu <liukexin@kylinos.cn>
Signed-off-by: George Guo <guodongtai@kylinos.cn>
---
scripts/livepatch/klp-build | 19 +++++++++++++++++--
1 file changed, 17 insertions(+), 2 deletions(-)
diff --git a/scripts/livepatch/klp-build b/scripts/livepatch/klp-build
index 27fe8824ef12..42cd58aff3d8 100755
--- a/scripts/livepatch/klp-build
+++ b/scripts/livepatch/klp-build
@@ -557,8 +557,15 @@ build_kernel() {
local cmd=()
local ARCH_KBUILD_CFLAGS_KERNEL=""
+ local ARCH_KCFLAGS=""
if [[ -v CONFIG_LOONGARCH && "$CONFIG_LOONGARCH" == "y" ]]; then
+ # -fPIC replaces the kernel's -fPIE (added under CONFIG_RELOCATABLE);
+ # without that config there is no -fPIE to replace.
+ [[ "${CONFIG_RELOCATABLE:-}" == "y" ]] || \
+ die "LoongArch klp-build requires CONFIG_RELOCATABLE=y"
+ ARCH_KCFLAGS="-fPIC"
+
# -mdirect-extern-access only exists under explicit relocs, and this
# function replaces KBUILD_CFLAGS_KERNEL wholesale (safe only then;
# the non-explicit build puts -Wa,-mla-global-with-pcrel there).
@@ -599,8 +606,16 @@ build_kernel() {
cmd+=("-s")
fi
cmd+=("-j$JOBS")
- cmd+=("KCFLAGS=-ffunction-sections -fdata-sections")
- cmd+=("KBUILD_CFLAGS_KERNEL=$ARCH_KBUILD_CFLAGS_KERNEL")
+ cmd+=("KCFLAGS=-ffunction-sections -fdata-sections${ARCH_KCFLAGS:+ $ARCH_KCFLAGS}")
+ # -fPIC is added for KLP via KCFLAGS above; the arch adds -fPIE via
+ # KBUILD_CFLAGS_KERNEL, which kbuild places after KCFLAGS on the
+ # built-in compile line. -fPIC/-fPIE is last-one-wins, so -fPIE would
+ # win. Setting KBUILD_CFLAGS_KERNEL on the command line replaces the
+ # arch value (not append), which drops -fPIE and lets -fPIC win. Only
+ # do this when an arch needs it (LoongArch).
+ if [[ -n "$ARCH_KBUILD_CFLAGS_KERNEL" ]]; then
+ cmd+=("KBUILD_CFLAGS_KERNEL=$ARCH_KBUILD_CFLAGS_KERNEL")
+ fi
cmd+=("vmlinux")
cmd+=("modules")
--
2.25.1
^ permalink raw reply related [flat|nested] 18+ messages in thread* Re: [PATCH v3 04/12] livepatch/klp-build: build LoongArch with -fPIC to keep GOT-indirect symbol references
2026-07-07 7:20 ` [PATCH v3 04/12] livepatch/klp-build: build LoongArch with -fPIC to keep GOT-indirect symbol references George Guo
@ 2026-07-08 15:05 ` Joe Lawrence
0 siblings, 0 replies; 18+ messages in thread
From: Joe Lawrence @ 2026-07-08 15:05 UTC (permalink / raw)
To: George Guo
Cc: chenhuacai, jpoimboe, peterz, jikos, mbenes, pmladek, kernel,
rostedt, ardb, nathan, nick.desaulniers+lkml, yangtiezhu,
jiaxun.yang, liukexin, guodongtai, xry111, wangyuli, loongarch,
live-patching, llvm, linux-kernel
On Tue, Jul 07, 2026 at 03:20:23PM +0800, George Guo wrote:
> From: George Guo <guodongtai@kylinos.cn>
>
> On LoongArch, klp-build livepatch modules panic when a patched function
> references a global defined in the same compilation unit (e.g.
> SYSCALL_DEFINE1(newuname) -> 'uts_sem' in kernel/sys.c).
>
> With CONFIG_RELOCATABLE=y the kernel is already -fPIE, so this is not
> absolute addressing; the problem is GOT indirection. For a same-unit
> global, -fPIE emits a direct PC-relative reference (R_LARCH_PCALA_*) and
> skips the GOT, while -fPIC routes it through the GOT (R_LARCH_GOT_PC_*).
> klp-build extracts the patched function into a separate module while
> 'uts_sem' stays in the core kernel, and the klp relocation machinery can
> only redirect such a cross-object reference through a GOT entry. The
> direct -fPIE reference has no GOT slot to fix up, so once the function is
> relocated its target is wrong and it faults.
>
> Force -fPIC for LoongArch KLP builds; -fPIE is not enough, as it
> optimizes away the very GOT indirection KLP relies on.
>
> This depends on the preceding patch: -fPIC is passed via KCFLAGS, but the
> arch adds -fPIE via KBUILD_CFLAGS_KERNEL, which kbuild applies after
> KCFLAGS (so -fPIE would win). That patch's command-line
> KBUILD_CFLAGS_KERNEL= assignment replaces the arch value and drops -fPIE,
> letting -fPIC take effect. The two patches must stay together.
>
This might be my personal preference, but I think it would be quicker to
review patches: ("livepatch/klp-build: disable direct-extern-access for
LoongArch to fix kernel panic") ("livepatch/klp-build: build LoongArch
with -fPIC to keep GOT-indirect symbol references") if they were
squashed into one patch.
With that, the commit messages can drop the forward/backward references,
while the combined commit remains complete thought, i.e. for LoongArch
KLP builds, replace the arch's KBUILD_CFLAGS_KERNEL (dropping -fPIE and
-mdirect-extern-access) and add -fPIC via KCFLAGS instead.
> Co-developed-by: Kexin Liu <liukexin@kylinos.cn>
> Signed-off-by: Kexin Liu <liukexin@kylinos.cn>
> Signed-off-by: George Guo <guodongtai@kylinos.cn>
> ---
> scripts/livepatch/klp-build | 19 +++++++++++++++++--
> 1 file changed, 17 insertions(+), 2 deletions(-)
>
> diff --git a/scripts/livepatch/klp-build b/scripts/livepatch/klp-build
> index 27fe8824ef12..42cd58aff3d8 100755
> --- a/scripts/livepatch/klp-build
> +++ b/scripts/livepatch/klp-build
> @@ -557,8 +557,15 @@ build_kernel() {
> local cmd=()
>
> local ARCH_KBUILD_CFLAGS_KERNEL=""
> + local ARCH_KCFLAGS=""
>
> if [[ -v CONFIG_LOONGARCH && "$CONFIG_LOONGARCH" == "y" ]]; then
> + # -fPIC replaces the kernel's -fPIE (added under CONFIG_RELOCATABLE);
> + # without that config there is no -fPIE to replace.
> + [[ "${CONFIG_RELOCATABLE:-}" == "y" ]] || \
> + die "LoongArch klp-build requires CONFIG_RELOCATABLE=y"
> + ARCH_KCFLAGS="-fPIC"
> +
> # -mdirect-extern-access only exists under explicit relocs, and this
> # function replaces KBUILD_CFLAGS_KERNEL wholesale (safe only then;
> # the non-explicit build puts -Wa,-mla-global-with-pcrel there).
> @@ -599,8 +606,16 @@ build_kernel() {
> cmd+=("-s")
> fi
> cmd+=("-j$JOBS")
> - cmd+=("KCFLAGS=-ffunction-sections -fdata-sections")
> - cmd+=("KBUILD_CFLAGS_KERNEL=$ARCH_KBUILD_CFLAGS_KERNEL")
> + cmd+=("KCFLAGS=-ffunction-sections -fdata-sections${ARCH_KCFLAGS:+ $ARCH_KCFLAGS}")
> + # -fPIC is added for KLP via KCFLAGS above; the arch adds -fPIE via
> + # KBUILD_CFLAGS_KERNEL, which kbuild places after KCFLAGS on the
> + # built-in compile line. -fPIC/-fPIE is last-one-wins, so -fPIE would
> + # win. Setting KBUILD_CFLAGS_KERNEL on the command line replaces the
> + # arch value (not append), which drops -fPIE and lets -fPIC win. Only
> + # do this when an arch needs it (LoongArch).
> + if [[ -n "$ARCH_KBUILD_CFLAGS_KERNEL" ]]; then
> + cmd+=("KBUILD_CFLAGS_KERNEL=$ARCH_KBUILD_CFLAGS_KERNEL")
> + fi
> cmd+=("vmlinux")
> cmd+=("modules")
>
I'd also pull out the configuration checks into validate_config() to be
consistent:
if [[ -v CONFIG_LOONGARCH ]]; then
[[ -v CONFIG_AS_HAS_EXPLICIT_RELOCS ]] || \
die "LoongArch klp-build requires CONFIG_AS_HAS_EXPLICIT_RELOCS=y"
[[ -v CONFIG_RELOCATABLE ]] || \
die "LoongArch klp-build requires CONFIG_RELOCATABLE=y"
fi
and then build_kernel() only needs to adjust the cmd / flags accordingly.
--
Joe
^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH v3 05/12] LoongArch: Fix EFI linking with -fdata-sections
2026-07-07 7:20 [PATCH v3 00/12] LoongArch: Add livepatch build (KLP) support George Guo
` (3 preceding siblings ...)
2026-07-07 7:20 ` [PATCH v3 04/12] livepatch/klp-build: build LoongArch with -fPIC to keep GOT-indirect symbol references George Guo
@ 2026-07-07 7:20 ` George Guo
2026-07-08 13:54 ` Joe Lawrence
2026-07-07 7:20 ` [PATCH v3 06/12] objtool/klp: Add LoongArch jump opcode bytes support George Guo
` (6 subsequent siblings)
11 siblings, 1 reply; 18+ messages in thread
From: George Guo @ 2026-07-07 7:20 UTC (permalink / raw)
To: chenhuacai, jpoimboe, peterz, jikos, mbenes, pmladek
Cc: kernel, joe.lawrence, rostedt, ardb, nathan,
nick.desaulniers+lkml, yangtiezhu, jiaxun.yang, liukexin,
guodongtai, xry111, wangyuli, loongarch, live-patching, llvm,
linux-kernel
From: George Guo <guodongtai@kylinos.cn>
When building with func-fdata-sections, the .init.bss section gets split
up into a bunch of .init.bss.<var> sections. Make sure they get linked
into .init.data.
Co-developed-by: Kexin Liu <liukexin@kylinos.cn>
Signed-off-by: Kexin Liu <liukexin@kylinos.cn>
Signed-off-by: George Guo <guodongtai@kylinos.cn>
---
arch/loongarch/kernel/vmlinux.lds.S | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/loongarch/kernel/vmlinux.lds.S b/arch/loongarch/kernel/vmlinux.lds.S
index 840d944c2f73..dc5fa017db94 100644
--- a/arch/loongarch/kernel/vmlinux.lds.S
+++ b/arch/loongarch/kernel/vmlinux.lds.S
@@ -96,7 +96,7 @@ SECTIONS
#endif
.init.bss : {
- *(.init.bss)
+ *(.init.bss .init.bss.*)
}
. = ALIGN(PECOFF_SEGMENT_ALIGN);
__initdata_end = .;
--
2.25.1
^ permalink raw reply related [flat|nested] 18+ messages in thread* Re: [PATCH v3 05/12] LoongArch: Fix EFI linking with -fdata-sections
2026-07-07 7:20 ` [PATCH v3 05/12] LoongArch: Fix EFI linking with -fdata-sections George Guo
@ 2026-07-08 13:54 ` Joe Lawrence
2026-07-08 16:07 ` Joe Lawrence
0 siblings, 1 reply; 18+ messages in thread
From: Joe Lawrence @ 2026-07-08 13:54 UTC (permalink / raw)
To: George Guo
Cc: chenhuacai, jpoimboe, peterz, jikos, mbenes, pmladek, kernel,
rostedt, ardb, nathan, nick.desaulniers+lkml, yangtiezhu,
jiaxun.yang, liukexin, guodongtai, xry111, wangyuli, loongarch,
live-patching, llvm, linux-kernel
On Tue, Jul 07, 2026 at 03:20:24PM +0800, George Guo wrote:
> From: George Guo <guodongtai@kylinos.cn>
>
> When building with func-fdata-sections, the .init.bss section gets split
nit: s/func-fdata-sections/-fdata-sections
> up into a bunch of .init.bss.<var> sections. Make sure they get linked
> into .init.data.
>
> Co-developed-by: Kexin Liu <liukexin@kylinos.cn>
> Signed-off-by: Kexin Liu <liukexin@kylinos.cn>
> Signed-off-by: George Guo <guodongtai@kylinos.cn>
> ---
> arch/loongarch/kernel/vmlinux.lds.S | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/arch/loongarch/kernel/vmlinux.lds.S b/arch/loongarch/kernel/vmlinux.lds.S
> index 840d944c2f73..dc5fa017db94 100644
> --- a/arch/loongarch/kernel/vmlinux.lds.S
> +++ b/arch/loongarch/kernel/vmlinux.lds.S
> @@ -96,7 +96,7 @@ SECTIONS
> #endif
>
> .init.bss : {
> - *(.init.bss)
> + *(.init.bss .init.bss.*)
Both arch/arm64/kernel/vmlinux.lds.S and
arch/loongarch/kernel/vmlinux.lds.S contain a "/* from the EFI stub */"
comment documenting the wildcard. Might be worth adding for v4.
--
Joe
^ permalink raw reply [flat|nested] 18+ messages in thread* Re: [PATCH v3 05/12] LoongArch: Fix EFI linking with -fdata-sections
2026-07-08 13:54 ` Joe Lawrence
@ 2026-07-08 16:07 ` Joe Lawrence
0 siblings, 0 replies; 18+ messages in thread
From: Joe Lawrence @ 2026-07-08 16:07 UTC (permalink / raw)
To: George Guo
Cc: chenhuacai, jpoimboe, peterz, jikos, mbenes, pmladek, kernel,
rostedt, ardb, nathan, nick.desaulniers+lkml, yangtiezhu,
jiaxun.yang, liukexin, guodongtai, xry111, wangyuli, loongarch,
live-patching, llvm, linux-kernel
On Wed, Jul 08, 2026 at 09:54:16AM -0400, Joe Lawrence wrote:
> On Tue, Jul 07, 2026 at 03:20:24PM +0800, George Guo wrote:
> > From: George Guo <guodongtai@kylinos.cn>
> >
> > When building with func-fdata-sections, the .init.bss section gets split
>
> nit: s/func-fdata-sections/-fdata-sections
>
> > up into a bunch of .init.bss.<var> sections. Make sure they get linked
> > into .init.data.
> >
> > Co-developed-by: Kexin Liu <liukexin@kylinos.cn>
> > Signed-off-by: Kexin Liu <liukexin@kylinos.cn>
> > Signed-off-by: George Guo <guodongtai@kylinos.cn>
> > ---
> > arch/loongarch/kernel/vmlinux.lds.S | 2 +-
> > 1 file changed, 1 insertion(+), 1 deletion(-)
> >
> > diff --git a/arch/loongarch/kernel/vmlinux.lds.S b/arch/loongarch/kernel/vmlinux.lds.S
> > index 840d944c2f73..dc5fa017db94 100644
> > --- a/arch/loongarch/kernel/vmlinux.lds.S
> > +++ b/arch/loongarch/kernel/vmlinux.lds.S
> > @@ -96,7 +96,7 @@ SECTIONS
> > #endif
> >
> > .init.bss : {
> > - *(.init.bss)
> > + *(.init.bss .init.bss.*)
>
> Both arch/arm64/kernel/vmlinux.lds.S and
> arch/loongarch/kernel/vmlinux.lds.S contain a "/* from the EFI stub */"
^^ typo: I meant the riscv version as well
Also the commit message says, "Make sure they get linked into
.init.data," but should that read, "... into .init.bss"?
--
Joe
^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH v3 06/12] objtool/klp: Add LoongArch jump opcode bytes support
2026-07-07 7:20 [PATCH v3 00/12] LoongArch: Add livepatch build (KLP) support George Guo
` (4 preceding siblings ...)
2026-07-07 7:20 ` [PATCH v3 05/12] LoongArch: Fix EFI linking with -fdata-sections George Guo
@ 2026-07-07 7:20 ` George Guo
2026-07-07 7:20 ` [PATCH v3 07/12] klp-build: Add LoongArch syscall patching macro George Guo
` (5 subsequent siblings)
11 siblings, 0 replies; 18+ messages in thread
From: George Guo @ 2026-07-07 7:20 UTC (permalink / raw)
To: chenhuacai, jpoimboe, peterz, jikos, mbenes, pmladek
Cc: kernel, joe.lawrence, rostedt, ardb, nathan,
nick.desaulniers+lkml, yangtiezhu, jiaxun.yang, liukexin,
guodongtai, xry111, wangyuli, loongarch, live-patching, llvm,
linux-kernel
From: George Guo <guodongtai@kylinos.cn>
Implement arch_jump_opcode_bytes() for LoongArch so that klp checksums
for jump/call instructions with non-relocated destination offsets are
position-independent, mirroring the x86 and arm64 implementations.
Mask out the embedded branch offset while preserving the opcode and the
register operands, which differ per instruction format:
- B/BL (reg0i26): no regs -> 0xfc000000
- BEQZ/BNEZ/BCEQZ/BCNEZ (reg1i21): keep rj/cj -> 0xfc0003e0
- JIRL/BEQ/BNE/.../BGEU (reg2i16): keep rj/rd -> 0xfc0003ff
Co-developed-by: Kexin Liu <liukexin@kylinos.cn>
Signed-off-by: Kexin Liu <liukexin@kylinos.cn>
Signed-off-by: George Guo <guodongtai@kylinos.cn>
---
tools/objtool/arch/loongarch/decode.c | 41 +++++++++++++++++++++++++++
1 file changed, 41 insertions(+)
diff --git a/tools/objtool/arch/loongarch/decode.c b/tools/objtool/arch/loongarch/decode.c
index 674e4efd138f..12facd0cc8d1 100644
--- a/tools/objtool/arch/loongarch/decode.c
+++ b/tools/objtool/arch/loongarch/decode.c
@@ -432,6 +432,47 @@ unsigned long arch_jump_table_sym_offset(struct reloc *reloc, struct reloc *tabl
}
}
+size_t arch_jump_opcode_bytes(struct objtool_file *file, struct instruction *insn,
+ unsigned char *buf)
+{
+ union loongarch_instruction *code;
+ u32 insn_word;
+
+ insn_word = le32toh(*(u32 *)(insn->sec->data->d_buf + insn->offset));
+ code = (union loongarch_instruction *)&insn_word;
+
+ switch (code->reg0i26_format.opcode) {
+ case b_op:
+ case bl_op:
+ /* reg0i26: 26-bit offset, no register operands */
+ insn_word &= 0xfc000000;
+ break;
+ case beqz_op:
+ case bnez_op:
+ case bceqz_op: /* == bcnez_op */
+ /* reg1i21: keep opcode + rj/cj at bits[9:5] */
+ insn_word &= 0xfc0003e0;
+ break;
+ case jirl_op:
+ case beq_op:
+ case bne_op:
+ case blt_op:
+ case bge_op:
+ case bltu_op:
+ case bgeu_op:
+ /* reg2i16: keep opcode + rj/rd at bits[9:0] */
+ insn_word &= 0xfc0003ff;
+ break;
+ default:
+ break;
+ }
+
+ insn_word = htole32(insn_word);
+ memcpy(buf, &insn_word, sizeof(insn_word));
+
+ return LOONGARCH_INSN_SIZE;
+}
+
#ifdef DISAS
int arch_disas_info_init(struct disassemble_info *dinfo)
--
2.25.1
^ permalink raw reply related [flat|nested] 18+ messages in thread* [PATCH v3 07/12] klp-build: Add LoongArch syscall patching macro
2026-07-07 7:20 [PATCH v3 00/12] LoongArch: Add livepatch build (KLP) support George Guo
` (5 preceding siblings ...)
2026-07-07 7:20 ` [PATCH v3 06/12] objtool/klp: Add LoongArch jump opcode bytes support George Guo
@ 2026-07-07 7:20 ` George Guo
2026-07-08 19:18 ` Joe Lawrence
2026-07-07 7:20 ` [PATCH v3 08/12] LoongArch: Add livepatch build (KLP) support George Guo
` (4 subsequent siblings)
11 siblings, 1 reply; 18+ messages in thread
From: George Guo @ 2026-07-07 7:20 UTC (permalink / raw)
To: chenhuacai, jpoimboe, peterz, jikos, mbenes, pmladek
Cc: kernel, joe.lawrence, rostedt, ardb, nathan,
nick.desaulniers+lkml, yangtiezhu, jiaxun.yang, liukexin,
guodongtai, xry111, wangyuli, loongarch, live-patching, llvm,
linux-kernel
From: George Guo <guodongtai@kylinos.cn>
Add LoongArch support for KLP_SYSCALL_DEFINEx(), mirroring the generic
__SYSCALL_DEFINEx() pattern from include/linux/syscalls.h.
Co-developed-by: Kexin Liu <liukexin@kylinos.cn>
Signed-off-by: Kexin Liu <liukexin@kylinos.cn>
Signed-off-by: George Guo <guodongtai@kylinos.cn>
---
include/linux/livepatch_helpers.h | 22 ++++++++++++++++++++++
1 file changed, 22 insertions(+)
diff --git a/include/linux/livepatch_helpers.h b/include/linux/livepatch_helpers.h
index 4b647b83865f..a8aad067177b 100644
--- a/include/linux/livepatch_helpers.h
+++ b/include/linux/livepatch_helpers.h
@@ -91,6 +91,28 @@
} \
static inline long __klp_do_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__))
+#elif defined(CONFIG_LOONGARCH)
+
+#define __KLP_SYSCALL_DEFINEx(x, name, ...) \
+ __diag_push(); \
+ __diag_ignore(GCC, 8, "-Wattribute-alias", \
+ "Type aliasing is used to sanitize syscall arguments");\
+ asmlinkage long sys##name(__MAP(x,__SC_DECL,__VA_ARGS__)) \
+ __attribute__((alias(__stringify(__se_sys##name)))); \
+ ALLOW_ERROR_INJECTION(sys##name, ERRNO); \
+ static inline long __klp_do_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__));\
+ asmlinkage long __se_sys##name(__MAP(x,__SC_LONG,__VA_ARGS__)); \
+ asmlinkage long __attribute__((optimize("-fno-optimize-sibling-calls")))\
+ __se_sys##name(__MAP(x,__SC_LONG,__VA_ARGS__)) \
+ { \
+ long ret = __klp_do_sys##name(__MAP(x,__SC_CAST,__VA_ARGS__));\
+ __MAP(x,__SC_TEST,__VA_ARGS__); \
+ __PROTECT(x, ret,__MAP(x,__SC_ARGS,__VA_ARGS__)); \
+ return ret; \
+ } \
+ __diag_pop(); \
+ static inline long __klp_do_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__))
+
#endif
#endif /* _LINUX_LIVEPATCH_HELPERS_H */
--
2.25.1
^ permalink raw reply related [flat|nested] 18+ messages in thread* Re: [PATCH v3 07/12] klp-build: Add LoongArch syscall patching macro
2026-07-07 7:20 ` [PATCH v3 07/12] klp-build: Add LoongArch syscall patching macro George Guo
@ 2026-07-08 19:18 ` Joe Lawrence
0 siblings, 0 replies; 18+ messages in thread
From: Joe Lawrence @ 2026-07-08 19:18 UTC (permalink / raw)
To: George Guo
Cc: chenhuacai, jpoimboe, peterz, jikos, mbenes, pmladek, kernel,
rostedt, ardb, nathan, nick.desaulniers+lkml, yangtiezhu,
jiaxun.yang, liukexin, guodongtai, xry111, wangyuli, loongarch,
live-patching, llvm, linux-kernel
On Tue, Jul 07, 2026 at 03:20:26PM +0800, George Guo wrote:
> From: George Guo <guodongtai@kylinos.cn>
>
> Add LoongArch support for KLP_SYSCALL_DEFINEx(), mirroring the generic
> __SYSCALL_DEFINEx() pattern from include/linux/syscalls.h.
>
> Co-developed-by: Kexin Liu <liukexin@kylinos.cn>
> Signed-off-by: Kexin Liu <liukexin@kylinos.cn>
> Signed-off-by: George Guo <guodongtai@kylinos.cn>
> ---
> include/linux/livepatch_helpers.h | 22 ++++++++++++++++++++++
> 1 file changed, 22 insertions(+)
>
> diff --git a/include/linux/livepatch_helpers.h b/include/linux/livepatch_helpers.h
> index 4b647b83865f..a8aad067177b 100644
> --- a/include/linux/livepatch_helpers.h
> +++ b/include/linux/livepatch_helpers.h
> @@ -91,6 +91,28 @@
> } \
> static inline long __klp_do_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__))
>
> +#elif defined(CONFIG_LOONGARCH)
> +
> +#define __KLP_SYSCALL_DEFINEx(x, name, ...) \
> + __diag_push(); \
> + __diag_ignore(GCC, 8, "-Wattribute-alias", \
> + "Type aliasing is used to sanitize syscall arguments");\
> + asmlinkage long sys##name(__MAP(x,__SC_DECL,__VA_ARGS__)) \
> + __attribute__((alias(__stringify(__se_sys##name)))); \
> + ALLOW_ERROR_INJECTION(sys##name, ERRNO); \
> + static inline long __klp_do_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__));\
> + asmlinkage long __se_sys##name(__MAP(x,__SC_LONG,__VA_ARGS__)); \
> + asmlinkage long __attribute__((optimize("-fno-optimize-sibling-calls")))\
> + __se_sys##name(__MAP(x,__SC_LONG,__VA_ARGS__)) \
> + { \
> + long ret = __klp_do_sys##name(__MAP(x,__SC_CAST,__VA_ARGS__));\
> + __MAP(x,__SC_TEST,__VA_ARGS__); \
> + __PROTECT(x, ret,__MAP(x,__SC_ARGS,__VA_ARGS__)); \
> + return ret; \
> + } \
> + __diag_pop(); \
> + static inline long __klp_do_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__))
> +
> #endif
Nit: The other macros in livepatch_helpers use tabs to pad out to the
line continuation '\'.
--
Joe
^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH v3 08/12] LoongArch: Add livepatch build (KLP) support
2026-07-07 7:20 [PATCH v3 00/12] LoongArch: Add livepatch build (KLP) support George Guo
` (6 preceding siblings ...)
2026-07-07 7:20 ` [PATCH v3 07/12] klp-build: Add LoongArch syscall patching macro George Guo
@ 2026-07-07 7:20 ` George Guo
2026-07-07 7:20 ` [PATCH v3 09/12] LoongArch: Select FTRACE_MCOUNT_USE_PATCHABLE_FUNCTION_ENTRY George Guo
` (3 subsequent siblings)
11 siblings, 0 replies; 18+ messages in thread
From: George Guo @ 2026-07-07 7:20 UTC (permalink / raw)
To: chenhuacai, jpoimboe, peterz, jikos, mbenes, pmladek
Cc: kernel, joe.lawrence, rostedt, ardb, nathan,
nick.desaulniers+lkml, yangtiezhu, jiaxun.yang, liukexin,
guodongtai, xry111, wangyuli, loongarch, live-patching, llvm,
linux-kernel
From: George Guo <guodongtai@kylinos.cn>
This allows automated livepatch module generation using objtool.
Co-developed-by: Kexin Liu <liukexin@kylinos.cn>
Signed-off-by: Kexin Liu <liukexin@kylinos.cn>
Signed-off-by: George Guo <guodongtai@kylinos.cn>
---
arch/loongarch/Kconfig | 1 +
tools/objtool/Makefile | 3 ++-
2 files changed, 3 insertions(+), 1 deletion(-)
diff --git a/arch/loongarch/Kconfig b/arch/loongarch/Kconfig
index 3b042dbb2c41..1dbf51ba9d6a 100644
--- a/arch/loongarch/Kconfig
+++ b/arch/loongarch/Kconfig
@@ -159,6 +159,7 @@ config LOONGARCH
select HAVE_IOREMAP_PROT
select HAVE_IRQ_EXIT_ON_IRQ_STACK
select HAVE_IRQ_TIME_ACCOUNTING
+ select HAVE_KLP_BUILD
select HAVE_KPROBES
select HAVE_KPROBES_ON_FTRACE
select HAVE_KRETPROBES
diff --git a/tools/objtool/Makefile b/tools/objtool/Makefile
index 94aabeee9736..83d645675ed9 100644
--- a/tools/objtool/Makefile
+++ b/tools/objtool/Makefile
@@ -8,7 +8,8 @@ ifeq ($(SRCARCH),x86)
endif
ifeq ($(SRCARCH),loongarch)
- BUILD_ORC := y
+ BUILD_ORC := y
+ ARCH_HAS_KLP := y
endif
ifeq ($(SRCARCH),arm64)
--
2.25.1
^ permalink raw reply related [flat|nested] 18+ messages in thread* [PATCH v3 09/12] LoongArch: Select FTRACE_MCOUNT_USE_PATCHABLE_FUNCTION_ENTRY
2026-07-07 7:20 [PATCH v3 00/12] LoongArch: Add livepatch build (KLP) support George Guo
` (7 preceding siblings ...)
2026-07-07 7:20 ` [PATCH v3 08/12] LoongArch: Add livepatch build (KLP) support George Guo
@ 2026-07-07 7:20 ` George Guo
2026-07-07 7:20 ` [PATCH v3 10/12] objtool/klp: Convert local label references in special sections George Guo
` (2 subsequent siblings)
11 siblings, 0 replies; 18+ messages in thread
From: George Guo @ 2026-07-07 7:20 UTC (permalink / raw)
To: chenhuacai, jpoimboe, peterz, jikos, mbenes, pmladek
Cc: kernel, joe.lawrence, rostedt, ardb, nathan,
nick.desaulniers+lkml, yangtiezhu, jiaxun.yang, liukexin,
guodongtai, xry111, wangyuli, loongarch, live-patching, llvm,
linux-kernel
From: George Guo <guodongtai@kylinos.cn>
arch/loongarch/Makefile uses -fpatchable-function-entry=2 when
CONFIG_DYNAMIC_FTRACE is set, but nothing selects
FTRACE_MCOUNT_USE_PATCHABLE_FUNCTION_ENTRY, so kbuild falls back to
FTRACE_MCOUNT_USE_RECORDMCOUNT and runs recordmcount on every object.
The pass is useless here: there are no _mcount calls to find, and the
real ftrace sites come from the __patchable_function_entries section
anyway.
It is not just wasted time. recordmcount needs a non-weak symbol in
each text section, to use as the base of the __mcount_loc relocations
it writes (see find_secsym_ndx()). GAS emits a section symbol for
every section, so GCC objects always have one. Clang's integrated
assembler drops unreferenced section symbols, so a clang object must
use the function's own symbol -- but find_secsym_ndx() skips weak
symbols. So with -ffunction-sections (which klp-build uses), a __weak
function like sched_clock is alone in its section with no usable
symbol, and recordmcount fails:
Cannot find symbol for section 5: .text.sched_clock.
kernel/sched/build_utility.o: failed
Select FTRACE_MCOUNT_USE_PATCHABLE_FUNCTION_ENTRY like arm64 and riscv
do, which disables the recordmcount pass altogether.
Reported-by: Joe Lawrence <joe.lawrence@redhat.com>
Suggested-by: Joe Lawrence <joe.lawrence@redhat.com>
Signed-off-by: George Guo <guodongtai@kylinos.cn>
---
arch/loongarch/Kconfig | 1 +
1 file changed, 1 insertion(+)
diff --git a/arch/loongarch/Kconfig b/arch/loongarch/Kconfig
index 1dbf51ba9d6a..a1549003c871 100644
--- a/arch/loongarch/Kconfig
+++ b/arch/loongarch/Kconfig
@@ -88,6 +88,7 @@ config LOONGARCH
select CPU_PM
select EDAC_SUPPORT
select EFI
+ select FTRACE_MCOUNT_USE_PATCHABLE_FUNCTION_ENTRY if DYNAMIC_FTRACE
select GENERIC_ATOMIC64 if 32BIT
select GENERIC_CLOCKEVENTS
select GENERIC_CMOS_UPDATE
--
2.25.1
^ permalink raw reply related [flat|nested] 18+ messages in thread* [PATCH v3 10/12] objtool/klp: Convert local label references in special sections
2026-07-07 7:20 [PATCH v3 00/12] LoongArch: Add livepatch build (KLP) support George Guo
` (8 preceding siblings ...)
2026-07-07 7:20 ` [PATCH v3 09/12] LoongArch: Select FTRACE_MCOUNT_USE_PATCHABLE_FUNCTION_ENTRY George Guo
@ 2026-07-07 7:20 ` George Guo
2026-07-07 7:20 ` [PATCH v3 11/12] objtool/klp: Fix ANNOTATE_DATA_SPECIAL parsing for local label references George Guo
2026-07-07 7:20 ` [PATCH v3 12/12] objtool/klp: Fold LoongArch paired ADD/SUB relocations into PCREL George Guo
11 siblings, 0 replies; 18+ messages in thread
From: George Guo @ 2026-07-07 7:20 UTC (permalink / raw)
To: chenhuacai, jpoimboe, peterz, jikos, mbenes, pmladek
Cc: kernel, joe.lawrence, rostedt, ardb, nathan,
nick.desaulniers+lkml, yangtiezhu, jiaxun.yang, liukexin,
guodongtai, xry111, wangyuli, loongarch, live-patching, llvm,
linux-kernel
From: George Guo <guodongtai@kylinos.cn>
GCC/GAS on LoongArch references special section entries (__ex_table,
__bug_table, __jump_table, .altinstructions) through local text labels
(.L*) instead of a section symbol plus offset. The assembler keeps the
label because of linker relaxation: a "section + constant offset"
reference would go stale when the linker deletes or shrinks
instructions, while a symbol reference can be recomputed after
relaxation.
convert_reloc_secsym_to_sym() only handles the section symbol form and
returns early for such label references. The label is never cloned
into the livepatch object, so should_keep_special_sym() cannot
correlate the entry with an included function and silently drops it: a
GCC-built livepatch module ends up missing the patched function's
__ex_table / __bug_table / __jump_table entries, with no error at
build or load time.
Redirect label references in text sections to the containing function
symbol, mirroring the section symbol case. A label with no containing
function symbol (e.g. hand-written asm in a plain .text section) can't
be correlated; skip it rather than failing, since such entries belong
to unchanged code and are dropped anyway.
Reported-by: Joe Lawrence <joe.lawrence@redhat.com>
Suggested-by: Joe Lawrence <joe.lawrence@redhat.com>
Signed-off-by: George Guo <guodongtai@kylinos.cn>
---
tools/objtool/klp-diff.c | 35 ++++++++++++++++++++++++++++++++++-
1 file changed, 34 insertions(+), 1 deletion(-)
diff --git a/tools/objtool/klp-diff.c b/tools/objtool/klp-diff.c
index b9624bd9439b..05fd70e24326 100644
--- a/tools/objtool/klp-diff.c
+++ b/tools/objtool/klp-diff.c
@@ -1423,8 +1423,41 @@ static int convert_reloc_secsym_to_sym(struct elf *elf, struct reloc *reloc)
if (!strcmp(reloc->sec->name, ".rela__patchable_function_entries"))
return convert_pfe_reloc(elf, reloc);
- if (!is_sec_sym(sym))
+ if (!is_sec_sym(sym)) {
+ /*
+ * Most toolchains reference special-section entries via the
+ * section symbol plus an offset. GCC/GAS on LoongArch instead
+ * references a local text label (.L*): LoongArch linker
+ * relaxation is the reason GAS keeps the label rather than
+ * reducing it to a section symbol reference. Such a label is
+ * never cloned into the livepatch object, so the entry would be
+ * silently dropped. Redirect the relocation to the containing
+ * function, mirroring the section-symbol case below.
+ */
+ if (is_local_label(sym) && is_text_sec(sec)) {
+ unsigned long offset = sym->offset + reloc_addend(reloc);
+
+ sym = find_symbol_containing_inclusive(sec, offset);
+ if (!sym) {
+ /*
+ * A local label with no containing function
+ * symbol (e.g. hand-written asm in a plain .text
+ * section). It can't be correlated to a function,
+ * so skip it rather than failing the build; such
+ * entries belong to unchanged code and are dropped
+ * anyway.
+ */
+ return 1;
+ }
+
+ reloc->sym = sym;
+ set_reloc_sym(elf, reloc, sym->idx);
+ set_reloc_addend(elf, reloc, offset - sym->offset);
+ return 0;
+ }
+
return 0;
+ }
sym = find_symbol_containing_inclusive(sec, arch_adjusted_addend(reloc));
if (!sym) {
--
2.25.1
^ permalink raw reply related [flat|nested] 18+ messages in thread* [PATCH v3 11/12] objtool/klp: Fix ANNOTATE_DATA_SPECIAL parsing for local label references
2026-07-07 7:20 [PATCH v3 00/12] LoongArch: Add livepatch build (KLP) support George Guo
` (9 preceding siblings ...)
2026-07-07 7:20 ` [PATCH v3 10/12] objtool/klp: Convert local label references in special sections George Guo
@ 2026-07-07 7:20 ` George Guo
2026-07-07 7:20 ` [PATCH v3 12/12] objtool/klp: Fold LoongArch paired ADD/SUB relocations into PCREL George Guo
11 siblings, 0 replies; 18+ messages in thread
From: George Guo @ 2026-07-07 7:20 UTC (permalink / raw)
To: chenhuacai, jpoimboe, peterz, jikos, mbenes, pmladek
Cc: kernel, joe.lawrence, rostedt, ardb, nathan,
nick.desaulniers+lkml, yangtiezhu, jiaxun.yang, liukexin,
guodongtai, xry111, wangyuli, loongarch, live-patching, llvm,
linux-kernel
From: George Guo <guodongtai@kylinos.cn>
create_fake_symbols() takes each annotated entry's offset from the
annotate relocation's addend alone. That works only when the
relocation points at the special section's section symbol. GCC/GAS
on LoongArch points it at the entry's local label instead, with a
zero addend: every entry then gets offset 0, the "distance to the
next annotation" size becomes 0, and the fallback sets the size to
the rest of the section.
So every fake symbol starts at offset 0 and covers the whole special
section. If any entry in the section belongs to a patched function,
should_keep_special_sym() keeps such a symbol, and the output module
gets the entire __bug_table (thousands of entries and klp
relocations) instead of just the patched function's entries.
Compute the offset as sym->offset + addend, which handles both the
section symbol form (sym->offset == 0) and the local label form
(addend == 0).
Reported-by: Joe Lawrence <joe.lawrence@redhat.com>
Signed-off-by: George Guo <guodongtai@kylinos.cn>
---
tools/objtool/klp-diff.c | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/tools/objtool/klp-diff.c b/tools/objtool/klp-diff.c
index 05fd70e24326..0fa3ce324346 100644
--- a/tools/objtool/klp-diff.c
+++ b/tools/objtool/klp-diff.c
@@ -1863,7 +1863,12 @@ static int create_fake_symbols(struct elf *elf)
if (annotype(elf, sec, reloc) != ANNOTYPE_DATA_SPECIAL)
continue;
- offset = reloc_addend(reloc);
+ /*
+ * The annotated location may be referenced via the section
+ * symbol plus addend, or via a local label (GCC/GAS on
+ * LoongArch): sym->offset + addend covers both forms.
+ */
+ offset = reloc->sym->offset + reloc_addend(reloc);
size = 0;
next_reloc = reloc;
@@ -1875,7 +1880,7 @@ static int create_fake_symbols(struct elf *elf)
next_reloc->sym->sec != reloc->sym->sec)
continue;
- size = reloc_addend(next_reloc) - offset;
+ size = (next_reloc->sym->offset + reloc_addend(next_reloc)) - offset;
break;
}
--
2.25.1
^ permalink raw reply related [flat|nested] 18+ messages in thread* [PATCH v3 12/12] objtool/klp: Fold LoongArch paired ADD/SUB relocations into PCREL
2026-07-07 7:20 [PATCH v3 00/12] LoongArch: Add livepatch build (KLP) support George Guo
` (10 preceding siblings ...)
2026-07-07 7:20 ` [PATCH v3 11/12] objtool/klp: Fix ANNOTATE_DATA_SPECIAL parsing for local label references George Guo
@ 2026-07-07 7:20 ` George Guo
2026-07-08 13:29 ` Xi Ruoyao
11 siblings, 1 reply; 18+ messages in thread
From: George Guo @ 2026-07-07 7:20 UTC (permalink / raw)
To: chenhuacai, jpoimboe, peterz, jikos, mbenes, pmladek
Cc: kernel, joe.lawrence, rostedt, ardb, nathan,
nick.desaulniers+lkml, yangtiezhu, jiaxun.yang, liukexin,
guodongtai, xry111, wangyuli, loongarch, live-patching, llvm,
linux-kernel
From: George Guo <guodongtai@kylinos.cn>
On LoongArch, the "key - ." field of a __jump_table entry can come out
as two relocations at the same offset, R_LARCH_ADD64 plus
R_LARCH_SUB64. clang's integrated assembler emits this pair when the
key symbol is not defined in the same translation unit (for example
__tracepoint_netif_rx); GAS, and clang for locally-defined keys,
produce a single R_LARCH_64_PCREL instead, which is why GCC builds do
not hit this. objtool's elf_create_reloc() allows only one relocation
per offset, so cloning such an entry fails with:
vmlinux.o: error: objtool: __jump_table_23683+0x8: duplicate reloc
When the SUB half points at the relocation's own position (the
"sym - ." pattern), the pair means the same thing as one PC-relative
relocation. Add arch_normalize_paired_reloc() which rewrites the ADD
half to R_LARCH_32_PCREL/R_LARCH_64_PCREL and skips the SUB half. The
LoongArch module loader supports both forms.
Reported-by: Joe Lawrence <joe.lawrence@redhat.com>
Signed-off-by: George Guo <guodongtai@kylinos.cn>
---
tools/objtool/arch/loongarch/decode.c | 62 +++++++++++++++++++
.../objtool/arch/loongarch/include/arch/elf.h | 18 ++++++
tools/objtool/klp-diff.c | 13 ++++
3 files changed, 93 insertions(+)
diff --git a/tools/objtool/arch/loongarch/decode.c b/tools/objtool/arch/loongarch/decode.c
index 12facd0cc8d1..273398ea4486 100644
--- a/tools/objtool/arch/loongarch/decode.c
+++ b/tools/objtool/arch/loongarch/decode.c
@@ -39,6 +39,68 @@ u64 arch_adjusted_addend(struct reloc *reloc)
return reloc_addend(reloc);
}
+/*
+ * A cross-section difference like the "key - ." field of a __jump_table
+ * entry may come out as a paired R_LARCH_ADD plus R_LARCH_SUB relocation
+ * at the same offset: clang's integrated assembler does this when the
+ * symbol is not defined in the same translation unit (GAS, and clang for
+ * locally-defined symbols, emit a single PCREL instead). objtool allows
+ * only one relocation per offset, so the pair breaks cloning.
+ *
+ * When the SUB half points at the reloc's own position ("sym - ."), the
+ * pair means the same as a single PC-relative relocation, which the
+ * module loader also supports: rewrite the ADD half to R_LARCH_*_PCREL
+ * and tell the caller to skip the SUB half.
+ *
+ * Return 1 to skip the reloc, 0 to proceed, -1 on error.
+ */
+int arch_normalize_paired_reloc(struct elf *elf, struct reloc *reloc)
+{
+ struct section *rsec = reloc->sec;
+ unsigned int sub_type, pcrel_type;
+ struct reloc *sub, *add;
+
+ switch (reloc_type(reloc)) {
+ case R_LARCH_ADD32:
+ sub_type = R_LARCH_SUB32;
+ pcrel_type = R_LARCH_32_PCREL;
+ break;
+ case R_LARCH_ADD64:
+ sub_type = R_LARCH_SUB64;
+ pcrel_type = R_LARCH_64_PCREL;
+ break;
+ case R_LARCH_SUB32:
+ case R_LARCH_SUB64:
+ /*
+ * Skip only if the paired ADD (the preceding reloc) has
+ * been rewritten to PCREL; otherwise leave the pair
+ * intact so a failed conversion stays loud.
+ */
+ add = reloc_idx(reloc) ? reloc - 1 : NULL;
+ if (add && reloc_offset(add) == reloc_offset(reloc) &&
+ (reloc_type(add) == R_LARCH_32_PCREL ||
+ reloc_type(add) == R_LARCH_64_PCREL))
+ return 1;
+ return 0;
+ default:
+ return 0;
+ }
+
+ /* The paired SUB reloc immediately follows the ADD */
+ sub = rsec_next_reloc(rsec, reloc);
+ if (!sub || reloc_offset(sub) != reloc_offset(reloc) ||
+ reloc_type(sub) != sub_type)
+ return 0;
+
+ /* Only a "sym - ." difference is PC-relative */
+ if (sub->sym->sec != rsec->base ||
+ sub->sym->offset + reloc_addend(sub) != reloc_offset(sub))
+ return 0;
+
+ set_reloc_type(elf, reloc, pcrel_type);
+ return 0;
+}
+
bool arch_pc_relative_reloc(struct reloc *reloc)
{
return false;
diff --git a/tools/objtool/arch/loongarch/include/arch/elf.h b/tools/objtool/arch/loongarch/include/arch/elf.h
index ec79062c9554..0103f27fccfc 100644
--- a/tools/objtool/arch/loongarch/include/arch/elf.h
+++ b/tools/objtool/arch/loongarch/include/arch/elf.h
@@ -15,6 +15,18 @@
#ifndef R_LARCH_64
#define R_LARCH_64 2
#endif
+#ifndef R_LARCH_ADD32
+#define R_LARCH_ADD32 50
+#endif
+#ifndef R_LARCH_ADD64
+#define R_LARCH_ADD64 51
+#endif
+#ifndef R_LARCH_SUB32
+#define R_LARCH_SUB32 55
+#endif
+#ifndef R_LARCH_SUB64
+#define R_LARCH_SUB64 56
+#endif
#ifndef R_LARCH_32_PCREL
#define R_LARCH_32_PCREL 99
#endif
@@ -34,4 +46,10 @@
#define R_TEXT32 R_LARCH_32_PCREL
#define R_TEXT64 R_LARCH_32_PCREL
+#define ARCH_HAS_PAIRED_RELOCS 1
+
+struct elf;
+struct reloc;
+int arch_normalize_paired_reloc(struct elf *elf, struct reloc *reloc);
+
#endif /* _OBJTOOL_ARCH_ELF_H */
diff --git a/tools/objtool/klp-diff.c b/tools/objtool/klp-diff.c
index 0fa3ce324346..02b2150e3ca3 100644
--- a/tools/objtool/klp-diff.c
+++ b/tools/objtool/klp-diff.c
@@ -1504,6 +1504,13 @@ static bool is_uncorrelated_section(struct section *sec)
strstarts(sec->name, ".data..Lanon."); /* Clang */
}
+#ifndef ARCH_HAS_PAIRED_RELOCS
+static inline int arch_normalize_paired_reloc(struct elf *elf, struct reloc *reloc)
+{
+ return 0;
+}
+#endif
+
/*
* Convert a relocation symbol reference to the needed format: either a section
* symbol or the underlying symbol itself. Return -1 error, 0 success, 1 skip.
@@ -1511,10 +1518,16 @@ static bool is_uncorrelated_section(struct section *sec)
static int convert_reloc_sym(struct elf *elf, struct reloc *reloc)
{
struct section *sec = reloc->sym->sec;
+ int ret;
if (reloc_type(reloc) == R_NONE)
return 1;
+ /* Fold paired ADD/SUB relocs (LoongArch) into a single PCREL */
+ ret = arch_normalize_paired_reloc(elf, reloc);
+ if (ret)
+ return ret;
+
if (is_uncorrelated_section(sec))
return convert_reloc_sym_to_secsym(elf, reloc);
--
2.25.1
^ permalink raw reply related [flat|nested] 18+ messages in thread* Re: [PATCH v3 12/12] objtool/klp: Fold LoongArch paired ADD/SUB relocations into PCREL
2026-07-07 7:20 ` [PATCH v3 12/12] objtool/klp: Fold LoongArch paired ADD/SUB relocations into PCREL George Guo
@ 2026-07-08 13:29 ` Xi Ruoyao
0 siblings, 0 replies; 18+ messages in thread
From: Xi Ruoyao @ 2026-07-08 13:29 UTC (permalink / raw)
To: WANG Rui, George Guo, chenhuacai, jpoimboe, peterz, jikos, mbenes,
pmladek
Cc: kernel, joe.lawrence, rostedt, ardb, nathan,
nick.desaulniers+lkml, yangtiezhu, jiaxun.yang, liukexin,
guodongtai, wangyuli, loongarch, live-patching, llvm,
linux-kernel
On Tue, 2026-07-07 at 15:20 +0800, George Guo wrote:
> From: George Guo <guodongtai@kylinos.cn>
>
> On LoongArch, the "key - ." field of a __jump_table entry can come out
> as two relocations at the same offset, R_LARCH_ADD64 plus
> R_LARCH_SUB64. clang's integrated assembler emits this pair when the
> key symbol is not defined in the same translation unit (for example
> __tracepoint_netif_rx); GAS, and clang for locally-defined keys,
> produce a single R_LARCH_64_PCREL instead, which is why GCC builds do
> not hit this.
Hmm, is this a flaw in LLVM? We have
config AS_HAS_THIN_ADD_SUB
def_bool $(cc-option,-Wa$(comma)-mthin-add-sub) || AS_IS_LLVM
so we are already expecting LLVM to emit R_LARCH_64_PCREL always instead
of ADD64/SUB64.
--
Xi Ruoyao <xry111@xry111.site>
^ permalink raw reply [flat|nested] 18+ messages in thread