Skip to content

Commit 59e4e35

Browse files
author
Suraj Jitindar Singh
committed
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>
1 parent a636944 commit 59e4e35

File tree

4 files changed

+102
-19
lines changed

4 files changed

+102
-19
lines changed

README.md

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

5252
- [x] x86-64
5353
- [x] ppc64le
54-
- [ ] arm64
54+
- [x] arm64
5555
- [ ] s390
5656

5757
Installation

kpatch-build/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ GCC_PLUGINS_DIR := $(shell gcc -print-file-name=plugin)
2222
PLUGIN_CFLAGS := $(filter-out -Wconversion, $(CFLAGS))
2323
PLUGIN_CFLAGS += -shared -I$(GCC_PLUGINS_DIR)/include \
2424
-Igcc-plugins -fPIC -fno-rtti -O2 -Wall
25+
else ifeq ($(ARCH),aarch64)
2526
else
2627
$(error Unsupported architecture ${ARCH}, check https://github.com/dynup/kpatch/#supported-architectures)
2728
endif

kpatch-build/create-diff-object.c

Lines changed: 53 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,9 @@
6262

6363
#ifdef __powerpc64__
6464
#define ABSOLUTE_RELA_TYPE R_PPC64_ADDR64
65-
#else
65+
#elif defined(__aarch64__)
66+
#define ABSOLUTE_RELA_TYPE R_AARCH64_ABS64
67+
#elif defined(__x86_64__)
6668
#define ABSOLUTE_RELA_TYPE R_X86_64_64
6769
#endif
6870

@@ -214,6 +216,22 @@ static struct rela *toc_rela(const struct rela *rela)
214216
(unsigned int)rela->addend);
215217
}
216218

