Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add LoongArch support for kpatch v2 #1427

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion kpatch-build/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
43 changes: 38 additions & 5 deletions kpatch-build/create-diff-object.c
Original file line number Diff line number Diff line change
Expand Up @@ -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");
}
Expand Down Expand Up @@ -694,6 +696,11 @@ static bool insn_is_load_immediate(struct kpatch_elf *kelf, void *addr)

break;

case LOONGARCH64:
/* to be done */
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TODO?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I m not sure here, so just commit "to be done". Actually it can pass my simple test case.


break;

case S390:
/* arg2: lghi %r3, imm */
if (insn[0] == 0xa7 && insn[1] == 0x39)
Expand Down Expand Up @@ -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,
},
Expand All @@ -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,
},
{
Expand Down Expand Up @@ -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");
Expand Down Expand Up @@ -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");
}
Expand Down Expand Up @@ -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");
}
Expand Down
3 changes: 3 additions & 0 deletions kpatch-build/kpatch-build
Original file line number Diff line number Diff line change
Expand Up @@ -393,6 +393,9 @@ find_special_section_data() {
"s390x")
check[a]=true # alt_instr
;;
"loongarch64")
check[a]=true # alt_instr
;;
esac

# Kernel CONFIG_ features
Expand Down
35 changes: 35 additions & 0 deletions kpatch-build/kpatch-elf.c
Original file line number Diff line number Diff line change
Expand Up @@ -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");
}
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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);
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just curious, which kernel source files are generating these symbols?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okey, I will try to find it.



if (skip)
continue;
log_debug("offset %d, type %d, %s %s %ld", rela->offset,
Expand Down Expand Up @@ -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");
}
Expand All @@ -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;
}

Expand Down
6 changes: 6 additions & 0 deletions kpatch-build/kpatch-elf.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
* ****************/
Expand Down Expand Up @@ -116,6 +121,7 @@ enum architecture {
PPC64 = 0x1 << 0,
X86_64 = 0x1 << 1,
S390 = 0x1 << 2,
LOONGARCH64 = 0x1 << 3,
};

struct kpatch_elf {
Expand Down
Loading