hiroの長い冒険日記

主にコンピュータ周辺の興味を持った内容を綴ります

【起動できず】qemu for windows を debian で cross build (whpx有効編)

前回までに、debian で 通常 option で cross build した qemu for windows が Windows10 で起動できる所まで確認した。

hiro20180901.hatenablog.com
hiro20180901.hatenablog.com

今回は、whpx を有効にして build し、Hyper-V 環境で起動できるかを確認してみた。

whpx 有効で configure

先ずは、何も準備しないで whpx を有効にして configure を実施してみた。

# PKG_CONFIG_LIBDIR=/usr/x86_64-w64-mingw32/lib/pkgconfig ../../../configure --cross-prefix=x86_64-w64-mingw32- --disable-guest-agent-msi --disable-werror --enable-whpx

ERROR: User requested feature WinHvPlatform
       configure was not able to find it.
       WinHvEmulation is not installed

まぁ、そうだよね。
configure :

... 略 ...
##########################################
# Windows Hypervisor Platform accelerator (WHPX) check
if test "$whpx" != "no" ; then
    if check_include "WinHvPlatform.h" && check_include "WinHvEmulation.h"; then
        whpx="yes"
    else
        if test "$whpx" = "yes"; then
            feature_not_found "WinHvPlatform" "WinHvEmulation is not installed"
        fi
        whpx="no"
    fi
fi
... 略 ...

WinHvPlatform.h と WinHvEmulation.h の存在を check している。

WinHv 関連の header file の準備

www.douban.com
こちらを参考に git で落としてきた。

# git clone --depth 1 https://android.googlesource.com/platform/prebuilts/gcc/linux-x86/host/x86_64-w64-mingw32-4.8
Cloning into 'x86_64-w64-mingw32-4.8'...
remote: Counting objects: 4086, done
remote: Finding sources: 100% (4086/4086)
remote: Total 4086 (delta 1947), reused 3891 (delta 1947)
Receiving objects: 100% (4086/4086), 52.63 MiB | 7.31 MiB/s, done.
Resolving deltas: 100% (1947/1947), done.
Checking out files: 100% (4002/4002), done.

# find x86_64-w64-mingw32-4.8 | grep -i winhv
x86_64-w64-mingw32-4.8/x86_64-w64-mingw32/include/WinHvPlatformDefs.h
x86_64-w64-mingw32-4.8/x86_64-w64-mingw32/include/WinHvEmulation.h
x86_64-w64-mingw32-4.8/x86_64-w64-mingw32/include/WinHvPlatform.h
x86_64-w64-mingw32-4.8/x86_64-w64-mingw32/lib/libWinHvPlatform.a
x86_64-w64-mingw32-4.8/x86_64-w64-mingw32/lib/libWinHvEmulation.a

# cp x86_64-w64-mingw32-4.8/mingw/include/WinHv* /usr/x86_64-w64-mingw32/include 
# cp x86_64-w64-mingw32-4.8/mingw/lib/libWinHv* /usr/x86_64-w64-mingw32/lib

whpx 有効で configure (再)

WinHv 関連の include と lib が準備できたので、configure に再チャレンジした。

