From af8c2cebd046dd3833cba8daac26e4d8109f7ff3 Mon Sep 17 00:00:00 2001 From: Zhipeng Xie Date: Thu, 20 Dec 2018 04:55:38 +0000 Subject: [PATCH 01/37] kpatch: add aarch64 support 1.use R_AARCH64_ABS64 for aarch64 2.add find_special_section_data_arm64 for arm64: arm64 kernel have no paravirt_patch_site or orc_entry structure in vmlinux, we don't need to check these two struct for arm64. Signed-off-by: Zhipeng Xie --- kpatch-build/Makefile | 2 +- kpatch-build/create-diff-object.c | 32 ++++++++++++++++++------------- kpatch-build/kpatch-build | 5 +++++ kpatch-build/kpatch-elf.c | 7 +++++++ kpatch-build/kpatch-elf.h | 1 + 5 files changed, 33 insertions(+), 14 deletions(-) diff --git a/kpatch-build/Makefile b/kpatch-build/Makefile index bebf3cd..5037677 100644 --- a/kpatch-build/Makefile +++ b/kpatch-build/Makefile @@ -22,7 +22,7 @@ PLUGIN_CFLAGS := $(filter-out -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 aarch64),) $(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 3604411..0b0b06b 100644 --- a/kpatch-build/create-diff-object.c +++ b/kpatch-build/create-diff-object.c @@ -175,6 +175,8 @@ static bool is_gcc6_localentry_bundled_sym(struct kpatch_elf *kelf, return false; case S390: return false; + case ARM64: + return false; default: ERROR("unsupported arch"); } @@ -2186,57 +2188,57 @@ static int fixup_group_size(struct kpatch_elf *kelf, int offset) static struct special_section special_sections[] = { { .name = "__bug_table", - .arch = X86_64 | PPC64 | S390, + .arch = X86_64 | PPC64 | S390 | ARM64, .group_size = bug_table_group_size, }, { .name = ".fixup", - .arch = X86_64 | PPC64 | S390, + .arch = X86_64 | PPC64 | S390 | ARM64, .group_size = fixup_group_size, }, { .name = "__ex_table", /* must come after .fixup */ - .arch = X86_64 | PPC64 | S390, + .arch = X86_64 | PPC64 | S390 | ARM64, .group_size = ex_table_group_size, }, { .name = "__jump_table", - .arch = X86_64 | PPC64 | S390, + .arch = X86_64 | PPC64 | S390 | ARM64, .group_size = jump_table_group_size, }, { .name = ".printk_index", - .arch = X86_64 | PPC64 | S390, + .arch = X86_64 | PPC64 | S390 | ARM64, .group_size = printk_index_group_size, }, { .name = ".smp_locks", - .arch = X86_64, + .arch = X86_64 | ARM64, .group_size = smp_locks_group_size, }, { .name = ".parainstructions", - .arch = X86_64, + .arch = X86_64 | ARM64, .group_size = parainstructions_group_size, }, { .name = ".altinstructions", - .arch = X86_64 | S390, + .arch = X86_64 | S390 | ARM64, .group_size = altinstructions_group_size, }, { .name = ".static_call_sites", - .arch = X86_64, + .arch = X86_64 | ARM64, .group_size = static_call_sites_group_size, }, { .name = ".retpoline_sites", - .arch = X86_64, + .arch = X86_64 | ARM64, .group_size = retpoline_sites_group_size, }, { .name = ".return_sites", - .arch = X86_64, + .arch = X86_64 | ARM64, .group_size = return_sites_group_size, }, { @@ -3097,7 +3099,9 @@ static int function_ptr_rela(const struct rela *rela) rela_toc->addend == (int)rela_toc->sym->sym.st_value && (rela->type == R_X86_64_32S || rela->type == R_PPC64_TOC16_HA || - rela->type == R_PPC64_TOC16_LO_DS)); + rela->type == R_PPC64_TOC16_LO_DS || + rela->type == R_AARCH64_ADR_PREL_PG_HI21 || + rela->type == R_AARCH64_ADD_ABS_LO12_NC)); } static bool need_dynrela(struct kpatch_elf *kelf, struct lookup_table *table, @@ -3570,7 +3574,8 @@ static void kpatch_create_mcount_sections(struct kpatch_elf *kelf) } switch(kelf->arch) { - case PPC64: { + case PPC64: + case ARM64: { bool found = false; list_for_each_entry(rela, &sym->sec->rela->relas, list) @@ -3806,6 +3811,7 @@ static void kpatch_find_func_profiling_calls(struct kpatch_elf *kelf) switch(kelf->arch) { case PPC64: + case ARM64: list_for_each_entry(rela, &sym->sec->rela->relas, list) { if (!strcmp(rela->sym->name, "_mcount")) { sym->has_func_profiling = 1; diff --git a/kpatch-build/kpatch-build b/kpatch-build/kpatch-build index 296fa48..73f8976 100755 --- a/kpatch-build/kpatch-build +++ b/kpatch-build/kpatch-build @@ -354,6 +354,9 @@ find_special_section_data() { "s390x") check[a]=true # alt_instr ;; + "aarch64") + check[a]=true # alt_instr + ;; esac # Kernel CONFIG_ features @@ -362,6 +365,8 @@ find_special_section_data() { [[ -n "$CONFIG_UNWINDER_ORC" ]] && check[o]=true # orc_entry [[ -n "$CONFIG_PARAVIRT" ]] && check[p]=true # paravirt_patch_site + [[ "$ARCH" == "aarch64" ]] && unset check[p] + local c AWK_OPTIONS for c in "${!check[@]}"; do AWK_OPTIONS+=" -vcheck_${c}=1" diff --git a/kpatch-build/kpatch-elf.c b/kpatch-build/kpatch-elf.c index 58dbe1a..069e102 100644 --- 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 ARM64: + return R_AARCH64_ABS64; 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 ARM64: 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 ARM64: return 4; case S390: @@ -501,6 +505,9 @@ struct kpatch_elf *kpatch_elf_open(const char *name) case EM_S390: kelf->arch = S390; break; + case EM_AARCH64: + kelf->arch = ARM64; + break; default: ERROR("Unsupported target architecture"); } diff --git a/kpatch-build/kpatch-elf.h b/kpatch-build/kpatch-elf.h index 3bc6e76..d887812 100644 --- a/kpatch-build/kpatch-elf.h +++ b/kpatch-build/kpatch-elf.h @@ -113,6 +113,7 @@ enum architecture { PPC64 = 0x1 << 0, X86_64 = 0x1 << 1, S390 = 0x1 << 2, + ARM64 = 0x1 << 3, }; struct kpatch_elf { -- 2.33.0