Skip to content

Commit 00082aa

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 <[email protected]> --- V1->V2: - Add # shellcheck disable=SC2086 - Add comment to kpatch_is_mapping_symbol()
1 parent bd6019c commit 00082aa

File tree

4 files changed

+107
-20
lines changed

4 files changed

+107
-20
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: 57 additions & 19 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,28 @@ static struct rela *toc_rela(const struct rela *rela)
214216
(unsigned int)rela->addend);
215217
}
216218

219+
#ifdef __aarch64__
220+
/*
221+
* Mapping symbols are used to mark and label the transitions between code and
222+
* data in elf files. They begin with a "$" dollar symbol. Don't correlate them
223+
* as they often all have the same name either "$x" to mark the start of code
224+
* or "$d" to mark the start of data.
225+
*/
226+
static bool kpatch_is_mapping_symbol(struct symbol *sym)
227+
{
228+
if (sym->name && sym->name[0] == '$'
229+
&& sym->type == STT_NOTYPE \
230+
&& sym->bind == STB_LOCAL)
231+
return 1;
232+
return 0;
233+
}
234+
#else
235+
static int kpatch_is_mapping_symbol(struct symbol *sym)
236+
{
237+
return 0;
238+
}
239+
#endif
240+
217241
/*
218242
* When compiling with -ffunction-sections and -fdata-sections, almost every
219243
* symbol gets its own dedicated section. We call such symbols "bundled"
@@ -564,6 +588,13 @@ static void kpatch_compare_correlated_section(struct section *sec)
564588
goto out;
565589
}
566590

591+
/* As above but for aarch64 */
592+
if (!strcmp(sec->name, ".rela__patchable_function_entries") ||
593+
!strcmp(sec->name, "__patchable_function_entries")) {
594+
sec->status = SAME;
595+
goto out;
596+
}
597+
567598
if (sec1->sh.sh_size != sec2->sh.sh_size ||
568599
sec1->data->d_size != sec2->data->d_size) {
569600
sec->status = CHANGED;
@@ -1030,6 +1061,9 @@ static void kpatch_correlate_symbols(struct list_head *symlist_orig,
10301061
!strncmp(sym_orig->name, ".LC", 3))
10311062
continue;
10321063

1064+
if (kpatch_is_mapping_symbol(sym_orig))
1065+
continue;
1066+
10331067
/* group section symbols must have correlated sections */
10341068
if (sym_orig->sec &&
10351069
sym_orig->sec->sh.sh_type == SHT_GROUP &&
@@ -1539,7 +1573,7 @@ static void kpatch_replace_sections_syms(struct kpatch_elf *kelf)
15391573
continue;
15401574
}
15411575

1542-
#ifdef __powerpc64__
1576+
#if defined(__powerpc64__) || defined(__aarch64__)
15431577
add_off = 0;
15441578
#else
15451579
if (rela->type == R_X86_64_PC32 ||
@@ -1571,7 +1605,8 @@ static void kpatch_replace_sections_syms(struct kpatch_elf *kelf)
15711605
end = sym->sym.st_value + sym->sym.st_size;
15721606

15731607
if (!is_text_section(sym->sec) &&
1574-
rela->type == R_X86_64_32S &&
1608+
(rela->type == R_X86_64_32S ||
1609+
rela->type == R_AARCH64_ABS64) &&
15751610
rela->addend == (long)sym->sec->sh.sh_size &&
15761611
end == (long)sym->sec->sh.sh_size) {
15771612

@@ -2047,35 +2082,36 @@ static int parainstructions_group_size(struct kpatch_elf *kelf, int offset)
20472082
return size;
20482083
}
20492084

2050-
static int altinstructions_group_size(struct kpatch_elf *kelf, int offset)
2085+
static int smp_locks_group_size(struct kpatch_elf *kelf, int offset)
2086+
{
2087+
return 4;
2088+
}
2089+
2090+
static int static_call_sites_group_size(struct kpatch_elf *kelf, int offset)
20512091
{
20522092
static int size = 0;
20532093
char *str;
20542094

20552095
if (!size) {
2056-
str = getenv("ALT_STRUCT_SIZE");
2096+
str = getenv("STATIC_CALL_STRUCT_SIZE");
20572097
if (!str)
2058-
ERROR("ALT_STRUCT_SIZE not set");
2098+
ERROR("STATIC_CALL_STRUCT_SIZE not set");
20592099
size = atoi(str);
20602100
}
20612101

20622102
return size;
20632103
}
2064-
2065-
static int smp_locks_group_size(struct kpatch_elf *kelf, int offset)
2066-
{
2067-
return 4;
2068-
}
2069-
2070-
static int static_call_sites_group_size(struct kpatch_elf *kelf, int offset)
2104+
#endif
2105+
#if defined(__x86_64__) || defined(__aarch64__)
2106+
static int altinstructions_group_size(struct kpatch_elf *kelf, int offset)
20712107
{
20722108
static int size = 0;
20732109
char *str;
20742110

20752111
if (!size) {
2076-
str = getenv("STATIC_CALL_STRUCT_SIZE");
2112+
str = getenv("ALT_STRUCT_SIZE");
20772113
if (!str)
2078-
ERROR("STATIC_CALL_STRUCT_SIZE not set");
2114+
ERROR("ALT_STRUCT_SIZE not set");
20792115
size = atoi(str);
20802116
}
20812117

@@ -2189,15 +2225,17 @@ static struct special_section special_sections[] = {
21892225
.name = ".parainstructions",
21902226
.group_size = parainstructions_group_size,
21912227
},
2192-
{
2193-
.name = ".altinstructions",
2194-
.group_size = altinstructions_group_size,
2195-
},
21962228
{
21972229
.name = ".static_call_sites",
21982230
.group_size = static_call_sites_group_size,
21992231
},
22002232
#endif
2233+
#if defined(__x86_64__) || defined(__aarch64__)
2234+
{
2235+
.name = ".altinstructions",
2236+
.group_size = altinstructions_group_size,
2237+
},
2238+
#endif
22012239
#ifdef __powerpc64__
22022240
{
22032241
.name = "__ftr_fixup",

kpatch-build/kpatch-build

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -375,10 +375,58 @@ 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+
# shellcheck disable=SC2086
383+
SPECIAL_VARS="$(readelf -wi "$VMLINUX" |
384+
gawk --non-decimal-data $AWK_OPTIONS '
385+
BEGIN { a = b = p = e = o = j = s = i = 0 }
386+
387+
# Set state if name matches
388+
a == 0 && /DW_AT_name.* alt_instr[[:space:]]*$/ {a = 1; next}
389+
b == 0 && /DW_AT_name.* bug_entry[[:space:]]*$/ {b = 1; next}
390+
e == 0 && /DW_AT_name.* exception_table_entry[[:space:]]*$/ {e = 1; next}
391+
j == 0 && /DW_AT_name.* jump_entry[[:space:]]*$/ {j = 1; next}
392+
i == 0 && /DW_AT_name.* pi_entry[[:space:]]*$/ {i = 1; next}
393+
394+
# Reset state unless this abbrev describes the struct size
395+
a == 1 && !/DW_AT_byte_size/ { a = 0; next }
396+
b == 1 && !/DW_AT_byte_size/ { b = 0; next }
397+
e == 1 && !/DW_AT_byte_size/ { e = 0; next }
398+
j == 1 && !/DW_AT_byte_size/ { j = 0; next }
399+
i == 1 && !/DW_AT_byte_size/ { i = 0; next }
400+
401+
# Now that we know the size, stop parsing for it
402+
a == 1 {printf("export ALT_STRUCT_SIZE=%d\n", $4); a = 2}
403+
b == 1 {printf("export BUG_STRUCT_SIZE=%d\n", $4); b = 2}
404+
e == 1 {printf("export EX_STRUCT_SIZE=%d\n", $4); e = 2}
405+
j == 1 {printf("export JUMP_STRUCT_SIZE=%d\n", $4); j = 2}
406+
i == 1 {printf("export PRINTK_INDEX_STRUCT_SIZE=%d\n", $4); i = 2}
407+
408+
# Bail out once we have everything
409+
a == 2 && b == 2 && e == 2 && (j == 2 || skip_j) && (i == 2 || skip_i) {exit}')"
410+
411+
[[ -n "$SPECIAL_VARS" ]] && eval "$SPECIAL_VARS"
412+
413+
[[ -z "$ALT_STRUCT_SIZE" ]] && die "can't find special struct alt_instr size"
414+
[[ -z "$BUG_STRUCT_SIZE" ]] && die "can't find special struct bug_entry size"
415+
[[ -z "$EX_STRUCT_SIZE" ]] && die "can't find special struct paravirt_patch_site size"
416+
[[ -z "$JUMP_STRUCT_SIZE" && "$CONFIG_JUMP_LABEL" -ne 0 ]] && die "can't find special struct jump_entry size"
417+
[[ -z "$PRINTK_INDEX_STRUCT_SIZE" && "$CONFIG_PRINTK_INDEX" -ne 0 ]] && die "can't find special struct pi_entry size"
418+
419+
return
420+
421+
}
422+
378423
find_special_section_data() {
379424
if [[ "$ARCH" = "ppc64le" ]]; then
380425
find_special_section_data_ppc64le
381426
return
427+
elif [[ "$ARCH" = "aarch64" ]]; then
428+
find_special_section_data_aarch64
429+
return
382430
fi
383431

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

0 commit comments

Comments
 (0)