# PKG_CONFIG_LIBDIR=/usr/x86_64-w64-mingw32/lib/pkgconfig ../../../configure --cross-prefix=x86_64-w64-mingw32- --disable-guest-agent-msi --disable-werror --enable-whpx
Install prefix    c:/Program Files/QEMU
BIOS directory    c:/Program Files/QEMU
firmware path     c:/Program Files/QEMU/share/qemu-firmware
binary directory  c:/Program Files/QEMU
library directory c:/Program Files/QEMU/lib
module directory  c:/Program Files/QEMU/lib
libexec directory c:/Program Files/QEMU/libexec
include directory c:/Program Files/QEMU/include
config directory  c:/Program Files/QEMU
local state directory   queried at runtime
Windows SDK       no
Source path       /qemu
GIT binary        git
GIT submodules    ui/keycodemapdb tests/fp/berkeley-testfloat-3 tests/fp/berkeley-softfloat-3 dtc capstone
C compiler        x86_64-w64-mingw32-gcc
Host C compiler   cc
C++ compiler      x86_64-w64-mingw32-g++
Objective-C compiler x86_64-w64-mingw32-gcc
ARFLAGS           rv
CFLAGS            -O2 -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 -g 
QEMU_CFLAGS       -I/usr/x86_64-w64-mingw32/sys-root/mingw/include/pixman-1 -I$(SRC_PATH)/dtc/libfdt -DHAS_LIBSSH2_SFTP_FSYNC -I/usr/x86_64-w64-mingw32/sys-root/mingw/include -mms-bitfields -I/usr/x86_64-w64-mingw32/sys-root/mingw/include/glib-2.0 -I/usr/x86_64-w64-mingw32/sys-root/mingw/lib/glib-2.0/include -I/usr/x86_64-w64-mingw32/sys-root/mingw/include -m64 -mcx16 -I$(SRC_PATH)/hosts/w32/include -mthreads -D_POSIX=1 -D__USE_MINGW_ANSI_STDIO=1 -DWIN32_LEAN_AND_MEAN -DWINVER=0x501 -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -Wextra -Wno-error=parentheses -Wno-error=format-extra-args -Wno-error=format -Wno-override-init -Wno-sign-compare -Wno-missing-field-initializers -Wno-unused-parameter -Wstrict-prototypes -Wredundant-decls -Wmissing-format-attribute -Wall -Wundef -Wwrite-strings -Wmissing-prototypes -fno-strict-aliasing -fno-common -fwrapv  -Wexpansion-to-defined -Wendif-labels -Wno-shift-negative-value -Wempty-body -Wnested-externs -Wformat-security -Wformat-y2k -Winit-self -Wignored-qualifiers -Wold-style-declaration -Wold-style-definition -Wtype-limits -I/usr/x86_64-w64-mingw32/sys-root/mingw/include -I/usr/x86_64-w64-mingw32/sys-root/mingw/include/p11-kit-1 -I/usr/x86_64-w64-mingw32/sys-root/mingw/include -I/usr/x86_64-w64-mingw32/sys-root/mingw/include -I/usr/x86_64-w64-mingw32/sys-root/mingw/include -I/usr/x86_64-w64-mingw32/sys-root/mingw/include/libpng16 -I/usr/x86_64-w64-mingw32/sys-root/mingw/include -I$(SRC_PATH)/capstone/include
LDFLAGS           -Wl,--nxcompat -Wl,--no-seh -Wl,--dynamicbase -Wl,--warn-common -m64 -g 
QEMU_LDFLAGS      -L$(BUILD_DIR)/dtc/libfdt 
make              make
install           install
python            python -B
smbd              /usr/sbin/smbd
module support    no
host CPU          x86_64
host big endian   no
target list       aarch64-softmmu alpha-softmmu arm-softmmu cris-softmmu hppa-softmmu i386-softmmu lm32-softmmu m68k-softmmu microblaze-softmmu microblazeel-softmmu mips-softmmu mips64-softmmu mips64el-softmmu mipsel-softmmu moxie-softmmu nios2-softmmu or1k-softmmu ppc-softmmu ppc64-softmmu riscv32-softmmu riscv64-softmmu s390x-softmmu sh4-softmmu sh4eb-softmmu sparc-softmmu sparc64-softmmu tricore-softmmu unicore32-softmmu x86_64-softmmu xtensa-softmmu xtensaeb-softmmu
gprof enabled     no
sparse enabled    no
strip binaries    yes
profiler          no
static build      no
SDL support       yes (2.0.7)
GTK support       yes (3.22.28)
GTK GL support    no
VTE support       no 
TLS priority      NORMAL
GNUTLS support    yes
libgcrypt         no
nettle            yes (3.4)
libtasn1          yes
curses support    yes
virgl support     no 
curl support      yes
mingw32 support   yes
Audio drivers     dsound
Block whitelist (rw) 
Block whitelist (ro) 
VirtFS support    no
Multipath support no
VNC support       yes
VNC SASL support  no
VNC JPEG support  yes
VNC PNG support   yes
xen support       no
brlapi support    no
bluez  support    no
Documentation     yes
Tools             qemu-ga qemu-img$(EXESUF) qemu-io$(EXESUF) qemu-edid$(EXESUF) 
PIE               no
vde support       no
netmap support    no
Linux AIO support no
(X)ATTR support   no
Install blobs     yes
KVM support       no
HAX support       yes
HVF support       no
WHPX support      yes
TCG support       yes
TCG debug enabled no
TCG interpreter   no
malloc trim support no
RDMA support      no
PVRDMA support    no
fdt support       git
membarrier        no
preadv support    no
fdatasync         no
madvise           no
posix_madvise     no
posix_memalign    no
libcap-ng support no
vhost-net support no
vhost-crypto support no
vhost-scsi support no
vhost-vsock support no
vhost-user support no
Trace backends    log
spice support     no 
rbd support       no
xfsctl support    no
smartcard support no
libusb            yes
usb net redir     yes
OpenGL support    no
OpenGL dmabufs    no
libiscsi support  no
libnfs support    no
build guest agent yes
QGA VSS support   no
QGA w32 disk info yes
QGA MSI support   no
seccomp support   no
coroutine backend win32
coroutine pool    no
debug stack usage no
mutex debugging   no
crypto afalg      no
GlusterFS support no
gcov              gcov
gcov enabled      no
TPM support       yes
libssh2 support   yes
TPM passthrough   no
TPM emulator      no
QOM debugging     yes
Live block migration yes
lzo support       yes
snappy support    no
bzip2 support     yes
NUMA host support no
libxml2           yes
tcmalloc support  no
jemalloc support  no
avx2 optimization yes
replication support yes
VxHS block device no
bochs support     yes
cloop support     yes
dmg support       yes
qcow v1 support   yes
vdi support       yes
vvfat support     yes
qed support       yes
parallels support yes
sheepdog support  yes
capstone          git
docker            no
libpmem support   no
libudev           no

