第16章 ゲスト仮想マシンデバイスの設定

Red Hat Enterprise Linux 7 は、ゲスト仮想マシンの以下の 3 つのクラスのデバイスに対応します。
  • エミュレートされたデバイス は、実際のハードウェアを模倣する純粋の仮想デバイスです。変換されていないゲストオペレーティングシステムは標準のインボックスドライバーを使ってこれらのデバイスと動作できるようになります。
  • Virtio デバイス (準仮想化 とも呼ばれる) は、仮想マシン内で最適に動作するように設計された仮想デバイスです。Virtio デバイスは、エミュレートされたデバイスと似ていますが、Linux 以外の仮想マシンにはこれらのデバイスが必要とするドライバーがデフォルトで含まれていません。仮想マシンマネージャー (virt-manager) や Red Hat Virtualization Hypervisor といった仮想化管理ソフトウェアは、対応する Linux 以外のゲストオペレーティングシステム用にこれらのドライバーを自動的にインストールします。Red Hat Enterprise Linux 7 は最高 216 の virtio デバイスに対応します。詳細については、5章KVM 準仮想化 (virtio) ドライバー を参照してください。
  • 割り当てデバイス は、仮想マシンに公開されている物理デバイスです。この方法は、パススルー とも呼ばれます。デバイス割り当てにより、仮想マシンによる PCI デバイスへの排他的アクセスが可能となり、PCI デバイスを使用した各種のタスクを実行できるようになります。また、PCI デバイスがゲストオペレーティングシステムに物理的に接続されているかのように表示させ、動作させることができます。Red Hat Enterprise Linux 7 は、1 仮想マシンあたり最高 32 の割り当てデバイスに対応します。
    デバイス割り当ては、グラフィックデバイスの選択 を含めて PCIe デバイス上でサポートされています。パラレル PCI デバイスは割り当てデバイスとしてのサポートが可能ですが、セキュリティーとシステム設定の競合により、極端な制限があります。
Red Hat Enterprise Linux 7 は、仮想マシンへの単一機能のスロットとして公開されるデバイスの PCI ホットプラグをサポートします。単一機能のホストデバイスとマルチ機能のホストデバイスの個別の機能は、このサポートを有効にするように設定できます。デバイスを仮想マシンへのマルチ機能の PCI スロットとして公開する設定は、ノンホットプラグアプリケーションの場合にお勧めします。
特定デバイスおよび関連する制限の詳細は、「デバイス」を参照してください。

注記

割り込み再マッピングのプラットフォームサポートは、割り当てデバイスを持つゲストをホストから完全に分離するために必要です。このサポートがない場合、ホストは悪意のあるゲストからの割り込み挿入攻撃に対して脆弱になる可能性があります。ゲストが信頼される環境では、管理者は allow_unsafe_interrupts モジュールに対して vfio_iommu_type1 オプションを使用する PCI デバイス割り当てを許可することを選択できます。これは、以下を含む .conf ファイル (例: local.conf) を /etc/modprobe.d に追加することで永続的に実行できます。
options vfio_iommu_type1 allow_unsafe_interrupts=1
または sysfs エントリーを動的に使用して同じことを実行します。
# echo 1 > /sys/module/vfio_iommu_type1/parameters/allow_unsafe_interrupts

16.1. PCI デバイス

PCI デバイス割り当ては、Intel VT-d または AMD IOMMU 対応のハードウェアプラットフォーム上でのみ利用可能です。PCI デバイス割り当てを機能させるには、Intel VT-d または AMD IOMMU の仕様がホストの BIOS で有効にされている必要があります。

