榮樂 英樹
株式会社イーゲル
2022-12-07 BitVisor Summit 11
BitVisor 2022年の主な変更
点
1
2
BitVisor 2022年の主な変更点
 Network
– Linuxでの割り込み“nobody
cared” 問題対策
– Intel GbE初期化処理改良
– Broadcom GbE初期化処理改良
 Core
– PKRU state pass-through
– movabs修正
– DMA_CTRL_PLATFORM_OPT
_IN_FLAGクリア
– earlyprintk用シリアルポート
 Process
– 名前無しの
msgregisterと
msgsenddesc対応
 NVMe
– ANS2隠蔽 +
Linux 5.10以降に対応
– QEMU 5.2.0以降に
対応
 その他細かな修正
3
Network: Linuxでの割り込み
“nobody cared” 問題対策
 BitVisor: virtio-net使用 & Intel GbE以外のNIC (割り込みが
実デバイスから直接生成されるケース)
 Linuxでの2つの問題:

インターフェイスdown時: Linuxはdownにしてもvirtioデバイスを停止しない。
キューがいっぱいになっても受信割り込みが発生し続け、しきい値を超えると
nobody caredが出てポーリングモードになる。

インターフェイスup時: net=ippassfilterを使用すると、VMM lwIPとのTCP通信が
Linuxに届かない。VMMとの通信が多いと、Linuxは受信割り込みだけを受け取り
続け、しきい値を超えるとnobody caredが出てポーリングモードになる。
 対策

バッファーフルになった時に割り込みを抑制するようにした。

100回に1回はパケットをゲスト側にも通すnet=ippassfilter2を追加した。
4
Network: Intel GbE初期化処理改
良
QEMU e1000e (8086:10d3, 82574L) 対応

82571EB/82572EI固有の初期化処理が悪影響を与えていたため最低限の
モデル識別が追加された。
82574L and 82571EB/82572EIでの通信性能改善

実デバイスの82574Lで確認
5
Network: Broadcom GbE初期化
処理改良
ファームウェアによる初期化がされていなくても使え
るように改良

ファームウェアによる初期化がされていないx86 PC環境での実際の動作状況
については未調査
6
Core: PKRU state pass-through
問題: VMware Workstationで回復不可能なエラーが発生

XCR0のPKRU stateを隠蔽してあったが、VMware Workstationは使えるつ
もりでxrstor64命令を実行するようで、VMM fault 13というエラー (どうやら一
般保護例外を表す) が発生していた

調査は、エラーメッセージを参考に、一般保護例外が発生した時の情報をログ
に出力するようにして行った
PKRU stateをpass-throughにして対応

PKRU (protection-key rights register for user pages) のアクセスはもともと
禁止していないためpass-throughでよい
7
Core: movabs修正
 64ビットでのmovabs命令 (機械語0xA0〜0xA3、ア
キュームレーターと64ビット直接アドレッシングのメモ
リー間の転送命令) の64ビットアドレスを誤って32ビッ
トとして解釈していたのを修正した。
 一部機種でEPT violationのpanicの原因となっていた。
 今まで発覚しなかった理由:

本命令の解釈を行うのはMMIOのフックのためで、MMIOフックで扱う、PCIデバ
イスのレジスターへのアクセスや、PCI configuration spaceへのアクセス
(MCFG) は、アドレスが機種ごとに異なるため、オペレーティングシステムは通
常本命令でなくレジスターを介したmov命令を用いる。

ファームウェアは、ビルド時にMCFGのアドレスが決まっているため、直接アド
レッシングとなる場合がある。
8
Core: DMA_CTRL_PLATFORM_
OPT_IN_FLAGクリア
DMA_CTRL_PLATFORM_OPT_IN_FLAGは、ACPI
DMA Remapping Reporting (DMAR)テーブルのフラグ
のひとつで、ファームウェアがVT-dのDMA remapping
を設定し、オペレーティングシステムが引き継げるよ
うにするものらしい。
ファームウェアはVMMの存在を知らないため、VMMの
アドレス空間がマップされていないアドレス変換テー
ブルをオペレーティングシステムに渡してしまい、
VMMのDMA転送ができなくなる。WindowsではBSoD
(DMA violation)の原因にもなる。これを避けるため、ク
リアするようにした。
9
Core: earlyprintk用シリアルポー
ト
Linuxの起動時のメッセージをVMM経由でsyslog等へ転
送できるようにするための簡易シリアルポート実装を
追加した。

make configでCONFIG_DEBUG_SERIAL=1に設定すると有効になる。
Linux起動パラメーター:
earlyprintk=serial,0x400,keep

