Skip to content

Commit c1034f5

Browse files
Suraj Jitindar Singhpuranjaymohan
authored andcommitted
kpatch-build: Enable ARM64 support
Add the final support required for aarch64 and enable building on that arch. Signed-off-by: Suraj Jitindar Singh <surajjs@amazon.com> [kpatch_line_macro_change_only() fixes] Signed-off-by: Puranjay Mohan <pjy@amazon.com>
1 parent 062fd46 commit c1034f5

5 files changed

Lines changed: 69 additions & 16 deletions

File tree

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ Supported Architectures
4040

4141
- [x] x86-64
4242
- [x] ppc64le
43-
- [ ] arm64
43+
- [x] arm64
4444
- [x] s390 [upstream prerequisites](doc/s390-upstream-prerequisites.md)
4545

4646
Installation

kpatch-build/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ PLUGIN_CFLAGS := $(filter-out -std=gnu11 -Wconversion, $(CFLAGS))
2121
PLUGIN_CFLAGS += -shared -I$(GCC_PLUGINS_DIR)/include \
2222
-Igcc-plugins -fPIC -fno-rtti -O2 -Wall
2323
endif
24-
ifeq ($(filter $(ARCH),s390x x86_64 ppc64le),)
24+
ifeq ($(filter $(ARCH),s390x x86_64 ppc64le aarch64),)
2525
$(error Unsupported architecture ${ARCH}, check https://github.com/dynup/kpatch/#supported-architectures)
2626
endif
2727

kpatch-build/create-diff-object.c

Lines changed: 58 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,8 @@ static bool is_gcc6_localentry_bundled_sym(struct kpatch_elf *kelf,
173173
struct symbol *sym)
174174
{
175175
switch(kelf->arch) {
176+
case AARCH64:
177+
return false;
176178
case PPC64:
177179
return ((PPC64_LOCAL_ENTRY_OFFSET(sym->sym.st_other) != 0) &&
178180
sym->sym.st_value == 8);
@@ -228,6 +230,31 @@ static struct rela *toc_rela(const struct rela *rela)
228230
(unsigned int)rela->addend);
229231
}
230232

233+
/*
234+
* Mapping symbols are used to mark and label the transitions between code and
235+
* data in elf files. They begin with a "$" dollar symbol. Don't correlate them
236+
* as they often all have the same name either "$x" to mark the start of code
237+
* or "$d" to mark the start of data.
238+
*/
239+
static bool kpatch_is_mapping_symbol(struct kpatch_elf *kelf, struct symbol *sym)
240+
{
241+
switch (kelf->arch) {
242+
case AARCH64:
243+
if (sym->name && sym->name[0] == '$'
244+
&& sym->type == STT_NOTYPE \
245+
&& sym->bind == STB_LOCAL)
246+
return true;
247+
case X86_64:
248+
case PPC64:
249+
case S390:
250+
return false;
251+
default:
252+
ERROR("unsupported arch");
253+
}
254+
255+
return false;
256+
}
257+
231258
/*
232259
* When compiling with -ffunction-sections and -fdata-sections, almost every
233260
* symbol gets its own dedicated section. We call such symbols "bundled"
@@ -706,6 +733,12 @@ static bool insn_is_load_immediate(struct kpatch_elf *kelf, void *addr)
706733

707734
break;
708735

736+
case AARCH64:
737+
/* Verify mov w2 <line number> */
738+
if ((insn[0] & 0b11111) == 0x2 && insn[3] == 0x52)
739+
return true;
740+
break;
741+
709742
default:
710743
ERROR("unsupported arch");
711744
}
@@ -746,6 +779,7 @@ static bool kpatch_line_macro_change_only(struct kpatch_elf *kelf,
746779
void *data1, *data2, *insn1, *insn2;
747780
struct rela *r, *rela;
748781
bool found, found_any = false;
782+
bool warn_printk_only = (kelf->arch == AARCH64);
749783

750784
if (sec->status != CHANGED ||
751785
is_rela_section(sec) ||
@@ -809,8 +843,15 @@ static bool kpatch_line_macro_change_only(struct kpatch_elf *kelf,
809843
!strncmp(rela->sym->name, "__func__.", 9))
810844
continue;
811845

846+
if (!strcmp(rela->sym->name, "__warn_printk")) {
847+
found = true;
848+
break;
849+
}
850+
851+
if (warn_printk_only)
852+
return false;
853+
812854
if (!strncmp(rela->sym->name, "warn_slowpath_", 14) ||
813-
!strcmp(rela->sym->name, "__warn_printk") ||
814855
!strcmp(rela->sym->name, "__might_sleep") ||
815856
!strcmp(rela->sym->name, "___might_sleep") ||
816857
!strcmp(rela->sym->name, "__might_fault") ||
@@ -1075,15 +1116,15 @@ static void kpatch_correlate_sections(struct list_head *seclist_orig,
10751116
}
10761117
}
10771118

1078-
static void kpatch_correlate_symbols(struct list_head *symlist_orig,
1079-
struct list_head *symlist_patched)
1119+
static void kpatch_correlate_symbols(struct kpatch_elf *kelf_orig,
1120+
struct kpatch_elf *kelf_patched)
10801121
{
10811122
struct symbol *sym_orig, *sym_patched;
10821123

1083-
list_for_each_entry(sym_orig, symlist_orig, list) {
1124+
list_for_each_entry(sym_orig, &kelf_orig->symbols, list) {
10841125
if (sym_orig->twin)
10851126
continue;
1086-
list_for_each_entry(sym_patched, symlist_patched, list) {
1127+
list_for_each_entry(sym_patched, &kelf_patched->symbols, list) {
10871128
if (kpatch_mangled_strcmp(sym_orig->name, sym_patched->name) ||
10881129
sym_orig->type != sym_patched->type || sym_patched->twin)
10891130
continue;
@@ -1103,6 +1144,9 @@ static void kpatch_correlate_symbols(struct list_head *symlist_orig,
11031144
!strncmp(sym_orig->name, ".LC", 3))
11041145
continue;
11051146

1147+
if (kpatch_is_mapping_symbol(kelf_orig, sym_orig))
1148+
continue;
1149+
11061150
/* group section symbols must have correlated sections */
11071151
if (sym_orig->sec &&
11081152
sym_orig->sec->sh.sh_type == SHT_GROUP &&
@@ -1508,7 +1552,7 @@ static void kpatch_correlate_elfs(struct kpatch_elf *kelf_orig,
15081552
struct kpatch_elf *kelf_patched)
15091553
{
15101554
kpatch_correlate_sections(&kelf_orig->sections, &kelf_patched->sections);
1511-
kpatch_correlate_symbols(&kelf_orig->symbols, &kelf_patched->symbols);
1555+
kpatch_correlate_symbols(kelf_orig, kelf_patched);
15121556
}
15131557

15141558
static void kpatch_compare_correlated_elements(struct kpatch_elf *kelf)
@@ -1624,7 +1668,8 @@ static void kpatch_replace_sections_syms(struct kpatch_elf *kelf)
16241668

16251669
if (is_text_section(relasec->base) &&
16261670
!is_text_section(sym->sec) &&
1627-
rela->type == R_X86_64_32S &&
1671+
(rela->type == R_X86_64_32S ||
1672+
rela->type == R_AARCH64_ABS64) &&
16281673
rela->addend == (long)sym->sec->sh.sh_size &&
16291674
end == (long)sym->sec->sh.sh_size) {
16301675

@@ -2493,28 +2538,28 @@ static bool static_call_sites_group_filter(struct lookup_table *lookup,
24932538
static struct special_section special_sections[] = {
24942539
{
24952540
.name = "__bug_table",
2496-
.arch = X86_64 | PPC64 | S390,
2541+
.arch = AARCH64 | X86_64 | PPC64 | S390,
24972542
.group_size = bug_table_group_size,
24982543
},
24992544
{
25002545
.name = ".fixup",
2501-
.arch = X86_64 | PPC64 | S390,
2546+
.arch = AARCH64 | X86_64 | PPC64 | S390,
25022547
.group_size = fixup_group_size,
25032548
},
25042549
{
25052550
.name = "__ex_table", /* must come after .fixup */
2506-
.arch = X86_64 | PPC64 | S390,
2551+
.arch = AARCH64 | X86_64 | PPC64 | S390,
25072552
.group_size = ex_table_group_size,
25082553
},
25092554
{
25102555
.name = "__jump_table",
2511-
.arch = X86_64 | PPC64 | S390,
2556+
.arch = AARCH64 | X86_64 | PPC64 | S390,
25122557
.group_size = jump_table_group_size,
25132558
.group_filter = jump_table_group_filter,
25142559
},
25152560
{
25162561
.name = ".printk_index",
2517-
.arch = X86_64 | PPC64 | S390,
2562+
.arch = AARCH64 | X86_64 | PPC64 | S390,
25182563
.group_size = printk_index_group_size,
25192564
},
25202565
{
@@ -2529,7 +2574,7 @@ static struct special_section special_sections[] = {
25292574
},
25302575
{
25312576
.name = ".altinstructions",
2532-
.arch = X86_64 | S390,
2577+
.arch = AARCH64 | X86_64 | S390,
25332578
.group_size = altinstructions_group_size,
25342579
},
25352580
{

kpatch-build/kpatch-build

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -402,6 +402,9 @@ find_special_section_data() {
402402
"s390x")
403403
check[a]=true # alt_instr
404404
;;
405+
"aarch64")
406+
check[a]=true # alt_instr
407+
;;
405408
esac
406409

407410
# Kernel CONFIG_ features

kpatch-build/kpatch-elf.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,8 @@ unsigned int absolute_rela_type(struct kpatch_elf *kelf)
142142
return R_X86_64_64;
143143
case S390:
144144
return R_390_64;
145+
case AARCH64:
146+
return R_AARCH64_ABS64;
145147
default:
146148
ERROR("unsupported arch");
147149
}
@@ -206,6 +208,7 @@ long rela_target_offset(struct kpatch_elf *kelf, struct section *relasec,
206208

207209
switch(kelf->arch) {
208210
case PPC64:
211+
case AARCH64:
209212
add_off = 0;
210213
break;
211214
case X86_64:
@@ -255,6 +258,8 @@ unsigned int insn_length(struct kpatch_elf *kelf, void *addr)
255258

256259
switch(kelf->arch) {
257260

261+
case AARCH64:
262+
return 4;
258263
case X86_64:
259264
insn_init(&decoded_insn, addr, 1);
260265
insn_get_length(&decoded_insn);
@@ -595,7 +600,7 @@ struct kpatch_elf *kpatch_elf_open(const char *name)
595600
kelf->arch = S390;
596601
break;
597602
case EM_AARCH64:
598-
kelf->arch = ARM64;
603+
kelf->arch = AARCH64;
599604
break;
600605
default:
601606
ERROR("Unsupported target architecture");

0 commit comments

Comments
 (0)