NOTE: cross-compilers enabled:  'x86_64-w64-mingw32-gcc'

今度は WHPX support yes となっている。

make

# make -j4 2>&1 > ~/qemu_make.log &

問題なく終了した。

make installer

installer の名前を変えて作成した。Makefile も前回の W64 についての変更を反映済み。

# cd /qemu/bin/ndebug/x86_64-w64-mingw32 && make installer INSTALLER=myinstaller_whpx.exe
make install prefix=/tmp/qemu-nsis
make[1]: Entering directory '/qemu/bin/ndebug/x86_64-w64-mingw32'
install -d -m 0755 "/tmp/qemu-nsis"
install -c -m 0644 qemu-doc.html "/tmp/qemu-nsis"
install -c -m 0644 qemu-doc.txt "/tmp/qemu-nsis"
install -c -m 0644 docs/interop/qemu-qmp-ref.html "/tmp/qemu-nsis"
install -c -m 0644 docs/interop/qemu-qmp-ref.txt "/tmp/qemu-nsis"
install -d -m 0755 "/tmp/qemu-nsis"
install -c -m 0755 qemu-img.exe qemu-io.exe qemu-edid.exe "/tmp/qemu-nsis"
x86_64-w64-mingw32-strip "/tmp/qemu-nsis/qemu-img.exe" "/tmp/qemu-nsis/qemu-io.exe" "/tmp/qemu-nsis/qemu-edid.exe"
# qemu-ga is included in TOOLS, but we need special install rules for w32
install -d -m 0755 "/tmp/qemu-nsis"
install -d -m 0755 "/tmp/qemu-nsis"
install -c -m 0755 qemu-ga.exe qemu-img.exe qemu-io.exe qemu-edid.exe  "/tmp/qemu-nsis"
x86_64-w64-mingw32-strip "/tmp/qemu-nsis/qemu-ga.exe" "/tmp/qemu-nsis/qemu-img.exe" "/tmp/qemu-nsis/qemu-io.exe" "/tmp/qemu-nsis/qemu-edid.exe"
set -e; for x in bios.bin bios-256k.bin sgabios.bin vgabios.bin vgabios-cirrus.bin vgabios-stdvga.bin vgabios-vmware.bin vgabios-qxl.bin vgabios-virtio.bin vgabios-ramfb.bin vgabios-bochs-display.bin ppc_rom.bin openbios-sparc32 openbios-sparc64 openbios-ppc QEMU,tcx.bin QEMU,cgthree.bin pxe-e1000.rom pxe-eepro100.rom pxe-ne2k_pci.rom pxe-pcnet.rom pxe-rtl8139.rom pxe-virtio.rom efi-e1000.rom efi-eepro100.rom efi-ne2k_pci.rom efi-pcnet.rom efi-rtl8139.rom efi-virtio.rom efi-e1000e.rom efi-vmxnet3.rom qemu-icon.bmp qemu_logo_no_text.svg bamboo.dtb canyonlands.dtb petalogix-s3adsp1800.dtb petalogix-ml605.dtb multiboot.bin linuxboot.bin linuxboot_dma.bin kvmvapic.bin s390-ccw.img s390-netboot.img spapr-rtas.bin slof.bin skiboot.lid palcode-clipper u-boot.e500 u-boot-sam460-20100605.bin qemu_vga.ndrv hppa-firmware.img; do \
	install -c -m 0644 /qemu/pc-bios/$x "/tmp/qemu-nsis"; \