入力が未実装のため、console=uart,io,0x400ではなく、earlyprintkにより出
力のみに設定すると便利
10
Process: 名前無しのmsgregister
とmsgsenddesc対応
名前ありの使い方:

msgregisterで名前と関数ポインターを登録する。

msgopenで登録済み名前を指定してオープンし、それをmsgsenddescに渡し
てプロセスに送る。
名前無しの使い方 (新):

msgregisterで名前をNULLにして関数ポインターを登録する。

msgsenddescに、msgopenで返された値を渡す代わりに、msgregisterで返
された値にMSGSENDDESC_MYFUNCをORして渡すことで、プロセスに送
る。
名前無しの用途:

特定のプロセスからのみ受け付けるコールバックを用意したい場合
11
NVMe: ANS2隠蔽 +
Linux 5.10以降に対応
ANS2隠蔽とは

driver=nvme_apple, ans2_wrapper=1を指定しておくことで、デバイスのクラ
スコードが018002ではなく010802としてオペレーティングシステムに検出さ
れ、ANS2の暗号化対象でなくなる。
Linux 5.10以降の挙動変化

それまでは、クラスコードが010802であれば、デバイスIDがANS2であっても、
通常の64バイトのI/Oコマンドがsubmitされていた。

5.10以降、クラスコードは無視され、デバイスIDがANS2であれば常に128バイ
トのI/Oコマンドがsubmitされるようになった。

Linuxは、いずれの場合もレジスターにはsubmission queueの長さを64バイト
と設定するため、VMMは、2番目にsubmitされたI/Oコマンドを見て、64バイト
の0で埋められていると、処理を128バイト用に切り替える。
12
NVMe: QEMU 5.2.0以降に
対応
QEMU 5.2.0以降のNVMeはnamespaceの数が256に増
えた

特別に設定しなければ、実際に使われるのは1つだけだが、IDENTIFY
CNS=0x01でNumber of Namespacesとして常に256が返され、IDENTIFY
CNS=0x02でNamespace Listを取得しない限り、256個をすべて問い合わせ
る必要があってタイムアウトの原因となっていた。
IDENTIFY CNS=0x02が使用可能であれば使用するよう
にして対応した。
13
その他細かな修正 (1/3)
Core

xsetbv命令の例外生成に対応

IA32_RTIT_CTLのVMCS field encodingミスを修正

IA32_XSS MSRのビットチェックを追加 (xrstors命令用)

UEFI・VT-x環境での仮想マシンから見たCR4.VMXEの初期値を修正

UEFI実装のsizeofに指定する変数名の誤りを修正

String実装を書き直してコードサイズを削減し性能を改善

cpu_interpreter: デフォルトセグメントの誤りと、rep prefixの例外処理を修正

VT-x unsafe nested virtualizationでvmxon命令の引数に対するアドレス変換を追
加

vmm.telnet_dbgsh=1の時にメインのスレッド以外でpanicすると二重にpanic処理
が行われハングしていた問題を修正
14
その他細かな修正 (2/3)
警告等メッセージ対策

CONFIG_TTY_SERIAL=1の時のunused variable

collect2: fatal error: ld terminated with signal 13 [Broken pipe]
Drivers

ブリッジを含めたI/O空間、メモリー空間、バスマスター有効を設定する
pci_enable_device()関数を追加 (ネットワークドライバーにあったものを共通化)
Network

Realtek NICでブリッジ有効化

virtio_net: MAPMEM_WRITE指定忘れを修正

virtio-net: Capability List Bitをセットした状態に見せる (QEMU e1000用)

virtio-net: 送信時の大きさチェック
15
その他細かな修正 (3/3)
NVMe

オペレーティングシステムがRMRRに沿ってVT-dのDMA remappingを設定し
ていない場合に強制的にマッピングを追加するようにした
Process

msgsenddescで送る先をnewprocessで得られたディスクリプターに限る

システムコール引数のチェックを一部追加
SQLite

時刻処理の関数の実装を改善
16
BitVisor 2022年の主な変更点
 Network
– Linuxでの割り込み“nobody
cared” 問題対策
– Intel GbE初期化処理改良
– Broadcom GbE初期化処理改良
 Core
– PKRU state pass-through
– movabs修正
– DMA_CTRL_PLATFORM_OPT
_IN_FLAGクリア
– earlyprintk用シリアルポート
 Process
– 名前無しの
msgregisterと
msgsenddesc対応
 NVMe
– ANS2隠蔽 +
Linux 5.10以降に対応
– QEMU 5.2.0以降に
対応
 その他細かな修正
最新リポジトリ
http://bitvisor.sf.net

BitVisor Summit 11「1. BitVisor 2022年の主な変更点」