이번 포스트에서는 RISC-V 툴체인을 설치해 리눅스 커널을 빌드하는 방법을 소개합니다.
먼저 RISC-V 툴체인을 설치하는 명령어를 입력합시다.
RISC-V 툴체인 소스를 내려받기
다음 명령어를 입력해 RISC-V 툴체인 소스를 내려받습니다.
$ git clone --recursive https://github.com/riscv/riscv-gnu-toolchain
아래는 리눅스 터미널에서 위 명령어를 입력한 후의 출력 결과입니다. 소스를 내려받는데 1시간 정도 걸리네요.
austindh.kim:~/src/risc-v_toolchain$ git clone --recursive https://github.com/riscv/riscv-gnu-toolchain
Cloning into 'riscv-gnu-toolchain'...
remote: Enumerating objects: 21, done.
remote: Counting objects: 100% (21/21), done.
remote: Compressing objects: 100% (14/14), done.
remote: Total 7795 (delta 7), reused 16 (delta 4), pack-reused 7774
Receiving objects: 100% (7795/7795), 4.75 MiB | 970.00 KiB/s, done.
Resolving deltas: 100% (3940/3940), done.
Submodule 'qemu' (https://git.qemu.org/git/qemu.git) registered for path 'qemu'
Submodule 'riscv-binutils' (https://github.com/riscv/riscv-binutils-gdb.git) registered for path 'riscv-binutils'
Submodule 'riscv-dejagnu' (https://github.com/riscv/riscv-dejagnu.git) registered for path 'riscv-dejagnu'
Submodule 'riscv-gcc' (https://github.com/riscv/riscv-gcc.git) registered for path 'riscv-gcc'
Submodule 'riscv-gdb' (https://github.com/riscv/riscv-binutils-gdb.git) registered for path 'riscv-gdb'
...
시간이 오래 걸리니 밥 먹기 전에 명령어를 입력해 놔야 겠습니다.
RISC-V 툴체인 소스 빌드하고 설치하기
소스를 전부 내려받은 다음에 아래와 같이 디렉터리를 생성합니다.
$ mkdir -p opt/riscv
$ mkdir build
$ cd build
$ ../configure --prefix=/home001/austindh.kim/src/risc-v_toolchain/riscv-gnu-toolchain/opt/riscv --enable-multilib
혹은
$ ../configure --prefix=/home001/austindh.kim/src/risc-v_toolchain/riscv-gnu-toolchain/opt/riscv
아래는 리눅스 터미널에서 위 명령어를 실행한 후 출력 결과입니다. 빌드되는데 2시간 정도가 소요됩니다.
austindh.kim:~/src/risc-v_toolchain$ mkdir -p opt/riscv
austindh.kim:~/src/risc-v_toolchain$ mkdir build
austindh.kim:~/src/risc-v_toolchain$ cd build
austindh.kim:~/src/risc-v_toolchain/build$ ../configure --prefix=/home001/austindh.kim/src/risc-v_toolchain/riscv-gnu-toolchain/opt/riscv
...
이번에는 다음 명령어를 실행해서 빌드를 수행합니다.
austindh.kim:~/src/risc-v_toolchain/build$ make linux
빌드가 끝나고 "~src/risc-v_toolchain/riscv-gnu-toolchain/opt/riscv/bin" 디렉터리로 이동하니, 다음과 같은 파일이 생성됐음을 확인할 수 있습니다.
austindh.kim:~/src/risc-v_toolchain/riscv-gnu-toolchain/opt/riscv/bin$ ls
riscv64-unknown-linux-gnu-addr2line riscv64-unknown-linux-gnu-gcc riscv64-unknown-linux-gnu-gdb riscv64-unknown-linux-gnu-objcopy ...
riscv64-unknown-linux-gnu-elfedit riscv64-unknown-linux-gnu-gcov-dump riscv64-unknown-linux-gnu-lto-dump riscv64-unknown-linux-gnu-strings
riscv64-unknown-linux-gnu-g++ riscv64-unknown-linux-gnu-gcov-tool riscv64-unknown-linux-gnu-nm riscv64-unknown-linux-gnu-strip
이제 RISC-V 툴체인 소스 빌드를 마무리했습니다.
RISC-V 툴체인으로 리눅스 커널 빌드하기
다음 명령어를 입력해 리눅스 커널 소스 코드를 내려 받습니다.
$ git clone https://kernel.googlesource.com/pub/scm/linux/kernel/git/next/linux-next
소스를 내려 받은 다음에 확인한 디렉터리 정보는 다음과 같습니다.
austindh.kim:~/src/dev_kernel/59_linux_kernel$ ls
linux-next
'riscv_kernel_build.sh' 이름으로 셸 스크립트 파일을 생성한 다음에, 아래 빌드 스크립트를 입력합니다.
#!/bin/bash
export PATH=$PATH:/home001/austindh.kim/src/risc-v_toolchain/riscv-gnu-toolchain/opt/riscv/bin
echo "configure build output path"
TOP_PATH=$( cd "$(dirname "$0")" ; pwd )
OUTPUT="$TOP_PATH/out"
BUILD_LOG="$TOP_PATH/rpi_build_log.txt"
OUTPUT_PATH=$( cd "$(dirname "$0")" ; pwd )
OUTPUT="$OUTPUT_PATH/out"
pushd linux-next > /dev/null
# configure defconfig
make ARCH=riscv O=$OUTPUT CROSS_COMPILE=riscv64-unknown-linux-gnu- defconfig -j16 2>&1
# build kernel with riscv tool-chain
make ARCH=riscv O=$OUTPUT CROSS_COMPILE=riscv64-unknown-linux-gnu- modules dtbs -j16 2>&1 | tee $BUILD_LOG
popd > /dev/null
위 빌드 스크립트에서 가장 중요한 명령어는 아래와 같습니다.
# configure defconfig
make ARCH=riscv O=$OUTPUT CROSS_COMPILE=riscv64-unknown-linux-gnu- defconfig -j16 2>&1
# build kernel with riscv tool-chain
make ARCH=riscv O=$OUTPUT CROSS_COMPILE=riscv64-unknown-linux-gnu- modules dtbs -j16 2>&1 | tee $BUILD_LOG
'arch/riscv/configs/defconfig' 파일을 다음과 같이 수정해 vmlinux에 디버깅 심벌이 추가되도록 합시다.
diff --git a/arch/riscv/configs/defconfig b/arch/riscv/configs/defconfig
index d58c93e..6ea8e83 100644
--- a/arch/riscv/configs/defconfig
+++ b/arch/riscv/configs/defconfig
@@ -20,6 +20,7 @@ CONFIG_SMP=y
CONFIG_JUMP_LABEL=y
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
+CONFIG_DEBUG_INFO=y
CONFIG_NET=y
CONFIG_PACKET=y
CONFIG_UNIX=y
'riscv_kernel_build.sh' 빌드 셸 스크립트를 실행해, RISCV 툴 체인으로 커널을 빌드합니다.
아래는 'riscv_kernel_build.sh' 빌드 셸 스크립트를 터미널에서 실행한 출력 화면입니다.
austindh.kim:~/src/dev_kernel/59_linux_kernel$ ./riscv_kernel_build.sh
configure build output path
make[1]: Entering directory '/home001/austindh.kim/src/dev_kernel/59_linux_kernel/out'
GEN Makefile
HOSTCC scripts/basic/fixdep
HOSTCC scripts/kconfig/conf.o
...
KSYMS .tmp_vmlinux.kallsyms2.S
AS .tmp_vmlinux.kallsyms2.S
LD vmlinux
SYSMAP System.map
MODPOST Module.symvers
CC [M] fs/nfs/flexfilelayout/nfs_layout_flexfiles.mod.o
LD [M] fs/nfs/flexfilelayout/nfs_layout_flexfiles.ko
'out' 폴더를 가니 제대로 커널이 빌드됐음을 확인할 수 있습니다.
austindh.kim:~/src/dev_kernel/59_linux_kernel/out$ ls
arch crypto include kernel mm modules.order scripts source virt vmlinux.symvers
block drivers init lib modules.builtin Module.symvers security System.map vmlinux
certs fs ipc Makefile modules.builtin.modinfo net sound usr vmlinux.o
RISC-V 바이너리 유틸리티 사용해보기
이번엔 다음 명령어를 입력해 vmlinux의 셉션 정보를 확인해보겠습니다.
$ ./riscv64-unknown-linux-gnu-objdump -x vmlinux | more
아래는 './riscv64-unknown-linux-gnu-objdump -x vmlinux | more' 빌드 셸 스크립트를 터미널에서 실행한 출력 화면입니다.
austindh.kim:~/src/dev_kernel/59_linux_kernel/out$ ./riscv64-unknown-linux-gnu-objdump -x vmlinux | more
vmlinux: file format elf64-littleriscv
vmlinux
architecture: riscv:rv64, flags 0x00000112:
EXEC_P, HAS_SYMS, D_PAGED
start address 0xffffffe000000000
Program Header:
LOAD off 0x0000000000001000 vaddr 0xffffffe000000000 paddr 0x0000000000000000 align 2**12
filesz 0x0000000000025af4 memsz 0x0000000000025af4 flags r-x
LOAD off 0x0000000000027000 vaddr 0xffffffe000026000 paddr 0x0000000000026000 align 2**12
filesz 0x0000000000019de8 memsz 0x0000000000019de8 flags rwx
LOAD off 0x0000000000041000 vaddr 0xffffffe000200000 paddr 0x0000000000200000 align 2**12
filesz 0x00000000006ce0a2 memsz 0x00000000006ce0a2 flags r-x
LOAD off 0x0000000000710000 vaddr 0xffffffe000a00000 paddr 0x0000000000a00000 align 2**12
filesz 0x000000000022a9fc memsz 0x000000000022a9fc flags rw-
LOAD off 0x000000000093b000 vaddr 0xffffffe000e00000 paddr 0x0000000000e00000 align 2**12
filesz 0x0000000000002400 memsz 0x0000000000002400 flags r--
LOAD off 0x000000000093e000 vaddr 0xffffffe001000000 paddr 0x0000000001000000 align 2**12
filesz 0x00000000000e19b4 memsz 0x0000000000131920 flags rw-
NOTE off 0x000000000093a9c0 vaddr 0xffffffe000c2a9c0 paddr 0x0000000000c2a9c0 align 2**2
filesz 0x000000000000003c memsz 0x000000000000003c flags r--
STACK off 0x0000000000000000 vaddr 0x0000000000000000 paddr 0x0000000000000000 align 2**4
filesz 0x0000000000000000 memsz 0x0000000000000000 flags rw-
출력 결과를 보니 아키텍처의 정보는 'riscv:rv64'이고 스타트업 코드의 위치는 0xffffffe000000000 주소임을 알 수 있습니다.
'RISC-V > RISC-V 빌드 및 환경' 카테고리의 다른 글
RISC-V ISA-interpreter (0) | 2024.04.03 |
---|---|
[RISC-V] secret behind 'tp'(X4) register in Linux kernel (0) | 2023.11.13 |
RISC-V Instruction Set Specifications [link] (0) | 2023.11.13 |
[RISC-V] sudo code for exception handling in Linux kernel (0) | 2023.11.13 |
[RISC-V Kernel build] How to build kernel for visionfive2 kernel ? (0) | 2023.11.10 |