手順16.1 Intel システムでの PCI デバイス割り当ての準備

  1. Intel VT-d 仕様を有効にします。

    Intel VT-d 仕様は、物理デバイスを仮想マシンに直接割り当てるためのハードウェアサポートを提供します。この仕様は、Red Hat Enterprise Linux で PCI デバイス割り当てを使用するために必要なものです。
    Intel VT-d 仕様は、BIOS で有効にされている必要があります。システムメーカーの中には、この仕様をデフォルトで無効にしているところもあります。この仕様に言及するために使用される用語はメーカーによって異なります。それぞれの該当する用語については、システムメーカーの資料を参照してください。
  2. カーネルで Intel VT-d をアクティブにします。

    カーネルで Intel VT-d をアクティブにするには、intel_iommu=oniommu=pt パラメーターを /etc/sysconfig/grub ファイルの GRUB_CMDLINX_LINUX 行の終わりの引用符の内側に追加します。
    以下は、Intel VT-d をアクティブにした grub ファイルの修正例です。
    GRUB_CMDLINE_LINUX="rd.lvm.lv=vg_VolGroup00/LogVol01
    vconsole.font=latarcyrheb-sun16 rd.lvm.lv=vg_VolGroup_1/root
    vconsole.keymap=us $([ -x /usr/sbin/rhcrashkernel-param ] && /usr/sbin/
    rhcrashkernel-param || :) rhgb quiet intel_iommu=on iommu=pt"
  3. 設定ファイルを再生成します。

    以下を実行して /etc/grub2.cfg を再生成します。
    grub2-mkconfig -o /etc/grub2.cfg
    UEFI ベースのホストの場合、ターゲットファイルは /etc/grub2-efi.cfg であることに注意してください。
  4. これで使用できるようになります。

    システムを再起動して、変更を有効にします。これでシステムで PCI デバイス割り当てを使用できるようになりました。

手順16.2 AMD システムでの PCI デバイス割り当ての準備

  1. AMD IOMMU 仕様を有効にします。

    AMD IOMMU 仕様は、Red Hat Enterprise Linux で PCI デバイス割り当てを使用するために必要なものです。この仕様は、BIOS で有効にされている必要があります。システムメーカーの中には、この仕様をデフォルトで無効にしているところもあります。
  2. IOMMU カーネルサポートを有効にします。

    amd_iommu=pt/etc/sysconfig/grub の GRUB_CMDLINX_LINUX 行の末尾の引用符の内側に追加し、AMD IOMMU 仕様が起動時に有効になるようにします。
  3. 設定ファイルを再生成します。

    以下を実行して /etc/grub2.cfg を再生成します。
    grub2-mkconfig -o /etc/grub2.cfg
    UEFI ベースのホストの場合、ターゲットファイルは /etc/grub2-efi.cfg であることに注意してください。
  4. これで使用できるようになります。

    システムを再起動して、変更を有効にします。これでシステムで PCI デバイス割り当てを使用できるようになりました。

注記

IOMMU についての詳細は、付録E IOMMU グループの使用 を参照してください。

16.1.1. virsh を使用した PCI デバイスの割り当て

以下のステップでは、KVM ハイパーバイザー上の仮想マシンに PCI デバイスを割り当てる方法を説明します。
以下の例では、PCI 識別子コードが pci_0000_01_00_0 の PCIe ネットワークコントローラーと guest1-rhel7-64 という名前の完全仮想化ゲストマシンを使用します。

