LoginSignup
1
1

More than 5 years have passed since last update.

bhyveのソースコードリーディングメモ(iommu_init():その2:AGAWとdomain)

Last updated at Posted at 2014-05-17

参考ドキュメント

前回ドキュメント

ASADA氏の公開記事

この記事から引用したときは「ChapterXX」とする。例えば第15回の記事なら(Chapter15)となる。

Intel ® Virtualization Technology for Directed I/O Architecture Specification

このドキュメントから引用したときは(仕様書:XXX)とする。

domainを作る

今回はiommu_init()の以下処理から読んでみる。

    /*
     * Create a domain for the devices owned by the host
     */
    maxaddr = vmm_mem_maxaddr();
    host_domain = IOMMU_CREATE_DOMAIN(maxaddr);
    if (host_domain == NULL)
        panic("iommu_init: unable to create a host domain");

IOMMU_INIT()経由でvtd_create_domain()が呼ばれる。

AGAW

    /*
     * Calculate AGAW.
     * Section 3.4.2 "Adjusted Guest Address Width", Architecture Spec.
     */

この処理では、最初に引数で与えられた最大物理アドレスのAGAW(Adjusted Guest Address Width)を計算する。
要するに「アドレス幅がどのくらいか」である。

上記引用コメント以下でごにょごにょと計算しているが、要するに以下表のようなagaw値を作りたいのである。

Address範囲 AGAW
0x00000000_00001000 - 0x00000000_001fffff 21
0x00000000_00200000 - 0x00000000_3fffffff 30
0x00000000_40000000 - 0x0000007f_ffffffff 39
0x00000080_00001000 - 0x0000ffff_ffffffff 48

なぜ、AGAWの計算が必要なのか。それは以下コメントにあるとおり、ページテーブルの深さが決まるためである。

    /*
     * Select the smallest Supported AGAW and the corresponding number
     * of page table levels.
     */

次に、IOMMU側でサポートされているAGAWを取得する。

    tmp = VTD_CAP_SAGAW(vtdmap->cap);

ここでちょっとCAPについて

CAPについては、仕様書10.4.2「Capability Register」を見て欲しい。これはその名前のとおり、「このremapping H/Wでできることを調べる」ためのレジスタである。
このレジスタのSAGAW(Supported Adjusted Guest Address Width)は5bitのビットフィールドでこのremapping H/Wでサポートするゲスト物理アドレスのアドレス長を表す。
現時点では、bit1,2がそれぞれ39bit Address Widthと48bit Address Widthを表す。

この関数のループでは、計算から求められたAGAWとハードがサポートしているAGAWの両方を満たすAGAWの中で一番最小のものを選ぶ。おそらく、できる限りページテーブルを小さくするためだと思われる。

domainについて

そして、domain構造体を割り当てる。仕様書3.2「Domains and Address Translation」の記述によると、「プラットホーム内の独立した環境に対して割り当てられたホストの物理アドレスのサブセット」であり、あるデバイスが使うアドレス空間を表現するためのものである。
※ただし、今回作成するドメインはホストの物理アドレス空間そのものと1:1対応する特殊なドメインを作成する。
IOMMU_CREATE_DOMAIN()を呼び出すところに以下コメントがあったことを思い出すと良い。

    /*
     * (省略)
     * Create a domain for the devices owned by the host
     * (省略)
     */
struct domain {
    uint64_t    *ptp;       /* first level page table page */
    int     pt_levels;  /* number of page table levels */
    int     addrwidth;  /* 'AW' field in context entry */
    int     spsmask;    /* supported super page sizes */
    u_int       id;     /* domain id */
    vm_paddr_t  maxaddr;    /* highest address to be mapped */
    SLIST_ENTRY(domain) next;
};

そして、domain構造体を初期化する。
ここで一点注意することがある。
domain構造体のptpメンバはゲストのアドレス空間を表現するためのページテーブルの仮想アドレスが格納される。
(次回あたり書くが、今回はホストドメインという「ホストの物理アドレス空間」を表現するための特殊なドメインを作成する)
この時点でptpが指すページテーブルはAGAWによって決まるLevel分の段数をすべて割り当てるのではなく、ルートとなるページテーブル(Page Map)をただひとつだけ割り当てることである。

今回はここまで。次回は物理アドレス間のマップ(Page Table)について書こうと思う。

1
1
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
1
1