Bootstrap

Windows 11 в голом QEMU/KVM на MX Linux: один скрипт, без virt-manager

Windows 11 в голом QEMU/KVM на MX Linux: один скрипт, без virt-manager

Есть у меня Debian-виртуалка, которую я годами запускаю одной строкой через alias в .bashrc. Без libvirt-XML, без virt-manager: qemu-system-x86_64 с пачкой флагов, SPICE-экран и мост в локальную сеть. Понадобилась рядом Windows 11, и захотелось сделать её так же, одним скриптом, который можно прочитать глазами и понять целиком.

Оказалось, что «так же» не получится. Windows 11 требует UEFI с Secure Boot и TPM 2.0, не знает про virtio и по-своему считает время. В статье разберу, что пришлось поменять, зачем нужен каждый флаг и на какие грабли я наступил во время установки.

Всё, что ниже, лежит в репозитории: github.com/ramanzes/qemu-win11-mx.

Исходная точка

Вот как запускается Debian-гость:

☯

Terminal:

⌕

≡

✕
alias qemudebian='sudo qemu-system-x86_64 \
    -enable-kvm \
    -m 8192 -smp 2 \
    -machine pc-q35-7.2 \
    -cpu host \
    -drive file=/var/lib/libvirt/images/debian13.qcow2,if=virtio,format=qcow2 \
    -boot order=c \
    -netdev bridge,br=virbr0,id=net0 \
    -device virtio-net-pci,netdev=net0,mac=52:54:00:12:34:56 \
    -vga qxl \
    -device virtio-tablet \
    -spice port=5930,disable-ticketing=on \
    -device intel-hda -device hda-duplex \
    -monitor stdio'

Почему не virt-manager? Он хороший, но конфигурация живёт в XML где-то в /etc/libvirt, и когда что-то идёт не так, приходится разбираться, во что libvirt превратил твои галочки. Тут же вся машина видна на одном экране. Её можно скопировать, закоммитить в git и поправить одной строкой.

Хост: MX Linux (он на базе Debian 12), процессор с аппаратной виртуализацией.

Чем Windows 11 отличается от Linux-гостя

Если взять alias выше и просто подсунуть ISO с Windows 11, установщик скажет «Этот компьютер не соответствует требованиям». Отличий четыре.

  1. UEFI и Secure Boot. По умолчанию QEMU грузится через SeaBIOS, то есть legacy BIOS. Windows 11 нужен UEFI, а для Secure Boot ещё и прошивка с ключами Microsoft. Это даёт пакет ovmf.
  2. TPM 2.0. Физический TPM хоста отдавать не нужно, есть программный эмулятор swtpm. QEMU подключается к нему через сокет.
  3. virtio. Linux знает virtio из коробки, Windows нет. Диск и сеть virtio установщик просто не увидит, пока не подсунешь драйверы с отдельного ISO virtio-win.iso.
  4. Мелочи. virtio-tablet без драйвера в Windows не работает, а usb-tablet работает. Windows по умолчанию считает, что аппаратные часы идут в локальном времени, а не в UTC.

Подготовка хоста

Пакеты

☯

Terminal:

⌕

≡

✕
sudo apt install qemu-system-x86 qemu-utils ovmf swtpm swtpm-tools \
     libvirt-daemon-system virt-viewer

Сначала проверяем, что процессор умеет в виртуализацию:

☯

Terminal:

⌕

≡

✕
egrep -c '(vmx|svm)' /proc/cpuinfo

Если вывод 0, идём в BIOS и включаем Intel VT-x или AMD-V (SVM).

libvirt-daemon-system здесь нужен не ради virt-manager, а ради сети: libvirt поднимает мост virbr0 с DHCP и NAT. Сам QEMU libvirt'ом не управляется.

Сеть: мост virbr0

Есть особенность MX Linux: по умолчанию он грузится с sysvinit, поэтому systemctl не поможет. Используем service:

☯

Terminal:

⌕

≡

✕
sudo service libvirtd start
sudo virsh net-start default
sudo virsh net-autostart default

QEMU подключается к мосту через qemu-bridge-helper. Хелпер откажется работать с мостом, которого нет в белом списке:

☯

Terminal:

⌕

≡

✕
sudo mkdir -p /etc/qemu
echo "allow virbr0" | sudo tee /etc/qemu/bridge.conf

Без этого файла запуск упадёт с ошибкой access denied by acl file.