手順16.3 virsh を使用した PCI デバイスのゲスト仮想マシンへの割り当て

  1. デバイスを特定します。

    最初に、仮想マシンへのデバイス割り当てに指定されているPCI デバイスを特定します。lspci コマンドで利用可能な PCI デバイスを一覧表示します。lspci の出力を grep を使って絞り込むことができます。
    この例では、以下の出力で強調表示されているイーサネットコントローラーを使用します。
    # lspci | grep Ethernet
    00:19.0 Ethernet controller: Intel Corporation 82567LM-2 Gigabit Network Connection
    01:00.0 Ethernet controller: Intel Corporation 82576 Gigabit Network Connection (rev 01)
    01:00.1 Ethernet controller: Intel Corporation 82576 Gigabit Network Connection (rev 01)
    このイーサネットコントローラーは、00:19.0 の短い識別子と共に表示されています。この PCI デバイスを仮想マシンに割り当てるには、virsh が使用する完全な識別子を見つける必要があります。
    これを実行するには、virsh nodedev-list コマンドを使用して、ホストマシンに接続されている特定の種類 (pci) のデバイスをすべて一覧表示します。次に出力を参照し、使用するデバイスの短い識別子にマップされている文字列を探します。
    この例では、短い識別子 00:19.0 を持つイーサネットコントローラーにマップされている文字列が強調表示されています。完全な識別子では、:. 文字がアンダースコアに置き換えられていることに注意してください。
    # virsh nodedev-list --cap pci
    pci_0000_00_00_0
    pci_0000_00_01_0
    pci_0000_00_03_0
    pci_0000_00_07_0
    pci_0000_00_10_0
    pci_0000_00_10_1
    pci_0000_00_14_0
    pci_0000_00_14_1
    pci_0000_00_14_2
    pci_0000_00_14_3
    pci_0000_00_19_0
    pci_0000_00_1a_0
    pci_0000_00_1a_1
    pci_0000_00_1a_2
    pci_0000_00_1a_7
    pci_0000_00_1b_0
    pci_0000_00_1c_0
    pci_0000_00_1c_1
    pci_0000_00_1c_4
    pci_0000_00_1d_0
    pci_0000_00_1d_1
    pci_0000_00_1d_2
    pci_0000_00_1d_7
    pci_0000_00_1e_0
    pci_0000_00_1f_0
    pci_0000_00_1f_2
    pci_0000_00_1f_3
    pci_0000_01_00_0
    pci_0000_01_00_1
    pci_0000_02_00_0
    pci_0000_02_00_1
    pci_0000_06_00_0
    pci_0000_07_02_0
    pci_0000_07_03_0
    使用するデバイスにマップされている PCI デバイス番号を書き留めてください。この番号は他のステップで必要になります。
  2. デバイス情報を確認します。

    ドメイン、バスおよび機能についての情報は、virsh nodedev-dumpxml コマンドの出力を参照してください。
    
    # virsh nodedev-dumpxml pci_0000_00_19_0
    <device>
      <name>pci_0000_00_19_0</name>
      <parent>computer</parent>
      <driver>
        <name>e1000e</name>
      </driver>
      <capability type='pci'>
        <domain>0</domain>
        <bus>0</bus>
        <slot>25</slot>
        <function>0</function>
        <product id='0x1502'>82579LM Gigabit Network Connection</product>
        <vendor id='0x8086'>Intel Corporation</vendor>
        <iommuGroup number='7'>
          <address domain='0x0000' bus='0x00' slot='0x19' function='0x0'/>
        </iommuGroup>
      </capability>
    </device>
    

    図16.1 内容のダンプ

    注記

    IOMMU グループは、IOMMU から見たデバイスの可視性と分離度に基づいて決定されます。それぞれの IOMMU グループには、1 つ以上のデバイスが含まれる可能性があります。複数のデバイスが表示される場合、すべてのエンドポイントが、ゲストに割り当てられるIOMMU グループ内のすべてのデバイスに対して要求される必要があります。これは、追加のエンドポイントをゲストに割り当てるか、または virsh nodedev-detach を使用してエンドポイントをホストドライバーから分離するかのいずれかの方法で実行できます。単一グループに含まれるデバイスは、複数のゲスト間で分割したり、ホストとゲストの間で分割したりすることができないことがあります。PCIe ルートポート、スイッチポート、およびブリッジなどエンドポイント以外のデバイスはホストドライバーから分離することはできません。これらはエンドポイントの割り当てを妨げることはありません。
    IOMMU グループ内のデバイスは、virsh nodedev-dumpxml 出力の iommuGroup セクションを使用して判別できます。グループの各メンバーは別個の「アドレス」フィールドで指定されます。この情報は、以下を使用して sysfs 内で見つけることもできます。
    $ ls /sys/bus/pci/devices/0000:01:00.0/iommu_group/devices/
    この出力の一例を示します。
    0000:01:00.0  0000:01:00.1
    0000.01.00.0 のみをゲストに割り当てるには、ゲストを起動する前に、使用されていないエンドポイントをホストから切り離す必要があります。
    $ virsh nodedev-detach pci_0000_01_00_1
  3. 必要な設定の詳細を決定します。

    設定ファイルに必要な値については、virsh nodedev-dumpxml pci_0000_00_19_0 コマンドの出力を参照してください。
    サンプルのデバイスには、bus = 0、slot = 25、function = 0 の値が設定されています。10 進法の設定では、これらの値を使用します。
    bus='0'
    slot='25'
    function='0'
  4. 設定の詳細を追加します。

    仮想マシン名を指定して virsh edit を実行し、<source> セクションにデバイスエントリーを追加して PCI デバイスをゲスト仮想マシンに割り当てます。
    # virsh edit guest1-rhel7-64
    <hostdev mode='subsystem' type='pci' managed='yes'>
      <source>
         <address domain='0' bus='0' slot='25' function='0'/>
      </source>
    </hostdev>
    

    図16.2 PCI デバイスの追加

    または、仮想マシン名とゲストの XML ファイルを指定して virsh attach-device を実行します。
    virsh attach-device guest1-rhel7-64 file.xml
  5. 仮想マシンを起動します。

    # virsh start guest1-rhel7-64
