linux-nextに来たRustでカーネルモジュールを書く（Rust対応カーネルの準備まで）

#動機
既に用意されているLinuxカーネルしか使用した事が無かったので、
どこかで一からカーネルビルドを試してみようと思っていたのですが、
同僚から聞いたRustでLinuxカーネルが書けるようになるという[記事](https://qiita.com/hon_no_mushi/items/81812bab0a114f105395)に興味があったので、
ついでにRust入門も兼ねて実践してみました。

いくつか理解しないまま設定している項目等もあるので、アドバイス頂けたら幸いです。


#使用した環境
VMware Workstation 15 Player上にUbuntu 20.04.2 LTS (Focal Fossa)をインストールした環境を使用しました。

#前準備
quick_start.rstの通りに実践します・・・が、[記事](https://qiita.com/hon_no_mushi/items/81812bab0a114f105395)に「開発に関連するところ！これは読んでおこう！」とあり、原文ではrustのnightly-2021-03-05以降で問題があります。
原文をちゃんと読むようにしましょう。

・rustupのインストール
rustup(rust公式インストーラー)を使用しました。

https://rustup.rs/

に従い、rustupをインストールします。

また、自分が使用した[next-20210503](https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git/tree/Documentation/rust/quick-start.rst?h=next-20210503)タグの時点ではnightlyなrustだと[issue](https://github.com/Rust-for-Linux/linux/issues/135)があり、Linux kernelのビルドが失敗します。
default toolchainを以下のように設定してください。

``` 
$ rustup default nightly-2021-02-20
```

・Clangのインストール
Ubuntu 20.04.2 LTSではclangのバージョンが10.0.0がインストールされますが、
next-20210503では10.0.1以降が要求されるようで、clang version 11.0.0-2を使用しました。

```
$ sudo apt install clang-11
$ sudo update-alternatives --install /usr/bin/clang clang /usr/bin/clang-11 100
$ sudo update-alternatives --install /usr/bin/cc cc /usr/bin/clang-11 100
```

・カーネルビルドに必要なパッケージのインストール

```
$ sudo apt-get install kernel-package libssl-dev
```


・その他のパッケージ
bindgen、rustfmt等、他のパッケージに関してはquick_start.rstの通りで問題ありませんでした。


#Rust対応カーネルの設定


1.linux-nextをcloneする

```
$ mkdir linux-next
$ cd linux-next
$ git clone git://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
```

自分はhomeディレクトリにlinux-nextディレクトリを掘ってcloneしましたが、
ビルド結果のパッケージファイルがhomeディレクトリに配置されるので、
home直下に置きたくない方はもう一つディレクトリを掘っても良いと思います。

2.カーネルコンフィグをコピー
現在動作している環境のコンフィグファイルをコピーします。

```
$ cp /boot/config-<kernel-version> ./.config
$ make CC=clang olddefconfig
```
<kernel-version>は適宜読み替えて下さい。

3 . Rustサポートのカーネルコンフィグを有効にする

```
$ make CC=clang menuconfig
```

で以下の設定を有効にします。
General setup  --->  Rust support を*
Kernel hacking  ---> Sample kernel code --> Rust sample --> 以下をすべて*に
また、clangを使用するため、
「Kernel hacking -> Compile-time checks and compiler options -> Generate BTF typeinfo」のチェックを外します。


4 . CONFIG_SYSTEM_TRUSTED_KEYSを無効にする
ビルドエラーとなるため、.configファイルのCONFIG_SYSTEM_TRUSTED_KEYSを以下のように修正します。

```
CONFIG_SYSTEM_TRUSTED_KEYS=""
```

#カーネルモジュールの追加


1 .　カーネルコンフィグ用の定義ファイルと独自モジュールを対象にするようMakefileを追加
下記のファイルそれぞれに以下の内容を追加します。

```txt:sample/rust/Kconfig
config SAMPLE_RUST_TOMBLIT_ORIGINAL
       bool "TOMBLIT_ORIGINAL"
       help
         This option is tomblit original sample.
```

```txt:samples/rust/Makefile
obj-$(CONFIG_SAMPLE_RUST_TOMBLIT_ORIGINAL)       += rust_tomblit_original.o
```

2 . 追加するモジュールのrustソースコードファイルの追加
今回は何も動作しないモジュールを追加しました。
元はrust_minimal.rsをコピーして使用します。

#ビルド
-jオプションは使用しているCPUによって適宜変更して下さい。

```
make -j12 CC=clang deb-pkg LOCALVERSION=-userust KDEB_PKGVERSION=$(make kernelversion)-1 
```

#インストール
ビルドが成功していれば、ホームディレクトリにlinux-image-5.12.0-next-20210503-userust_5.12.0-1_amd64.deb等のファイルが出来ているはずです。これらをインストールします。

```
$ sudo dpkg -i linux-headers-5.12.0-next-20210503-userust_5.12.0-1_amd64.deb
$ sudo dpkg -i linux-image-5.12.0-next-20210503-userust_5.12.0-1_amd64.deb 
```

再起動してカーネルバージョンが以下のようになっていれば成功です。

```
$ uname -a
Linux ubuntu 5.12.0-next-20210503-userust #1 SMP Sun May 16 21:16:42 PDT 2021 x86_64 x86_64 x86_64 GNU/Linux
```

#うまくいっていない点
・ローダブルカーネルモジュールの作成
サンプルのCONFIG_SAMPLE_RUST_CHRDEV等もローダブルにすると、ビルドエラーになってしまっています。
rustのマングリングが非常に長いシンボル名を生成するようなのですが、それ以上の原因はつかめていません。

```
		ERROR: modpost: too long symbol "_RNvXsx_NtCsbDqzXfLQacH_4core6resultINtB5_6ResultuNtNtCsbDqzXfLQacH_6kernel5error5ErrorENtNtNtB7_3ops3try3Try11into_resultBP_" [samples/rust/rust_chrdev.ko]
```

・リビルド
リビルドをする際に以下のエラーメッセージで止まる事があります。

```
	dpkg-source: info: use the '3.0 (quilt)' format to have separate and documented changes to upstream files, see dpkg-source(1)
	dpkg-source: error: unrepresentable changes to source
```

#参考にしたもの
https://rust-for-linux.github.io/docs/kernel/index.html