chakokuのブログ(rev4)

日々のごった煮ブログです

Xen上で動作する一番小さいカーネルを作ってみる

Xenの技術解説本(仮想化技術Xen)にカーネルの作り方があったので勉強のために作ってみた(結論を先に書くと、アセンブラの段階でエラーです→場当たり的に回避)。
・走っているXenのバージョンを確認(64bit版 Version4.1.4-3)


# dmesg
[ 0.000000] Xen version: 4.1.4 (preserve-AD)

# dpkg --list | grep Xen
ii libxen-4.1 4.1.4-3+deb7u1 amd64 Public libs for Xen
ii libxenstore3.0 4.1.4-3+deb7u1 amd64 Xenstore communications library for Xen
ii xen-hypervisor-4.1-amd64 4.1.4-3+deb7u1 amd64 Xen Hypervisor on AMD64
ii xen-linux-system-3.2.0-4-amd64 3.2.46-1+deb7u1 amd64 Xen system with Linux 3.2 on 64-bit PCs (meta-package)
ii xen-linux-system-amd64 3.2+46 amd64 Xen system with Linux for 64-bit PCs (meta-package)
ii xen-system-amd64 4.1.4-3+deb7u1 amd64 Xen System on AMD64 (meta-package)
ii xen-utils-common 4.1.4-3+deb7u1 all Xen administrative tools - common files
ii xenstore-utils 4.1.4-3+deb7u1 amd64 Xenstore utilities for Xen

Xenプロジェクトサイトから4.1.4のXenソースを入手(Header等が必要なため)
・仮想化技術Xenサンプルソースをサポートページから入手
サンプルソースを展開、32bitを64bitに修正(その後、32bitに戻し)
Xenのヘッダをしかるべき場所に配置(リンク設定)
コンパイルしてみた。結果、エラー。。


$ make
cc -D__ASSEMBLY__ -I../xen/xen/include/public -c -o bootstrap.x86_64.o bootstrap.x86_64.S
bootstrap.x86_64.S: Assembler messages:
bootstrap.x86_64.S:19: Error: operand type mismatch for `push'
make: *** [bootstrap.x86_64.o] Error 1
該当行は以下

_start:
cld
lss stack_start,%esp
push %esi <<<<<<<
call start_kernel
見た目そんなに変ではないけど
適当なソースをgccコンパイルしてアセンブラ出力させると、pushlのニーモニックが使われている。アドホックにpushlに書き換えてみたけどやっぱりエラーは消えない。ニーモニックの勉強からやらないと何が悪いのか分からず。
下の関連リンク集にもつけましたけど、64bitアセンブラの手ほどきをしてくれているWebページもあるので、一旦アセンブラまで立ち戻って簡単なプログラミングをやってみるつもりです。まぁちょっとしたオプション付け忘れとかその程度の間違いなんだろうと思っていますが。。

■追記(130923)
どうやら、エラーになるのは、32bit版のコード生成と、64bit版のコード生成でサポートされている命令体系が違っているためらしかった。多分、64ビットモードではpush %esiというのがサポートされていないと思われる(あくまでも推測(ご参考:「What are the qualitative differences in reverse engineering x64/Win64 code versus x32/Win32 code?」))。
エラーになる場合(64bitコード生成)


$ as --64 test.S
test.S: Assembler messages:
test.S:2: Error: operand type mismatch for `push'
アセンブルできる場合(32bitコード生成)

$ as --32 test.S
64bit版ソースコードに直すのはかなり大変と思われるので、32bit版コードを生成するようにコンパイラに指定することで対応。
下記のように32bit版でアセンブルするように引数で指定したらアセンブラは通った

$ cc -Wa,-32 -D__ASSEMBLY__ -I../xen/xen/include/public -c -o bootstrap.x86_32.o bootstrap.x86_32.S
同様に32bit版を指定したらCソースのコンパイルはエラーになった。ヘッダファイル(bits/wchar.h)が見つけられないようだ。

$ cc -m32 -std=c99 -I../xen/xen/include/public -c -o kernel.o kernel.c
In file included from /usr/lib/gcc/x86_64-linux-gnu/4.6/include/stdint.h:3:0,
from kernel.c:1:
/usr/include/stdint.h:27:24: fatal error: bits/wchar.h: No such file or directory
compilation terminated.
場当たり的に、bitsフォルダへのパスを引数で指定して逃げた。正しい対応方法ではないと思うけど。。まずはコンパイルを通すのを最優先。

$ cc -m32 -std=c99 -I../xen/xen/include/public -I/usr/include/x86_64-linux-gnu/ -c -o kernel.o kernel.c
$ make
なんとかバイナリ(fileName:testkernel)が生成された。けど、、32bit版バイナリで大丈夫だろうか。ハイパーバイザー上で動作するゲストOSに対して、64bit版の縛りとかないので、32bit版でも走るんだろうと思いますが。。

$ file testkernel
testkernel: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), statically linked,
BuildID[sha1]=0x459b478e89333be5e0179851ab3a41f9a4ce64cf, not stripped
Xenのハイパーバイザー上で稼動させるには、環境設定ファイルとか必要なので、実行はまた後日。

■追記(130924)
当初アセンブラで以下の命令がエラーになった理由は、esiは32bit長のためx64(64bit版の命令体系)では
サポートしていない組み合わせであることが分かった。(Intelの命令体系説明書より)


push %esi
esiの64bit長の名前はrsiであり、上記コードを以下に書き換えたら64bit版のコードで生成できた

push %rsi
というわけで、ワークアランドでいろいろやった結果、32bit版カーネルと64bit版カーネルの2種類ができた。

■追記(130929)
作成したKernelを立ち上げてみた。。するとサポートされていないバージョン?だと言って Xen ハイパーバイザに怒られた。問題は、bootstrap.x86_32.SのXEN_VERの表記をどうするのが正しいか?だと思う。一応解説本通りに作ったのだけど、ハイパーバイザーがxen-4.1だから?? ハイパーバイザーのソース(xc_com_boot.c)のチェックルーチンを見てみるか。。


root# xm create ./testkernel.cfg
Using config file "././testkernel.cfg".
Error: (2, 'Invalid kernel', 'panic: xc_dom_boot.c:126: xc_dom_compat_check: guest type xen-3.0-x86_32
not supported by xen kernel, sorry')


■ご参考URL
仮想化技術Xenが提供しているサンプルコードの置き場所
(本で紹介されているURLから別のサイトに引越ししています)
http://www.informit.com/store/definitive-guide-to-the-xen-hypervisor-9780132349710
上記は英語版の書籍のページであり、上記ページのDownloadタブを選択して、
Source Code
Download the book examples
のリンクを押下
http://www.informit.com/content/images/9780132349710/sourcecode/examples.tgz

Xenプロジェクト 4.1.4のソース置き場
http://xenproject.org/downloads/xen-archives/supported-xen-41-series/xen-414.html

64bitアセンブリ理解関連
What are the qualitative differences in reverse engineering x64/Win64 code versus x32/Win32 code?(32bit版と64bit版の違いを説明)
http://reverseengineering.stackexchange.com/questions/305/what-are-the-qualitative-differences-in-reverse-engineering-x64-win64-code-versu
Jun様による、「Linuxで64bit アセンブリプログラミング」
http://www.mztn.org/lxasm64/amd00.html
「x64 アセンブリーの概要」
http://www.isus.jp/article/introduction-to-x64-assembly/
AMD Developer Guides & Manuals」
http://developer.amd.com/resources/documentation-articles/developer-guides-manuals/