Upgrade to Pro — share decks privately, control downloads, hide ads and more …

BHyVe Internals

BHyVe Internals

Takuya ASADA

May 26, 2012
Tweet

More Decks by Takuya ASADA

Other Decks in Technology

Transcript

  1. 1
    BHyVe internals
    @syuu1228

    View Slide

  2. 2
    1, BHyVe 概要

    View Slide

  3. 3
    BHyVe とは

    FreeBSD 版の Linux KVM のようなもの

    Intel VT を用いたハイパーバイザ
    ● 開発の初期段階でごく限定的な機能が実装されている
                ↓
    最低限のハイパーバイザ実装のよいサンプルになりそう

    View Slide

  4. 4
    新しい Web サイトと GSoC
    web site
    http://www.bhyve.org/
    GSoC 2012: BHyVe BIOS emulation
    to boot legacy systems
    http://bit.ly/bhyve_bios

    View Slide

  5. 5
    実装状況

    Intel VT-x, EPT 必須 (= Nehalem 以降必須 )

    BIOS 非対応 (disk ブート出来ない )

    対応デバイス :
    – virtio-net, virtio-blk
    – pci passthrough(VT-d)
    – paravirtual console/debug port
    – UART

    対応 OS:
    – FreeBSD 8, 9, 10

    View Slide

  6. 6
    /usr/sbin/bhyve
    vmm.ko
    BSD kernel
    IOCTL(VM_RUN)
    Guest kernel
    User
    program
    VMLAUNCH
    VMExit
    動作イメージ

    View Slide

  7. 7
    使い方

    /boot/loader.conf
    hw.physmem="0x100000000"
    (ホストのメモリ割り当てを減らしてゲスト用の領域を
    用意)

    kldload vmm.ko
    /usr/sbin/bhyveload -m ${lowmem} -M {highmem} -h {bootdir} $
    {vmname}
    /usr/sbin/bhyve -c ${cpus} -m ${lowmem} -M{highmem} \
    -s 1,virtio-net,tap0 -s 2,virtio-blk,${diskdev}

    View Slide

  8. 8
    各コマンドの役割分担

    /usr/sbin/bhyveload
    VM インスタンスを作成し、 BSD カーネルを VM インスタンスのメモ
    リ領域にロードして起動可能な状態を作る

    /usr/sbin/bhyve
    bhyveload が初期化した VM インスタンスを実行し、ディス
    ク、 NIC 、コンソールなどのデバイスエミュレーション処理を行う
    VM インスタンスの状態は、プロセス内ではなく /dev/vmm/${vmname}
    というデバイス上、つまりカーネル内に保持される。
    このファイルへ read(), write(), mmap() する事により VM 内のメモリ空
    間にアクセス出来る。

    View Slide

  9. 9
    bhyveload の動作

    sysctl(“hw.vmm.create”, vm_name)
    → /dev/vmm/${vm_name} を作成

    open(/dev/vmm/${vm_name})

    seg.gpa = 0
    seg.len = mem_size
    ioctl(fd, VM_MAP_MEMORY, seg)
    membase = mmap(NULL, mem_size, PROT_READ|
    PROT_WRITE, MAP_SHARED, fd, 0)

    userboot.so を使って membase の領域へ BSD カーネルを
    memcpy()

    View Slide

  10. 10
    userboot.so

    FreeBSD のブートローダをユーザ空間で動くように移植
    したもの

    メモリやレジスタへの読み書きを wrap 、ゲストのメモリ
    空間/レジスタへアクセス
    (メモリ空間は mmap 、レジスタの読み書きは ioctl 経由
    で VMM が管理するゲストのデスクリプタへ)

    これを利用して kload が実装されている
    ( Linux における kexec と同じ)

    View Slide

  11. 11
    bhyve の動作

    open(/dev/vmm/${vm_name})
    ● デバイス初期化

    pthread_create(fbsdrun_start_thread)
    fbsdrun_start_thread() {
    while(1) {
    ioctl(VM_RUN, &vmexit)
    handler[vmexit.exitcode](&vmexit, &vcpu);
    }
    }
    ● メイン関数はデバイスエミュレーションの処理要求イベントを
    kevent() で待つ

    View Slide

  12. 12
    デモ
    http://www.youtube.com/watch?v=N2TbKzE_puA

    View Slide

  13. 13
    2, CPU の初期化と
    OS のロード

    View Slide

  14. 14
    vCPU の初期化

    bhyveload で以下の初期化を実施
    – CR0 = PE | PG | NE # ページング、プロテクトモード
    – CR4 = PAE | VMXE # PAE 、 VMX 有効
    – EFER = LME | LMA # long mode 有効
    – GDT 初期化&セグメントレジスタ初期化
    – タスクレジスタ初期化
    – ページテーブル& CR3 初期化
    – RSP 初期化
    – エントリポイント設定

    View Slide

  15. 15
    mptable の初期化

    /usr/sbin/bhyve から実行(引数の CPU 数を使用)

    (未実装な ACPI を使わずに)セカンダリ CPU の情報を
    OS に伝える

    BIOS ROM 領域上にテーブルを用意

    PCI デバイスや割り込みの情報の伝達にも使ってる?

    View Slide

  16. 16
    bhyveload の役割
    ● ホストのユーザ空間でブートローダを起動して、カーネ
    ルをロードする為のレジスタ/セグメント/ページテー
    ブルの初期化を行う

    ゲストはいきなり 64bit モードでカーネルを実行

    View Slide

  17. 17
    3, IO デバイス
    エミュレーション

    View Slide

  18. 18
    ゲストカーネルのコンフィグレーション
    device pci
    device bvmconsole
    device bvmdebug
    device mptable
    ACPI や多くのデバイスは無効
    virtio.ko, if_vtnet.ko, virtio_pci.ko, virtio_blk.ko はモジュール
    としてビルド

    View Slide

  19. 19
    /usr/sbin/bhyve
    vmm.ko
    BSD kernel
    IOCTL return
    Guest kernel
    VMExit
    IO エミュレーション
    IO 命令
    console
    PCI
    net blk
    io emulation 実行

    View Slide

  20. 20
    IO エミュレーション

    ゲスト OS が in/out 命令を実行、 VMExit

    vmm.ko で EXIT_REASON_INOUT をハンドル

    VM_EXITCODE_INOUT で ioctl を return 、カーネルか
    ら /usr/sbin/bhyve へ制御を移す

    handler[VM_EXITCODE_INOUT]()
          ↓
    inout_handlers[port].handler()
    の順にハンドラがコールされ、 IO ポートに割り当てられ
    たハンドラが実行される

    View Slide

  21. 21
    bvm_console

    IO 空間の 0x220 に inl / outl で読み書き
    ● ゲストドライバ
    – int getc(void) { return inl(0x220); }
    – void putc(int c) { outl(0x220, c); }
    – 割り込みなどない。

    VMM
    – if (in) {
    read(fd, &c, 1);
    *eax = (c & 0xff);
    }else
    write(fd, *eax, 1);

    View Slide

  22. 22
    PCI バス

    CONFIG_ADDRESS レジスタ: 0xcf8

    CONFIG_DATA レジスタ: 0xcfc – 0xcff

    各仮想 PCI デバイスは初期化時に自分のコンフィグレジ
    スタの値を設定

    各仮想 PCI デバイスの IO レジスタはデバイス初期化時に
    動的に確保

    View Slide

  23. 23
    PCI デバイスの MSI 割り込みサポート

    PCI 割り込みとして MSI 割り込みのみサポート

    デバイス初期化時に configuration space 上の MSI capable フラグ
    を有効化

    /usr/sbin/bhyve からの割り込み要求は、 VM_LAPIC_IRQ ioctl と
    して vmm.ko へ送られる
    引数として cpuid と vector ナンバを指定

    vmm.ko で ioctl を受けて vlapic にレジスタ値をセット

    vmlaunch 前に vlapic の値をチェックして、割り込みがあったら
    VMCS にフラグをセット

    View Slide

  24. 24
    MSR register のエミュレーション

    Local APIC をエミュレートする為に、 wrmsr/rdmsr 命令で
    VMExit を発生させ、エミュレーションを行なっている

    ほぼ vmm.ko でエミュレーションを行なっているが、初期
    化周りの一部の処理で /usr/sbin/bhyve へエミュレーション
    を行わせている

    View Slide

  25. 25
    タイマー

    Local APIC Timer
    vmlaunch 前にタイマーの値を計算、 vlapic へ割り込みを設定
    vmm.ko 内でエミュレーション

    TSC
    rdtsc を trap していないように見える
    (その場合どうなるんだろう??)

    PIT 8254
    /usr/sbin/bhybe で IO ポートアクセスのエミュレーションをして
    いる
    割り込むコードが見当たらないような…??

    View Slide

  26. 26
    virtio-net, blk

    PCI デバイス、 IO エミュレーションと MSI 割り込みを使


    /usr/sbin/bhyve でエミュレーション

    MMIO は使っていない
    (そもそも MMIO に対応していないっぽい…)

    View Slide

  27. 27
    pci passthrough(VT-d)
    ● デフォルトでは使わない

    Intel VT-d を使って PCI デバイスをゲストに割り当てる機


    物理デバイス→ゲストへの割り込み転送は vmm.ko 内で行
    なっているが、 io は一度 /usr/sbin/bhyve へ戻しているよう
    に見える

    MMIO 空間は EPT 経由でゲストにマップしている模様

    View Slide

  28. 28
    UART

    ( bvm_console がダサいので)最近実装されました

    てっきり PC の COM ポートをエミュレーション出来るよ
    うにしたのかと思ったら、なんと PCI デバイス…。

    Siig CyberSerial 1-port と自己申告

    IOAPIC 未実装だから割り込みも未実装\ (^o^) /

    View Slide

  29. 29
    まとめ
    ● たったこれだけのデバイスエミュレーションで、
    (ちょっと苦しいけど)ゲスト OS が動く事が分かる
    – 但し、準仮想化デバイスを幾つか使っているのでゲスト側ドラ
    イバが必須

    現状では FreeBSD しか動かないが、 FreeBSD カーネルに
    依存している訳ではない事がわかる
    – bhyveload を fork して自分の起動したい OS に対応したものを書
    けば、動きそう

    View Slide

  30. 30
    おまけ

    BHyVe Hackathon 参加者募集中

    http://bit.ly/bhyve_hackathon
    詳しくは @syuu1228 まで

    View Slide