Диск, UEFI-переменные, TPM

☯

Terminal:

⌕

≡

✕
cd /var/lib/libvirt/images
sudo qemu-img create -f qcow2 win11.qcow2 80G
sudo cp /usr/share/OVMF/OVMF_VARS_4M.ms.fd win11_VARS.fd
sudo mkdir -p win11-tpm

Здесь важно понимать, что OVMF состоит из двух файлов:

  • OVMF_CODE_4M.secboot.fd — сама прошивка. Она общая и подключается только на чтение.
  • OVMF_VARS_4M.ms.fd — шаблон NVRAM, то есть переменных UEFI: порядок загрузки, ключи Secure Boot. Суффикс .ms значит, что в него уже записаны ключи Microsoft. Каждой ВМ нужна своя копия, потому что прошивка в неё пишет.

Если вместо копии подключить системный шаблон напрямую, вы либо получите ошибку доступа, либо (под sudo) молча испортите шаблон для всех будущих машин.

Если у вас других имён файлов, посмотрите ls /usr/share/OVMF/. Набор зависит от версии пакета.

ISO-образы

☯

Terminal:

⌕

≡

✕
sudo wget https://fedorapeople.org/groups/virt/virtio-win/direct-downloads/stable-virtio/virtio-win.iso

Сам Win11.iso скачиваем с официальной страницы microsoft.com/software-download и кладём в ту же папку.

Скрипт запуска

☯

Terminal:

⌕

≡

✕
#!/bin/bash
IMG=/var/lib/libvirt/images

# TPM-эмулятор: запускается перед каждым стартом ВМ
sudo swtpm socket --tpm2 --daemon \
  --tpmstate dir=$IMG/win11-tpm \
  --ctrl type=unixio,path=$IMG/win11-tpm/sock

sudo qemu-system-x86_64 \
  -enable-kvm -m 8192 -smp 4 \
  -machine q35,smm=on \
  -cpu host,hv_relaxed,hv_spinlocks=0x1fff,hv_vapic,hv_time \
  -global driver=cfi.pflash01,property=secure,value=on \
  -drive if=pflash,format=raw,readonly=on,file=/usr/share/OVMF/OVMF_CODE_4M.secboot.fd \
  -drive if=pflash,format=raw,file=$IMG/win11_VARS.fd \
  -chardev socket,id=chrtpm,path=$IMG/win11-tpm/sock \
  -tpmdev emulator,id=tpm0,chardev=chrtpm -device tpm-tis,tpmdev=tpm0 \
  -drive file=$IMG/win11.qcow2,if=virtio,format=qcow2 \
  -drive file=$IMG/Win11.iso,media=cdrom \
  -drive file=$IMG/virtio-win.iso,media=cdrom \
  -boot menu=on \
  -rtc base=localtime \
  -netdev bridge,br=virbr0,id=net0 \
  -device virtio-net-pci,netdev=net0,mac=52:54:00:12:34:57 \
  -vga qxl \
  -device qemu-xhci -device usb-tablet \
  -spice port=5931,disable-ticketing=on \
  -device intel-hda -device hda-duplex \
  -monitor stdio

Разберу по блокам, что тут нового по сравнению с Debian.

TPM

☯

Terminal:

⌕

≡

✕
swtpm socket --tpm2 --daemon \
  --tpmstate dir=$IMG/win11-tpm \
  --ctrl type=unixio,path=$IMG/win11-tpm/sock

swtpm — это отдельный процесс, который эмулирует TPM 2.0 и хранит его состояние в win11-tpm/. Папку нельзя удалять: если включите в Windows BitLocker, его ключи окажутся там.

Со стороны QEMU три параметра: -chardev открывает сокет, -tpmdev emulator говорит «TPM живёт по ту сторону сокета», -device tpm-tis создаёт само устройство, которое увидит гость.

UEFI и Secure Boot

☯

Terminal:

⌕

≡

✕
-machine q35,smm=on
-global driver=cfi.pflash01,property=secure,value=on
-drive if=pflash,...,readonly=on,file=.../OVMF_CODE_4M.secboot.fd
-drive if=pflash,...,file=$IMG/win11_VARS.fd

Сборка OVMF с Secure Boot требует режима SMM (System Management Mode). Это smm=on. Флаг secure=on для pflash защищает переменные от записи из обычного режима, иначе гость мог бы переписать ключи Secure Boot в обход прошивки. Без этих двух флагов secboot-прошивка просто не запустится: будет чёрный экран.

