diff --git a/kpatch-build/Makefile b/kpatch-build/Makefile index 4e964b7f..0f019698 100644 --- a/kpatch-build/Makefile +++ b/kpatch-build/Makefile @@ -21,7 +21,7 @@ PLUGIN_CFLAGS := $(filter-out -std=gnu11 -Wconversion, $(CFLAGS)) PLUGIN_CFLAGS += -shared -I$(GCC_PLUGINS_DIR)/include \ -Igcc-plugins -fPIC -fno-rtti -O2 -Wall endif -ifeq ($(filter $(ARCH),s390x x86_64 ppc64le),) +ifeq ($(filter $(ARCH),s390x x86_64 ppc64le loongarch64),) $(error Unsupported architecture ${ARCH}, check https://github.com/dynup/kpatch/#supported-architectures) endif diff --git a/kpatch-build/create-diff-object.c b/kpatch-build/create-diff-object.c index 531df648..52d9292a 100644 --- a/kpatch-build/create-diff-object.c +++ b/kpatch-build/create-diff-object.c @@ -180,6 +180,8 @@ static bool is_gcc6_localentry_bundled_sym(struct kpatch_elf *kelf, return false; case S390: return false; + case LOONGARCH64: + return false; default: ERROR("unsupported arch"); } @@ -694,6 +696,11 @@ static bool insn_is_load_immediate(struct kpatch_elf *kelf, void *addr) break; + case LOONGARCH64: + /* to be done */ + + break; + case S390: /* arg2: lghi %r3, imm */ if (insn[0] == 0xa7 && insn[1] == 0x39) @@ -2420,22 +2427,22 @@ static bool static_call_sites_group_filter(struct lookup_table *lookup, static struct special_section special_sections[] = { { .name = "__bug_table", - .arch = X86_64 | PPC64 | S390, + .arch = X86_64 | PPC64 | S390 | LOONGARCH64, .group_size = bug_table_group_size, }, { .name = ".fixup", - .arch = X86_64 | PPC64 | S390, + .arch = X86_64 | PPC64 | S390 | LOONGARCH64, .group_size = fixup_group_size, }, { .name = "__ex_table", /* must come after .fixup */ - .arch = X86_64 | PPC64 | S390, + .arch = X86_64 | PPC64 | S390 | LOONGARCH64, .group_size = ex_table_group_size, }, { .name = "__jump_table", - .arch = X86_64 | PPC64 | S390, + .arch = X86_64 | PPC64 | S390 | LOONGARCH64, .group_size = jump_table_group_size, .group_filter = jump_table_group_filter, }, @@ -2456,7 +2463,7 @@ static struct special_section special_sections[] = { }, { .name = ".altinstructions", - .arch = X86_64 | S390, + .arch = X86_64 | S390 | LOONGARCH64, .group_size = altinstructions_group_size, }, { @@ -2870,6 +2877,11 @@ static void kpatch_mark_ignored_sections(struct kpatch_elf *kelf) !strcmp(sec->name, "__patchable_function_entries")) sec->ignore = 1; } + + if (kelf->arch == LOONGARCH64) { + if(strncmp(sec->name,".rela.orc_unwind_ip",19)) + sec->ignore = 1; + } } sec = find_section_by_name(&kelf->sections, ".kpatch.ignore.sections"); @@ -3831,6 +3843,21 @@ static void kpatch_create_ftrace_callsite_sections(struct kpatch_elf *kelf, bool insn_offset = sym->sym.st_value; break; } + case LOONGARCH64: { + bool found = false; + unsigned char *insn = sym->sec->data->d_buf + sym->sym.st_value; + + /* 0x03400000 is NOP instruction for LoongArch. */ + if(insn[0] == 0x00 && insn[1] == 0x00 && insn[2] == 0x40 && insn[3] == 0x03 && + insn[4] == 0x00 && insn[5] == 0x00 && insn[6] == 0x40 && insn[7] == 0x03) + found = true; + + if (!found) + ERROR("%s: unexpected instruction at the start of the function", sym->name); + + insn_offset = 0; + break; + } default: ERROR("unsupported arch"); } @@ -4081,6 +4108,12 @@ static void kpatch_find_func_profiling_calls(struct kpatch_elf *kelf) insn[4] == 0x00 && insn[5] == 0x00) sym->has_func_profiling = 1; break; + case LOONGARCH64: + + if (kpatch_symbol_has_pfe_entry(kelf, sym)) + sym->has_func_profiling = 1; + break; + default: ERROR("unsupported arch"); } diff --git a/kpatch-build/kpatch-build b/kpatch-build/kpatch-build index bc112fc9..a9ea853d 100755 --- a/kpatch-build/kpatch-build +++ b/kpatch-build/kpatch-build @@ -393,6 +393,9 @@ find_special_section_data() { "s390x") check[a]=true # alt_instr ;; + "loongarch64") + check[a]=true # alt_instr + ;; esac # Kernel CONFIG_ features diff --git a/kpatch-build/kpatch-elf.c b/kpatch-build/kpatch-elf.c index 7e9d2c81..e4f2927c 100755 --- a/kpatch-build/kpatch-elf.c +++ b/kpatch-build/kpatch-elf.c @@ -142,6 +142,8 @@ unsigned int absolute_rela_type(struct kpatch_elf *kelf) return R_X86_64_64; case S390: return R_390_64; + case LOONGARCH64: + return R_LARCH_64; default: ERROR("unsupported arch"); } @@ -206,6 +208,7 @@ long rela_target_offset(struct kpatch_elf *kelf, struct section *relasec, switch(kelf->arch) { case PPC64: + case LOONGARCH64: add_off = 0; break; case X86_64: @@ -261,6 +264,7 @@ unsigned int insn_length(struct kpatch_elf *kelf, void *addr) return decoded_insn.length; case PPC64: + case LOONGARCH64: return 4; case S390: @@ -332,6 +336,22 @@ static void kpatch_create_rela_list(struct kpatch_elf *kelf, rela->sym->name, rela->addend); } + if (kelf->arch == LOONGARCH64) { + /* + * LoongArch GCC creates local labels such as .LBB7266, + * replace them with section symbols. + */ + if (rela->sym->sec && (rela->sym->type == STT_NOTYPE) && + (rela->sym->bind == STB_LOCAL)) { + log_debug("local label: %s -> ", rela->sym->name); + + rela->addend += rela->sym->sym.st_value; + rela->sym = rela->sym->sec->secsym; + log_debug("section symbol: %s\n", rela->sym->name); + } + } + + if (skip) continue; log_debug("offset %d, type %d, %s %s %ld", rela->offset, @@ -593,6 +613,9 @@ struct kpatch_elf *kpatch_elf_open(const char *name) case EM_S390: kelf->arch = S390; break; + case EM_LOONGARCH: + kelf->arch = LOONGARCH64; + break; default: ERROR("Unsupported target architecture"); } @@ -618,6 +641,18 @@ struct kpatch_elf *kpatch_elf_open(const char *name) if (find_section_by_name(&kelf->sections, "__patchable_function_entries")) kelf->has_pfe = true; + if (kelf->arch == LOONGARCH64) { + struct symbol *sym, *tmp; + + /* Delete local labels created by LoongArch GCC */ + list_for_each_entry_safe(sym, tmp, &kelf->symbols, list) { + if (sym->sec && !is_rela_section(sym->sec) && + (sym->type == STT_NOTYPE) && + (sym->bind == STB_LOCAL)) + list_del(&sym->list); + } + } + return kelf; } diff --git a/kpatch-build/kpatch-elf.h b/kpatch-build/kpatch-elf.h index e47acf97..b3543e3b 100644 --- a/kpatch-build/kpatch-elf.h +++ b/kpatch-build/kpatch-elf.h @@ -31,6 +31,11 @@ #define SHF_RELA_LIVEPATCH 0x00100000 #define SHN_LIVEPATCH 0xff20 +#ifndef __loongarch__ +#define EM_LOONGARCH 258 /* LoongArch */ +#define R_LARCH_64 2 +#endif + /******************* * Data structures * ****************/ @@ -116,6 +121,7 @@ enum architecture { PPC64 = 0x1 << 0, X86_64 = 0x1 << 1, S390 = 0x1 << 2, + LOONGARCH64 = 0x1 << 3, }; struct kpatch_elf {