owned this note
owned this note
Published
Linked with GitHub
## add a system call to kernel (v5.15.137)
**感謝各位持續回報問題,TA目前也會繼續把解決的問題寫上來**
**<font size=4>MAC M系列CPU add a system call(我們感謝這位同學的付出):https://hackmd.io/@70cpQQYYTB2IhWlu_xBrTQ/BJ9V8YdV6</font>**
![image.png](https://hackmd.io/_uploads/H1Ni3o7Qp.png)
### 系統環境
* 作業系統: ubuntu 22.04
* Kernel 版本: 5.15.137
ubuntu下載點: https://www.ubuntu-tw.org/modules/tinyd0
虛擬機的部分可以用vmware或hyper v或virtual box
vmware pro 安裝 https://www.youtube.com/watch?v=b7WgB2S3gDk
hyper v是 windows內建的,所以不用安裝,還是附上教學:
1.https://www.youtube.com/watch?v=GjpuUpNEPTc
2.https://www.youtube.com/watch?v=8KLa6_6Vyiw
### 下載 Kernel Source
到 [Kernel Archive](https://www.kernel.org/) 下載 kernel source,選擇 5.15.137 kernel。
```
# 進入 root 模式
sudo su
# 也可以用這個指令來下載kernel
wget -P ~/ https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.15.137.tar.xz
```
雖然可以下載最新版本的kernel是6.5.9,但考慮到最新版本在compile kernel時可能會出現一些error是stack overflow查不到的新型error所以不推薦,所以這邊還是用5.15.137做展示
**<font size=4>解壓縮</font>**
```
# 把檔案解壓縮到 /usr/src 目錄底下
tar -xvf linux-5.15.137.tar.xz -C /usr/src
```
**<font size=4>更新apt</font>**
```
sudo apt update && sudo apt upgrade -y
```
**<font size=4>先把會用到的套件安裝好</font>**
```
# 這個套件可以幫我們 build 出 kernel-pakage
sudo apt install build-essential libncurses-dev libssl-dev libelf-dev bison flex -y
```
**<font size=4>安裝vim</font>**
```
sudo apt install vim -y
```
**<font size=4>清除安裝的package</font>**
```
sudo apt clean && sudo apt autoremove -y
```
### 新增 syscall
**<font size=4>建立資料夾</font>**
```
# 把目錄轉到剛剛解壓縮完的 kernel 檔案夾
cd /usr/src/linux-5.15.137
# 在裡面創建一個名叫 hello 的資料夾
mkdir hello
# 把目錄轉到 hello 資料夾
cd hello
```
**<font size=4>建立 hello.c</font>**
```
vim hello.c
```
**<font size=4>hello.c 的內容</font>**
```C=
#include <linux/kernel.h>
#include <linux/syscalls.h>
SYSCALL_DEFINE0(hello){
printk("Hello world!\n");
return 0;
}
```
**<font size=4>於同一個目錄下再建立一個 Makefile</font>**
```
vim Makefile
```
**<font size=4>Makefile 的內容</font>**
```
obj-y := hello.o
```
**<font size=4>接著回上個目錄改 Makefile</font>**
```
# 回上個目錄
cd ..
# 打開此目錄下的 Makefile
vim Makefile
```
**<font size=4>可以找到 core-y 如下圖</font>**
註: vim編輯檔案的時候,可以用輸入 **?core-y** 來找到core-y這個關鍵字
![](https://i.imgur.com/Chuo6PJ.png)
**<font size=4>在最後面補上 hello 這樣 kernel 在編譯時才會到 hello 目錄</font>**
```
core-y += kernel/ certs/ mm/ fs/ ipc/ security/ crypto/ hello/
```
**<font size=4>接下來要去修改 syscall_64.tbl 檔</font>**
```
vim arch/x86/entry/syscalls/syscall_64.tbl
```
**<font size=4>在最後一行添加上 system call,然後請把編號記住, 等一下會用</font>**
![image.png](https://hackmd.io/_uploads/BycWdTeQp.png)
**<font size=4>接著編輯 syscalls.h 檔,將 syscall 的原型添加進檔案 (#endif之前)</font>**
```
# 把目錄轉回去
cd /usr/src/linux-5.15.137
vim include/linux/syscalls.h
#加入一行(這行直接加在檔案的最下面就好)
註: 在vim編輯檔案的時候 可以按shift+G就會跳到最後一行
asmlinkage long sys_hello(void);
```
![image.png](https://hackmd.io/_uploads/rya8HiQQa.png)
### 編譯 kernel
**<font size=4>可以用 make localmodconfig 來設定組態</font>**
```
make localmodconfig
#這邊會跳出一大堆問你要不要裝的套件,全部按enter跳過就好
```
**<font size=4>ps:很多教學都會教你make menuconfig來設定.config檔,但那個.config檔太大,會導致kernel編譯要很久,所以建議用make localmodconfig只抓kernel需要的config,這樣可以大幅降低kernel編譯時間</font>**
**<font size=4>以i7-10700這顆cpu來說,用make menuconfig要30幾分鐘,但make localmodconfig這樣只要7分鐘,跟鬼一樣= =(白眼之間要空格)</font>**
**<font size=4>查看這台虛擬機是幾核心</font>**
```
nproc
```
![image.png](https://hackmd.io/_uploads/B1daroXQ6.png)
**<font size=4>然後直接make</font>**
```
# 這個代表用12核心去編譯kernel
make -j12
```
要記得如果你的核心有16核的話,不要用16核去編譯,盡量抓1/2~3/4
ex:16核就用8核~12核去編,比較不會當機
**<font size=4>把kernel安裝上去</font>**
```
sudo make modules_install -j12
再打
sudo make install -j12
```
**<font size=4>更新作業系統的bootloader成新的kernel</font>**
```
sudo update-grub
```
**<font size=4>虛擬機要重新開機</font>**
```
reboot
```
**<font size=4>重開機後再看看 kernel 版本有沒有變新</font>**
```
uname -r
```
![image.png](https://hackmd.io/_uploads/SyGpujQX6.png)
**<font size=4>update grub之後如果沒有更新成5.15.137</font>**
**<font size=4>解法一</font>**
**<font size=4>如果ubuntu安裝的版本(可以去~/usr/src看)比下載的kernel(5.15.137)還要新的話,這邊就不會更新到,解決的方法就是reboot重開機,然後一直按F4,之後會有選單,選advance,然後把5.15.137版設定成優先權最高(這邊很像重灌windows時,要去bios設定隨身碟開機)</font>**
**<font size=4>PS : make modules_install -j12把kernel安裝上去的時候,因為ubuntu會自動去辨識現在最新的kernel版本是哪一版,如果安裝的kernel比系統目前版本還新,會直接預設成現在系統的kernel</font>**
**<font size=4>可以參考下面這篇</font>**
[安装了内核重启后内核版本没有更新 调处grub引导界面](https://blog.csdn.net/keke_Memory/article/details/124947773)
**<font size=4>解法二</font>**
![image](https://hackmd.io/_uploads/SyGquceVa.png)
**<font size=4>用vim編輯/etc/default/grub</font>**
![image](https://hackmd.io/_uploads/BJ_U_5eV6.png)
```
把GRUB_TIMEOUT_STYLE從hidden改成menu
再把GRUB_TIMEOUT從0改成-1
然後離開這個檔案
再打
update-grub
reboot
```
**<font size=4>解法三</font>**
**<font size=4>如果你是用gcp的話參考這個</font>**
```
vim /etc/default/grub.d/50-cloudimg-settings.cfg
把裡面有一行DRUB_DEFAULT改成"1>2"
update-grub
reboot
```
### 測試 syscall
```
# 創建一個 hello.c
vim hello.c
```
**<font size=4>hello.c 的內容如下</font>**
```C=
#include <linux/kernel.h>
#include <unistd.h>
#include <sys/syscall.h>
#include <stdio.h>
int main(){
/* 使用我們剛剛新增的 system call */
long int sys = syscall(449);
/* print 出 syscall 的回傳值, 若為 0 則代表成功 */
printf("sys_hello return %ld\n", sys);
return 0;
}
```
```
# 編譯 hello.c
gcc -o hello hello.c
# 執行
./hello
```
**<font size=4>使用 dmesg 來查看 kernel 內的訊息</font>**
```
sudo dmesg
```
![image.png](https://hackmd.io/_uploads/S1IUtom7p.png)
### 一些參考網址:
1.[add a system call教學網址](https://dev.to/jasper/adding-a-system-call-to-the-linux-kernel-5-8-1-in-ubuntu-20-04-lts-2ga8)
編譯kernel的時候會跳出的error解法:
2.[内核错误: No rule to make target ‘debian/canonical-certs.pem‘, needed by ‘certs/x509_certificate_list‘](https://blog.csdn.net/qq_36393978/article/details/118157426)
3.[BTF: .tmp_vmlinux.btf: pahole (pahole) is not available](https://stackoverflow.com/questions/61657707/btf-tmp-vmlinux-btf-pahole-pahole-is-not-available)
4.CONFIG_X86_X32 enabled but no binutils support
```
cd usr/src/linux 5.15.137
vim .config
原本CONFIG_DEBUG_INFO=n,這裡改成y就好
```
5.[安装了内核重启后内核版本没有更新 调处grub引导界面](https://blog.csdn.net/keke_Memory/article/details/124947773)