done
make -C po install
make[2]: Entering directory '/qemu/bin/ndebug/x86_64-w64-mingw32/po'
for obj in bg.mo tr.mo it.mo hu.mo fr_FR.mo zh_CN.mo de_DE.mo; do \
    base=$(basename $obj .mo); \
    install -d /tmp/qemu-nsis/share/locale/$base/LC_MESSAGES; \
    install -m644 $obj /tmp/qemu-nsis/share/locale/$base/LC_MESSAGES/qemu.mo; \
done
make[2]: Leaving directory '/qemu/bin/ndebug/x86_64-w64-mingw32/po'
install -d -m 0755 "/tmp/qemu-nsis/keymaps"
set -e; for x in da     en-gb  et  fr     fr-ch  is  lt  modifiers  no  pt-br  sv ar      de     en-us  fi  fr-be  hr     it  lv  nl         pl  ru     th common  de-ch  es     fo  fr-ca  hu     ja  mk  nl-be      pt  sl     tr bepo    cz; do \
	install -c -m 0644 /qemu/pc-bios/keymaps/$x "/tmp/qemu-nsis/keymaps"; \
done
install -c -m 0644 /qemu/bin/ndebug/x86_64-w64-mingw32/trace-events-all "/tmp/qemu-nsis/trace-events-all"
for d in aarch64-softmmu alpha-softmmu arm-softmmu cris-softmmu hppa-softmmu i386-softmmu lm32-softmmu m68k-softmmu microblaze-softmmu microblazeel-softmmu mips-softmmu mips64-softmmu mips64el-softmmu mipsel-softmmu moxie-softmmu nios2-softmmu or1k-softmmu ppc-softmmu ppc64-softmmu riscv32-softmmu riscv64-softmmu s390x-softmmu sh4-softmmu sh4eb-softmmu sparc-softmmu sparc64-softmmu tricore-softmmu unicore32-softmmu x86_64-softmmu xtensa-softmmu xtensaeb-softmmu; do \
make --no-print-directory --quiet BUILD_DIR=/qemu/bin/ndebug/x86_64-w64-mingw32 TARGET_DIR=$d/ -C $d install || exit 1 ; \
        done