これで PCI デバイスは正しく仮想マシンに割り当てられ、ゲストオペレーティングシステムからアクセスできるようになります。

16.1.2. virt-manager を使用した PCI デバイスの割り当て

PCI デバイスは、グラフィカルな virt-manager ツールを使ってゲスト仮想マシンに追加することができます。以下の手順では、Gigabit イーサネットコントローラーをゲスト仮想マシンに追加します。

手順16.4 virt-manager を使用した PCI デバイスのゲスト仮想マシンへの割り当て

  1. ハードウェア設定を開きます。

    ゲスト仮想マシンを開き、ハードウェアを追加 ボタンをクリックして新規デバイスを仮想マシンに追加します。
    The virtual machine hardware window with the Information button selected on the top taskbar and Overview selected on the left menu pane.

    図16.3 仮想マシンのハードウェア情報ウィンドウ

  2. PCI デバイスを選択します。

    左側の PCI Host Deviceハードウェア リストから を選択します。
    未使用の PCI デバイスを選択します。別のゲストが使用中の PCI デバイスを選択するとエラーが発生するので注意してください。以下の例では、予備のオーディオコントローラーが使用されます。完了 をクリックしてセットアップを終了します。
    The Add new virtual hardware wizard with PCI Host Device selected on the left menu pane, showing a list of host devices for selection in the right menu pane.

    図16.4 新しい仮想ハードウェアを追加ウィザード

  3. 新規デバイスを追加します。

    セットアップが完了し、これでゲスト仮想マシンは PCI デバイスに直接アクセスできます。
    The virtual machine hardware window with the Information button selected on the top taskbar and Overview selected on the left menu pane, displaying the newly added PCI Device in the list of virtual machine devices in the left menu pane.

    図16.5 仮想マシンのハードウェア情報ウィンドウ

注記

デバイスの割り当てに失敗する場合、ホストに依然として接続されている他のエンドポイントが同じ IOMMU グループ内にある可能性があります。virt-manager を使用してグループ情報を取得する方法はありませんが、virsh コマンドを使用して IOMMU グループの範囲を分析することができ、必要な場合はデバイスを分離することができます。
IOMMU グループについての詳細および virsh を使用してエンドポイントデバイスを切り離す方法については、「virsh を使用した PCI デバイスの割り当て」注記 を参照してください。

16.1.3. virt-install を使用した PCI デバイスの割り当て

virt-install コマンドを使ってゲストをインストールする際に、PCI デバイスを割り当てることができます。この場合、--host-device パラメーターを使用します。

