Skip to content

Commit 72b3942

Browse files
Yinan Liurostedt
authored andcommitted
scripts: ftrace - move the sort-processing in ftrace_init
When the kernel starts, the initialization of ftrace takes up a portion of the time (approximately 6~8ms) to sort mcount addresses. We can save this time by moving mcount-sorting to compile time. Link: https://lkml.kernel.org/r/[email protected] Signed-off-by: Yinan Liu <[email protected]> Reported-by: kernel test robot <[email protected]> Reported-by: kernel test robot <[email protected]> Signed-off-by: Steven Rostedt <[email protected]>
1 parent 1c1857d commit 72b3942

File tree

5 files changed

+137
-8
lines changed

5 files changed

+137
-8
lines changed

kernel/trace/ftrace.c

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6406,8 +6406,15 @@ static int ftrace_process_locs(struct module *mod,
64066406
if (!count)
64076407
return 0;
64086408

6409-
sort(start, count, sizeof(*start),
6410-
ftrace_cmp_ips, NULL);
6409+
/*
6410+
* Sorting mcount in vmlinux at build time depend on
6411+
* CONFIG_BUILDTIME_TABLE_SORT, while mcount loc in
6412+
* modules can not be sorted at build time.
6413+
*/
6414+
if (!IS_ENABLED(CONFIG_BUILDTIME_TABLE_SORT) || mod) {
6415+
sort(start, count, sizeof(*start),
6416+
ftrace_cmp_ips, NULL);
6417+
}
64116418

64126419
start_pg = ftrace_allocate_pages(count);
64136420
if (!start_pg)

scripts/Makefile

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ hostprogs-always-$(CONFIG_SYSTEM_EXTRA_CERTIFICATE) += insert-sys-cert
1717
hostprogs-always-$(CONFIG_SYSTEM_REVOCATION_LIST) += extract-cert
1818

1919
HOSTCFLAGS_sorttable.o = -I$(srctree)/tools/include
20+
HOSTLDLIBS_sorttable = -lpthread
2021
HOSTCFLAGS_asn1_compiler.o = -I$(srctree)/include
2122
HOSTCFLAGS_sign-file.o = $(CRYPTO_CFLAGS)
2223
HOSTLDLIBS_sign-file = $(CRYPTO_LIBS)
@@ -29,7 +30,10 @@ ARCH := x86
2930
endif
3031
HOSTCFLAGS_sorttable.o += -I$(srctree)/tools/arch/x86/include
3132
HOSTCFLAGS_sorttable.o += -DUNWINDER_ORC_ENABLED
32-
HOSTLDLIBS_sorttable = -lpthread
33+
endif
34+
35+
ifdef CONFIG_DYNAMIC_FTRACE
36+
HOSTCFLAGS_sorttable.o += -DMCOUNT_SORT_ENABLED
3337
endif
3438

3539
# The following programs are only built on demand

scripts/link-vmlinux.sh

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -400,6 +400,9 @@ if [ -n "${CONFIG_DEBUG_INFO_BTF}" -a -n "${CONFIG_BPF}" ]; then
400400
${RESOLVE_BTFIDS} vmlinux
401401
fi
402402

403+
info SYSMAP System.map
404+
mksysmap vmlinux System.map
405+
403406
if [ -n "${CONFIG_BUILDTIME_TABLE_SORT}" ]; then
404407
info SORTTAB vmlinux
405408
if ! sorttable vmlinux; then
@@ -408,9 +411,6 @@ if [ -n "${CONFIG_BUILDTIME_TABLE_SORT}" ]; then
408411
fi
409412
fi
410413

411-
info SYSMAP System.map
412-
mksysmap vmlinux System.map
413-
414414
# step a (see comment above)
415415
if [ -n "${CONFIG_KALLSYMS}" ]; then
416416
mksysmap ${kallsyms_vmlinux} .tmp_System.map

scripts/sorttable.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@
3030
#include <stdlib.h>
3131
#include <string.h>
3232
#include <unistd.h>
33+
#include <errno.h>
34+
#include <pthread.h>
3335

3436
#include <tools/be_byteshift.h>
3537
#include <tools/le_byteshift.h>

scripts/sorttable.h

Lines changed: 118 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@
1919

2020
#undef extable_ent_size
2121
#undef compare_extable
22+
#undef get_mcount_loc
23+
#undef sort_mcount_loc
24+
#undef elf_mcount_loc
2225
#undef do_sort
2326
#undef Elf_Addr
2427
#undef Elf_Ehdr
@@ -41,6 +44,9 @@
4144
#ifdef SORTTABLE_64
4245
# define extable_ent_size 16
4346
# define compare_extable compare_extable_64
47+
# define get_mcount_loc get_mcount_loc_64
48+
# define sort_mcount_loc sort_mcount_loc_64
49+
# define elf_mcount_loc elf_mcount_loc_64
4450
# define do_sort do_sort_64
4551
# define Elf_Addr Elf64_Addr
4652
# define Elf_Ehdr Elf64_Ehdr
@@ -62,6 +68,9 @@
6268
#else
6369
# define extable_ent_size 8
6470
# define compare_extable compare_extable_32
71+
# define get_mcount_loc get_mcount_loc_32
72+
# define sort_mcount_loc sort_mcount_loc_32
73+
# define elf_mcount_loc elf_mcount_loc_32
6574
# define do_sort do_sort_32
6675
# define Elf_Addr Elf32_Addr
6776
# define Elf_Ehdr Elf32_Ehdr
@@ -84,8 +93,6 @@
8493

8594
#if defined(SORTTABLE_64) && defined(UNWINDER_ORC_ENABLED)
8695
/* ORC unwinder only support X86_64 */
87-
#include <errno.h>
88-
#include <pthread.h>
8996
#include <asm/orc_types.h>
9097

9198
#define ERRSTR_MAXSZ 256
@@ -191,7 +198,64 @@ static int compare_extable(const void *a, const void *b)
191198
return 1;
192199
return 0;
193200
}
201+
#ifdef MCOUNT_SORT_ENABLED
202+
struct elf_mcount_loc {
203+
Elf_Ehdr *ehdr;
204+
Elf_Shdr *init_data_sec;
205+
uint_t start_mcount_loc;
206+
uint_t stop_mcount_loc;
207+
};
208+
209+
/* Sort the addresses stored between __start_mcount_loc to __stop_mcount_loc in vmlinux */
210+
static void *sort_mcount_loc(void *arg)
211+
{
212+
struct elf_mcount_loc *emloc = (struct elf_mcount_loc *)arg;
213+
uint_t offset = emloc->start_mcount_loc - _r(&(emloc->init_data_sec)->sh_addr)
214+
+ _r(&(emloc->init_data_sec)->sh_offset);
215+
uint_t count = emloc->stop_mcount_loc - emloc->start_mcount_loc;
216+
unsigned char *start_loc = (void *)emloc->ehdr + offset;
217+
218+
qsort(start_loc, count/sizeof(uint_t), sizeof(uint_t), compare_extable);
219+
return NULL;
220+
}
221+
222+
/* Get the address of __start_mcount_loc and __stop_mcount_loc in System.map */
223+
static void get_mcount_loc(uint_t *_start, uint_t *_stop)
224+
{
225+
FILE *file_start, *file_stop;
226+
char start_buff[20];
227+
char stop_buff[20];
228+
int len = 0;
229+
230+
file_start = popen(" grep start_mcount System.map | awk '{print $1}' ", "r");
231+
if (!file_start) {
232+
fprintf(stderr, "get start_mcount_loc error!");
233+
return;
234+
}
235+
236+
file_stop = popen(" grep stop_mcount System.map | awk '{print $1}' ", "r");
237+
if (!file_stop) {
238+
fprintf(stderr, "get stop_mcount_loc error!");
239+
pclose(file_start);
240+
return;
241+
}
242+
243+
while (fgets(start_buff, sizeof(start_buff), file_start) != NULL) {
244+
len = strlen(start_buff);
245+
start_buff[len - 1] = '\0';
246+
}
247+
*_start = strtoul(start_buff, NULL, 16);
248+
249+
while (fgets(stop_buff, sizeof(stop_buff), file_stop) != NULL) {
250+
len = strlen(stop_buff);
251+
stop_buff[len - 1] = '\0';
252+
}
253+
*_stop = strtoul(stop_buff, NULL, 16);
194254

255+
pclose(file_start);
256+
pclose(file_stop);
257+
}
258+
#endif
195259
static int do_sort(Elf_Ehdr *ehdr,
196260
char const *const fname,
197261
table_sort_t custom_sort)
@@ -217,6 +281,12 @@ static int do_sort(Elf_Ehdr *ehdr,
217281
int idx;
218282
unsigned int shnum;
219283
unsigned int shstrndx;
284+
#ifdef MCOUNT_SORT_ENABLED
285+
struct elf_mcount_loc mstruct;
286+
uint_t _start_mcount_loc = 0;
287+
uint_t _stop_mcount_loc = 0;
288+
pthread_t mcount_sort_thread;
289+
#endif
220290
#if defined(SORTTABLE_64) && defined(UNWINDER_ORC_ENABLED)
221291
unsigned int orc_ip_size = 0;
222292
unsigned int orc_size = 0;
@@ -253,6 +323,17 @@ static int do_sort(Elf_Ehdr *ehdr,
253323
symtab_shndx = (Elf32_Word *)((const char *)ehdr +
254324
_r(&s->sh_offset));
255325

326+
#ifdef MCOUNT_SORT_ENABLED
327+
/* locate the .init.data section in vmlinux */
328+
if (!strcmp(secstrings + idx, ".init.data")) {
329+
get_mcount_loc(&_start_mcount_loc, &_stop_mcount_loc);
330+
mstruct.ehdr = ehdr;
331+
mstruct.init_data_sec = s;
332+
mstruct.start_mcount_loc = _start_mcount_loc;
333+
mstruct.stop_mcount_loc = _stop_mcount_loc;
334+
}
335+
#endif
336+
256337
#if defined(SORTTABLE_64) && defined(UNWINDER_ORC_ENABLED)
257338
/* locate the ORC unwind tables */
258339
if (!strcmp(secstrings + idx, ".orc_unwind_ip")) {
@@ -294,6 +375,23 @@ static int do_sort(Elf_Ehdr *ehdr,
294375
goto out;
295376
}
296377
#endif
378+
379+
#ifdef MCOUNT_SORT_ENABLED
380+
if (!mstruct.init_data_sec || !_start_mcount_loc || !_stop_mcount_loc) {
381+
fprintf(stderr,
382+
"incomplete mcount's sort in file: %s\n",
383+
fname);
384+
goto out;
385+
}
386+
387+
/* create thread to sort mcount_loc concurrently */
388+
if (pthread_create(&mcount_sort_thread, NULL, &sort_mcount_loc, &mstruct)) {
389+
fprintf(stderr,
390+
"pthread_create mcount_sort_thread failed '%s': %s\n",
391+
strerror(errno), fname);
392+
goto out;
393+
}
394+
#endif
297395
if (!extab_sec) {
298396
fprintf(stderr, "no __ex_table in file: %s\n", fname);
299397
goto out;
@@ -376,5 +474,23 @@ static int do_sort(Elf_Ehdr *ehdr,
376474
}
377475
}
378476
#endif
477+
478+
#ifdef MCOUNT_SORT_ENABLED
479+
if (mcount_sort_thread) {
480+
void *retval = NULL;
481+
/* wait for mcount sort done */
482+
rc = pthread_join(mcount_sort_thread, &retval);
483+
if (rc) {
484+
fprintf(stderr,
485+
"pthread_join failed '%s': %s\n",
486+
strerror(errno), fname);
487+
} else if (retval) {
488+
rc = -1;
489+
fprintf(stderr,
490+
"failed to sort mcount '%s': %s\n",
491+
(char *)retval, fname);
492+
}
493+
}
494+
#endif
379495
return rc;
380496
}

0 commit comments

Comments
 (0)