前提条件
VMを構築する前にやるべきこと
以下のDiscordサーバーは、それぞれVFIOとLooking Glassに精通した人が数多く存在しており、また初心者が陥りやすいトラブルについての解説も豊富です。Discordの検索機能で問題が解決することも多いため、事前に入っておくと良いでしょう。
なおVMの構築には英語力が必須であり、英語が読めない場合構築難易度が跳ね上がりますので注意してください。
PCコンポーネント
| コンポーネント | 条件 | 筆者の環境 | 説明 |
|---|---|---|---|
| CPU | AMD | Ryzen 9950x | Intelは今回カバーしない |
| MOBO | ASUS ProArt B650-CREATOR | IOMMU非対応は不可 | |
| GPU(ホスト) | Radeon | RX 7700XT | |
| GPU(ゲスト) | NVIDIA | RTX 4060 TI | |
| SSD(ゲスト) | Samsung 990 Pro 2TB | なくても良い |
CPUについて
IntelとAMDでは、それぞれ対応している機能が異なり必要な設定も変わります。
またIntelのCPUを使用する場合、PコアとEコアの二種類を考慮して設定を行わなければならないため、AMDのCPUより手間が増えます。
QEMUを使ったVMのサンプル設定ではAMDが圧倒的に多く使われているため、こちらも手間を減らす意味でAMDのCPUを使ったほうが良いです。
GPUについて
LinuxでGPUを使う場合、ドライバーの出来が良いためNVIDIAよりAMD製のGPUを推奨します。
ただRadeonの一部GPUには「GPU Reset Bug」があり、VM内でRadeonのGPUを使った場合、一度VMをシャットダウンするとホスト側を再起動しない限りGPUが使えなくなります。この問題を回避するため、VM側ではNVIDIAを使うことが推奨されます。
AMD製のCPUに搭載されている内蔵GPUは特に「GPU Reset Bug」の影響を大きく受ける他、マザーボードのドライバからVBIOSを抽出して読み込むよう別途設定が必要であり、更にそこまでしてもLooking Glassがまともに動かない問題を抱えているため、AMDの内蔵GPUはVMで使えないものと考えたほうが良いでしょう。
SSDについて
QEMUの機能としてハードディスクのエミュレーションがあるため、必ず別途SSDを買う必要はありません。ただ、別途SSDを用意することで次の利点が得られます。
- VM・デュアルブートの両方に対応した構成を作成できる
- ハードディスクのエミュレーションにCPUのリソースを取られないため、性能向上が見込める
ホスト側環境
$ uname -a
Linux arch 6.16.1-arch1-1 #1 SMP PREEMPT_DYNAMIC Fri, 15 Aug 2025 16:04:43 +0000 x86_64 GNU/Linux
ホスト側OSとしては、Arch Linuxを使うことが望ましいです。Arch Linux Wikiには、Linuxでゲームをする・VMを立てるうえで重要な情報が数多く記載されています。
また、Arch Linuxを使う場合、最低でも以下のパッケージは入れておく必要があります。
| パッケージ | 詳細 |
|---|---|
| qemu-full | QEMU本体 |
| libvirt | QEMUをXMLで宣言的に扱うためのソフトウェア |
| virt-viewer | libvirtをGUIから操作するためのソフトウェア |
Windows VMの構築
はじめに、Windows ISOを以下のURLからダウンロードしてください。
ダウンロードが完了したら、まずGPUパススルーなしでのWindows VM構築を始めます。virt-viewerをインストールした後、以下のコマンドを実行してVirtual Machine ManagerのGUIを立ち上げます。
$ virt-manager
なおVirtual Machine Managerはroot権限を要求しますが、以下の設定を行うことで、ユーザー権限で動作するようになります。
-
/etc/libvirt/qemu.confに以下の設定を付け加える
user = "<ユーザー名>"
- 以下のコマンドを実行する
$ usermod -aG libvirt $(whoami)
- PCを再起動する
Virtual Machine Managerの設定更新
VMの構築前に、一点だけ設定しておくべき箇所があります。上の「Edit」タブから「Preferences」を選択すると設定ダイアログがでますので、ここから「Enable XML editing」を有効にしてください。
設定が完了したら、ダイアログを閉じ、元の画面左上にあるアイコンを押して新規VMを作成します。
新規VMの作成
Local install mediaを選択し、先程ダウンロードしたWindows ISOを選択してください。
CPUとメモリの設定が完了したらハードディスクの作成を求められますが、もしVMのために別途SSDを購入してある場合、この設定は必要がないため「Enable storage for this virtual machine」のチェックを外してください。
もしSSDがない場合、ホスト側の空き容量に応じて適切なサイズでハードディスクの作成を行ってください。
最後の確認画面ですが、VMを起動する前に行う設定があるため「Customize configuration before install」にチェックを入れて「Finish」を押します。
VMの設定に関するダイアログが開いたら、「Overview」→「XML」にてVMの定義ファイルを直接確認・編集できます。
VM定義ファイルの確認・編集
OS Firmwareの確認
定義ファイルが開けたら、まず<os />のfirmwareがefiになっているか確認してください。
<os firmware="efi">
ここでfirmwareの設定が抜け落ちていると、UEFIモードではなくBIOSモードでWindowsが起動することになります。BIOSモードでインストールしてしまうと後々デュアルブートができなくなってしまうため、この項目はインストール前に確認する必要があります。
SSDの追加
別途SSDを用意した人は、先程ハードディスクの作成を行わなかったため、SSDのPCIeをVMにパススルーする必要があります。
ダイアログの「Add Hardware」ボタンから「PCI Host Device」を選択し、SSDを選択してください。この選択ダイアログではパススルーできるもののほか、現在使用中のデバイスも表示されるため、誤ってホスト側のSSDを選択しないよう気をつけてください。
なおこの段階ではGPUをパススルーするのに必要な設定がまだ行われていないためGPUの設定はまだ行わないでください。
Windowsのインストール
これらの事前準備が完了したら、ダイアログ左上の「Begin Installation」を押してWindowsのインストールを始めます。
なお、もしインストールを中断した場合でも、VMの設定ダイアログ内にある「Boot Options」にて「SATA CDROM 1」のチェックをつけると再度Windows ISOから起動できます。
VM内の画面を操作して、Windowsのインストールが完了したら次の項目へ進みます。
GPUのパススルー
このセクションの大部分は、Arch Linux Wikiの以下のページを参考にして書かれています。詳細についてはこちらを確認してください。
vfio-pciのバインド
pciutilsパッケージのlspci -nnkを実行して、接続されている全てのPCIeデバイスを表示します。出力結果から、パススルーしたいGPUのデバイスIDを確認します。
$ lspci -nnk
...
05:00.0 VGA compatible controller [0300]: NVIDIA Corporation AD106 [GeForce RTX 4060 Ti] [10de:2803] (rev a1)
Subsystem: ASUSTeK Computer Inc. Device [1043:88f8]
Kernel driver in use: nouveau
Kernel modules: nouveau
05:00.1 Audio device [0403]: NVIDIA Corporation AD106M High Definition Audio Controller [10de:22bd] (rev a1)
Subsystem: ASUSTeK Computer Inc. Device [1043:88f8]
Kernel driver in use: snd_hda_intel
Kernel modules: snd_hda_intel
...
今回の場合RTX 4060 Tiをパススルーしたいと仮定して、この場合のデバイスIDは10de:2803となります。
デバイスIDが確認できたら、起動時のカーネルパラメータにvfio-pci.ids=<デバイスID>を追加します。カーネルパラメータの設定方法は、ホストOSのインストール時に設定したブートローダーによって異なります。
カーネルパラメータの設定(systemd-boot)
systemd-bootをブートローダーとして選択した場合、起動エントリの設定ファイルは通常/boot/loader/entries/ディレクトリ以下に存在します。この中のエントリを編集し、optionsの末尾にvfio-pci.ids=<デバイスID>を追記します。
title Arch Linux
linux /vmlinuz-linux
initrd /initramfs-linux.img
options root=/dev/vg0/lv0 rw acpi_enforce_resources=lax vfio-pci.ids=10de:2803
カーネルパラメータの設定(grub)
GRUBの場合、/etc/default/grubを開いて、ダブルクオーテーションの中にvfio-pci.ids=<デバイスID>を追記します。
GRUB_CMDLINE_LINUX_DEFAULT="vfio-pci.ids=10de:2803"
その後以下のコマンドを実行し、grubの設定ファイルを再生成します。
$ grub-mkconfig -o /boot/grub/grub.cfg
vfio-pciの読み込み設定
/etc/mkinitcpio.confを開き、MODULESの項目にvfio_pci、vfio、そしてvfio_iommu_type1を追加します。
MODULES=(vfio_pci vfio vfio_iommu_type1)
また、HOOKSの項目にてmodconfが含まれていることを確認します。
HOOKS=(base systemd autodetect microcode modconf kms keyboard keymap consolefont block lvm2 filesystems fsck)
これらの設定が正しく出来ていることを確認できたら、以下のコマンドでinitramfsを再生成します。
$ sudo mkinitcpio -P
vfio-pciの読み込み確認
PCを再起動し、再度lspci -nnkコマンドを実行してvfio-pciがパススルーしたいGPUに適切にバインドされていることを確認します。
$ lspci -nnk
...
05:00.0 VGA compatible controller [0300]: NVIDIA Corporation AD106 [GeForce RTX 4060 Ti] [10de:2803] (rev a1)
Subsystem: ASUSTeK Computer Inc. Device [1043:88f8]
Kernel driver in use: vfio-pci
Kernel modules: nouveau
05:00.1 Audio device [0403]: NVIDIA Corporation AD106M High Definition Audio Controller [10de:22bd] (rev a1)
Subsystem: ASUSTeK Computer Inc. Device [1043:88f8]
Kernel driver in use: snd_hda_intel
Kernel modules: snd_hda_intel
...
もしKernel driverにvfio-pciがバインドされていない場合、カーネルのログからIOMMU及びvfio-pci関連のメッセージで絞り込み、何らかのエラーメッセージが出力されていないか確認します。
$ sudo dmesg | grep -i 'IOMMU\|vfio-pci'
PCIeデバイスの追加
GPUパススルーの準備が出来たので、再びVirtual Machine ManagerからVMの設定ダイアログを開きます。
左下のAdd Hardweareを選択し、「PCI Host Device」からGPUを選択します。
ほとんどのGPUにはオーディオデバイスが付属していますが、これも同様に追加してください。なおオーディオデバイスは動的にvfio-pciへとバインドできるため、vfio-pciに関する設定は必要ありません。
設定を適用しVMを起動すると、パススルーしたGPUから映像出力が出ているはずです。
USBデバイスのアタッチ
USBコントローラのパススルー
USBコントローラもGPUと同様、パススルーを行うことができます。これを利用して、KVMスイッチを同じPCの異なるUSBポートに差し込み、片方のUSBポートのみVMにパススルーすることでUSBデバイスを簡単に切り替えられます。
USBコントローラは、vfio-pciドライバにバインドする必要がありません。
動的にアタッチ
libvirtパッケージに含まれるvirshコマンドを利用すると、すでに接続されているUSBデバイスをVMへ動的にアタッチすることができます。
まず、usbutilsパッケージのlsusbコマンドで接続されているUSBデバイスを表示します。
$ lsusb
...
Bus 007 Device 003: ID 0853:0200 Topre Corporation RealForce Compact Keyboard
...
キーボード(ID 0853:0200)をパススルーしたいと仮定して、以下のようなファイルを作成します。
<hostdev mode='subsystem' type='usb' managed='yes'>
<source>
<vendor id='0x<IDの上部4桁>'/>
<product id='0x<IDの下部4桁>'/>
</source>
</hostdev>
<hostdev mode='subsystem' type='usb' managed='yes'>
<source>
<vendor id='0x0853'/>
<product id='0x0200'/>
</source>
</hostdev>
ファイルの作成が完了したら、以下のコマンドを実行するとVMにUSBデバイスがアタッチされます。
$ sudo virsh attach-device <VM名> <ファイル名>
アタッチされたUSBデバイスをデタッチするためには、以下のコマンドを実行します。
$ sudo virsh detach-device <VM名> <ファイル名>
キーボードやマウスをアタッチした場合、ホスト側で操作ができなくなりデタッチできなくなることがあります。このような場合、以下のいずれかの手段で対応してください。
- ゲストOSをシャットダウンする
- アタッチしたUSBデバイスを物理的に抜き差しする
Looking Glass
Looking Glassを使うことで、パススルーされたGPUからの出力をホスト側にそのまま出力できる他、ゲスト側のキーボード及びマウスをUSBデバイスを直接アタッチすることなく扱うことができるようになります。
Looking Glass(ホスト)のインストール
AUR helperを使っている場合、looking-glass-gitパッケージをインストールします。
$ yay -S looking-glass-git
もしくは公式サイトよりソースをダウンロードして、自らコンパイルすることもできます。
linux-headers及びdkmsパッケージをインストールします。
$ sudo pacman -S linux-headers dkms
kvmfrカーネルモジュールをシステムにインストールします。
$ git clone https://github.com/gnif/LookingGlass
$ cd LookingGlass/module
$ sudo dkms install "."
/etc/modprobe.d/kvmfr.confに、kvmfrの設定を以下の通り記入します。
options kvmfr static_size_mb=<メモリサイズ>
なおメモリサイズは、以下の表より決定してください。
| 解像度 | 通常 | HDR |
|---|---|---|
| 1920x1080(1080p) | 32 | 64 |
| 1920x1200(1200p) | 32 | 64 |
| 2560x1440(1440p) | 64 | 128 |
| 3840x2160(2160p/4K) | 128 | 256 |
例えば1920x1080の場合、設定は以下の通りです。
options kvmfr static_size_mb=32
/etc/modules-load.d/kvmfr.confに、以下の内容を記入します。
kvmfr
/etc/udev/rules.d/70-kvmfr.rulesに、以下の内容を記入します。
SUBSYSTEM=="kvmfr", GROUP="kvm", MODE="0660", TAG+="uaccess"
ユーザーのグループにkvmを追加します。
$ usermod -aG kvm $(whoami)
一通り設定が完了したら、PCを再起動して設定を反映させます。
libvirtの設定
VMの定義ファイル1行目を、以下の通り変更します。
<domain type='kvm' xmlns:qemu='http://libvirt.org/schemas/domain/qemu/1.0'>
これにより、QEMUのコマンドライン引数をlibvirtから直接渡すことができるようになります。
<domain />セクションの最下部に、以下の内容を追加します。
<qemu:commandline>
<qemu:arg value="-device"/>
<qemu:arg value="{"driver":"ivshmem-plain","id":"shmem0","memdev":"looking-glass"}"/>
<qemu:arg value="-object"/>
<qemu:arg value="{"qom-type":"memory-backend-file","id":"looking-glass","mem-path":"/dev/kvmfr0","size":67108864,"share":true}"/>
</qemu:commandline>
<devices />セクションにて<input type='table'/>を削除し、タブレットを無効化します。
また同セクションにて以下の通りデバイスを追加します。
<devices>
...
<input type='mouse' bus='virtio'/>
<input type='keyboard' bus='virtio'/>
<channel type="spicevmc">
<target type="virtio" name="com.redhat.spice.0"/>
<address type="virtio-serial" controller="0" bus="0" port="1"/>
</channel>
...
</devices>
これによりLooking Glassでマウス・キーボードが使えるようになり、またクリップボードもホストとゲスト間で共有されるようになります。
Looking Glass(ゲスト)のインストール
ゲストOSを起動して、こちらのページより「Bleeding Edge」内の「Windows Host Binary」をダウンロード・インストールします。
インストールが完了したら、システムトレイに「Looking Glass (host)」が表示されていることを確認してください。
もし表示されていない場合、「Looking Glass」で検索をかけて起動してください。
VirtIO Win Guest Toolsのインストール
こちらのページよりvirtio-win-guest-tools.exeをダウンロード・インストールします。
インストールが完了したら、C:\Program Files\Virtio-Win\Vioinput\vioinput.inf及びC:\Program Files\Virtio-Win\Vioserial\vioser.infをそれぞれ右クリックしインストールしてください。
Looking Glassの使用
これらの操作が全て完了すると、以下のコマンドを実行することで、ホストOSからLooking Glass経由でゲストを操作できるようになります。
$ looking-glass-client
もしキーボード、マウスもしくはクリップボード共有のいずれかの機能が動作しない場合は、デバイスマネージャーにてVirtIOのドライバが適切にロードされているか確認してください。もし読み込まれていない場合、再度ドライバーのインストールを試してください。
パフォーマンスチューニング
CPU Pinning
VM内のコアをホスト側のコアを1対1関係で結びつける(CPU Pinning)ことによって、キャッシュミスが低減しパフォーマンスが向上します。
CPU Pinningを行うためには、まずCPUの構成(トポロジー)を把握する必要があります。hwlocパッケージのlstopoコマンドを利用すると、CPUのトポロジーを視覚的に把握できます。
lstopo -p
これはRyzen 9950Xでの例です。GUIから、このコアには2つのダイがあり、1つのコア内にはそれぞれ2つの論理プロセッサが、0と16、1と17、7と23のようにペアとなって存在していることがわかります。
CPU Pinningを行う場合、キャッシュが最大限有効利用されるよう設定します。したがって、例えば全論理プロセッサのうち半分をVMに割り当てるとき、片方のダイのみをVMに割り当てることで、共通のL3キャッシュがVMで利用されて性能が向上します。
AMDのX3D系CPUで2つ以上のCCDがあるCPU(例: 9950X3D)を使っている場合、0番目のダイと1番目のダイのうち0番目のダイにしか3D V-Cacheは搭載されていません。この場合、CPU Pinningを行うコアによって、ホスト及びゲストの性能がそれぞれ変化します。
以下の例は、1番目のダイの全てのコアをVMに割り当てる設定です。
<vcpu placement="static">16</vcpu>
<iothreads>1</iothreads>
<cputune>
<vcpupin vcpu="0" cpuset="8"/>
<vcpupin vcpu="1" cpuset="24"/>
<vcpupin vcpu="2" cpuset="9"/>
<vcpupin vcpu="3" cpuset="25"/>
<vcpupin vcpu="4" cpuset="10"/>
<vcpupin vcpu="5" cpuset="26"/>
<vcpupin vcpu="6" cpuset="11"/>
<vcpupin vcpu="7" cpuset="27"/>
<vcpupin vcpu="8" cpuset="12"/>
<vcpupin vcpu="9" cpuset="28"/>
<vcpupin vcpu="10" cpuset="13"/>
<vcpupin vcpu="11" cpuset="29"/>
<vcpupin vcpu="12" cpuset="14"/>
<vcpupin vcpu="13" cpuset="30"/>
<vcpupin vcpu="14" cpuset="15"/>
<vcpupin vcpu="15" cpuset="31"/>
<emulatorpin ccpuset='0-1,16-17'/>
<iothreadpin iothread='1' cpuset='0,16'/>
</cputune>
...
<cpu mode="host-passthrough" check="none" migratable="on">
<topology sockets="1" dies="1" clusters="1" cores="8" threads="2"/>
</cpu>
cputuneのvcpupinを見れば分かるように、cpusetは8と24、9と25のように、ペアをそれぞれ順番で指定します。
emulatorpinはホスト側のエミュレーターを処理するプロセッサを指定します。emulatorpinは、最低でも4つのプロセッサを指定することが推奨されます。
iothreadpinは、エミュレートされたハードディスクを処理するプロセッサを指定します。iothreads及びiothreadpinは、物理的なSSDをパススルーして使う場合は指定する必要がありません。
なお、全てのプロセッサをVMに割り当てると、逆に性能が劣化する場合があります。
Do not assign all your CPU cores to your guest VM, you must at minimum reserve two CPU cores (4 threads) for your host system to use. For example, if you have a 6 core CPU, only assign 4 cores (8 threads) to the guest.
ハイパースレッディングの有効化
<cpu />セクションにて、以下の設定を追加することでAMDのハイパースレッディングが有効になりパフォーマンスが向上します。
<feature policy='require' name='topoext'/>
ゲストOSでの仮想化技術の無効化
Hyper-Vを無効にした状態でも、Virtualization-based SecurityによってゲストOS内でVMが動作し、パフォーマンスが著しく低下することがあります。
これを防止する一番簡単な方法は、<cpu />セクションにて以下の設定を付け足すことです。
<feature policy='disable' name='svm'/>
これによりVM内でCPUの仮想化技術が無効化され、ゲストOS内で更にVMが立ち上がるのを確実に阻止できます。
memballoonの無効化
VFIOでのパススルーを用いたセットアップでは、memballoonが有効になっているとパフォーマンスが著しく低下します。memballoonの設定項目を次の通り変更して、memballoonを無効にします。
<memballoon model="none"/>
The VirtIO memballoon device enables the host to dynamically reclaim memory from your VM by growing the balloon inside the guest, reserving reclaimed memory. Libvirt adds this device to guests by default.
However, this device causes major performance issues with VFIO passthrough setups, and should be disabled.
Find the tag and set its type to none:
AVICの設定
AMDのCPUにおいては、AVICの設定を有効にすることでCPUの割り込みに関する性能を向上させることができます。
なおAVIC機能にはCPU Pinningが必須であり、また性能向上を見込むためにはCPU Pinningしたコアがホストから使えなくなるよう追加の設定が必要です。
まず、カーネルパラメータでkvm_amd.avic=1を設定し、PCを再起動してAVICが有効になっていることを確認します。
$ cat /sys/module/kvm_amd/parameters/avic
Y
一部マザーボードにおいてはCPUのAVIC機能がセキュリティのため無効になっていることがあり、追加でkvm_amd.force_avic=1を設定する必要があります。
次に、<features />の<hyperv />セクションに以下の設定を追加します。
<hyperv mode="custom">
...
<avic state="on" />
</hyperv>
<clock />セクションの<timer name="pit" ... />を以下のように書き換えます。
<clock offset="localtime">
<timer name="rtc" tickpolicy="catchup"/>
<timer name="pit" present="yes" tickpolicy="discard"/>
<timer name="hpet" present="no"/>
<timer name="hypervclock" present="yes"/>
</clock>
定義ファイル1行目を以下のように書き換えます。
<domain xmlns:qemu="http://libvirt.org/schemas/domain/qemu/1.0" type="kvm">
定義ファイルの末尾に、overcommitの設定を追加します。
<qemu:commandline>
<qemu:arg value='-overcommit'/>
<qemu:arg value='cpu-pm=on'/>
</qemu:commandline>
すでにLooking Glassの設定がある場合は、<qemu:commandline />の最後に今回の<qemu:arg ... />を追記してください。
overcommitの設定を有効にすることで、Pinningされたコアの使用率がホストから見て常に100%となり、ホスト側がPinningされたCPUを利用する頻度が減ります。
これを無効化した場合でもAVIC機能は引き続き利用されますが、ホストからの割り込みによって逆に性能が低下します。
VM検知の回避
以下の設定を行うことで、簡易的なVM検知を回避することができます。
QEMUのデバイス名を検知するものや、エミュレートされたハードディスクを検知するもの、RDTSC命令を使って特定のCPU命令の処理時間を調べるものはこれらの設定では回避できません。
KVMの隠蔽
<features />セクションにて、以下の設定を追加するとCPUIDからKVMが隠蔽されます。
<kvm>
<hidden state="on"/>
</kvm>
この設定が無い場合、ゲストOSがLinuxの場合においてKVMが検知されてパフォーマンスが向上します。一方ゲストOSがWindowsの場合、この設定は性能面で影響を及ぼしません。
ハイパーバイザーの隠蔽
<cpu />セクションにて、以下の設定を追加するとゲストOSは自身が仮想マシンで動いていることを認識できなくなります。
<feature policy="disable" name="hypervisor"/>
ただし、この設定を有効にするとパフォーマンスは大幅に低下します。
QEMUにおいてはHyper-Vをエミュレートすることで、Hyper-V独自の機能を活用し性能を向上させています。しかしながら、この設定を有効にするとそれらの機能(<features />の<hyperv />セクション)が無効になります。
必要性が無い場合を除いて、この設定は有効にしないことをおすすめします。
Hyper-VのベンダーID変更
<features />の<hyperv />セクションに以下の行を追加します。
<vendor_id state="on" value="Unknown"/>
この設定を追加すると、ゲストは自身が「Microsoft Hv」ではない、独自のHyper-V実装で動作していると判断するようになります。
この設定は性能面で影響を及ぼしません。
SMBIOSの設定
<os />セクションにて以下の設定を追加すると、SMBIOSの値が、QEMUが生成したものからホストOS側の内容へと切り替わります。
<smbios mode="host"/>
この設定は性能面で影響を及ぼしません。
その他のTips
オーディオ設定
PipeWire
<devices />セクションに以下の内容を追加して、ゲストOSの音声入力・音声出力をPipeWireにリダイレクトします。
<devices>
...
<audio id="1" type="pipewire" runtimeDir="/run/user/1000">
<input name="qemuinput"/>
<output name="qemuoutput"/>
</audio>
...
</devices>
Looking Glass(Spice)
Spiceを利用して、Looking Glassに音声入力・音声出力を対応させます。
<devices>
...
<audio id='1' type='spice'/>
...
</devices>
ホスト側のシャットダウン時にVMをシャットダウンする
libvirt-guestsサービスを有効にします。
$ systemctl start libvirt-guests
$ systemctl enable libvirt-guests
libvirt-guestsの設定を変更して、デフォルトの挙動をシャットダウンに変更します。
ON_SHUTDOWN=shutdown
SHUTDOWN_TIMEOUT=60
<devices />セクションに以下の設定を追加して、QEMU Guest Agentを有効にします。
<channel type="unix">
<source mode="bind" path="/var/lib/libvirt/qemu/f16x86_64.agent"/>
<target type="virtio" name="org.qemu.guest_agent.0"/>
<address type="virtio-serial" controller="0" bus="0" port="2"/>
</channel>
なお、Windows VM側にてVirtIO Win Guestのインストールが必要です。
筆者の構成
<domain xmlns:qemu="http://libvirt.org/schemas/domain/qemu/1.0" type="kvm">
<name>win11</name>
<uuid>7a9d95c1-de8a-4e91-a599-8945a95516b4</uuid>
<metadata>
<libosinfo:libosinfo xmlns:libosinfo="http://libosinfo.org/xmlns/libvirt/domain/1.0">
<libosinfo:os id="http://microsoft.com/win/11"/>
</libosinfo:libosinfo>
</metadata>
<memory unit="KiB">33554432</memory>
<currentMemory unit="KiB">33554432</currentMemory>
<vcpu placement="static">16</vcpu>
<cputune>
<vcpupin vcpu="0" cpuset="8"/>
<vcpupin vcpu="1" cpuset="24"/>
<vcpupin vcpu="2" cpuset="9"/>
<vcpupin vcpu="3" cpuset="25"/>
<vcpupin vcpu="4" cpuset="10"/>
<vcpupin vcpu="5" cpuset="26"/>
<vcpupin vcpu="6" cpuset="11"/>
<vcpupin vcpu="7" cpuset="27"/>
<vcpupin vcpu="8" cpuset="12"/>
<vcpupin vcpu="9" cpuset="28"/>
<vcpupin vcpu="10" cpuset="13"/>
<vcpupin vcpu="11" cpuset="29"/>
<vcpupin vcpu="12" cpuset="14"/>
<vcpupin vcpu="13" cpuset="30"/>
<vcpupin vcpu="14" cpuset="15"/>
<vcpupin vcpu="15" cpuset="31"/>
<emulatorpin cpuset="0-1,16-17"/>
</cputune>
<os firmware="efi">
<type arch="x86_64" machine="pc-q35-10.0">hvm</type>
<firmware>
<feature enabled="no" name="enrolled-keys"/>
<feature enabled="yes" name="secure-boot"/>
</firmware>
<loader readonly="yes" secure="yes" type="pflash" format="raw">/usr/share/edk2/x64/OVMF_CODE.secboot.4m.fd</loader>
<nvram template="/usr/share/edk2/x64/OVMF_VARS.4m.fd" templateFormat="raw" format="raw">/var/lib/libvirt/qemu/nvram/win11_VARS.secboot.fd</nvram>
<bootmenu enable="no"/>
<smbios mode="host"/>
</os>
<features>
<acpi/>
<apic/>
<hyperv mode="custom">
<relaxed state="on"/>
<vapic state="on"/>
<spinlocks state="on" retries="8191"/>
<vpindex state="on"/>
<runtime state="on"/>
<synic state="on"/>
<stimer state="on"/>
<vendor_id state="on" value="Unknown"/>
<frequencies state="on"/>
<tlbflush state="on"/>
<ipi state="on"/>
</hyperv>
<kvm>
<hidden state="on"/>
</kvm>
<vmport state="off"/>
<smm state="on"/>
</features>
<cpu mode="host-passthrough" check="none" migratable="on">
<topology sockets="1" dies="1" clusters="1" cores="8" threads="2"/>
<feature policy="require" name="topoext"/>
</cpu>
<clock offset="localtime">
<timer name="rtc" tickpolicy="catchup"/>
<timer name="pit" tickpolicy="delay"/>
<timer name="hpet" present="no"/>
<timer name="hypervclock" present="yes"/>
</clock>
<on_poweroff>destroy</on_poweroff>
<on_reboot>restart</on_reboot>
<on_crash>destroy</on_crash>
<pm>
<suspend-to-mem enabled="no"/>
<suspend-to-disk enabled="no"/>
</pm>
<devices>
<emulator>/usr/bin/qemu-system-x86_64</emulator>
<controller type="usb" index="0" model="qemu-xhci" ports="15">
<address type="pci" domain="0x0000" bus="0x02" slot="0x00" function="0x0"/>
</controller>
<controller type="pci" index="0" model="pcie-root"/>
<controller type="pci" index="1" model="pcie-root-port">
<model name="pcie-root-port"/>
<target chassis="1" port="0x10"/>
<address type="pci" domain="0x0000" bus="0x00" slot="0x02" function="0x0" multifunction="on"/>
</controller>
<controller type="pci" index="2" model="pcie-root-port">
<model name="pcie-root-port"/>
<target chassis="2" port="0x11"/>
<address type="pci" domain="0x0000" bus="0x00" slot="0x02" function="0x1"/>
</controller>
<controller type="pci" index="3" model="pcie-root-port">
<model name="pcie-root-port"/>
<target chassis="3" port="0x12"/>
<address type="pci" domain="0x0000" bus="0x00" slot="0x02" function="0x2"/>
</controller>
<controller type="pci" index="4" model="pcie-root-port">
<model name="pcie-root-port"/>
<target chassis="4" port="0x13"/>
<address type="pci" domain="0x0000" bus="0x00" slot="0x02" function="0x3"/>
</controller>
<controller type="pci" index="5" model="pcie-root-port">
<model name="pcie-root-port"/>
<target chassis="5" port="0x14"/>
<address type="pci" domain="0x0000" bus="0x00" slot="0x02" function="0x4"/>
</controller>
<controller type="pci" index="6" model="pcie-root-port">
<model name="pcie-root-port"/>
<target chassis="6" port="0x15"/>
<address type="pci" domain="0x0000" bus="0x00" slot="0x02" function="0x5"/>
</controller>
<controller type="pci" index="7" model="pcie-root-port">
<model name="pcie-root-port"/>
<target chassis="7" port="0x16"/>
<address type="pci" domain="0x0000" bus="0x00" slot="0x02" function="0x6"/>
</controller>
<controller type="pci" index="8" model="pcie-root-port">
<model name="pcie-root-port"/>
<target chassis="8" port="0x17"/>
<address type="pci" domain="0x0000" bus="0x00" slot="0x02" function="0x7"/>
</controller>
<controller type="pci" index="9" model="pcie-root-port">
<model name="pcie-root-port"/>
<target chassis="9" port="0x18"/>
<address type="pci" domain="0x0000" bus="0x00" slot="0x03" function="0x0" multifunction="on"/>
</controller>
<controller type="pci" index="10" model="pcie-root-port">
<model name="pcie-root-port"/>
<target chassis="10" port="0x19"/>
<address type="pci" domain="0x0000" bus="0x00" slot="0x03" function="0x1"/>
</controller>
<controller type="pci" index="11" model="pcie-root-port">
<model name="pcie-root-port"/>
<target chassis="11" port="0x1a"/>
<address type="pci" domain="0x0000" bus="0x00" slot="0x03" function="0x2"/>
</controller>
<controller type="pci" index="12" model="pcie-root-port">
<model name="pcie-root-port"/>
<target chassis="12" port="0x1b"/>
<address type="pci" domain="0x0000" bus="0x00" slot="0x03" function="0x3"/>
</controller>
<controller type="pci" index="13" model="pcie-root-port">
<model name="pcie-root-port"/>
<target chassis="13" port="0x1c"/>
<address type="pci" domain="0x0000" bus="0x00" slot="0x03" function="0x4"/>
</controller>
<controller type="pci" index="14" model="pcie-root-port">
<model name="pcie-root-port"/>
<target chassis="14" port="0x1d"/>
<address type="pci" domain="0x0000" bus="0x00" slot="0x03" function="0x5"/>
</controller>
<controller type="pci" index="15" model="pcie-root-port">
<model name="pcie-root-port"/>
<target chassis="15" port="0x8"/>
<address type="pci" domain="0x0000" bus="0x00" slot="0x01" function="0x0"/>
</controller>
<controller type="pci" index="16" model="pcie-to-pci-bridge">
<model name="pcie-pci-bridge"/>
<address type="pci" domain="0x0000" bus="0x05" slot="0x00" function="0x0"/>
</controller>
<controller type="sata" index="0">
<address type="pci" domain="0x0000" bus="0x00" slot="0x1f" function="0x2"/>
</controller>
<controller type="virtio-serial" index="0">
<address type="pci" domain="0x0000" bus="0x03" slot="0x00" function="0x0"/>
</controller>
<interface type="bridge">
<mac address="52:54:00:44:17:c3"/>
<source bridge="virbr0"/>
<model type="e1000e"/>
<link state="up"/>
<address type="pci" domain="0x0000" bus="0x01" slot="0x00" function="0x0"/>
</interface>
<channel type="spicevmc">
<target type="virtio" name="com.redhat.spice.0"/>
<address type="virtio-serial" controller="0" bus="0" port="1"/>
</channel>
<channel type="unix">
<source mode="bind" path="/var/lib/libvirt/qemu/f16x86_64.agent"/>
<target type="virtio" name="org.qemu.guest_agent.0"/>
<address type="virtio-serial" controller="0" bus="0" port="2"/>
</channel>
<input type="mouse" bus="ps2"/>
<input type="keyboard" bus="ps2"/>
<input type="keyboard" bus="virtio">
<address type="pci" domain="0x0000" bus="0x04" slot="0x00" function="0x0"/>
</input>
<input type="mouse" bus="virtio">
<address type="pci" domain="0x0000" bus="0x08" slot="0x00" function="0x0"/>
</input>
<tpm model="tpm-tis">
<backend type="emulator" version="1.2"/>
</tpm>
<graphics type="spice" autoport="yes">
<listen type="address"/>
<image compression="off"/>
<gl enable="no"/>
</graphics>
<sound model="ich9">
<address type="pci" domain="0x0000" bus="0x00" slot="0x1b" function="0x0"/>
</sound>
<audio id="1" type="pipewire" runtimeDir="/run/user/1000">
<input name="qemuinput"/>
<output name="qemuoutput"/>
</audio>
<video>
<model type="none"/>
</video>
<hostdev mode="subsystem" type="pci" managed="yes">
<source>
<address domain="0x0000" bus="0x05" slot="0x00" function="0x0"/>
</source>
<address type="pci" domain="0x0000" bus="0x06" slot="0x00" function="0x0"/>
</hostdev>
<hostdev mode="subsystem" type="pci" managed="yes">
<source>
<address domain="0x0000" bus="0x05" slot="0x00" function="0x1"/>
</source>
<address type="pci" domain="0x0000" bus="0x07" slot="0x00" function="0x0"/>
</hostdev>
<hostdev mode="subsystem" type="pci" managed="yes">
<source>
<address domain="0x0000" bus="0x0f" slot="0x00" function="0x0"/>
</source>
<boot order="1"/>
<address type="pci" domain="0x0000" bus="0x09" slot="0x00" function="0x0"/>
</hostdev>
<hostdev mode="subsystem" type="pci" managed="yes">
<source>
<address domain="0x0000" bus="0x10" slot="0x00" function="0x4"/>
</source>
<address type="pci" domain="0x0000" bus="0x0a" slot="0x00" function="0x0"/>
</hostdev>
<watchdog model="itco" action="reset"/>
<memballoon model="none"/>
</devices>
<qemu:commandline>
<qemu:arg value="-device"/>
<qemu:arg value="{"driver":"ivshmem-plain","id":"shmem0","memdev":"looking-glass"}"/>
<qemu:arg value="-object"/>
<qemu:arg value="{"qom-type":"memory-backend-file","id":"looking-glass","mem-path":"/dev/kvmfr0","size":67108864,"share":true}"/>
</qemu:commandline>
</domain>















