<리눅스 커널 자료>

 

Linux 6.10:

https://kernelnewbies.org/Linux_6.10 
https://lwn.net/Articles/973687/
https://lwn.net/Articles/974869 

Linux 6.11:

https://kernelnewbies.org/Linux_6.11 
https://lwn.net/Articles/982034 
 https://lwn.net/Articles/983760 

 

<유익한 자료>

 

문c 블로그:
http://jake.dothome.co.kr/

SiFive blog:

https://www.five-embeddev.com/

Linux foundation:
https://training.linuxfoundation.org/training/porting-software-to-risc-v-lfd114/

Practical Debugging for Embedded RISC‑V

https://www.amazon.com/Practical-Debugging-Embedded-RISC%E2%80%91V-RISCV-Based/dp/1806699354/

https://www.inflearn.com/roadmaps/9218  

 

 

필수 유틸리티 설치:

$ sudo apt-get install texinfo git build-essential bison zlib1g-dev libncurses5-dev libncursesw5-dev  pkg-config flex swig libgmp-dev libmpfr-dev libmpc-dev -y

Crash Utility 소스 내려 받기:

$ git clone https://github.com/crash-utility/crash

Crash Utility 소스 빌드:

$ cd crash
$ make target=RISCV64
...
TARGET: RISCV64
 CRASH: 9.0.1++
   GDB: 16.2
[...]
ar -rs crashlib.a main.o tools.o global_data.o memory.o
[...]
ar: creating crashlib.a
CXXLD  gdb

Crash utility 실행:

- 빌드가 마무리되면 crash 파일이 생성됨. 
- crash 파일에 실행 권한을 부여하고 (chmod 777 crash) vmcore와 vmlinux 디렉터리로 이동

$ ./crash vmcore vmlinux

crash 8.0.5++

Copyright (C) 2002-2024  Red Hat, Inc.
Copyright (C) 2004, 2005, 2006, 2010  IBM Corporation
...
    KERNEL: vmlinux  [TAINTED]
    DUMPFILE: vmcore
        CPUS: 4
[...]
    NODENAME: starfive
     RELEASE: 6.6.20+
     VERSION: #13 SMP Mon Aug 19 12:58:52 KST 2024
     MACHINE: riscv64  (unknown Mhz)    

 

 

RISC-V 기반의 리눅스 커널에서는,
do_irq() 함수에서 인터럽트에 대한 처리를 수행한다:

arch/riscv/kernel/traps.c
asmlinkage void noinstr do_irq(struct pt_regs *regs)
{
	irqentry_state_t state = irqentry_enter(regs);

	if (IS_ENABLED(CONFIG_IRQ_STACKS) && on_thread_stack())
		call_on_irq_stack(regs, handle_riscv_irq);
	else
		handle_riscv_irq(regs);

	irqentry_exit(regs, state);
}


대부분 64 아키텍처 기반의 리눅스 커널에서는 call_on_irq_stack() 함수가 호출되어서, 인터럽트 핸들러를 호출한다. 인터럽트에 대한 처리를 마무리하면 결국 irqentry_exit() 함수가 호출된다.

인터럽트 처리를 마무리한 후 유저 스페이스로 복귀하는 코드는 이제 모두 kernel/entry 디렉토리에 위치한다.
irqentry_exit() 함수의 구현부는 다음과 같다:

https://elixir.bootlin.com/linux/v6.17.13/source/kernel/entry/common.c 
noinstr void irqentry_exit(struct pt_regs *regs, irqentry_state_t state)
{
	lockdep_assert_irqs_disabled();

	/* Check whether this returns to user mode */
	if (user_mode(regs)) {
		irqentry_exit_to_user_mode(regs);


유저 모드에서 코드가 실행 중이다가 인터럽트가 유발되면 커널 공간으로 접근한다.
이 시점의 유저 공간에서 실행 중인 레지스터는 struct pt_regs *regs 구조체로 표현할 수 있다.
user_mode(regs) 코드는 인터럽트가 유발되는 시점이 유저 공간인지를 체크한다.

이 조건에서 irqentry_exit_to_user_mode() 함수를 호출한다.

irqentry_exit_to_user_mode() 함수의 구현부이다.

 

kernel/entry/common.c
noinstr void irqentry_exit_to_user_mode(struct pt_regs *regs)
{
	instrumentation_begin();
	exit_to_user_mode_prepare(regs);
	instrumentation_end();
	exit_to_user_mode();
}


exit_to_user_mode_prepare() 함수는 유저 공간으로 복귀하기 전에,
프로세스의 상태를 체크한다. task_struct 구조체를 통해 프로세스가 시그널 
펜딩인지, 혹은 처리해야 할 동작이 있는지 점검한다. 

 

아래는 exit_to_user_mode_prepare() 함수의 구현부이다.

include/linux/irq-entry-common.h
static __always_inline void exit_to_user_mode_prepare(struct pt_regs *regs)
{
	unsigned long ti_work;

	lockdep_assert_irqs_disabled();

	/* Flush pending rcuog wakeup before the last need_resched() check */
	tick_nohz_user_enter_prepare();

	ti_work = read_thread_flags();
	if (unlikely(ti_work & EXIT_TO_USER_MODE_WORK))
		ti_work = exit_to_user_mode_loop(regs, ti_work);

	arch_exit_to_user_mode_prepare(regs, ti_work);

	/* Ensure that kernel state is sane for a return to userspace */
	kmap_assert_nomap();
	lockdep_assert_irqs_disabled();
	lockdep_sys_exit();
}



가장 마지막 코드에서 lockdep_sys_exit() 함수를 호출한다.

lockdep_sys_exit() 함수의 구현부는 다음과 같다: 

https://elixir.bootlin.com/linux/v6.17.13/source/kernel/locking/lockdep.c 
asmlinkage __visible void lockdep_sys_exit(void)
{
	struct task_struct *curr = current;

	if (unlikely(curr->lockdep_depth)) {
		if (!debug_locks_off())
			return;
		nbcon_cpu_emergency_enter();
		pr_warn("\n");
		pr_warn("================================================\n");
		pr_warn("WARNING: lock held when returning to user space!\n");
		print_kernel_ident();
		pr_warn("------------------------------------------------\n");
		pr_warn("%s/%d is leaving the kernel with locks still held!\n",
				curr->comm, curr->pid);
		lockdep_print_held_locks(curr);
		nbcon_cpu_emergency_exit();
	}

무엇인가 lock을 획득하고 릴리즈하지 않는다면 이를 커널 코드로 출력한다.

lockdep_print_held_locks() 함수의 구현부이다. 

 

https://elixir.bootlin.com/linux/v6.17.13/source/kernel/locking/lockdep.c 
static void lockdep_print_held_locks(struct task_struct *p)
{
	int i, depth = READ_ONCE(p->lockdep_depth);

	if (!depth)
		printk("no locks held by %s/%d.\n", p->comm, task_pid_nr(p));
	else
		printk("%d lock%s held by %s/%d:\n", depth,
		       str_plural(depth), p->comm, task_pid_nr(p));
	/*
	 * It's not reliable to print a task's held locks if it's not sleeping
	 * and it's not the current task.
	 */
	if (p != current && task_is_running(p))
		return;
	for (i = 0; i < depth; i++) {
		printk(" #%d: ", i);
		print_lock(p->held_locks + i);
	}
}

 

이미 held하고 처리하지 않는 락의 정보를 출력한다.

로그 리뷰

사실 여기까지 커널 코드를 분석한 이유는, 아래와 같은 커널 에러 로그를 확인했기 때문이다.
아래 코드를 분석하면서, 어느 커널 코드에서 에러 로그를 출력하는지 궁금했다.

[   94.930394] <6>lkdtm: Performing direct entry SPINLOCKUP
[   94.936805] <4>
[   94.938349] <4>================================================
[   94.944069] <4>WARNING: lock held when returning to user space!
[   94.949789] <4>6.17.0+ #3 Not tainted
[   94.953245] <4>------------------------------------------------
[   94.958962] <4>bash/976 is leaving the kernel with locks still held!
[   94.965121] <4>1 lock held by bash/976:
[   94.968751] <4> #0: ffffffff81f86298 (lock_me_up){+.+.}-{3:3}, at: lkdtm_SPINLOCKUP+0x18/0x20
[   94.977345] <3>BUG: sleeping function called from invalid context at kernel/task_work.c:229
[   94.985623] <3>in_atomic(): 1, irqs_disabled(): 0, non_block: 0, pid: 976, name: bash
[   94.993377] <3>preempt_count: 1, expected: 0
[   94.997462] <4>INFO: lockdep is turned off.

 

다음 포스트에서는 커널 함수와 crash utility 분석을 함께 진행하겠다.

0723 - 리눅스 BSP 브링업 (실습 참고 자료) - part2

 

KEA (part1): Boot-time ftrace 설정 및 실습 (feat. 리눅스 BSP 브링업 과정)
https://youtu.be/C79JWmxnWHo
.


KEA (part2): userspace 동작 디버깅 실습 (feat. 리눅스 BSP 브링업 과정)
https://youtu.be/U5_5nR8OqME

 

 

console_runtime.sh

#!/bin/bash

echo 0 > /sys/kernel/debug/tracing/tracing_on
sleep 1
echo "tracing_off" 

echo 0 > /sys/kernel/debug/tracing/events/enable
sleep 1
echo "events disabled"

echo  do_init_module > /sys/kernel/debug/tracing/set_ftrace_filter
sleep 1
echo "set_ftrace_filter init"

echo function > /sys/kernel/debug/tracing/current_tracer
sleep 1
echo "function tracer enabled"

echo 0 > /sys/kernel/debug/tracing/events/irq/irq_handler_entry/enable

echo 0 > /sys/kernel/debug/tracing/events/sched/sched_switch/enable
echo 0 > /sys/kernel/debug/tracing/events/sched/sched_wakeup/enable

echo 0 > /sys/kernel/debug/tracing/events/sched/sched_process_fork/enable
echo 0 > /sys/kernel/debug/tracing/events/sched/sched_process_exit/enable

#echo 1 > /sys/kernel/debug/tracing/events/watchdog/enable
echo 1 >  /sys/kernel/debug/tracing/events/printk/enable
#echo 1 > /sys/kernel/debug/tracing/events/signal/enable

#echo bcm2835_mmc_irq bcm2835_mbox_irq > /sys/kernel/debug/tracing/set_ftrace_filter
#echo _do_fork copy_process* >> /sys/kernel/debug/tracing/set_ftrace_filter
sleep 1
echo "event enabled"

sleep 1
echo "set_ftrace_filter enabled"

echo 1 > /sys/kernel/debug/tracing/options/func_stack_trace
echo 1 > /sys/kernel/debug/tracing/options/stacktrace
echo 1 > /sys/kernel/debug/tracing/options/sym-offset
echo "function stack trace enabled"

echo 1 > /sys/kernel/debug/tracing/tracing_on
echo "tracing_on"  

 

get_ftrace.sh  

 

#!/bin/bash

echo 0 > /sys/kernel/debug/tracing/tracing_on
echo "ftrace off"

sleep 3

cp /sys/kernel/debug/tracing/trace . 
mv trace ftrace_log.c 

 

>>>

디버깅 아키텍처: 디버깅과 관련된 너무나도 유익한 자료가 있음

https://docs.qualcomm.com/bundle/publicresource/topics/80-70018-12/Debug-overview.html

부팅 아키텍처: 부팅 과정에 대한 내용 

https://docs.qualcomm.com/bundle/publicresource/topics/80-70014-4/overview.html
https://docs.qualcomm.com/bundle/publicresource/topics/80-PV086-5P/boot-flow.html? 

QDSP에 대한 내용

 https://docs.qualcomm.com/bundle/publicresource/topics/80-78185-2/dsp.html?product=1601111740035277  

 

>>>

+ See the kernel log with callstacks

vi /boot/firmware/cmdline.txt
console=serial0,115200 console=tty1 root=PARTUUID=5dfb71d8-02 rootfstype=ext4 fsck.repair=yes rootwait quiet splash plymouth.ignore-serial-consoles ds=nocloud;i=rpi-imager-1784272617112 cfg80211.ieee80211_regdom=US trace_buf_size=2M trace_event=printk:console trace_options=stacktrace,sym-addr,sym-offset ftrace=function ftrace_filter=bcm2835_clk_probe initcall_debug   

 

>>>

vi /boot/firmware/cmdline.txt
console=serial0,115200 console=tty1 root=PARTUUID=5dfb71d8-02 rootfstype=ext4 fsck.repair=yes rootwait quiet splash plymouth.ignore-serial-consoles ds=nocloud;i=rpi-imager-1784272617112 cfg80211.ieee80211_regdom=US trace_buf_size=4M trace_event=printk:console,initcall:*,module:*  

 

 

git clone --depth=1 https://github.com/raspberrypi/linux   

 

//

 

0723 - 리눅스 BSP 브링업 (실습 참고 자료)

 

 Install utilities to build U-Boot 

$ sudo apt update

$ sudo apt install -y \
    build-essential \
    gcc-aarch64-linux-gnu \
    bison \
    flex \
    bc \
    libssl-dev \
    libgnutls28-dev \
    libncurses-dev \
    device-tree-compiler \
    swig \
    python3-dev \
    python3-setuptools \
    python3-pyelftools \
    python3-yaml \
    python3-jsonschema \
    uuid-dev

 

The commands to build U-Boot 

$ git clone --branch v2025.01 https://github.com/u-boot/u-boot.git
$ cd u-boot
$ export ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu-
$ make rpi_4_defconfig
$ make  

 

diff --git a/Makefile b/Makefile
index cf948f48028..dd370829fff 100644
--- a/Makefile
+++ b/Makefile
@@ -432,6 +432,7 @@ KBUILD_CFLAGS   := -Wall -Wstrict-prototypes \
                   -Wno-format-security \
                   -fno-builtin -ffreestanding $(CSTD_FLAG)
 KBUILD_CFLAGS  += -fshort-wchar -fno-strict-aliasing
+KBUILD_CFLAGS  += -save-temps=obj
 KBUILD_AFLAGS   := -D__ASSEMBLY__
 KBUILD_LDFLAGS  :=

 

 

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

 

vi arch/arm/cpu/armv8/spin_table.c

 

 

<command history>

 

 2000  shutdown -h now
 2001  ls
 2002  cd src
 2003  ls
 2004  cd uboot_src/
 2005  ls
 2006  cd u-boot/
 2007  ls
 2008  export ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu-
 2009  make O=out rpi_4_defconfig
 2010  make O=out
 2011  ls
 2012  cd out/
 2013  ls
 2014  cd ..
 2015  git clean -xdf
 2016  ls
 2017  make O=out rpi_4_defconfig
 2018  make O=out
 2019  git clean -xdf
 2020  make O=out rpi_4_defconfig
 2021  vi Makefile
 2022  make O=out -j3
 2023  cd out/
 2024  find . -name *.i
 2025  vi ./boot/bootflow.i
 2026  vi ./boot/bootm_os.i
 2027  cd ..
 2028  git diff Makefile  > preprocess.patch
 2029  git checkout -f Makefile
 2030  mv preprocess.patch ../
 2031  git clean -xdf
 2032  make O=out rpi_4_defconfig
 2033  make O=out
 2034  cd arch/
 2035  ls
 2036  cd arm
 2037  ls
 2038  cd cpu
 2039  ls
 2040  cd armv7
 2041  ls
 2042  vi cpu.c
 2043  cd ..
 2044  ls
 2045  clear
 2046  make O=out
 2047  vi arch/arm/cpu/armv8/spin_table.c
 2048  make O=out
 2049  find . -name bootm_os.c
 2050  vi ./boot/bootm_os.c
 2051  make O=out
 2052  vi ./boot/bootm_os.c
 2053  make O=out
 2054  vi boot/bootm_os.c -c :46
 2055  git status
 2056  git checkout -f arch/arm/cpu/armv7/cpu.c  arch/arm/cpu/armv8/spin_table.c   boot/bootm_os.c
 2057  git clean -xdf
 2058  git status
 2059  git diff Makefile
 2060  vi Makefile
 2061  git log -p
 2062  make clean
 2063  git clean -xdf
 2064  vi Makefile
 2065  git clean -xdf
 2066  history | grep make
 2067  make O=out rpi_4_defconfig
 2068  cd out/
 2069  ls
 2070  clear
 2071  find . -name *.i
 2072  cd boot
 2073  ls
 2074  vi bootm_os.i
 2075  dmesg
 2076  dmesg   | grep command
 2077  dmesg > kernel_log.c
 2078  vi kernel_log.c
 2079  ls /proc
 2080  ls /proc/cmdline
 2081  cat /proc/cmdline
 2082  cat /proc/cmdline
 2083  history

 

 

'Pallet > note-Linux kernel' 카테고리의 다른 글

arm64: errata: Mitigate TLBI errata on NVIDIA Olympus CPU  (0) 2026.07.12
(07/13) Page reclaims  (0) 2023.07.13

홍보: 제가 진행하는 '리눅스 BSP 브링업 및 부팅 타임 최적화' 재직자 교육 (2일, 국비 지원 무료 과정)

저번 주에 한국전자정보통신산업진흥회에서 진행하는 'RISC-V 프로세스 구조 및 리눅스 커널 포팅과 활용' 
강의를 잘 마무리했습니다. 이어서 아래 주제로 교육을 진행합니다.

 - 리눅스 커널 부팅 최적화 (리눅스 BSP 브링업 및 부팅 타임 최적화)
 - 7월 20일~7월 21일
 - 상암동 교육장(한국전자정보통신산업진흥회 교육장)

14시간(2일) 과정으로, 이 과정에 신청하시면 무료로 (국비 지원) 리눅스 시스템을 브링업하는데
필요한 다양한 실무 스킬을 익힐 수 있습니다. 이번 과정에서 설명드리는 핵심 콘텐츠는 다음과 같습니다:

1. 바이너리 덤프와 ftrace 분석을 통해서 부팅 시간을 최적화하는데 필요한 유익한 스킬을 공유드립니다.
2. Qualcomm Snapdragon 칩셋에서 부팅하는 과정을 케이스 스터디로 설명합니다.
3. 브링업 과정에서 만나는 다양한 이슈에 대해서 설명합니다.
4. 부팅 시간을 줄일 수 있는 패치와 디바이스 트리를 디버깅하는 패치도 설명합니다.
5. Armv8-A 뿐만 아니라 RISC-V을 비교하면서 부팅 프로세스에 대해서 상세하게 설명합니다.
6. u-boot 부트로더를 통해 어떤 방식으로 리눅스 디바이스 드라이버의 DTS가 처리되는지 설명합니다.
 
아래는 관련 문의처와 홈페이지 링크(상세 강의 커리큐럼)입니다.

1. 문의처: 인적자원개발실 컨소시엄 담당자(02-6388-6147, 6127 / hrd@gokea.org)

2. 링크
https://www.educ.or.kr/plato/?mode=info&did=55&uid=1201&special=N
과정: 리눅스 커널 부팅 최적화 (리눅스 BSP 브링업 및 부팅 타임 최적화)

감사합니다.
 

ec7216f92e4e arm64: errata: Mitigate TLBI errata on NVIDIA Olympus CPU 

 

#define __repeat_tlbi_sync(op, arg...)                                          \
do {                                                                            \
        if (!alternative_has_cap_unlikely(ARM64_WORKAROUND_REPEAT_TLBI))        \
                break;                                                          \
        __tlbi(op, ##arg);                                                      \
        dsb(ish);                                                               \
} while (0)

static inline void __tlbi_sync_s1ish(struct mm_struct *mm)
{
        dsb(ish);
        __repeat_tlbi_sync(vale1is, 0);
        sme_dvmsync(mm);
}

static inline void flush_tlb_mm(struct mm_struct *mm)
{
unsigned long asid;

dsb(ishst);
asid = __TLBI_VADDR(0, ASID(mm));
__tlbi(aside1is, asid);
__tlbi_user(aside1is, asid);
__tlbi_sync_s1ish(mm);
mmu_notifier_arch_invalidate_secondary_tlbs(mm, 0, -1UL);

 

 

at linux kernel level:

 

Erratum이 있는 CPU로 판별되면 Linux는

tlbi vmalle1
dsb ish

tlbi vmalle1
dsb ish
isb

를 실행하는 코드를 선택 

 

 

'Pallet > note-Linux kernel' 카테고리의 다른 글

0723 - 리눅스 BSP 브링업 (실습 참고 자료) - part1  (0) 2026.07.21
(07/13) Page reclaims  (0) 2023.07.13

install necessary utilities:

$ sudo apt-get install git build-essential bison zlib1g-dev libncurses5-dev libncursesw5-dev  pkg-config flex swig -y

$ sudo apt install linux-libc-dev libbpf-dev libelf-dev

$ git clone https://git.kernel.org/pub/scm/libs/libtrace/libtraceevent.git
$ cd libtraceevent
$ git checkout libtraceevent-1.8.0
$ sudo make install

git clone https://git.kernel.org/pub/scm/libs/libtrace/libtracefs.git
cd libtracefs
make 
sudo make install

trace-cmd 빌드 명령어: 

git clone https://git.kernel.org/pub/scm/linux/kernel/git/rostedt/trace-cmd.git
cd trace-cmd
git checkout trace-cmd-v2.9.4
make 
make install


echo "[START] crash-trace"
git clone https://github.com/fujitsu/crash-trace.git
cp crash-trace/trace.c crash/extensions/
cd crash
make target=RISCV64 extensions
cp extensions/trace.so ~/bin
cd ../../
echo "[END] crash-trace"

crash utility 실행하는 셸 스크립트:

#!/bin/bash

export CRASH_EXTENSIONS=/home/austin/src/riscv64_crash/crash/extensions
export TRACE_CMD=/home/austin/src/extentions/trace-cmd/trace-cmd/tracecmd/trace-cmd

/home/austin/src/riscv64_crash/crash/crash_RV64 vmcore $1 

trace.so를 로딩하는 방법

crash_RV64> extend /home/austin/src/riscv64_crash/crash/extensions/trace.so
/home/austin/src/riscv64_crash/crash/extensions/trace.so: shared object loaded

+ Recent posts