手順16.5 virt-install を使用したゲスト仮想マシンへのPCI デバイス割り当て

  1. デバイスを特定します。

    ゲスト仮想マシンへのデバイス割り当てに指定されているPCI デバイスを特定します。
    # lspci | grep Ethernet
    00:19.0 Ethernet controller: Intel Corporation 82567LM-2 Gigabit Network Connection
    01:00.0 Ethernet controller: Intel Corporation 82576 Gigabit Network Connection (rev 01)
    01:00.1 Ethernet controller: Intel Corporation 82576 Gigabit Network Connection (rev 01)
    virsh nodedev-list コマンドは、システムに接続されている全デバイスを一覧表示し、各 PCI デバイスを文字列で特定します。出力を PCI デバイスに限定するには、以下のコマンドを入力します。
    # virsh nodedev-list --cap pci
    pci_0000_00_00_0
    pci_0000_00_01_0
    pci_0000_00_03_0
    pci_0000_00_07_0
    pci_0000_00_10_0
    pci_0000_00_10_1
    pci_0000_00_14_0
    pci_0000_00_14_1
    pci_0000_00_14_2
    pci_0000_00_14_3
    pci_0000_00_19_0
    pci_0000_00_1a_0
    pci_0000_00_1a_1
    pci_0000_00_1a_2
    pci_0000_00_1a_7
    pci_0000_00_1b_0
    pci_0000_00_1c_0
    pci_0000_00_1c_1
    pci_0000_00_1c_4
    pci_0000_00_1d_0
    pci_0000_00_1d_1
    pci_0000_00_1d_2
    pci_0000_00_1d_7
    pci_0000_00_1e_0
    pci_0000_00_1f_0
    pci_0000_00_1f_2
    pci_0000_00_1f_3
    pci_0000_01_00_0
    pci_0000_01_00_1
    pci_0000_02_00_0
    pci_0000_02_00_1
    pci_0000_06_00_0
    pci_0000_07_02_0
    pci_0000_07_03_0
    PCI デバイス番号は他のステップで必要になるので、書き留めます。
    ドメイン、バスおよび各種機能についての情報は、virsh nodedev-dumpxml コマンドの出力を参照することができます。
    # virsh nodedev-dumpxml pci_0000_01_00_0
    
    <device>
      <name>pci_0000_01_00_0</name>
      <parent>pci_0000_00_01_0</parent>
      <driver>
        <name>igb</name>
      </driver>
      <capability type='pci'>
        <domain>0</domain>
        <bus>1</bus>
        <slot>0</slot>
        <function>0</function>
        <product id='0x10c9'>82576 Gigabit Network Connection</product>
        <vendor id='0x8086'>Intel Corporation</vendor>
        <iommuGroup number='7'>
          <address domain='0x0000' bus='0x00' slot='0x19' function='0x0'/>
        </iommuGroup>
      </capability>
    </device>
    

    図16.6 PCI デバイスファイルの内容

    注記

    IOMMU グループに複数のエンドポイントがあり、それらのすべてがゲストに割り当てられている訳ではない場合、ゲストを起動する前に以下のコマンドを実行して、他のエンドポイントをホストから手動で切り離す必要があります。
    $ virsh nodedev-detach pci_0000_00_19_1
    IOMMU グループの詳細は、「virsh を使用した PCI デバイスの割り当て」注記 を参照してください。
  2. デバイスを追加します。

    virsh nodedev コマンドの PCI 識別子の出力を --host-device パラメーターの値として使います。
    virt-install \
    --name=guest1-rhel7-64 \
    --disk path=/var/lib/libvirt/images/guest1-rhel7-64.img,size=8 \
    --vcpus=2 --ram=2048 \
    --location=http://example1.com/installation_tree/RHEL7.0-Server-x86_64/os \
    --nonetworks \
    --os-type=linux \
    --os-variant=rhel7
    --host-device=pci_0000_01_00_0
  3. インストールを完了します。

    これでゲストのインストールが完了しました。PCI デバイスはゲストに接続されています。

16.1.4. 割り当てた PCI デバイスの接続解除

ホストの PCI デバイスがゲストマシンに割り当てられると、ホストはこのデバイスを使用できなくなります。PCI デバイスが managed モードにある場合は (managed='yes'ドメイン XML ファイル パラメーターを使って設定)、必要に応じてゲストマシンに接続し、ゲストマシンから切り離し、再びホストマシンに接続することができます。PCI デバイスが managed モードにない場合は、virsh または virt-manager を使って PCI デバイスをゲストマシンから切り離し、再び接続することができます。

手順16.6 virsh を使用した PCI デバイスのゲストからの接続解除

  1. デバイスの接続を解除します。

    以下のコマンドを使ってゲストの XML ファイル内から PCI デバイスを削除することで、ゲストから PCI デバイスを切り離します。
    # virsh detach-device name_of_guest file.xml
  2. デバイスをホストに再接続します (オプション)。

    デバイスが managed モードの場合は、このステップを省略します。デバイスはホストに自動的に戻ります。
    デバイスが managed モードを使用していない場合は、以下のコマンドを使用して PCI デバイスをホストマシンに再接続します。
    # virsh nodedev-reattach device
    たとえば、pci_0000_01_00_0 デバイスをホストに再接続するには、以下のようにします。
    # virsh nodedev-reattach pci_0000_01_00_0
    これでこのデバイスはホストで使用できます。