Флаг -boot order=c из Debian-версии тут не работает. Порядок загрузки при UEFI хранит сама прошивка в VARS. Вместо него -boot menu=on: в начале загрузки можно нажать Esc и выбрать устройство вручную.

Hyper-V enlightenments

☯

Terminal:

⌕

≡

✕
-cpu host,hv_relaxed,hv_spinlocks=0x1fff,hv_vapic,hv_time

Windows умеет определять, что работает под гипервизором, и использует паравиртуальные интерфейсы Hyper-V. KVM умеет их эмулировать:

  • hv_relaxed отключает watchdog, который в виртуалке при нагрузке на хост может выдавать BSOD CLOCK_WATCHDOG_TIMEOUT;
  • hv_spinlocks даёт гостю подсказку, когда отдать процессор вместо бесконечной крутилки на спинлоке;
  • hv_vapic — паравиртуальный контроллер прерываний;
  • hv_time — паравиртуальные часы, главный пункт для отзывчивости.

Без них Windows работает, но заметно медленнее, особенно когда простаивает: виртуалка ест процессор хоста.

Диски

☯

Terminal:

⌕

≡

✕
-drive file=$IMG/win11.qcow2,if=virtio,format=qcow2
-drive file=$IMG/Win11.iso,media=cdrom
-drive file=$IMG/virtio-win.iso,media=cdrom

Два CD-привода: установщик и драйверы. На машине q35 CD-приводы садятся на SATA (AHCI), который Windows знает. А вот системный диск virtio, и как раз с этим связана первая грабля (о ней ниже).

Остальное

  • -rtc base=localtime: Windows считает, что аппаратные часы идут в местном времени. Если отдать ей UTC (как Linux-гостю), часы в Windows будут сдвинуты на ваш часовой пояс.
  • -device qemu-xhci -device usb-tablet: USB 3.0 контроллер и планшет. Планшет даёт абсолютные координаты курсора, и мышь не «залипает» в окне. usb-tablet Windows понимает без драйверов, в отличие от virtio-tablet.
  • MAC ...:57 и SPICE-порт 5931 отличаются от Debian-гостя (...:56 и 5930), чтобы обе машины могли работать одновременно.

Подключаемся к экрану:

☯

Terminal:

⌕

≡

✕
remote-viewer spice://localhost:5931

Установка и грабли

«Press any key to boot from CD»

Первая надпись появится на пару секунд, и пока вы переключаетесь в окно viewer'а, она может пропасть. Тогда UEFI не найдёт загрузочного диска и вывалится в UEFI Shell. Ничего страшного: введите reset и будьте быстрее, или нажмите Esc на старте и выберите CD в Boot Manager.

Установщик не видит диск

Доходим до выбора раздела, а там пусто. Первая мысль: что-то не так с образом. Проверяю на хосте:

☯

Terminal:

⌕

≡

✕
$ sudo ls -la /var/lib/libvirt/images/win11.qcow2
-rw-r--r-- 1 root root 393216 Oct 15 12:28 win11.qcow2

384 килобайта вместо 80 гигабайт выглядят тревожно, но это нормально. qcow2 — разреженный формат, файл растёт по мере записи. Настоящий размер показывает qemu-img info:

☯

Terminal:

⌕

≡

✕
sudo qemu-img info /var/lib/libvirt/images/win11.qcow2
# virtual size: 80 GiB

Проблема не в диске, а в драйвере: диск подключён как virtio, а установщик Windows про virtio не знает. Лечится так:

  1. Нажимаем «Загрузить драйвер», затем «Обзор».
  2. Открываем CD virtio-win и папку viostor\w11\amd64.
  3. Выбираем Red Hat VirtIO SCSI controller и жмём «Далее».
  4. Появляется «Незанятое пространство на диске 0: 80 ГБ».

Если драйвер не появляется в списке, снимите галочку «Скрыть драйверы, несовместимые с оборудованием» и проверьте, что выбрали w11\amd64, а не w10 или ARM64.

Совет, который я бы хотел знать заранее: на этом же экране загрузите и драйвер сети, NetKVM\w11\amd64. Тогда установщик сразу увидит сеть, и следующей грабли не будет.

Можно было бы обойти проблему, подключив диск как SATA, но тогда вы потеряете в скорости. Одна загрузка драйвера стоит того.

