LoginSignup
2
0

More than 5 years have passed since last update.

BitVisorのMSR Bitmapについて

Posted at

これはBitVisor Advent Calendar 2018の16日目の記事です.

@morimolymolyです.
研究でBitVisorを扱っています.よろしくおねがいします.
Twitterブログもやっています.

今日はBitVisorのMSR周り,特にMSR Bitmapのお話をします.

MSR Bitmapとは

通常,MSRへのアクセスがあった場合,毎回VM Exitが起こりゲストからハイパーバイザへと制御が移ります.しかしVMExitなどのコンテキストスイッチはオーバーヘッドになるため,不要なVMExitは減らすべきです.そこで特定のMSRアクセスのみトラップして,ほかをパススルーするために,BitVisorではMSR Bitmapを導入しています.
Exception BitmapやPFEC_MASK(PageFault Error Code Match)やPFEC_MATCH(PageFault Error Code Match)も例外やページフォールトを選択的にトラップするための手段で,MSR Bitmapと似ていますね.

さて,MSR Bitmapには以下の4種類あります.

  • Read bitmap for low MSRs: MSRのIndexが00000000H to 00001FFFH
  • Read bitmap for high MSRs : MSRのIndexがC0000000H to C0001FFFH.MSR Bitmapのアドレスに0x400足したところ.
  • Write bitmap for low MSRs : MSRのインデックスが00000000H to 00001FFFH.MSR Bitmapのアドレスに0x800足したところ.
  • Write bitmap for high MSRs: MSRのインデックスがC0000000H to C0001FFFH.MSR Bitmapのアドレスに0xC00足したところ.

BitVisorでのMSR Bitmapの扱い

MSR Bitmapはcore/msr_pass.cにて実装されています.
static void msr_pass_init (void)が初期化部分です.
基本的にはcurrent->vmctl.msrpassを引数をセットして呼び出しています.
vmctlはAMD-VとIntel VT-xを抽象化するレイヤです.
それぞれ,core/svm.ccore/vt.cにてstatic struct vmctl_func funcに代入しているところが関数ポインタの初期化部分なので,追いかけるときはここを起点として読みます.
msrpassはそれぞれ,core/svm_msr.ccore/vt_msr.cに実装があります.
ここではIntel Vt-xの実装を読んでみましょう.

void
vt_msrpass (u32 msrindex, bool wr, bool pass)
{
    u8 *p;

    switch (msrindex) {
    case MSR_IA32_SYSENTER_CS:
    case MSR_IA32_SYSENTER_ESP:
    case MSR_IA32_SYSENTER_EIP:
// 省略...
    case MSR_IA32_MTRR_PHYSMASK8:
    case MSR_IA32_MTRR_PHYSMASK9:
    case MSR_IA32_PAT:
        pass = false;
        break;
    case MSR_IA32_MTRRCAP:
    case MSR_IA32_FEATURE_CONTROL:
    case MSR_IA32_VMX_PROCBASED_CTLS2:
        if (!wr)
            pass = false;
        break;
    }
    p = current->u.vt.msrbmp->msrbmp;
    if (wr)
        p += 0x800;
    if (msrindex <= 0x1FFF)
        vt_setmsrbmp (p, msrindex, !pass);
    else if (msrindex >= 0xC0000000 && msrindex <= 0xC0001FFF)
        vt_setmsrbmp (p + 0x400, msrindex - 0xC0000000, !pass);
}

msrindexはMSRのインデックス,wrは書き込みならtrue,passはpass-throughするならtrueです.トラップしたい場合はpassをfalseにします.

static void
vt_setmsrbmp (u8 *p, u32 bitoffset, int bit)
{
    if (bit)
        p[bitoffset >> 3] |= 1 << (bitoffset & 7);
    else
        p[bitoffset >> 3] &= ~(1 << (bitoffset & 7));
}

ここが書き込み部分.

宣伝:仮想化技術slack HyperVillage

特に活動しているわけではないですが,仮想化技術関連のslackを立ち上げました.
招待URL
4人しか人がいないですが,ぜひ入ってくれるとうれしいです.(あわよくば実装の相談など……)

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0