219+
#ifdef __aarch64__
220+
static int kpatch_is_mapping_symbol(struct symbol *sym)
221+
{
222+
if (sym->name && sym->name[0] == '$'
223+
&& sym->type == STT_NOTYPE \
224+
&& sym->bind == STB_LOCAL)
225+
return 1;
226+
return 0;
227+
}
228+
#else
229+
static int kpatch_is_mapping_symbol(struct symbol *sym)
230+
{
231+
return 0;
232+
}
233+
#endif
234+
217235
/*
218236
* When compiling with -ffunction-sections and -fdata-sections, almost every
219237
* symbol gets its own dedicated section. We call such symbols "bundled"
@@ -563,6 +581,13 @@ static void kpatch_compare_correlated_section(struct section *sec)
563581
goto out;
564582
}
565583

584+
/* As above but for aarch64 */
585+
if (!strcmp(sec->name, ".rela__patchable_function_entries") ||
586+
!strcmp(sec->name, "__patchable_function_entries")) {
587+
sec->status = SAME;
588+
goto out;
589+
}
590+
566591
if (sec1->sh.sh_size != sec2->sh.sh_size ||
567592
sec1->data->d_size != sec2->data->d_size) {
568593
sec->status = CHANGED;
@@ -1027,6 +1052,9 @@ static void kpatch_correlate_symbols(struct list_head *symlist_orig,
10271052
!strncmp(sym_orig->name, ".LC", 3))
10281053
continue;
10291054

1055+
if (kpatch_is_mapping_symbol(sym_orig))
1056+
continue;
1057+
10301058
/* group section symbols must have correlated sections */
10311059
if (sym_orig->sec &&
10321060
sym_orig->sec->sh.sh_type == SHT_GROUP &&
@@ -1536,7 +1564,7 @@ static void kpatch_replace_sections_syms(struct kpatch_elf *kelf)
15361564
continue;
15371565
}
15381566

1539-
#ifdef __powerpc64__
1567+
#if defined(__powerpc64__) || defined(__aarch64__)
15401568
add_off = 0;
15411569
#else
15421570
if (rela->type == R_X86_64_PC32 ||
@@ -1568,7 +1596,11 @@ static void kpatch_replace_sections_syms(struct kpatch_elf *kelf)
15681596
end = sym->sym.st_value + sym->sym.st_size;
15691597

15701598
if (!is_text_section(sym->sec) &&
1599+
#ifdef __x86_64__
15711600
rela->type == R_X86_64_32S &&
1601+
#elif defined(__aarch64__)
1602+
rela->type == R_AARCH64_ABS64 &&
1603+
#endif
15721604
rela->addend == (long)sym->sec->sh.sh_size &&
15731605
end == (long)sym->sec->sh.sh_size) {
15741606

@@ -2073,35 +2105,36 @@ static int parainstructions_group_size(struct kpatch_elf *kelf, int offset)
20732105
return size;
20742106
}
20752107

2076-
static int altinstructions_group_size(struct kpatch_elf *kelf, int offset)
2108+
static int smp_locks_group_size(struct kpatch_elf *kelf, int offset)
2109+
{
2110+
return 4;
2111+
}
2112+
2113+
static int static_call_sites_group_size(struct kpatch_elf *kelf, int offset)
20772114
{
20782115
static int size = 0;
20792116
char *str;
20802117

20812118
if (!size) {
2082-
str = getenv("ALT_STRUCT_SIZE");
2119+
str = getenv("STATIC_CALL_STRUCT_SIZE");
20832120
if (!str)
2084-
ERROR("ALT_STRUCT_SIZE not set");
2121+
ERROR("STATIC_CALL_STRUCT_SIZE not set");
20852122
size = atoi(str);
20862123
}
20872124

20882125
return size;
20892126
}
2090-
2091-
static int smp_locks_group_size(struct kpatch_elf *kelf, int offset)
2092-
{
2093-
return 4;
2094-
}
2095-
2096-
static int static_call_sites_group_size(struct kpatch_elf *kelf, int offset)
2127+
#endif
2128+
#if defined(__x86_64__) || defined(__aarch64__)
2129+
static int altinstructions_group_size(struct kpatch_elf *kelf, int offset)
20972130
{
20982131
static int size = 0;
20992132
char *str;
21002133

21012134
if (!size) {
2102-
str = getenv("STATIC_CALL_STRUCT_SIZE");
2135+
str = getenv("ALT_STRUCT_SIZE");
21032136
if (!str)
2104-
ERROR("STATIC_CALL_STRUCT_SIZE not set");
2137+
ERROR("ALT_STRUCT_SIZE not set");
21052138
size = atoi(str);
21062139
}
21072140

@@ -2215,15 +2248,17 @@ static struct special_section special_sections[] = {
22152248
.name = ".parainstructions",
22162249
.group_size = parainstructions_group_size,
22172250
},
2218-
{
2219-
.name = ".altinstructions",
2220-
.group_size = altinstructions_group_size,
2221-
},
22222251
{
22232252
.name = ".static_call_sites",
22242253
.group_size = static_call_sites_group_size,
22252254
},
22262255
#endif
2256+
#if defined(__x86_64__) || defined(__aarch64__)
2257+
{
2258+
.name = ".altinstructions",
2259+
.group_size = altinstructions_group_size,
2260+
},
2261+
#endif
22272262
#ifdef __powerpc64__
22282263
{
22292264
.name = "__ftr_fixup",

kpatch-build/kpatch-build

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -375,10 +375,57 @@ find_special_section_data_ppc64le() {
375375
return
376376
}
377377

378+
find_special_section_data_aarch64() {
379+
[[ "$CONFIG_JUMP_LABEL" -eq 0 ]] && AWK_OPTIONS="-vskip_j=1"
380+
[[ "$CONFIG_PRINTK_INDEX" -eq 0 ]] && AWK_OPTIONS="$AWK_OPTIONS -vskip_i=1"
381+
382+
SPECIAL_VARS="$(readelf -wi "$VMLINUX" |
383+
gawk --non-decimal-data $AWK_OPTIONS '
384+
BEGIN { a = b = p = e = o = j = s = i = 0 }
385+
386+
# Set state if name matches
387+
a == 0 && /DW_AT_name.* alt_instr[[:space:]]*$/ {a = 1; next}
388+
b == 0 && /DW_AT_name.* bug_entry[[:space:]]*$/ {b = 1; next}
389+
e == 0 && /DW_AT_name.* exception_table_entry[[:space:]]*$/ {e = 1; next}
390+
j == 0 && /DW_AT_name.* jump_entry[[:space:]]*$/ {j = 1; next}
391+
i == 0 && /DW_AT_name.* pi_entry[[:space:]]*$/ {i = 1; next}
392+
393+
# Reset state unless this abbrev describes the struct size
394+
a == 1 && !/DW_AT_byte_size/ { a = 0; next }
395+
b == 1 && !/DW_AT_byte_size/ { b = 0; next }
396+
e == 1 && !/DW_AT_byte_size/ { e = 0; next }
397+
j == 1 && !/DW_AT_byte_size/ { j = 0; next }
398+
i == 1 && !/DW_AT_byte_size/ { i = 0; next }
399+
400+
# Now that we know the size, stop parsing for it
401+
a == 1 {printf("export ALT_STRUCT_SIZE=%d\n", $4); a = 2}
402+
b == 1 {printf("export BUG_STRUCT_SIZE=%d\n", $4); b = 2}
403+
e == 1 {printf("export EX_STRUCT_SIZE=%d\n", $4); e = 2}
404+
j == 1 {printf("export JUMP_STRUCT_SIZE=%d\n", $4); j = 2}
405+
i == 1 {printf("export PRINTK_INDEX_STRUCT_SIZE=%d\n", $4); i = 2}
406+
407+
# Bail out once we have everything
408+
a == 2 && b == 2 && e == 2 && (j == 2 || skip_j) && (i == 2 || skip_i) {exit}')"
409+
410+
[[ -n "$SPECIAL_VARS" ]] && eval "$SPECIAL_VARS"
411+
412+
[[ -z "$ALT_STRUCT_SIZE" ]] && die "can't find special struct alt_instr size"
413+
[[ -z "$BUG_STRUCT_SIZE" ]] && die "can't find special struct bug_entry size"
414+
[[ -z "$EX_STRUCT_SIZE" ]] && die "can't find special struct paravirt_patch_site size"
415+
[[ -z "$JUMP_STRUCT_SIZE" && "$CONFIG_JUMP_LABEL" -ne 0 ]] && die "can't find special struct jump_entry size"
416+
[[ -z "$PRINTK_INDEX_STRUCT_SIZE" && "$CONFIG_PRINTK_INDEX" -ne 0 ]] && die "can't find special struct pi_entry size"
417+
418+
return
419+
420+
}
421+
378422
find_special_section_data() {
379423
if [[ "$ARCH" = "ppc64le" ]]; then
380424
find_special_section_data_ppc64le
381425
return
426+
elif [[ "$ARCH" = "aarch64" ]]; then
427+
find_special_section_data_aarch64
428+
return
382429
fi
383430

384431
[[ "$CONFIG_PARAVIRT" -eq 0 ]] && AWK_OPTIONS="-vskip_p=1"

0 commit comments

Comments
 (0)