<version: ES1>
Overview
이번 포스트에서는 커널 v5.10에 반영된 boottime-trace를 소개합니다. 관련 문서는 아래 링크에서 확인할 수 있습니다.
강의 동영상 링크는 다음과 같습니다.
boottime-trace는 커멘드 라인을 통해 ftrace 설정을 해서 부팅 과정에서 ftrace의 주요 기능을 enable하는 기능입니다. 위 링크에서 소개된 패치는 initrd가 존재해야 효과가 있어(ex: 우분투), 배포판마다 활성화가 하기는 어렵습니다. 안드로이드나 크로뮴 OS에서는 initrd을 사용하지 않습니다.
소스 분석
v5.15 버전의 리눅스 커널 소스에서 확인한 디렉토리에서 커맨드 라인을 읽는 ftrace 옵션과 콜백 함수 리스트는 아래와 같습니다. ('kernel/trace'에서 서칭 )
$ egrep -nr __setup *
ftrace.c:5526:__setup("ftrace_notrace=", set_ftrace_notrace);
ftrace.c:5534:__setup("ftrace_filter=", set_ftrace_filter);
ftrace.c:5546:__setup("ftrace_graph_filter=", set_graph_function);
ftrace.c:5553:__setup("ftrace_graph_notrace=", set_graph_notrace_function);
ftrace.c:5562:__setup("ftrace_graph_max_depth=", set_graph_max_depth_function);
trace.c:197:__setup("ftrace=", set_cmdline_ftrace);
trace.c:213:__setup("ftrace_dump_on_oops", set_ftrace_dump_on_oops);
trace.c:221:__setup("traceoff_on_warning", stop_trace_on_warning);
trace.c:230:__setup("alloc_snapshot", boot_alloc_snapshot);
trace.c:240:__setup("trace_options=", set_trace_boot_options);
trace.c:251:__setup("trace_clock=", set_trace_boot_clock);
trace.c:263:__setup("tp_printk", set_tracepoint_printk);
trace.c:270:__setup("tp_printk_stop_on_boot", set_tracepoint_printk_stop);
trace.c:1507:__setup("trace_buf_size=", set_buf_size);
trace.c:1522:__setup("tracing_thresh=", set_tracing_thresh);
trace_events.c:3438:__setup("trace_event=", setup_trace_event);
trace_kprobe.c:36:__setup("kprobe_event=", set_kprobe_boot_events);
trace_stack.c:552:__setup("stacktrace", enable_stacktrace);
커맨드 라인에 boottime-trace 설정하기
크로뮴 OS
먼저 크로뮴 OS에서 아래 패치를 적용하면 커멘드 라인이 업데이트됩니다.
diff --git a/chromeos/config/x86_64/chromiumos-x86_64.flavour.config b/chromeos/config/x86_64/chromiumos-x86_64.flavour.config
index 084c67d005dd..ad8f8bddc233 100644
— a/chromeos/config/x86_64/chromiumos-x86_64.flavour.config
+++ b/chromeos/config/x86_64/chromiumos-x86_64.flavour.config
+CONFIG_CMDLINE="crashkernel=512M ftrace=function ftrace_filter=*_probe*
+CONFIG_CMDLINE_BOOL=y
'ftrace=function ftrace_filter=*_probe*'이 핵심 구문입니다.
라즈비안
이번에는 라즈비안에서 boottime-trace 커맨드 라인을 추가하는 방법을 소개합니다. 라즈비안은 디바이스 트리에서 부트 커멘트 라인을 업데이트할 수 있습니다. 아래는 arm32 기반 라즈비안에서 커멘드 라인을 수정하는 패치입니다. (소스 베이스: v5.15.33)
diff --git a/arch/arm/boot/dts/bcm2711-rpi-4-b.dts b/arch/arm/boot/dts/bcm2711-rpi-4-b.dts
index 8c0ab39..47e552e 100644
--- a/arch/arm/boot/dts/bcm2711-rpi-4-b.dts
+++ b/arch/arm/boot/dts/bcm2711-rpi-4-b.dts
@@ -282,7 +282,7 @@
/ {
chosen {
- bootargs = "coherent_pool=1M 8250.nr_uarts=1 snd_bcm2835.enable_compat_alsa=0 snd_bcm2835.enable_hdmi=1";
+ bootargs = "coherent_pool=1M 8250.nr_uarts=1 snd_bcm2835.enable_compat_alsa=0 snd_bcm2835.enable_hdmi=1 ftrace=function ftrace_filter=*_probe*";
};
aliases {
위 패치는 Arm64 기반 라즈비안에 적용됩니다. bcm2711-rpi-4-b.dts 파일을 열면 "arm/boot/dts/bcm2711-rpi-4-b.dts"을 include하기 때문입니다.
arch/arm64/boot/dts/broadcom/bcm2711-rpi-4-b.dts
#include "../../../../arm/boot/dts/bcm2711-rpi-4-b.dts"
(리서치 1)
검색 과정에서 사용한 명령어는 다음과 같습니다.
rpi_5_15_src/linux/arch/arm/boot/dts$ find . -name "bcm271*.*" -type f | xargs grep bootargs
./bcm2711-rpi-cm4.dts: bootargs = "coherent_pool=1M 8250.nr_uarts=1 snd_bcm2835.enable_compat_alsa=0 snd_bcm2835.enable_hdmi=1";
./bcm2711-rpi-4-b.dts: bootargs = "coherent_pool=1M 8250.nr_uarts=1 snd_bcm2835.enable_compat_alsa=0 snd_bcm2835.enable_hdmi=1 ftrace=function ftrace_filter=*_probe*";
./bcm2711-rpi-400.dts: bootargs = "coherent_pool=1M 8250.nr_uarts=1 snd_bcm2835.enable_compat_alsa=0 snd_bcm2835.enable_hdmi=1";
./bcm2710-rpi-3-b.dts: bootargs = "coherent_pool=1M 8250.nr_uarts=1 snd_bcm2835.enable_compat_alsa=0 snd_bcm2835.enable_hdmi=1";
./bcm2710-rpi-zero-2-w.dts: bootargs = "coherent_pool=1M 8250.nr_uarts=1 snd_bcm2835.enable_compat_alsa=0 snd_bcm2835.enable_hdmi=1";
./bcm2710-rpi-3-b-plus.dts: bootargs = "coherent_pool=1M 8250.nr_uarts=1 snd_bcm2835.enable_compat_alsa=0 snd_bcm2835.enable_hdmi=1";
./bcm2711-rpi-cm4s.dts: bootargs = "coherent_pool=1M 8250.nr_uarts=1 snd_bcm2835.enable_compat_alsa=0 snd_bcm2835.enable_hdmi=1";
각각 서로 다른 라즈베리 파이에 대해 다음 파일이 적용됩니다.
modified: arch/arm/boot/dts/bcm2711-rpi-4-b.dts
modified: arch/arm/boot/dts/bcm2711-rpi-400.dts
modified: arch/arm/boot/dts/bcm2711-rpi-cm4s.dts
(리서치 2)
CONFIG_ARCH_BCM_2835가 bcm2711_defconfig에 enable돼 있습니다.
out64/.config
...
293 # CONFIG_ARCH_APPLE is not set
294 CONFIG_ARCH_BCM2835=y
295 # CONFIG_ARCH_BCM4908 is not set
296 # CONFIG_ARCH_BCM_IPROC is not set
ARCH_BCM_2835를 Makefile에서 검색해 bcm27* dtb 파일이 빌드에 포함됨을 확인했습니다.
arch/arm64/boot/dts/broadcom/Makefile
# SPDX-License-Identifier: GPL-2.0
dtb-$(CONFIG_ARCH_BCM2835) += bcm2711-rpi-400.dtb \
bcm2711-rpi-4-b.dtb \
bcm2837-rpi-3-a-plus.dtb \
bcm2837-rpi-3-b.dtb \
bcm2837-rpi-3-b-plus.dtb \
bcm2837-rpi-cm3-io3.dtb
dtb-$(CONFIG_ARCH_BCM2835) += bcm2710-rpi-zero-2.dtb
dtb-$(CONFIG_ARCH_BCM2835) += bcm2710-rpi-2-b.dtb
dtb-$(CONFIG_ARCH_BCM2835) += bcm2710-rpi-3-b.dtb
dtb-$(CONFIG_ARCH_BCM2835) += bcm2710-rpi-3-b-plus.dtb
dtb-$(CONFIG_ARCH_BCM2835) += bcm2711-rpi-4-b.dtb
dtb-$(CONFIG_ARCH_BCM2835) += bcm2711-rpi-400.dtb
dtb-$(CONFIG_ARCH_BCM2835) += bcm2710-rpi-cm3.dtb
dtb-$(CONFIG_ARCH_BCM2835) += bcm2711-rpi-cm4.dtb
subdir-y += bcm4908
subdir-y += northstar2
subdir-y += stingray
# Enable fixups to support overlays on BCM2835 platforms
ifeq ($(CONFIG_ARCH_BCM2835),y)
DTC_FLAGS += -@
endif
샘플 ftrace 메시지
부트 커멘드 라인으로 "ftrace=function ftrace_filter=*initcall*"을 적용한 후
받은 ftrace 메시지는 다음과 같습니다.
# tracer: function
#
# entries-in-buffer/entries-written: 6800/6800 #P:4
#
# _-----=> irqs-off
# / _----=> need-resched
# | / _---=> hardirq/softirq
# || / _--=> preempt-depth
# ||| / delay
# TASK-PID CPU# |||| TIMESTAMP FUNCTION
# | | | |||| | |
<idle>-0 [000] d..1 0.250968: arch_probe_nr_irqs <-early_irq_init
<idle>-0 [000] ...1 0.252607: physflat_probe <-default_setup_apic_routing
<idle>-0 [000] ...1 0.252608: flat_probe <-default_setup_apic_routing
init-1 [000] .... 0.270282: watchdog_nmi_probe <-lockup_detector_init
init-1 [000] .... 0.281332: bus_probe_device <-device_add
init-1 [000] .... 0.281348: add_probe_files <-bus_register
...
init-1 [002] d..2 0.641288: sched_switch: prev_comm=swapper/0 prev_pid=1 prev_prio=120 prev_state=D ==> next_comm=swapper/2 next_pid=0 next_prio=120
<idle>-0 [003] d..2 0.641309: sched_switch: prev_comm=swapper/3 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=kworker/u8:1 next_pid=76 next_prio=120
kworker/u8:1-76 [003] d..2 0.641337: sched_switch: prev_comm=kworker/u8:1 prev_pid=76 prev_prio=120 prev_state=R+ ==> next_comm=irq/42-mmc1 next_pid=107 next_prio=49
irq/42-mmc1-107 [003] d..2 0.641396: sched_switch: prev_comm=irq/42-mmc1 prev_pid=107 prev_prio=49 prev_state=S ==> next_comm=kworker/u8:1 next_pid=76 next_prio=120
kworker/u8:1-76 [003] d..2 0.641407: sched_switch: prev_comm=kworker/u8:1 prev_pid=76 prev_prio=120 prev_state=S ==> next_comm=swapper/3 next_pid=0 next_prio=120
<idle>-0 [002] d..2 0.641408: sched_switch: prev_comm=swapper/2 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=kworker/u8:1 next_pid=125 next_prio=120
<idle>-0 [001] d..2 0.641414: sched_switch: prev_comm=swapper/1 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=kworker/1:0 next_pid=20 next_prio=120
kworker/1:0-20 [001] d..2 0.641458: sched_switch: prev_comm=kworker/1:0 prev_pid=20 prev_prio=120 prev_state=D ==> next_comm=swapper/1 next_pid=0 next_prio=120
kworker/u8:1-125 [002] d..2 0.641476: signal_generate: sig=17 errno=0 code=1 comm=kworker/u8:1 pid=76 grp=1 res=1
kworker/u8:1-125 [002] d..2 0.641482: sched_switch: prev_comm=kworker/u8:1 prev_pid=125 prev_prio=120 prev_state=Z ==> next_comm=swapper/2 next_pid=0 next_prio=120
<idle>-0 [003] d..2 0.641483: sched_switch: prev_comm=swapper/3 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=kworker/u8:1 next_pid=76 next_prio=120
kworker/u8:1-76 [003] d..2 0.641492: sched_switch: prev_comm=kworker/u8:1 prev_pid=76 prev_prio=120 prev_state=I ==> next_comm=swapper/3 next_pid=0 next_prio=120
<idle>-0 [002] d..2 0.641494: sched_switch: prev_comm=swapper/2 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=swapper/0 next_pid=1 next_prio=120
init-1 [002] d..2 0.641502: sched_switch: prev_comm=swapper/0 prev_pid=1 prev_prio=120 prev_state=D ==> next_comm=swapper/2 next_pid=0 next_prio=120
<idle>-0 [003] d..2 0.641504: sched_switch: prev_comm=swapper/3 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=kworker/u8:1 next_pid=76 next_prio=120
kworker/u8:1-76 [003] d..2 0.641520: sched_switch: prev_comm=kworker/u8:1 prev_pid=76 prev_prio=120 prev_state=S ==> next_comm=swapper/3 next_pid=0 next_prio=120
<idle>-0 [002] d..2 0.641521: sched_switch: prev_comm=swapper/2 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=kworker/u8:1 next_pid=126 next_prio=120
kworker/u8:1-126 [002] d..2 0.641543: signal_generate: sig=17 errno=0 code=1 comm=kworker/u8:1 pid=76 grp=1 res=1
kworker/u8:1-126 [002] d..2 0.641548: sched_switch: prev_comm=kworker/u8:1 prev_pid=126 prev_prio=120 prev_state=Z ==> next_comm=swapper/2 next_pid=0 next_prio=120
<idle>-0 [003] d..2 0.641549: sched_switch: prev_comm=swapper/3 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=kworker/u8:1 next_pid=76 next_prio=120
kworker/u8:1-76 [003] d..2 0.641555: sched_switch: prev_comm=kworker/u8:1 prev_pid=76 prev_prio=120 prev_state=I ==> next_comm=swapper/3 next_pid=0 next_prio=120
<idle>-0 [002] d..2 0.641557: sched_switch: prev_comm=swapper/2 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=swapper/0 next_pid=1 next_prio=120
init-1 [002] d..2 0.641565: sched_switch: prev_comm=swapper/0 prev_pid=1 prev_prio=120 prev_state=D ==> next_comm=swapper/2 next_pid=0 next_prio=120
<idle>-0 [001] d..2 0.641586: sched_switch: prev_comm=swapper/1 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=kthreadd next_pid=2 next_prio=120
kthreadd-2 [001] d..2 0.641612: sched_switch: prev_comm=kthreadd prev_pid=2 prev_prio=120 prev_state=S ==> next_comm=swapper/1 next_pid=0 next_prio=120
<idle>-0 [002] d..2 0.641613: sched_switch: prev_comm=swapper/2 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=kthreadd next_pid=127 next_prio=120
cryptomgr_probe-127 [002] d..2 0.641619: sched_switch: prev_comm=kthreadd prev_pid=127 prev_prio=120 prev_state=D ==> next_comm=swapper/2 next_pid=0 next_prio=120
<idle>-0 [003] d..2 0.641620: sched_switch: prev_comm=swapper/3 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=swapper/0 next_pid=1 next_prio=120
init-1 [003] d..2 0.641628: sched_switch: prev_comm=swapper/0 prev_pid=1 prev_prio=120 prev_state=D ==> next_comm=swapper/3 next_pid=0 next_prio=120
<idle>-0 [002] d..2 0.641629: sched_switch: prev_comm=swapper/2 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=cryptomgr_probe next_pid=127 next_prio=120
cryptomgr_probe-127 [002] .... 0.641630: cryptomgr_probe <-kthread
...
init-1 [001] .... 0.642319: driver_deferred_probe_trigger <-deferred_probe_initcall
init-1 [001] d..2 0.642321: sched_switch: prev_comm=swapper/0 prev_pid=1 prev_prio=120 prev_state=D ==> next_comm=kworker/1:4 next_pid=109 next_prio=120
kworker/1:4-109 [001] .... 0.642321: deferred_probe_work_func <-process_one_work
kworker/1:4-109 [001] d..2 0.642323: sched_switch: prev_comm=kworker/1:4 prev_pid=109 prev_prio=120 prev_state=R+ ==> next_comm=swapper/0 next_pid=1 next_prio=120
init-1 [001] d..1 0.642327: console: [ 0.640227] PM: Magic number: 10:467:470
<idle>-0 [002] d.h3 0.642461: console: [ 0.640361] atkbd serio0: Unknown key released (translated set 2, code 0x7c on isa0060/serio0).
<idle>-0 [002] d.h3 0.642464: console: [ 0.640365] atkbd serio0: Use 'setkeycodes 7c <keycode>' to make it known.
init-1 [001] d..1 0.642535: console: [ 0.640435] ALSA device list:
init-1 [001] d..1 0.642539: console: [ 0.640440] No soundcards found.
init-1 [001] d..1 0.642558: console: [ 0.640459] Warning: unable to open an initial console. Fallback to ttynull.
init-1 [001] d..1 0.642563: console: [ 0.640464] printk: console [ttynull0] enabled
init-1 [001] d..2 0.642587: sched_switch: prev_comm=swapper/0 prev_pid=1 prev_prio=120 prev_state=D ==> next_comm=kworker/1:4 next_pid=109 next_prio=120
kworker/1:4-109 [001] d..2 0.642590: sched_switch: prev_comm=kworker/1:4 prev_pid=109 prev_prio=120 prev_state=I ==> next_comm=swapper/1 next_pid=0 next_prio=120
<idle>-0 [002] d..2 0.642630: sched_switch: prev_comm=swapper/2 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=irq/39-mmc0 next_pid=105 next_prio=49
<idle>-0 [001] d..2 0.642670: sched_switch: prev_comm=swapper/1 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=kworker/1:0 next_pid=20 next_prio=120
'Core BSP 분석 > 리눅스 커널 핵심 분석' 카테고리의 다른 글
중요 사이트: 리눅스 커널 디바이스 드라이버 (0) | 2023.05.07 |
---|---|
[리눅스커널] 특정 슬럽 오브젝트 트레이싱 (0) | 2023.05.07 |
[리눅스커널] LKDTM(Linux Kernel Dump Test Module) 소개 -c (0) | 2023.05.07 |
[리눅스커널] IPI Call 요청: SGI(Software Generated Interrupt) 요청 (로우 레벨 뷰) (0) | 2023.05.07 |
[리눅스커널] IPI(Inter Processor Interrupt) Call 요청 루틴(하이 레벨 뷰) (0) | 2023.05.07 |