make[1]: Leaving directory '/qemu/bin/ndebug/x86_64-w64-mingw32'
(cd /tmp/qemu-nsis; \
         for i in qemu-system-*.exe; do \
           arch=${i%.exe}; \
           arch=${arch#qemu-system-}; \
           echo Section \"$arch\" Section_$arch; \
           echo SetOutPath \"\$INSTDIR\"; \
           echo File \"\${BINDIR}\\$i\"; \
           echo SectionEnd; \
         done \
        ) >/tmp/qemu-nsis/system-emulations.nsh
makensis -V2 -NOCD -DW64 \
                -DCONFIG_DOCUMENTATION="y" \
                -DCONFIG_GTK="y" \
                -DBINDIR="/tmp/qemu-nsis" \
                 \
                -DSRCDIR="/qemu" \
                -DOUTFILE="myinstaller_whpx.exe" \
                -DDISPLAYVERSION="3.1.0" \
                /qemu/qemu.nsi
rm -r /tmp/qemu-nsis
# ls -l myinstaller_whpx.exe
-rw-r--r-- 1 root root 80992027 Feb 16 18:05 myinstaller_whpx.exe

すんなり出来た。

Windows10 で whpx 有効で起動

Windows10 で起動し、scp で持ってきた後に install、whpx 有効で起動してみた。どうやら dll が installer に含まれていないようで、配布されている installer に上書きする形で実行ファイルのみ置き換えた。

$ ./qemu-system-x86_64.exe -accel accel=whpx
C:\Program Files\qemu\qemu-system-x86_64.exe: WHPX: No accelerator found, hr=00000000
C:\Program Files\qemu\qemu-system-x86_64.exe: failed to initialize WHPX: No space left on device

だめみたい。Virtualbox と同じ現象だと思う。

qemu whpx-all.c whpx_accel_init():

... 略 ...
    HRESULT hr;
... 略 ...
    hr = whp_dispatch.WHvGetCapability(
        WHvCapabilityCodeHypervisorPresent, &whpx_cap,
        sizeof(whpx_cap), &whpx_cap_size);
    if (FAILED(hr) || !whpx_cap.HypervisorPresent) {
        error_report("WHPX: No accelerator found, hr=%08lx", hr);
        ret = -ENOSPC;
        goto error;
    }
... 略 ...

VirtualBox NEMR3Native-win.cpp nemR3WinInitCheckCapabilities():

... 略 ...
	    HRESULT hrc = WHvGetCapabilityWrapper(WHvCapabilityCodeHypervisorPresent, &Caps, sizeof(Caps));
	    DWORD   rcWin = GetLastError();
	    if (FAILED(hrc))
	        return RTErrInfoSetF(pErrInfo, VERR_NEM_INIT_FAILED,
	                             "WHvGetCapability/WHvCapabilityCodeHypervisorPresent failed: %Rhrc (Last=%#x/%u)",
	                             hrc, RTNtLastStatusValue(), RTNtLastErrorValue());
	    if (!Caps.HypervisorPresent)
	    {
	        if (!RTPathExists(RTPATH_NT_PASSTHRU_PREFIX "Device\\VidExo"))
	            return RTErrInfoSetF(pErrInfo, VERR_NEM_NOT_AVAILABLE,
	                                 "WHvCapabilityCodeHypervisorPresent is FALSE! Make sure you have enabled the 'Windows Hypervisor Platform' feature.");
	        return RTErrInfoSetF(pErrInfo, VERR_NEM_NOT_AVAILABLE, "WHvCapabilityCodeHypervisorPresent is FALSE! (%u)", rcWin);
	    }
	    LogRel(("NEM: WHvCapabilityCodeHypervisorPresent is TRUE, so this might work...\n"));
... 略 ...

if が単独か多重かの違いで、判断条件は同じ。

結果

  • installer に dll が入っていない。make installer の部分でもう少し対処が必要。
  • WHPX 有効で起動させると No accelerator found。Hypervisor Platform は有効なのだけどね。
  • Virtualbox の error message からすると、FAILED(hr) の条件は通っていて、!whpx_cap.HypervisorPresent の条件で失敗していると思う。

Windows Hypervisor Platform | Microsoft Docs
確か、qemu の whpx 部分は Microsoft の方が GPL2 で提供してくれたはずなので、WHvGetCapability の使い方を間違う事は無いと思う。他の Hyper-V (Docker 含む)の機能が正常に動作しているのに、qemuVirtualbox が動作しない、というのが残念。
WHvGetCapability | Microsoft Docs

The WHvCapabilityCodeHypervisorPresent capability can be used to determine whether the Windows Hypervisor is running on a host and the functions of the platform APIs can be used to create VM partitions.

Return Value
If the operation completed successfully, the return value is S_OK.

これからすると、やっぱり両方が成立しないと Hyper-V 有効にならないのだが ... 片方をはずしてみるか。