Нет сети при первом запуске (OOBE)

Я про NetKVM вспомнил уже после того, как установка пошла. Windows 11 Home и Pro на этапе первичной настройки хотят интернет и учётку Microsoft, а сетевой карты не видно.

Начинать заново не нужно, вариантов три.

Кнопка «Установить драйвер». Когда сетевой карты нет, на экране «Подключитесь к сети» обычно есть такая ссылка. Указываем ей NetKVM\w11\amd64 на CD virtio.

Командная строка. Если кнопки нет: Shift+F10, находим букву CD с драйверами (dir D:, dir E:, нужен тот, где лежат папки NetKVM и viostor) и ставим драйвер вручную:

☯

Terminal:

⌕

≡

✕
pnputil /add-driver E:\NetKVM\w11\amd64\*.inf /install

Через несколько секунд сеть появится. Если экран не обновится сам, нажмите «Назад».

Локальная учётка без сети. Shift+F10, затем:

☯

Terminal:

⌕

≡

✕
start ms-cxh:localonly

Откроется окно создания локального пользователя. На старых сборках Windows 11 то же самое делал OOBE\BYPASSNRO, но в свежих его убрали. Драйвер сети тогда ставим уже из системы (см. ниже).

После установки

Открываем CD virtio-win и запускаем virtio-win-guest-tools.exe. Он ставит сразу всё: сеть, видеодрайвер QXL (без него разрешение не поднимется выше базового), balloon, а ещё SPICE agent. Последний даёт общий буфер обмена с хостом и автоматическое разрешение при изменении размера окна viewer'а.

После этого обе строки с ISO из скрипта можно удалить или закомментировать.

Что можно улучшить

Скрипт намеренно простой. Если хочется выжать больше, вот направления, которые я оставил на потом:

  • Явная топология CPU. -smp 4,sockets=1,cores=4,threads=1. Windows для клиентских редакций ограничивает число процессорных сокетов, поэтому лучше давать ядра, а не сокеты. Свежий QEMU и так раскладывает -smp 4 по ядрам, но явное лучше неявного.
  • Кеш и TRIM. cache=none,aio=native,discard=unmap в строке диска: меньше двойного кеширования, и qcow2 будет сжиматься, когда Windows освобождает место. discard для virtio-blk работает в свежих версиях QEMU и драйвера.
  • Больше enlightenments. hv_vpindex, hv_synic, hv_stimer, hv_reset, hv_frequencies. Или одним флагом hv-passthrough (тогда, правда, теряется переносимость на другое железо).
  • Не от root. Сейчас всё запускается через sudo, так проще с доступом к /var/lib/libvirt/images и мосту. Аккуратнее положить образы в домашнюю папку, добавить себя в группу kvm и дать qemu-bridge-helper бит setuid (в Debian так и задумано).

Итог

Отличия от Linux-гостя сводятся к четырём вещам: OVMF с Secure Boot, swtpm, драйверы virtio с отдельного ISO и пара мелких флагов. Основные проблемы при установке вызывает virtio: установщик не видит ни диск, ни сеть, пока ему не подсунуть драйверы. Если загрузить viostor и NetKVM на экране выбора диска, установка проходит без сюрпризов.

Скрипт и инструкция на русском и английском: github.com/ramanzes/qemu-win11-mx. Pull request'ы с улучшениями приветствуются.

Копирование материалов разрешается только с указанием автора Roman Sakhno и индексируемой прямой ссылкой на сайт (http://itdid.ru)!

Добавляйтесь ко мне в друзья ВКонтакте: http://vk.com/sahroman.
Если Вы хотите дать оценку мне и моей работе, то напишите её в моей группе: http://vk.com/sahroman.

Если у Вас остались какие-либо вопросы, либо у Вас есть желание высказаться по поводу этой статьи, то Вы можете оставить свой комментарий внизу страницы.

Порекомендуйте эту статью друзьям:

Если Вам понравился сайт, то разместите ссылку на него (у себя на сайте, на форуме, в контакте):

  1. Кнопка:

    Она выглядит вот так: Как настроить свой компьютер

  2. Текстовая ссылка:

    Она выглядит вот так: Как настроить свой компьютер

  3. BB-код ссылки для форумов (например, можете поставить её в подписи):

Комментарии (0):

Для добавления комментариев надо войти в систему.
Если Вы ещё не зарегистрированы на сайте, то сначала зарегистрируйтесь.