手順16.7 virt-manager を使用した PCI デバイスのゲストからの接続解除

  1. 仮想ハードウェアの詳細画面を開きます。

    virt-manager で、デバイスを含む仮想マシンをダブルクリックします。仮想マシンの情報を表示 ボタンを選択し、仮想ハードウェアの一覧を表示します。
    The Show virtual hardware details button.

    図16.7 仮想ハードウェア詳細ボタン

  2. デバイスを選択し、削除します。

    左側パネルの仮想デバイスの一覧より、接続を解除する PCI デバイスを選択します。
    The PCI device details and the Remove button.

    図16.8 接続解除する PCI デバイスの選択

    削除 ボタンをクリックします。これでデバイスがホストで使用可能になります。

16.1.5. PCI ブリッジの作成

PCI (Peripheral Component Interconnect) ブリッジは、ネットワークカード、モデムおよび音声カードなどのデバイスに接続するために使用されます。物理デバイスと同様に、仮想デバイスも PCI ブリッジに接続することができます。かつてゲスト仮想マシンに追加できる PCI デバイスの数は 31 のみでした。現在では、31 番目の PCI デバイスが追加されると、PCI ブリッジが自動的に 31 番目のスロットに配置され、追加の PCI デバイスはその PCI ブリッジに移行します。それぞれの PCI ブリッジには、追加の 31 デバイスに対応する 31 のスロットがあり、それらすべてをブリッジにすることができます。この方法で、900 を超えるデバイスをゲスト仮想マシンで利用可能にすることができます。このアクションは、ゲスト仮想マシンが実行中の場合には実行できないことに注意してください。シャットダウンしているゲスト仮想マシンに PCI デバイスを追加する必要があります。

16.1.5.1. PCI ブリッジのホットプラグ/アンホットプラグサポート

PCI ブリッジのホットプラグ/アンホットプラグは、以下のデバイスタイプでサポートされています。
  • virtio-net-pci
  • virtio-scsi-pci
  • e1000
  • rtl8139
  • virtio-serial-pci
  • virtio-balloon-pci

16.1.6. PCI デバイス割り当ての制限

PCI デバイス割り当て (PCI デバイスの仮想マシンへのアタッチ) で PCIe デバイスのデバイス割り当てを有効にするには、ホストシステムが AMD IOMMU または Intel VT-d サポートを備えている必要があります。
Red Hat Enterprise Linux 7 では、ゲストデバイスドライバーによる PCI 設定領域へのアクセスは制限されています。この制限により、拡張された PCI 設定領域にあるデバイス機能に依存するドライバーが設定に失敗する場合があります。
Red Hat Enterprise Linux 7 仮想マシン 1 台あたりに割り当てられるデバイスの合計数は 32 という制限があります。これは、仮想マシンにある PCI ブリッジの数やそれらの機能がどのようにマルチファンクションスロットを構成するように組み合わされるかにかかわらず、32 の PCI 機能に変換されることを意味します。
割り込み再マッピングのプラットフォームサポートは、割り当てデバイスを持つゲストをホストから完全に分離するために必要です。このサポートがない場合、ホストは悪意のあるゲストからの割り込み挿入攻撃に対して脆弱になる可能性があります。ゲストが信頼される環境では、管理者は allow_unsafe_interrupts モジュールに対して vfio_iommu_type1 オプションを使用する PCI デバイス割り当て許可を選択できます。これは、以下を含む .conf ファイル (例: local.conf) を /etc/modprobe.d に追加することで永続的に実行できます。
options vfio_iommu_type1 allow_unsafe_interrupts=1
または sysfs エントリーを動的に使用して同じことを実行します。
# echo 1 > /sys/module/vfio_iommu_type1/parameters/allow_unsafe_interrupts