Qemeソース分析
7497 ワード
参考:http://lists.gnu.org/archive/html/qemu-devel/2011-04/pdfhC5rVdz7U8.pdf
1.QemeとBochsの違い:
1.Bochs
BochsとQemeはソフトウェアのシミュレーションを主とする仮想ソフトウェアですが、両者の違いは何ですか?
Bochsは、ターゲットプログラム(OSおよび実行中のアプリケーション)をソフトウェアでシミュレートしたものです。Bochsは自分の内部でCPU、メモリ、IO装置のデータ構造を維持しています。Bochsがコマンドをシミュレーションするたびに、このコマンドに従って実際のハードウェア上で実行する時に発生すべき効果は、これらのソフトウェアのハードウェアデータ構造を維持する上で相応の影響を与えます。
このような一つ一つの処理方法は、実際の運転時と全く同じ粒度を維持し、学習と調整に便利です。しかし、これは一対の多マッピング方式であり、すなわち一つの機構命令であり、N個の命令実行と解釈されるので、効率の低下は避けられない。
2.qeme
Qemeは他の粒度のシミュレーションを行っています。
qemuはターゲットプログラムから、現在実行したいコードの一部を切り取り(Translation Blockと呼ばれる)、このコードをまず中間言語に訳してから、中間言語をホストシステム関連のバイナリコードに訳します。
Translation Blockの粒径は単一の機構指令の粒度より大きいので、qemeはbatch処理命令のシミュレーション動作に相当するので、プログレッシブ処理のBochs性能よりも若干速くなります。
また、QemeはTranslation Blockのキャッシュを最適化し、複数の接続を実行するTranslation Blockをリンクして同じロットで処理する。この2つの方法は繰り返し実行されるコードセグメントのシミュレーション性能を大幅に向上させる。
3.まとめ
簡単に言えば、Bochsは学習に適しています。また、簡単な任務処理もできます。Bochsが持っている調合器もとても力があります。BochsでLinuxカーネルを調整するのはいい選択です。http://www.cnblogs.com/long123king/p/3559816.htmlなど)が、実際に大型のオペレーティングシステムをシミュレートするのにはBochsが適していません。
Qemuは処理方式に最適化があるので、Bochsのようにコマンドレベルの実行過程を“元の味”で表現することができないので、勉強にはあまり適していません。しかし、Qemeの性能向上により、カーネル仮想モジュールkvm、さらにはxenにも対応することができますので、Qemeは、主流の仮想デスクトップソフト(Virtual Box、Vmwareなど)のように、複数のオペレーティングシステムをスムーズに実行することができます。Linux上でWindowsを仮想化する必要があるなら、きっとqemeの方がいいと思います。
tb_find_fast:次のTB(Translation Block)を検索し、ホストコードを生成する。
tcg_qemutb_exec:生成されたホストコードを実行し、ホストコードは三つの部分から構成されています。
2.Qemeの処理フロー
qemuのシミュレーションのメインサイクルはcpu-exc.cにあります。cpu_exec関数で
Translation Blockを準備します。キャッシュに用意されているTranslation Blockがあれば、そのまま返します。そうでないとtb_を呼び出しますfind_slow関数は、新しいTBを作成します。
そしてtcg_gen_コードはtcg_を呼び出すことができますgen_code_commonは、TBから中間コードを取り出し、ホストコードに変換する。
2.cpu_tb_exec:
生成されたTBを実行します。
code_gen_prologureは、TB全体に対して動的に生成されたprologueを指す。
転載先:https://www.cnblogs.com/long123king/p/3584053.html
1.QemeとBochsの違い:
1.Bochs
BochsとQemeはソフトウェアのシミュレーションを主とする仮想ソフトウェアですが、両者の違いは何ですか?
Bochsは、ターゲットプログラム(OSおよび実行中のアプリケーション)をソフトウェアでシミュレートしたものです。Bochsは自分の内部でCPU、メモリ、IO装置のデータ構造を維持しています。Bochsがコマンドをシミュレーションするたびに、このコマンドに従って実際のハードウェア上で実行する時に発生すべき効果は、これらのソフトウェアのハードウェアデータ構造を維持する上で相応の影響を与えます。
このような一つ一つの処理方法は、実際の運転時と全く同じ粒度を維持し、学習と調整に便利です。しかし、これは一対の多マッピング方式であり、すなわち一つの機構命令であり、N個の命令実行と解釈されるので、効率の低下は避けられない。
2.qeme
Qemeは他の粒度のシミュレーションを行っています。
qemuはターゲットプログラムから、現在実行したいコードの一部を切り取り(Translation Blockと呼ばれる)、このコードをまず中間言語に訳してから、中間言語をホストシステム関連のバイナリコードに訳します。
Translation Blockの粒径は単一の機構指令の粒度より大きいので、qemeはbatch処理命令のシミュレーション動作に相当するので、プログレッシブ処理のBochs性能よりも若干速くなります。
また、QemeはTranslation Blockのキャッシュを最適化し、複数の接続を実行するTranslation Blockをリンクして同じロットで処理する。この2つの方法は繰り返し実行されるコードセグメントのシミュレーション性能を大幅に向上させる。
3.まとめ
簡単に言えば、Bochsは学習に適しています。また、簡単な任務処理もできます。Bochsが持っている調合器もとても力があります。BochsでLinuxカーネルを調整するのはいい選択です。http://www.cnblogs.com/long123king/p/3559816.htmlなど)が、実際に大型のオペレーティングシステムをシミュレートするのにはBochsが適していません。
Qemuは処理方式に最適化があるので、Bochsのようにコマンドレベルの実行過程を“元の味”で表現することができないので、勉強にはあまり適していません。しかし、Qemeの性能向上により、カーネル仮想モジュールkvm、さらにはxenにも対応することができますので、Qemeは、主流の仮想デスクトップソフト(Virtual Box、Vmwareなど)のように、複数のオペレーティングシステムをスムーズに実行することができます。Linux上でWindowsを仮想化する必要があるなら、きっとqemeの方がいいと思います。
tb_find_fast:次のTB(Translation Block)を検索し、ホストコードを生成する。
tcg_qemutb_exec:生成されたホストコードを実行し、ホストコードは三つの部分から構成されています。
2.Qemeの処理フロー
qemuのシミュレーションのメインサイクルはcpu-exc.cにあります。cpu_exec関数で
for(;;)
{
......
tb = tb_find_fast(env);
......
next_tb = cpu_tb_exec(cpu, tc_ptr);
......
}
1.tb_find_fast:Translation Blockを準備します。キャッシュに用意されているTranslation Blockがあれば、そのまま返します。そうでないとtb_を呼び出しますfind_slow関数は、新しいTBを作成します。
tb_find_fast
|
tb_find_slow
|
tb_gen_code
|
cpu_gen_code
|
gen_intermediate_code 【Guest Code --> tcg op( )】
|
tcg_gen_code【tcg op( ) --> Host Code】
その中で、ゲンゲintermediate_codeはシステムに関連する関数で実現され、x 86の実装はtaget-i 386/translate.cにあり、内部でdisas_を呼び出します。insnプログレッシブコマンドで処理します。そしてtcg_gen_コードはtcg_を呼び出すことができますgen_code_commonは、TBから中間コードを取り出し、ホストコードに変換する。
2.cpu_tb_exec:
生成されたTBを実行します。
cpu_tb_exec
|
tcg_qemu_tb_exec
#define tcg_qemu_tb_exec(tb_ptr) ((long REGPARM (*)(void *))code_gen_prologue)(tb_ptr)
prologueとepilogueはcomplerがターゲットコードを生成する時、関数スタックフレームの保存と回復のコードに対して、私達は手当たり次第に例を挙げます。objdump -d vl.o
下のコードの赤い部分はそれぞれ関数のprologueとepilogueです。000000000000013a :
13a: 55
13b: 48 89 e5
13e: 53
13f: 48 83 ec 28
143: 48 89 7d d8 mov %rdi,-0x28(%rbp)
147: 89 75 d4 mov %esi,-0x2c(%rbp)
14a: 64 48 8b 04 25 28 00 mov %fs:0x28,%rax
151: 00 00
153: 48 89 45 e8 mov %rax,-0x18(%rbp)
157: 31 c0 xor %eax,%eax
159: 8b 45 d4 mov -0x2c(%rbp),%eax
15c: 83 f8 40 cmp $0x40,%eax
15f: 77 42 ja 1a3
161: 48 8b 45 d8 mov -0x28(%rbp),%rax
165: 48 8b 10 mov (%rax),%rdx
168: 8b 45 d4 mov -0x2c(%rbp),%eax
16b: 48 98 cltq
16d: 83 e0 3f and $0x3f,%eax
170: 48 85 c0 test %rax,%rax
173: 74 19 je 18e
175: 8b 45 d4 mov -0x2c(%rbp),%eax
178: 83 e0 3f and $0x3f,%eax
17b: be 01 00 00 00 mov $0x1,%esi
180: 89 c1 mov %eax,%ecx
182: 48 d3 e6 shl %cl,%rsi
185: 48 89 f0 mov %rsi,%rax
188: 48 83 e8 01 sub $0x1,%rax
18c: eb 07 jmp 195
18e: 48 c7 c0 ff ff ff ff mov $0xffffffffffffffff,%rax
195: 48 21 d0 and %rdx,%rax
198: 48 85 c0 test %rax,%rax
19b: 0f 94 c0 sete %al
19e: 0f b6 c0 movzbl %al,%eax
1a1: eb 11 jmp 1b4
1a3: 8b 55 d4 mov -0x2c(%rbp),%edx
1a6: 48 8b 45 d8 mov -0x28(%rbp),%rax
1aa: 89 d6 mov %edx,%esi
1ac: 48 89 c7 mov %rax,%rdi
1af: e8 00 00 00 00 callq 1b4
1b4: 48 8b 5d e8 mov -0x18(%rbp),%rbx
1b8: 64 48 33 1c 25 28 00 xor %fs:0x28,%rbx
1bf: 00 00
1c1: 74 05 je 1c8
1c3: e8 00 00 00 00 callq 1c8
1c8: 48 83 c4 28
1cc: 5b
1cd: 5d
1ce: c3 retq
qemeの実行プロセスの中で、もともとはqemeのコードで、私達はstatic codeと呼ぶことができます。TBによって生成されたホストコードは、dynamic codeと呼ばれることができます。だから、static codeがdynamic codeを呼び出してくれる入り口が必要です。qemeは似たような関数のprologueを採用しています。これもなぜ私達がコードを見たのですか?gen_prologueの原因。code_gen_prologureは、TB全体に対して動的に生成されたprologueを指す。
転載先:https://www.cnblogs.com/long123king/p/3584053.html